From 4de139784149eddb472e5e5bf8552e12d74c832d Mon Sep 17 00:00:00 2001 From: Larry Finger Date: Thu, 22 Jul 2021 18:57:16 -0500 Subject: [PATCH] rtl8188eu: Flatten hap/ Signed-off-by: Larry Finger --- hal/Hal8188EPwrSeq.c => Hal8188EPwrSeq.c | 0 ...Mask8188E_USB.c => HalEfuseMask8188E_USB.c | 0 ...Mask8188E_USB.h => HalEfuseMask8188E_USB.h | 0 hal/HalPwrSeqCmd.c => HalPwrSeqCmd.c | 0 Makefile | 124 +- {hal/btc => btc}/halbtcoutsrc.h | 0 {hal/btc => btc}/mp_precomp.h | 0 hal/efuse_mask.h => efuse_mask.h | 0 hal/hal8188e_s_fw.c => hal8188e_s_fw.c | 0 hal/hal8188e_s_fw.h => hal8188e_s_fw.h | 0 hal/hal8188e_t_fw.c => hal8188e_t_fw.c | 0 hal/hal8188e_t_fw.h => hal8188e_t_fw.h | 0 ...8erateadaptive.c => hal8188erateadaptive.c | 0 ...8erateadaptive.h => hal8188erateadaptive.h | 0 hal/hal8188ereg.h => hal8188ereg.h | 0 hal/hal_btcoex.c => hal_btcoex.c | 0 ...btcoex_wifionly.c => hal_btcoex_wifionly.c | 0 hal/hal_com.c => hal_com.c | 0 hal/hal_com_c2h.h => hal_com_c2h.h | 0 hal/hal_com_phycfg.c => hal_com_phycfg.c | 0 hal/hal_dm.c => hal_dm.c | 0 hal/hal_dm.h => hal_dm.h | 0 hal/hal_intf.c => hal_intf.c | 0 hal/hal_mcc.c => hal_mcc.c | 0 hal/hal_mp.c => hal_mp.c | 0 hal/hal_phy.c => hal_phy.c | 0 hal/hal_usb.c => hal_usb.c | 0 hal/hal_usb_led.c => hal_usb_led.c | 0 hal/halcomtxbf.h => halcomtxbf.h | 0 hal/halhwimg.h => halhwimg.h | 0 hal/halhwimg8188e_bb.c => halhwimg8188e_bb.c | 0 hal/halhwimg8188e_bb.h => halhwimg8188e_bb.h | 0 ...halhwimg8188e_mac.c => halhwimg8188e_mac.c | 0 ...halhwimg8188e_mac.h => halhwimg8188e_mac.h | 0 hal/halhwimg8188e_rf.c => halhwimg8188e_rf.c | 0 hal/halhwimg8188e_rf.h => halhwimg8188e_rf.h | 0 ...halphyrf_8188e_ce.c => halphyrf_8188e_ce.c | 0 ...halphyrf_8188e_ce.h => halphyrf_8188e_ce.h | 0 hal/halphyrf_ap.h => halphyrf_ap.h | 0 hal/halphyrf_ce.c => halphyrf_ce.c | 0 hal/halphyrf_ce.h => halphyrf_ce.h | 0 hal/haltxbfinterface.h => haltxbfinterface.h | 0 hal/haltxbfjaguar.h => haltxbfjaguar.h | 0 hostapd-0.8/COPYING | 340 - hostapd-0.8/README | 72 - hostapd-0.8/hostapd/Android.mk | 816 -- hostapd-0.8/hostapd/ChangeLog | 647 -- hostapd-0.8/hostapd/Makefile | 836 --- hostapd-0.8/hostapd/README | 387 - hostapd-0.8/hostapd/README-WPS | 291 - hostapd-0.8/hostapd/config_file.c | 2119 ------ hostapd-0.8/hostapd/config_file.h | 20 - hostapd-0.8/hostapd/ctrl_iface.c | 1131 --- hostapd-0.8/hostapd/ctrl_iface.h | 32 - hostapd-0.8/hostapd/defconfig | 208 - hostapd-0.8/hostapd/dump_state.c | 183 - hostapd-0.8/hostapd/dump_state.h | 20 - hostapd-0.8/hostapd/eap_register.c | 139 - hostapd-0.8/hostapd/eap_register.h | 20 - hostapd-0.8/hostapd/eap_testing.txt | 77 - hostapd-0.8/hostapd/hlr_auc_gw.c | 715 -- hostapd-0.8/hostapd/hlr_auc_gw.milenage_db | 13 - hostapd-0.8/hostapd/hostapd.8 | 59 - hostapd-0.8/hostapd/hostapd.accept | 6 - hostapd-0.8/hostapd/hostapd.conf | 1040 --- hostapd-0.8/hostapd/hostapd.deny | 5 - hostapd-0.8/hostapd/hostapd.eap_user | 91 - hostapd-0.8/hostapd/hostapd.radius_clients | 4 - hostapd-0.8/hostapd/hostapd.sim_db | 9 - hostapd-0.8/hostapd/hostapd.vlan | 9 - hostapd-0.8/hostapd/hostapd.wpa_psk | 9 - hostapd-0.8/hostapd/hostapd_cli.1 | 89 - hostapd-0.8/hostapd/hostapd_cli.c | 1044 --- hostapd-0.8/hostapd/logwatch/README | 9 - hostapd-0.8/hostapd/logwatch/hostapd | 65 - hostapd-0.8/hostapd/logwatch/hostapd.conf | 10 - hostapd-0.8/hostapd/main.c | 599 -- hostapd-0.8/hostapd/nt_password_hash.c | 53 - hostapd-0.8/hostapd/wired.conf | 40 - hostapd-0.8/src/Makefile | 11 - hostapd-0.8/src/ap/Makefile | 8 - hostapd-0.8/src/ap/accounting.c | 505 -- hostapd-0.8/src/ap/accounting.h | 45 - hostapd-0.8/src/ap/ap_config.c | 627 -- hostapd-0.8/src/ap/ap_config.h | 417 -- hostapd-0.8/src/ap/ap_drv_ops.c | 632 -- hostapd-0.8/src/ap/ap_drv_ops.h | 197 - hostapd-0.8/src/ap/ap_list.c | 399 - hostapd-0.8/src/ap/ap_list.h | 78 - hostapd-0.8/src/ap/ap_mlme.c | 184 - hostapd-0.8/src/ap/ap_mlme.h | 40 - hostapd-0.8/src/ap/authsrv.c | 217 - hostapd-0.8/src/ap/authsrv.h | 21 - hostapd-0.8/src/ap/beacon.c | 540 -- hostapd-0.8/src/ap/beacon.h | 36 - hostapd-0.8/src/ap/ctrl_iface_ap.c | 108 - hostapd-0.8/src/ap/ctrl_iface_ap.h | 25 - hostapd-0.8/src/ap/drv_callbacks.c | 539 -- hostapd-0.8/src/ap/hostapd.c | 929 --- hostapd-0.8/src/ap/hostapd.h | 262 - hostapd-0.8/src/ap/hw_features.c | 754 -- hostapd-0.8/src/ap/hw_features.h | 70 - hostapd-0.8/src/ap/iapp.c | 535 -- hostapd-0.8/src/ap/iapp.h | 45 - hostapd-0.8/src/ap/ieee802_11.c | 1884 ----- hostapd-0.8/src/ap/ieee802_11.h | 68 - hostapd-0.8/src/ap/ieee802_11_auth.c | 524 -- hostapd-0.8/src/ap/ieee802_11_auth.h | 31 - hostapd-0.8/src/ap/ieee802_11_ht.c | 267 - hostapd-0.8/src/ap/ieee802_1x.c | 2085 ------ hostapd-0.8/src/ap/ieee802_1x.h | 89 - hostapd-0.8/src/ap/p2p_hostapd.c | 120 - hostapd-0.8/src/ap/p2p_hostapd.h | 41 - hostapd-0.8/src/ap/peerkey_auth.c | 402 - hostapd-0.8/src/ap/pmksa_cache_auth.c | 425 -- hostapd-0.8/src/ap/pmksa_cache_auth.h | 64 - hostapd-0.8/src/ap/preauth_auth.c | 279 - hostapd-0.8/src/ap/preauth_auth.h | 58 - hostapd-0.8/src/ap/sta_info.c | 796 -- hostapd-0.8/src/ap/sta_info.h | 165 - hostapd-0.8/src/ap/tkip_countermeasures.c | 94 - hostapd-0.8/src/ap/tkip_countermeasures.h | 20 - hostapd-0.8/src/ap/utils.c | 88 - hostapd-0.8/src/ap/vlan_init.c | 905 --- hostapd-0.8/src/ap/vlan_init.h | 59 - hostapd-0.8/src/ap/wmm.c | 327 - hostapd-0.8/src/ap/wmm.h | 29 - hostapd-0.8/src/ap/wpa_auth.c | 2838 ------- hostapd-0.8/src/ap/wpa_auth.h | 285 - hostapd-0.8/src/ap/wpa_auth_ft.c | 1779 ----- hostapd-0.8/src/ap/wpa_auth_glue.c | 571 -- hostapd-0.8/src/ap/wpa_auth_glue.h | 22 - hostapd-0.8/src/ap/wpa_auth_i.h | 234 - hostapd-0.8/src/ap/wpa_auth_ie.c | 824 --- hostapd-0.8/src/ap/wpa_auth_ie.h | 56 - hostapd-0.8/src/ap/wps_hostapd.c | 1380 ---- hostapd-0.8/src/ap/wps_hostapd.h | 72 - hostapd-0.8/src/common/Makefile | 8 - hostapd-0.8/src/common/defs.h | 270 - hostapd-0.8/src/common/eapol_common.h | 47 - hostapd-0.8/src/common/ieee802_11_common.c | 347 - hostapd-0.8/src/common/ieee802_11_common.h | 81 - hostapd-0.8/src/common/ieee802_11_defs.h | 800 -- hostapd-0.8/src/common/privsep_commands.h | 75 - hostapd-0.8/src/common/version.h | 10 - hostapd-0.8/src/common/wpa_common.c | 927 --- hostapd-0.8/src/common/wpa_common.h | 361 - hostapd-0.8/src/common/wpa_ctrl.c | 500 -- hostapd-0.8/src/common/wpa_ctrl.h | 274 - hostapd-0.8/src/crypto/.gitignore | 1 - hostapd-0.8/src/crypto/Makefile | 56 - hostapd-0.8/src/crypto/aes-cbc.c | 86 - hostapd-0.8/src/crypto/aes-ctr.c | 61 - hostapd-0.8/src/crypto/aes-eax.c | 151 - hostapd-0.8/src/crypto/aes-encblock.c | 38 - hostapd-0.8/src/crypto/aes-internal-dec.c | 151 - hostapd-0.8/src/crypto/aes-internal-enc.c | 121 - hostapd-0.8/src/crypto/aes-internal.c | 805 -- hostapd-0.8/src/crypto/aes-omac1.c | 124 - hostapd-0.8/src/crypto/aes-unwrap.c | 79 - hostapd-0.8/src/crypto/aes-wrap.c | 76 - hostapd-0.8/src/crypto/aes.h | 27 - hostapd-0.8/src/crypto/aes_i.h | 122 - hostapd-0.8/src/crypto/aes_wrap.h | 48 - hostapd-0.8/src/crypto/crypto.h | 469 -- hostapd-0.8/src/crypto/crypto_cryptoapi.c | 789 -- hostapd-0.8/src/crypto/crypto_gnutls.c | 305 - .../src/crypto/crypto_internal-cipher.c | 256 - .../src/crypto/crypto_internal-modexp.c | 55 - hostapd-0.8/src/crypto/crypto_internal-rsa.c | 115 - hostapd-0.8/src/crypto/crypto_internal.c | 205 - hostapd-0.8/src/crypto/crypto_libtomcrypt.c | 732 -- hostapd-0.8/src/crypto/crypto_none.c | 29 - hostapd-0.8/src/crypto/crypto_nss.c | 213 - hostapd-0.8/src/crypto/crypto_openssl.c | 505 -- hostapd-0.8/src/crypto/des-internal.c | 499 -- hostapd-0.8/src/crypto/des_i.h | 31 - hostapd-0.8/src/crypto/dh_group5.c | 40 - hostapd-0.8/src/crypto/dh_group5.h | 23 - hostapd-0.8/src/crypto/dh_groups.c | 633 -- hostapd-0.8/src/crypto/dh_groups.h | 32 - hostapd-0.8/src/crypto/fips_prf_cryptoapi.c | 25 - hostapd-0.8/src/crypto/fips_prf_gnutls.c | 26 - hostapd-0.8/src/crypto/fips_prf_internal.c | 74 - hostapd-0.8/src/crypto/fips_prf_nss.c | 25 - hostapd-0.8/src/crypto/fips_prf_openssl.c | 83 - hostapd-0.8/src/crypto/md4-internal.c | 278 - hostapd-0.8/src/crypto/md5-internal.c | 293 - hostapd-0.8/src/crypto/md5-non-fips.c | 113 - hostapd-0.8/src/crypto/md5.c | 111 - hostapd-0.8/src/crypto/md5.h | 35 - hostapd-0.8/src/crypto/md5_i.h | 29 - hostapd-0.8/src/crypto/milenage.c | 329 - hostapd-0.8/src/crypto/milenage.h | 33 - hostapd-0.8/src/crypto/ms_funcs.c | 476 -- hostapd-0.8/src/crypto/ms_funcs.h | 64 - hostapd-0.8/src/crypto/random.c | 337 - hostapd-0.8/src/crypto/random.h | 34 - hostapd-0.8/src/crypto/rc4.c | 60 - hostapd-0.8/src/crypto/sha1-internal.c | 308 - hostapd-0.8/src/crypto/sha1-pbkdf2.c | 100 - hostapd-0.8/src/crypto/sha1-tlsprf.c | 109 - hostapd-0.8/src/crypto/sha1-tprf.c | 76 - hostapd-0.8/src/crypto/sha1.c | 163 - hostapd-0.8/src/crypto/sha1.h | 33 - hostapd-0.8/src/crypto/sha1_i.h | 29 - hostapd-0.8/src/crypto/sha256-internal.c | 243 - hostapd-0.8/src/crypto/sha256.c | 157 - hostapd-0.8/src/crypto/sha256.h | 27 - hostapd-0.8/src/crypto/tls.h | 569 -- hostapd-0.8/src/crypto/tls_gnutls.c | 1457 ---- hostapd-0.8/src/crypto/tls_internal.c | 651 -- hostapd-0.8/src/crypto/tls_none.c | 229 - hostapd-0.8/src/crypto/tls_nss.c | 680 -- hostapd-0.8/src/crypto/tls_openssl.c | 2992 -------- hostapd-0.8/src/crypto/tls_schannel.c | 767 -- hostapd-0.8/src/drivers/.gitignore | 2 - hostapd-0.8/src/drivers/Apple80211.h | 156 - hostapd-0.8/src/drivers/Makefile | 9 - hostapd-0.8/src/drivers/MobileApple80211.c | 189 - hostapd-0.8/src/drivers/MobileApple80211.h | 43 - hostapd-0.8/src/drivers/driver.h | 3230 -------- hostapd-0.8/src/drivers/driver_atheros.c | 1381 ---- hostapd-0.8/src/drivers/driver_broadcom.c | 599 -- hostapd-0.8/src/drivers/driver_bsd.c | 1573 ---- hostapd-0.8/src/drivers/driver_hostap.c | 1648 ----- hostapd-0.8/src/drivers/driver_hostap.h | 216 - hostapd-0.8/src/drivers/driver_iphone.m | 466 -- hostapd-0.8/src/drivers/driver_madwifi.c | 1856 ----- hostapd-0.8/src/drivers/driver_ndis.c | 3331 --------- hostapd-0.8/src/drivers/driver_ndis.h | 65 - hostapd-0.8/src/drivers/driver_ndis_.c | 105 - hostapd-0.8/src/drivers/driver_nl80211.c | 6550 ----------------- hostapd-0.8/src/drivers/driver_none.c | 99 - hostapd-0.8/src/drivers/driver_osx.m | 459 -- hostapd-0.8/src/drivers/driver_privsep.c | 758 -- hostapd-0.8/src/drivers/driver_ralink.c | 1498 ---- hostapd-0.8/src/drivers/driver_ralink.h | 383 - hostapd-0.8/src/drivers/driver_roboswitch.c | 480 -- hostapd-0.8/src/drivers/driver_rtl.h | 113 - hostapd-0.8/src/drivers/driver_rtw.c | 1902 ----- hostapd-0.8/src/drivers/driver_test.c | 3391 --------- hostapd-0.8/src/drivers/driver_wext.c | 2356 ------ hostapd-0.8/src/drivers/driver_wext.h | 87 - hostapd-0.8/src/drivers/driver_wired.c | 629 -- hostapd-0.8/src/drivers/drivers.c | 120 - hostapd-0.8/src/drivers/drivers.mak | 191 - hostapd-0.8/src/drivers/drivers.mk | 183 - hostapd-0.8/src/drivers/linux_ioctl.c | 198 - hostapd-0.8/src/drivers/linux_ioctl.h | 27 - hostapd-0.8/src/drivers/ndis_events.c | 808 -- hostapd-0.8/src/drivers/netlink.c | 204 - hostapd-0.8/src/drivers/netlink.h | 34 - hostapd-0.8/src/drivers/nl80211_copy.h | 1939 ----- hostapd-0.8/src/drivers/priv_netlink.h | 113 - hostapd-0.8/src/drivers/rfkill.c | 194 - hostapd-0.8/src/drivers/rfkill.h | 31 - hostapd-0.8/src/drivers/wireless_copy.h | 1185 --- hostapd-0.8/src/eap_common/Makefile | 8 - hostapd-0.8/src/eap_common/chap.c | 34 - hostapd-0.8/src/eap_common/chap.h | 23 - hostapd-0.8/src/eap_common/eap_common.c | 184 - hostapd-0.8/src/eap_common/eap_common.h | 28 - hostapd-0.8/src/eap_common/eap_defs.h | 86 - hostapd-0.8/src/eap_common/eap_fast_common.c | 304 - hostapd-0.8/src/eap_common/eap_fast_common.h | 113 - hostapd-0.8/src/eap_common/eap_gpsk_common.c | 423 -- hostapd-0.8/src/eap_common/eap_gpsk_common.h | 66 - hostapd-0.8/src/eap_common/eap_ikev2_common.c | 132 - hostapd-0.8/src/eap_common/eap_ikev2_common.h | 42 - hostapd-0.8/src/eap_common/eap_pax_common.c | 150 - hostapd-0.8/src/eap_common/eap_pax_common.h | 97 - hostapd-0.8/src/eap_common/eap_peap_common.c | 88 - hostapd-0.8/src/eap_common/eap_peap_common.h | 22 - hostapd-0.8/src/eap_common/eap_psk_common.c | 74 - hostapd-0.8/src/eap_common/eap_psk_common.h | 78 - hostapd-0.8/src/eap_common/eap_pwd_common.c | 312 - hostapd-0.8/src/eap_common/eap_pwd_common.h | 79 - hostapd-0.8/src/eap_common/eap_sake_common.c | 393 - hostapd-0.8/src/eap_common/eap_sake_common.h | 102 - hostapd-0.8/src/eap_common/eap_sim_common.c | 1215 --- hostapd-0.8/src/eap_common/eap_sim_common.h | 235 - hostapd-0.8/src/eap_common/eap_tlv_common.h | 118 - hostapd-0.8/src/eap_common/eap_ttls.h | 71 - hostapd-0.8/src/eap_common/eap_wsc_common.c | 39 - hostapd-0.8/src/eap_common/eap_wsc_common.h | 33 - hostapd-0.8/src/eap_common/ikev2_common.c | 797 -- hostapd-0.8/src/eap_common/ikev2_common.h | 344 - hostapd-0.8/src/eap_peer/Makefile | 11 - hostapd-0.8/src/eap_peer/eap.c | 2159 ------ hostapd-0.8/src/eap_peer/eap.h | 292 - hostapd-0.8/src/eap_peer/eap_aka.c | 1389 ---- hostapd-0.8/src/eap_peer/eap_config.h | 669 -- hostapd-0.8/src/eap_peer/eap_fast.c | 1712 ----- hostapd-0.8/src/eap_peer/eap_fast_pac.c | 923 --- hostapd-0.8/src/eap_peer/eap_fast_pac.h | 56 - hostapd-0.8/src/eap_peer/eap_gpsk.c | 738 -- hostapd-0.8/src/eap_peer/eap_gtc.c | 151 - hostapd-0.8/src/eap_peer/eap_i.h | 356 - hostapd-0.8/src/eap_peer/eap_ikev2.c | 506 -- hostapd-0.8/src/eap_peer/eap_leap.c | 416 -- hostapd-0.8/src/eap_peer/eap_md5.c | 120 - hostapd-0.8/src/eap_peer/eap_methods.c | 373 - hostapd-0.8/src/eap_peer/eap_methods.h | 114 - hostapd-0.8/src/eap_peer/eap_mschapv2.c | 883 --- hostapd-0.8/src/eap_peer/eap_otp.c | 107 - hostapd-0.8/src/eap_peer/eap_pax.c | 531 -- hostapd-0.8/src/eap_peer/eap_peap.c | 1288 ---- hostapd-0.8/src/eap_peer/eap_psk.c | 483 -- hostapd-0.8/src/eap_peer/eap_pwd.c | 744 -- hostapd-0.8/src/eap_peer/eap_sake.c | 500 -- hostapd-0.8/src/eap_peer/eap_sim.c | 1101 --- hostapd-0.8/src/eap_peer/eap_tls.c | 289 - hostapd-0.8/src/eap_peer/eap_tls_common.c | 1021 --- hostapd-0.8/src/eap_peer/eap_tls_common.h | 126 - hostapd-0.8/src/eap_peer/eap_tnc.c | 434 -- hostapd-0.8/src/eap_peer/eap_ttls.c | 1986 ----- hostapd-0.8/src/eap_peer/eap_vendor_test.c | 195 - hostapd-0.8/src/eap_peer/eap_wsc.c | 553 -- hostapd-0.8/src/eap_peer/ikev2.c | 1304 ---- hostapd-0.8/src/eap_peer/ikev2.h | 65 - hostapd-0.8/src/eap_peer/mschapv2.c | 123 - hostapd-0.8/src/eap_peer/mschapv2.h | 34 - hostapd-0.8/src/eap_peer/tncc.c | 1369 ---- hostapd-0.8/src/eap_peer/tncc.h | 42 - hostapd-0.8/src/eap_server/Makefile | 8 - hostapd-0.8/src/eap_server/eap.h | 128 - hostapd-0.8/src/eap_server/eap_i.h | 201 - hostapd-0.8/src/eap_server/eap_methods.h | 54 - hostapd-0.8/src/eap_server/eap_server.c | 1384 ---- hostapd-0.8/src/eap_server/eap_server_aka.c | 1278 ---- hostapd-0.8/src/eap_server/eap_server_fast.c | 1620 ---- hostapd-0.8/src/eap_server/eap_server_gpsk.c | 634 -- hostapd-0.8/src/eap_server/eap_server_gtc.c | 230 - .../src/eap_server/eap_server_identity.c | 180 - hostapd-0.8/src/eap_server/eap_server_ikev2.c | 539 -- hostapd-0.8/src/eap_server/eap_server_md5.c | 177 - .../src/eap_server/eap_server_methods.c | 175 - .../src/eap_server/eap_server_mschapv2.c | 575 -- hostapd-0.8/src/eap_server/eap_server_pax.c | 570 -- hostapd-0.8/src/eap_server/eap_server_peap.c | 1387 ---- hostapd-0.8/src/eap_server/eap_server_psk.c | 518 -- hostapd-0.8/src/eap_server/eap_server_pwd.c | 844 --- hostapd-0.8/src/eap_server/eap_server_sake.c | 543 -- hostapd-0.8/src/eap_server/eap_server_sim.c | 798 -- hostapd-0.8/src/eap_server/eap_server_tls.c | 286 - .../src/eap_server/eap_server_tls_common.c | 400 - hostapd-0.8/src/eap_server/eap_server_tnc.c | 582 -- hostapd-0.8/src/eap_server/eap_server_ttls.c | 1430 ---- .../src/eap_server/eap_server_vendor_test.c | 198 - hostapd-0.8/src/eap_server/eap_server_wsc.c | 517 -- hostapd-0.8/src/eap_server/eap_sim_db.c | 1338 ---- hostapd-0.8/src/eap_server/eap_sim_db.h | 91 - hostapd-0.8/src/eap_server/eap_tls_common.h | 91 - hostapd-0.8/src/eap_server/ikev2.c | 1206 --- hostapd-0.8/src/eap_server/ikev2.h | 67 - hostapd-0.8/src/eap_server/tncs.c | 1273 ---- hostapd-0.8/src/eap_server/tncs.h | 49 - hostapd-0.8/src/eapol_auth/Makefile | 8 - hostapd-0.8/src/eapol_auth/eapol_auth_dump.c | 231 - hostapd-0.8/src/eapol_auth/eapol_auth_sm.c | 1145 --- hostapd-0.8/src/eapol_auth/eapol_auth_sm.h | 92 - hostapd-0.8/src/eapol_auth/eapol_auth_sm_i.h | 183 - hostapd-0.8/src/eapol_supp/Makefile | 8 - hostapd-0.8/src/eapol_supp/eapol_supp_sm.c | 1913 ----- hostapd-0.8/src/eapol_supp/eapol_supp_sm.h | 352 - hostapd-0.8/src/l2_packet/Makefile | 8 - hostapd-0.8/src/l2_packet/l2_packet.h | 130 - hostapd-0.8/src/l2_packet/l2_packet_freebsd.c | 316 - hostapd-0.8/src/l2_packet/l2_packet_linux.c | 210 - hostapd-0.8/src/l2_packet/l2_packet_ndis.c | 522 -- hostapd-0.8/src/l2_packet/l2_packet_none.c | 123 - hostapd-0.8/src/l2_packet/l2_packet_pcap.c | 386 - hostapd-0.8/src/l2_packet/l2_packet_privsep.c | 267 - hostapd-0.8/src/l2_packet/l2_packet_winpcap.c | 341 - hostapd-0.8/src/lib.rules | 21 - hostapd-0.8/src/p2p/Makefile | 9 - hostapd-0.8/src/p2p/p2p.c | 3490 --------- hostapd-0.8/src/p2p/p2p.h | 1473 ---- hostapd-0.8/src/p2p/p2p_build.c | 431 -- hostapd-0.8/src/p2p/p2p_dev_disc.c | 365 - hostapd-0.8/src/p2p/p2p_go_neg.c | 1127 --- hostapd-0.8/src/p2p/p2p_group.c | 673 -- hostapd-0.8/src/p2p/p2p_i.h | 638 -- hostapd-0.8/src/p2p/p2p_invitation.c | 489 -- hostapd-0.8/src/p2p/p2p_parse.c | 718 -- hostapd-0.8/src/p2p/p2p_pd.c | 347 - hostapd-0.8/src/p2p/p2p_sd.c | 951 --- hostapd-0.8/src/p2p/p2p_utils.c | 271 - hostapd-0.8/src/radius/.gitignore | 1 - hostapd-0.8/src/radius/Makefile | 22 - hostapd-0.8/src/radius/radius.c | 1317 ---- hostapd-0.8/src/radius/radius.h | 273 - hostapd-0.8/src/radius/radius_client.c | 1499 ---- hostapd-0.8/src/radius/radius_client.h | 265 - hostapd-0.8/src/radius/radius_server.c | 1527 ---- hostapd-0.8/src/radius/radius_server.h | 217 - hostapd-0.8/src/rsn_supp/Makefile | 8 - hostapd-0.8/src/rsn_supp/peerkey.c | 1186 --- hostapd-0.8/src/rsn_supp/peerkey.h | 87 - hostapd-0.8/src/rsn_supp/pmksa_cache.c | 476 -- hostapd-0.8/src/rsn_supp/pmksa_cache.h | 127 - hostapd-0.8/src/rsn_supp/preauth.c | 518 -- hostapd-0.8/src/rsn_supp/preauth.h | 85 - hostapd-0.8/src/rsn_supp/tdls.c | 2069 ------ hostapd-0.8/src/rsn_supp/wpa.c | 2644 ------- hostapd-0.8/src/rsn_supp/wpa.h | 351 - hostapd-0.8/src/rsn_supp/wpa_ft.c | 1039 --- hostapd-0.8/src/rsn_supp/wpa_i.h | 290 - hostapd-0.8/src/rsn_supp/wpa_ie.c | 447 -- hostapd-0.8/src/rsn_supp/wpa_ie.h | 60 - hostapd-0.8/src/tls/.gitignore | 1 - hostapd-0.8/src/tls/Makefile | 37 - hostapd-0.8/src/tls/asn1.c | 212 - hostapd-0.8/src/tls/asn1.h | 72 - hostapd-0.8/src/tls/bignum.c | 230 - hostapd-0.8/src/tls/bignum.h | 38 - hostapd-0.8/src/tls/libtommath.c | 3381 --------- hostapd-0.8/src/tls/pkcs1.c | 201 - hostapd-0.8/src/tls/pkcs1.h | 28 - hostapd-0.8/src/tls/pkcs5.c | 238 - hostapd-0.8/src/tls/pkcs5.h | 22 - hostapd-0.8/src/tls/pkcs8.c | 193 - hostapd-0.8/src/tls/pkcs8.h | 22 - hostapd-0.8/src/tls/rsa.c | 358 - hostapd-0.8/src/tls/rsa.h | 29 - hostapd-0.8/src/tls/tlsv1_client.c | 667 -- hostapd-0.8/src/tls/tlsv1_client.h | 59 - hostapd-0.8/src/tls/tlsv1_client_i.h | 87 - hostapd-0.8/src/tls/tlsv1_client_read.c | 976 --- hostapd-0.8/src/tls/tlsv1_client_write.c | 798 -- hostapd-0.8/src/tls/tlsv1_common.c | 241 - hostapd-0.8/src/tls/tlsv1_common.h | 216 - hostapd-0.8/src/tls/tlsv1_cred.c | 493 -- hostapd-0.8/src/tls/tlsv1_cred.h | 46 - hostapd-0.8/src/tls/tlsv1_record.c | 409 - hostapd-0.8/src/tls/tlsv1_record.h | 74 - hostapd-0.8/src/tls/tlsv1_server.c | 592 -- hostapd-0.8/src/tls/tlsv1_server.h | 54 - hostapd-0.8/src/tls/tlsv1_server_i.h | 77 - hostapd-0.8/src/tls/tlsv1_server_read.c | 1134 --- hostapd-0.8/src/tls/tlsv1_server_write.c | 791 -- hostapd-0.8/src/tls/x509v3.c | 1985 ----- hostapd-0.8/src/tls/x509v3.h | 129 - hostapd-0.8/src/utils/.gitignore | 1 - hostapd-0.8/src/utils/Makefile | 39 - hostapd-0.8/src/utils/base64.c | 154 - hostapd-0.8/src/utils/base64.h | 23 - hostapd-0.8/src/utils/build_config.h | 105 - hostapd-0.8/src/utils/common.c | 387 - hostapd-0.8/src/utils/common.h | 502 -- hostapd-0.8/src/utils/edit.c | 1161 --- hostapd-0.8/src/utils/edit.h | 27 - hostapd-0.8/src/utils/edit_readline.c | 184 - hostapd-0.8/src/utils/edit_simple.c | 96 - hostapd-0.8/src/utils/eloop.c | 627 -- hostapd-0.8/src/utils/eloop.h | 316 - hostapd-0.8/src/utils/eloop_none.c | 401 - hostapd-0.8/src/utils/eloop_win.c | 623 -- hostapd-0.8/src/utils/includes.h | 59 - hostapd-0.8/src/utils/ip_addr.c | 83 - hostapd-0.8/src/utils/ip_addr.h | 34 - hostapd-0.8/src/utils/list.h | 98 - hostapd-0.8/src/utils/os.h | 508 -- hostapd-0.8/src/utils/os_internal.c | 471 -- hostapd-0.8/src/utils/os_none.c | 226 - hostapd-0.8/src/utils/os_unix.c | 474 -- hostapd-0.8/src/utils/os_win32.c | 222 - hostapd-0.8/src/utils/pcsc_funcs.c | 1238 ---- hostapd-0.8/src/utils/pcsc_funcs.h | 68 - hostapd-0.8/src/utils/radiotap.c | 287 - hostapd-0.8/src/utils/radiotap.h | 242 - hostapd-0.8/src/utils/radiotap_iter.h | 41 - hostapd-0.8/src/utils/state_machine.h | 144 - hostapd-0.8/src/utils/trace.c | 329 - hostapd-0.8/src/utils/trace.h | 74 - hostapd-0.8/src/utils/uuid.c | 77 - hostapd-0.8/src/utils/uuid.h | 24 - hostapd-0.8/src/utils/wpa_debug.c | 484 -- hostapd-0.8/src/utils/wpa_debug.h | 307 - hostapd-0.8/src/utils/wpabuf.c | 304 - hostapd-0.8/src/utils/wpabuf.h | 168 - hostapd-0.8/src/wps/Makefile | 8 - hostapd-0.8/src/wps/http.h | 29 - hostapd-0.8/src/wps/http_client.c | 374 - hostapd-0.8/src/wps/http_client.h | 46 - hostapd-0.8/src/wps/http_server.c | 312 - hostapd-0.8/src/wps/http_server.h | 39 - hostapd-0.8/src/wps/httpread.c | 861 --- hostapd-0.8/src/wps/httpread.h | 123 - hostapd-0.8/src/wps/ndef.c | 175 - hostapd-0.8/src/wps/upnp_xml.c | 252 - hostapd-0.8/src/wps/upnp_xml.h | 23 - hostapd-0.8/src/wps/wps.c | 627 -- hostapd-0.8/src/wps/wps.h | 964 --- hostapd-0.8/src/wps/wps_attr_build.c | 422 -- hostapd-0.8/src/wps/wps_attr_parse.c | 630 -- hostapd-0.8/src/wps/wps_attr_process.c | 335 - hostapd-0.8/src/wps/wps_common.c | 704 -- hostapd-0.8/src/wps/wps_defs.h | 336 - hostapd-0.8/src/wps/wps_dev_attr.c | 444 -- hostapd-0.8/src/wps/wps_dev_attr.h | 44 - hostapd-0.8/src/wps/wps_enrollee.c | 1350 ---- hostapd-0.8/src/wps/wps_er.c | 1959 ----- hostapd-0.8/src/wps/wps_er.h | 117 - hostapd-0.8/src/wps/wps_er_ssdp.c | 211 - hostapd-0.8/src/wps/wps_i.h | 301 - hostapd-0.8/src/wps/wps_nfc.c | 117 - hostapd-0.8/src/wps/wps_nfc_pn531.c | 113 - hostapd-0.8/src/wps/wps_registrar.c | 3273 -------- hostapd-0.8/src/wps/wps_ufd.c | 235 - hostapd-0.8/src/wps/wps_upnp.c | 1210 --- hostapd-0.8/src/wps/wps_upnp.h | 48 - hostapd-0.8/src/wps/wps_upnp_ap.c | 91 - hostapd-0.8/src/wps/wps_upnp_event.c | 423 -- hostapd-0.8/src/wps/wps_upnp_i.h | 193 - hostapd-0.8/src/wps/wps_upnp_ssdp.c | 938 --- hostapd-0.8/src/wps/wps_upnp_web.c | 1324 ---- hostapd-0.8/src/wps/wps_validate.c | 1981 ----- include/drv_types.h | 2 +- include/hal_com.h | 2 +- include/hal_data.h | 2 +- include/rtw_odm.h | 2 +- hal/mp_precomp.h => mp_precomp.h | 0 os_dep/ioctl_linux.c | 4 +- os_dep/ioctl_mp.c | 2 +- hal/phydm.c => phydm.c | 0 hal/phydm.h => phydm.h | 0 hal/phydm_acs.c => phydm_acs.c | 0 hal/phydm_acs.h => phydm_acs.h | 0 hal/phydm_adaptivity.c => phydm_adaptivity.c | 0 hal/phydm_adaptivity.h => phydm_adaptivity.h | 0 ...ydm_adc_sampling.c => phydm_adc_sampling.c | 0 ...ydm_adc_sampling.h => phydm_adc_sampling.h | 0 hal/phydm_antdect.c => phydm_antdect.c | 0 hal/phydm_antdect.h => phydm_antdect.h | 0 hal/phydm_antdiv.c => phydm_antdiv.c | 0 hal/phydm_antdiv.h => phydm_antdiv.h | 0 ...phydm_beamforming.h => phydm_beamforming.h | 0 hal/phydm_ccx.c => phydm_ccx.c | 0 hal/phydm_ccx.h => phydm_ccx.h | 0 ...phydm_cfotracking.c => phydm_cfotracking.c | 0 ...phydm_cfotracking.h => phydm_cfotracking.h | 0 hal/phydm_debug.c => phydm_debug.c | 0 hal/phydm_debug.h => phydm_debug.h | 0 hal/phydm_dfs.c => phydm_dfs.c | 0 hal/phydm_dfs.h => phydm_dfs.h | 0 hal/phydm_dig.c => phydm_dig.c | 0 hal/phydm_dig.h => phydm_dig.h | 0 ...namic_rx_path.c => phydm_dynamic_rx_path.c | 0 ...namic_rx_path.h => phydm_dynamic_rx_path.h | 0 ...ersaving.c => phydm_dynamicbbpowersaving.c | 0 ...ersaving.h => phydm_dynamicbbpowersaving.h | 0 ...dynamictxpower.c => phydm_dynamictxpower.c | 0 ...dynamictxpower.h => phydm_dynamictxpower.h | 0 ...edcaturbocheck.c => phydm_edcaturbocheck.c | 0 ...edcaturbocheck.h => phydm_edcaturbocheck.h | 0 hal/phydm_features.h => phydm_features.h | 0 ...ydm_hal_txbf_api.c => phydm_hal_txbf_api.c | 0 ...ydm_hal_txbf_api.h => phydm_hal_txbf_api.h | 0 hal/phydm_hwconfig.c => phydm_hwconfig.c | 0 hal/phydm_hwconfig.h => phydm_hwconfig.h | 0 hal/phydm_interface.c => phydm_interface.c | 0 hal/phydm_interface.h => phydm_interface.h | 0 hal/phydm_iqk.h => phydm_iqk.h | 0 hal/phydm_kfree.c => phydm_kfree.c | 0 hal/phydm_kfree.h => phydm_kfree.h | 0 ...ydm_noisemonitor.c => phydm_noisemonitor.c | 0 ...ydm_noisemonitor.h => phydm_noisemonitor.h | 0 hal/phydm_pathdiv.c => phydm_pathdiv.c | 0 hal/phydm_pathdiv.h => phydm_pathdiv.h | 0 ...rtracking_ce.c => phydm_powertracking_ce.c | 0 ...rtracking_ce.h => phydm_powertracking_ce.h | 0 hal/phydm_pre_define.h => phydm_pre_define.h | 0 hal/phydm_precomp.h => phydm_precomp.h | 0 hal/phydm_rainfo.c => phydm_rainfo.c | 0 hal/phydm_rainfo.h => phydm_rainfo.h | 0 hal/phydm_reg.h => phydm_reg.h | 0 ...regconfig8188e.c => phydm_regconfig8188e.c | 0 ...regconfig8188e.h => phydm_regconfig8188e.h | 0 ...m_regdefine11ac.h => phydm_regdefine11ac.h | 0 ...ydm_regdefine11n.h => phydm_regdefine11n.h | 0 hal/phydm_rtl8188e.c => phydm_rtl8188e.c | 0 hal/phydm_rtl8188e.h => phydm_rtl8188e.h | 0 hal/phydm_types.h => phydm_types.h | 0 hal/rtchnlplan.c => rtchnlplan.c | 0 hal/rtchnlplan.h => rtchnlplan.h | 0 hal/rtl8188e_cmd.c => rtl8188e_cmd.c | 0 hal/rtl8188e_dm.c => rtl8188e_dm.c | 0 ...rtl8188e_hal_init.c => rtl8188e_hal_init.c | 0 hal/rtl8188e_phycfg.c => rtl8188e_phycfg.c | 0 hal/rtl8188e_rf6052.c => rtl8188e_rf6052.c | 0 hal/rtl8188e_rxdesc.c => rtl8188e_rxdesc.c | 0 hal/rtl8188e_sreset.c => rtl8188e_sreset.c | 0 hal/rtl8188e_xmit.c => rtl8188e_xmit.c | 0 hal/rtl8188eu_led.c => rtl8188eu_led.c | 0 hal/rtl8188eu_recv.c => rtl8188eu_recv.c | 0 hal/rtl8188eu_xmit.c => rtl8188eu_xmit.c | 0 rtw_efuse.c | 2 +- rtw_mp.c | 2 +- hal/usb_halinit.c => usb_halinit.c | 0 hal/usb_ops_linux.c => usb_ops_linux.c | 0 hal/version_rtl8188e.h => version_rtl8188e.h | 0 603 files changed, 71 insertions(+), 220876 deletions(-) rename hal/Hal8188EPwrSeq.c => Hal8188EPwrSeq.c (100%) rename hal/HalEfuseMask8188E_USB.c => HalEfuseMask8188E_USB.c (100%) rename hal/HalEfuseMask8188E_USB.h => HalEfuseMask8188E_USB.h (100%) rename hal/HalPwrSeqCmd.c => HalPwrSeqCmd.c (100%) rename {hal/btc => btc}/halbtcoutsrc.h (100%) rename {hal/btc => btc}/mp_precomp.h (100%) rename hal/efuse_mask.h => efuse_mask.h (100%) rename hal/hal8188e_s_fw.c => hal8188e_s_fw.c (100%) rename hal/hal8188e_s_fw.h => hal8188e_s_fw.h (100%) rename hal/hal8188e_t_fw.c => hal8188e_t_fw.c (100%) rename hal/hal8188e_t_fw.h => hal8188e_t_fw.h (100%) rename hal/hal8188erateadaptive.c => hal8188erateadaptive.c (100%) rename hal/hal8188erateadaptive.h => hal8188erateadaptive.h (100%) rename hal/hal8188ereg.h => hal8188ereg.h (100%) rename hal/hal_btcoex.c => hal_btcoex.c (100%) rename hal/hal_btcoex_wifionly.c => hal_btcoex_wifionly.c (100%) rename hal/hal_com.c => hal_com.c (100%) rename hal/hal_com_c2h.h => hal_com_c2h.h (100%) rename hal/hal_com_phycfg.c => hal_com_phycfg.c (100%) rename hal/hal_dm.c => hal_dm.c (100%) rename hal/hal_dm.h => hal_dm.h (100%) rename hal/hal_intf.c => hal_intf.c (100%) rename hal/hal_mcc.c => hal_mcc.c (100%) rename hal/hal_mp.c => hal_mp.c (100%) rename hal/hal_phy.c => hal_phy.c (100%) rename hal/hal_usb.c => hal_usb.c (100%) rename hal/hal_usb_led.c => hal_usb_led.c (100%) rename hal/halcomtxbf.h => halcomtxbf.h (100%) rename hal/halhwimg.h => halhwimg.h (100%) rename hal/halhwimg8188e_bb.c => halhwimg8188e_bb.c (100%) rename hal/halhwimg8188e_bb.h => halhwimg8188e_bb.h (100%) rename hal/halhwimg8188e_mac.c => halhwimg8188e_mac.c (100%) rename hal/halhwimg8188e_mac.h => halhwimg8188e_mac.h (100%) rename hal/halhwimg8188e_rf.c => halhwimg8188e_rf.c (100%) rename hal/halhwimg8188e_rf.h => halhwimg8188e_rf.h (100%) rename hal/halphyrf_8188e_ce.c => halphyrf_8188e_ce.c (100%) rename hal/halphyrf_8188e_ce.h => halphyrf_8188e_ce.h (100%) rename hal/halphyrf_ap.h => halphyrf_ap.h (100%) rename hal/halphyrf_ce.c => halphyrf_ce.c (100%) rename hal/halphyrf_ce.h => halphyrf_ce.h (100%) rename hal/haltxbfinterface.h => haltxbfinterface.h (100%) rename hal/haltxbfjaguar.h => haltxbfjaguar.h (100%) delete mode 100644 hostapd-0.8/COPYING delete mode 100644 hostapd-0.8/README delete mode 100644 hostapd-0.8/hostapd/Android.mk delete mode 100644 hostapd-0.8/hostapd/ChangeLog delete mode 100644 hostapd-0.8/hostapd/Makefile delete mode 100644 hostapd-0.8/hostapd/README delete mode 100644 hostapd-0.8/hostapd/README-WPS delete mode 100644 hostapd-0.8/hostapd/config_file.c delete mode 100644 hostapd-0.8/hostapd/config_file.h delete mode 100644 hostapd-0.8/hostapd/ctrl_iface.c delete mode 100644 hostapd-0.8/hostapd/ctrl_iface.h delete mode 100644 hostapd-0.8/hostapd/defconfig delete mode 100644 hostapd-0.8/hostapd/dump_state.c delete mode 100644 hostapd-0.8/hostapd/dump_state.h delete mode 100644 hostapd-0.8/hostapd/eap_register.c delete mode 100644 hostapd-0.8/hostapd/eap_register.h delete mode 100644 hostapd-0.8/hostapd/eap_testing.txt delete mode 100644 hostapd-0.8/hostapd/hlr_auc_gw.c delete mode 100644 hostapd-0.8/hostapd/hlr_auc_gw.milenage_db delete mode 100644 hostapd-0.8/hostapd/hostapd.8 delete mode 100644 hostapd-0.8/hostapd/hostapd.accept delete mode 100644 hostapd-0.8/hostapd/hostapd.conf delete mode 100644 hostapd-0.8/hostapd/hostapd.deny delete mode 100644 hostapd-0.8/hostapd/hostapd.eap_user delete mode 100644 hostapd-0.8/hostapd/hostapd.radius_clients delete mode 100644 hostapd-0.8/hostapd/hostapd.sim_db delete mode 100644 hostapd-0.8/hostapd/hostapd.vlan delete mode 100644 hostapd-0.8/hostapd/hostapd.wpa_psk delete mode 100644 hostapd-0.8/hostapd/hostapd_cli.1 delete mode 100644 hostapd-0.8/hostapd/hostapd_cli.c delete mode 100644 hostapd-0.8/hostapd/logwatch/README delete mode 100644 hostapd-0.8/hostapd/logwatch/hostapd delete mode 100644 hostapd-0.8/hostapd/logwatch/hostapd.conf delete mode 100644 hostapd-0.8/hostapd/main.c delete mode 100644 hostapd-0.8/hostapd/nt_password_hash.c delete mode 100644 hostapd-0.8/hostapd/wired.conf delete mode 100644 hostapd-0.8/src/Makefile delete mode 100644 hostapd-0.8/src/ap/Makefile delete mode 100644 hostapd-0.8/src/ap/accounting.c delete mode 100644 hostapd-0.8/src/ap/accounting.h delete mode 100644 hostapd-0.8/src/ap/ap_config.c delete mode 100644 hostapd-0.8/src/ap/ap_config.h delete mode 100644 hostapd-0.8/src/ap/ap_drv_ops.c delete mode 100644 hostapd-0.8/src/ap/ap_drv_ops.h delete mode 100644 hostapd-0.8/src/ap/ap_list.c delete mode 100644 hostapd-0.8/src/ap/ap_list.h delete mode 100644 hostapd-0.8/src/ap/ap_mlme.c delete mode 100644 hostapd-0.8/src/ap/ap_mlme.h delete mode 100644 hostapd-0.8/src/ap/authsrv.c delete mode 100644 hostapd-0.8/src/ap/authsrv.h delete mode 100644 hostapd-0.8/src/ap/beacon.c delete mode 100644 hostapd-0.8/src/ap/beacon.h delete mode 100644 hostapd-0.8/src/ap/ctrl_iface_ap.c delete mode 100644 hostapd-0.8/src/ap/ctrl_iface_ap.h delete mode 100644 hostapd-0.8/src/ap/drv_callbacks.c delete mode 100644 hostapd-0.8/src/ap/hostapd.c delete mode 100644 hostapd-0.8/src/ap/hostapd.h delete mode 100644 hostapd-0.8/src/ap/hw_features.c delete mode 100644 hostapd-0.8/src/ap/hw_features.h delete mode 100644 hostapd-0.8/src/ap/iapp.c delete mode 100644 hostapd-0.8/src/ap/iapp.h delete mode 100644 hostapd-0.8/src/ap/ieee802_11.c delete mode 100644 hostapd-0.8/src/ap/ieee802_11.h delete mode 100644 hostapd-0.8/src/ap/ieee802_11_auth.c delete mode 100644 hostapd-0.8/src/ap/ieee802_11_auth.h delete mode 100644 hostapd-0.8/src/ap/ieee802_11_ht.c delete mode 100644 hostapd-0.8/src/ap/ieee802_1x.c delete mode 100644 hostapd-0.8/src/ap/ieee802_1x.h delete mode 100644 hostapd-0.8/src/ap/p2p_hostapd.c delete mode 100644 hostapd-0.8/src/ap/p2p_hostapd.h delete mode 100644 hostapd-0.8/src/ap/peerkey_auth.c delete mode 100644 hostapd-0.8/src/ap/pmksa_cache_auth.c delete mode 100644 hostapd-0.8/src/ap/pmksa_cache_auth.h delete mode 100644 hostapd-0.8/src/ap/preauth_auth.c delete mode 100644 hostapd-0.8/src/ap/preauth_auth.h delete mode 100644 hostapd-0.8/src/ap/sta_info.c delete mode 100644 hostapd-0.8/src/ap/sta_info.h delete mode 100644 hostapd-0.8/src/ap/tkip_countermeasures.c delete mode 100644 hostapd-0.8/src/ap/tkip_countermeasures.h delete mode 100644 hostapd-0.8/src/ap/utils.c delete mode 100644 hostapd-0.8/src/ap/vlan_init.c delete mode 100644 hostapd-0.8/src/ap/vlan_init.h delete mode 100644 hostapd-0.8/src/ap/wmm.c delete mode 100644 hostapd-0.8/src/ap/wmm.h delete mode 100644 hostapd-0.8/src/ap/wpa_auth.c delete mode 100644 hostapd-0.8/src/ap/wpa_auth.h delete mode 100644 hostapd-0.8/src/ap/wpa_auth_ft.c delete mode 100644 hostapd-0.8/src/ap/wpa_auth_glue.c delete mode 100644 hostapd-0.8/src/ap/wpa_auth_glue.h delete mode 100644 hostapd-0.8/src/ap/wpa_auth_i.h delete mode 100644 hostapd-0.8/src/ap/wpa_auth_ie.c delete mode 100644 hostapd-0.8/src/ap/wpa_auth_ie.h delete mode 100644 hostapd-0.8/src/ap/wps_hostapd.c delete mode 100644 hostapd-0.8/src/ap/wps_hostapd.h delete mode 100644 hostapd-0.8/src/common/Makefile delete mode 100644 hostapd-0.8/src/common/defs.h delete mode 100644 hostapd-0.8/src/common/eapol_common.h delete mode 100644 hostapd-0.8/src/common/ieee802_11_common.c delete mode 100644 hostapd-0.8/src/common/ieee802_11_common.h delete mode 100644 hostapd-0.8/src/common/ieee802_11_defs.h delete mode 100644 hostapd-0.8/src/common/privsep_commands.h delete mode 100644 hostapd-0.8/src/common/version.h delete mode 100644 hostapd-0.8/src/common/wpa_common.c delete mode 100644 hostapd-0.8/src/common/wpa_common.h delete mode 100644 hostapd-0.8/src/common/wpa_ctrl.c delete mode 100644 hostapd-0.8/src/common/wpa_ctrl.h delete mode 100644 hostapd-0.8/src/crypto/.gitignore delete mode 100644 hostapd-0.8/src/crypto/Makefile delete mode 100644 hostapd-0.8/src/crypto/aes-cbc.c delete mode 100644 hostapd-0.8/src/crypto/aes-ctr.c delete mode 100644 hostapd-0.8/src/crypto/aes-eax.c delete mode 100644 hostapd-0.8/src/crypto/aes-encblock.c delete mode 100644 hostapd-0.8/src/crypto/aes-internal-dec.c delete mode 100644 hostapd-0.8/src/crypto/aes-internal-enc.c delete mode 100644 hostapd-0.8/src/crypto/aes-internal.c delete mode 100644 hostapd-0.8/src/crypto/aes-omac1.c delete mode 100644 hostapd-0.8/src/crypto/aes-unwrap.c delete mode 100644 hostapd-0.8/src/crypto/aes-wrap.c delete mode 100644 hostapd-0.8/src/crypto/aes.h delete mode 100644 hostapd-0.8/src/crypto/aes_i.h delete mode 100644 hostapd-0.8/src/crypto/aes_wrap.h delete mode 100644 hostapd-0.8/src/crypto/crypto.h delete mode 100644 hostapd-0.8/src/crypto/crypto_cryptoapi.c delete mode 100644 hostapd-0.8/src/crypto/crypto_gnutls.c delete mode 100644 hostapd-0.8/src/crypto/crypto_internal-cipher.c delete mode 100644 hostapd-0.8/src/crypto/crypto_internal-modexp.c delete mode 100644 hostapd-0.8/src/crypto/crypto_internal-rsa.c delete mode 100644 hostapd-0.8/src/crypto/crypto_internal.c delete mode 100644 hostapd-0.8/src/crypto/crypto_libtomcrypt.c delete mode 100644 hostapd-0.8/src/crypto/crypto_none.c delete mode 100644 hostapd-0.8/src/crypto/crypto_nss.c delete mode 100644 hostapd-0.8/src/crypto/crypto_openssl.c delete mode 100644 hostapd-0.8/src/crypto/des-internal.c delete mode 100644 hostapd-0.8/src/crypto/des_i.h delete mode 100644 hostapd-0.8/src/crypto/dh_group5.c delete mode 100644 hostapd-0.8/src/crypto/dh_group5.h delete mode 100644 hostapd-0.8/src/crypto/dh_groups.c delete mode 100644 hostapd-0.8/src/crypto/dh_groups.h delete mode 100644 hostapd-0.8/src/crypto/fips_prf_cryptoapi.c delete mode 100644 hostapd-0.8/src/crypto/fips_prf_gnutls.c delete mode 100644 hostapd-0.8/src/crypto/fips_prf_internal.c delete mode 100644 hostapd-0.8/src/crypto/fips_prf_nss.c delete mode 100644 hostapd-0.8/src/crypto/fips_prf_openssl.c delete mode 100644 hostapd-0.8/src/crypto/md4-internal.c delete mode 100644 hostapd-0.8/src/crypto/md5-internal.c delete mode 100644 hostapd-0.8/src/crypto/md5-non-fips.c delete mode 100644 hostapd-0.8/src/crypto/md5.c delete mode 100644 hostapd-0.8/src/crypto/md5.h delete mode 100644 hostapd-0.8/src/crypto/md5_i.h delete mode 100644 hostapd-0.8/src/crypto/milenage.c delete mode 100644 hostapd-0.8/src/crypto/milenage.h delete mode 100644 hostapd-0.8/src/crypto/ms_funcs.c delete mode 100644 hostapd-0.8/src/crypto/ms_funcs.h delete mode 100644 hostapd-0.8/src/crypto/random.c delete mode 100644 hostapd-0.8/src/crypto/random.h delete mode 100644 hostapd-0.8/src/crypto/rc4.c delete mode 100644 hostapd-0.8/src/crypto/sha1-internal.c delete mode 100644 hostapd-0.8/src/crypto/sha1-pbkdf2.c delete mode 100644 hostapd-0.8/src/crypto/sha1-tlsprf.c delete mode 100644 hostapd-0.8/src/crypto/sha1-tprf.c delete mode 100644 hostapd-0.8/src/crypto/sha1.c delete mode 100644 hostapd-0.8/src/crypto/sha1.h delete mode 100644 hostapd-0.8/src/crypto/sha1_i.h delete mode 100644 hostapd-0.8/src/crypto/sha256-internal.c delete mode 100644 hostapd-0.8/src/crypto/sha256.c delete mode 100644 hostapd-0.8/src/crypto/sha256.h delete mode 100644 hostapd-0.8/src/crypto/tls.h delete mode 100644 hostapd-0.8/src/crypto/tls_gnutls.c delete mode 100644 hostapd-0.8/src/crypto/tls_internal.c delete mode 100644 hostapd-0.8/src/crypto/tls_none.c delete mode 100644 hostapd-0.8/src/crypto/tls_nss.c delete mode 100644 hostapd-0.8/src/crypto/tls_openssl.c delete mode 100644 hostapd-0.8/src/crypto/tls_schannel.c delete mode 100644 hostapd-0.8/src/drivers/.gitignore delete mode 100644 hostapd-0.8/src/drivers/Apple80211.h delete mode 100644 hostapd-0.8/src/drivers/Makefile delete mode 100644 hostapd-0.8/src/drivers/MobileApple80211.c delete mode 100644 hostapd-0.8/src/drivers/MobileApple80211.h delete mode 100644 hostapd-0.8/src/drivers/driver.h delete mode 100644 hostapd-0.8/src/drivers/driver_atheros.c delete mode 100644 hostapd-0.8/src/drivers/driver_broadcom.c delete mode 100644 hostapd-0.8/src/drivers/driver_bsd.c delete mode 100644 hostapd-0.8/src/drivers/driver_hostap.c delete mode 100644 hostapd-0.8/src/drivers/driver_hostap.h delete mode 100644 hostapd-0.8/src/drivers/driver_iphone.m delete mode 100644 hostapd-0.8/src/drivers/driver_madwifi.c delete mode 100644 hostapd-0.8/src/drivers/driver_ndis.c delete mode 100644 hostapd-0.8/src/drivers/driver_ndis.h delete mode 100644 hostapd-0.8/src/drivers/driver_ndis_.c delete mode 100644 hostapd-0.8/src/drivers/driver_nl80211.c delete mode 100644 hostapd-0.8/src/drivers/driver_none.c delete mode 100644 hostapd-0.8/src/drivers/driver_osx.m delete mode 100644 hostapd-0.8/src/drivers/driver_privsep.c delete mode 100644 hostapd-0.8/src/drivers/driver_ralink.c delete mode 100644 hostapd-0.8/src/drivers/driver_ralink.h delete mode 100644 hostapd-0.8/src/drivers/driver_roboswitch.c delete mode 100644 hostapd-0.8/src/drivers/driver_rtl.h delete mode 100644 hostapd-0.8/src/drivers/driver_rtw.c delete mode 100644 hostapd-0.8/src/drivers/driver_test.c delete mode 100644 hostapd-0.8/src/drivers/driver_wext.c delete mode 100644 hostapd-0.8/src/drivers/driver_wext.h delete mode 100644 hostapd-0.8/src/drivers/driver_wired.c delete mode 100644 hostapd-0.8/src/drivers/drivers.c delete mode 100644 hostapd-0.8/src/drivers/drivers.mak delete mode 100644 hostapd-0.8/src/drivers/drivers.mk delete mode 100644 hostapd-0.8/src/drivers/linux_ioctl.c delete mode 100644 hostapd-0.8/src/drivers/linux_ioctl.h delete mode 100644 hostapd-0.8/src/drivers/ndis_events.c delete mode 100644 hostapd-0.8/src/drivers/netlink.c delete mode 100644 hostapd-0.8/src/drivers/netlink.h delete mode 100644 hostapd-0.8/src/drivers/nl80211_copy.h delete mode 100644 hostapd-0.8/src/drivers/priv_netlink.h delete mode 100644 hostapd-0.8/src/drivers/rfkill.c delete mode 100644 hostapd-0.8/src/drivers/rfkill.h delete mode 100644 hostapd-0.8/src/drivers/wireless_copy.h delete mode 100644 hostapd-0.8/src/eap_common/Makefile delete mode 100644 hostapd-0.8/src/eap_common/chap.c delete mode 100644 hostapd-0.8/src/eap_common/chap.h delete mode 100644 hostapd-0.8/src/eap_common/eap_common.c delete mode 100644 hostapd-0.8/src/eap_common/eap_common.h delete mode 100644 hostapd-0.8/src/eap_common/eap_defs.h delete mode 100644 hostapd-0.8/src/eap_common/eap_fast_common.c delete mode 100644 hostapd-0.8/src/eap_common/eap_fast_common.h delete mode 100644 hostapd-0.8/src/eap_common/eap_gpsk_common.c delete mode 100644 hostapd-0.8/src/eap_common/eap_gpsk_common.h delete mode 100644 hostapd-0.8/src/eap_common/eap_ikev2_common.c delete mode 100644 hostapd-0.8/src/eap_common/eap_ikev2_common.h delete mode 100644 hostapd-0.8/src/eap_common/eap_pax_common.c delete mode 100644 hostapd-0.8/src/eap_common/eap_pax_common.h delete mode 100644 hostapd-0.8/src/eap_common/eap_peap_common.c delete mode 100644 hostapd-0.8/src/eap_common/eap_peap_common.h delete mode 100644 hostapd-0.8/src/eap_common/eap_psk_common.c delete mode 100644 hostapd-0.8/src/eap_common/eap_psk_common.h delete mode 100644 hostapd-0.8/src/eap_common/eap_pwd_common.c delete mode 100644 hostapd-0.8/src/eap_common/eap_pwd_common.h delete mode 100644 hostapd-0.8/src/eap_common/eap_sake_common.c delete mode 100644 hostapd-0.8/src/eap_common/eap_sake_common.h delete mode 100644 hostapd-0.8/src/eap_common/eap_sim_common.c delete mode 100644 hostapd-0.8/src/eap_common/eap_sim_common.h delete mode 100644 hostapd-0.8/src/eap_common/eap_tlv_common.h delete mode 100644 hostapd-0.8/src/eap_common/eap_ttls.h delete mode 100644 hostapd-0.8/src/eap_common/eap_wsc_common.c delete mode 100644 hostapd-0.8/src/eap_common/eap_wsc_common.h delete mode 100644 hostapd-0.8/src/eap_common/ikev2_common.c delete mode 100644 hostapd-0.8/src/eap_common/ikev2_common.h delete mode 100644 hostapd-0.8/src/eap_peer/Makefile delete mode 100644 hostapd-0.8/src/eap_peer/eap.c delete mode 100644 hostapd-0.8/src/eap_peer/eap.h delete mode 100644 hostapd-0.8/src/eap_peer/eap_aka.c delete mode 100644 hostapd-0.8/src/eap_peer/eap_config.h delete mode 100644 hostapd-0.8/src/eap_peer/eap_fast.c delete mode 100644 hostapd-0.8/src/eap_peer/eap_fast_pac.c delete mode 100644 hostapd-0.8/src/eap_peer/eap_fast_pac.h delete mode 100644 hostapd-0.8/src/eap_peer/eap_gpsk.c delete mode 100644 hostapd-0.8/src/eap_peer/eap_gtc.c delete mode 100644 hostapd-0.8/src/eap_peer/eap_i.h delete mode 100644 hostapd-0.8/src/eap_peer/eap_ikev2.c delete mode 100644 hostapd-0.8/src/eap_peer/eap_leap.c delete mode 100644 hostapd-0.8/src/eap_peer/eap_md5.c delete mode 100644 hostapd-0.8/src/eap_peer/eap_methods.c delete mode 100644 hostapd-0.8/src/eap_peer/eap_methods.h delete mode 100644 hostapd-0.8/src/eap_peer/eap_mschapv2.c delete mode 100644 hostapd-0.8/src/eap_peer/eap_otp.c delete mode 100644 hostapd-0.8/src/eap_peer/eap_pax.c delete mode 100644 hostapd-0.8/src/eap_peer/eap_peap.c delete mode 100644 hostapd-0.8/src/eap_peer/eap_psk.c delete mode 100644 hostapd-0.8/src/eap_peer/eap_pwd.c delete mode 100644 hostapd-0.8/src/eap_peer/eap_sake.c delete mode 100644 hostapd-0.8/src/eap_peer/eap_sim.c delete mode 100644 hostapd-0.8/src/eap_peer/eap_tls.c delete mode 100644 hostapd-0.8/src/eap_peer/eap_tls_common.c delete mode 100644 hostapd-0.8/src/eap_peer/eap_tls_common.h delete mode 100644 hostapd-0.8/src/eap_peer/eap_tnc.c delete mode 100644 hostapd-0.8/src/eap_peer/eap_ttls.c delete mode 100644 hostapd-0.8/src/eap_peer/eap_vendor_test.c delete mode 100644 hostapd-0.8/src/eap_peer/eap_wsc.c delete mode 100644 hostapd-0.8/src/eap_peer/ikev2.c delete mode 100644 hostapd-0.8/src/eap_peer/ikev2.h delete mode 100644 hostapd-0.8/src/eap_peer/mschapv2.c delete mode 100644 hostapd-0.8/src/eap_peer/mschapv2.h delete mode 100644 hostapd-0.8/src/eap_peer/tncc.c delete mode 100644 hostapd-0.8/src/eap_peer/tncc.h delete mode 100644 hostapd-0.8/src/eap_server/Makefile delete mode 100644 hostapd-0.8/src/eap_server/eap.h delete mode 100644 hostapd-0.8/src/eap_server/eap_i.h delete mode 100644 hostapd-0.8/src/eap_server/eap_methods.h delete mode 100644 hostapd-0.8/src/eap_server/eap_server.c delete mode 100644 hostapd-0.8/src/eap_server/eap_server_aka.c delete mode 100644 hostapd-0.8/src/eap_server/eap_server_fast.c delete mode 100644 hostapd-0.8/src/eap_server/eap_server_gpsk.c delete mode 100644 hostapd-0.8/src/eap_server/eap_server_gtc.c delete mode 100644 hostapd-0.8/src/eap_server/eap_server_identity.c delete mode 100644 hostapd-0.8/src/eap_server/eap_server_ikev2.c delete mode 100644 hostapd-0.8/src/eap_server/eap_server_md5.c delete mode 100644 hostapd-0.8/src/eap_server/eap_server_methods.c delete mode 100644 hostapd-0.8/src/eap_server/eap_server_mschapv2.c delete mode 100644 hostapd-0.8/src/eap_server/eap_server_pax.c delete mode 100644 hostapd-0.8/src/eap_server/eap_server_peap.c delete mode 100644 hostapd-0.8/src/eap_server/eap_server_psk.c delete mode 100644 hostapd-0.8/src/eap_server/eap_server_pwd.c delete mode 100644 hostapd-0.8/src/eap_server/eap_server_sake.c delete mode 100644 hostapd-0.8/src/eap_server/eap_server_sim.c delete mode 100644 hostapd-0.8/src/eap_server/eap_server_tls.c delete mode 100644 hostapd-0.8/src/eap_server/eap_server_tls_common.c delete mode 100644 hostapd-0.8/src/eap_server/eap_server_tnc.c delete mode 100644 hostapd-0.8/src/eap_server/eap_server_ttls.c delete mode 100644 hostapd-0.8/src/eap_server/eap_server_vendor_test.c delete mode 100644 hostapd-0.8/src/eap_server/eap_server_wsc.c delete mode 100644 hostapd-0.8/src/eap_server/eap_sim_db.c delete mode 100644 hostapd-0.8/src/eap_server/eap_sim_db.h delete mode 100644 hostapd-0.8/src/eap_server/eap_tls_common.h delete mode 100644 hostapd-0.8/src/eap_server/ikev2.c delete mode 100644 hostapd-0.8/src/eap_server/ikev2.h delete mode 100644 hostapd-0.8/src/eap_server/tncs.c delete mode 100644 hostapd-0.8/src/eap_server/tncs.h delete mode 100644 hostapd-0.8/src/eapol_auth/Makefile delete mode 100644 hostapd-0.8/src/eapol_auth/eapol_auth_dump.c delete mode 100644 hostapd-0.8/src/eapol_auth/eapol_auth_sm.c delete mode 100644 hostapd-0.8/src/eapol_auth/eapol_auth_sm.h delete mode 100644 hostapd-0.8/src/eapol_auth/eapol_auth_sm_i.h delete mode 100644 hostapd-0.8/src/eapol_supp/Makefile delete mode 100644 hostapd-0.8/src/eapol_supp/eapol_supp_sm.c delete mode 100644 hostapd-0.8/src/eapol_supp/eapol_supp_sm.h delete mode 100644 hostapd-0.8/src/l2_packet/Makefile delete mode 100644 hostapd-0.8/src/l2_packet/l2_packet.h delete mode 100644 hostapd-0.8/src/l2_packet/l2_packet_freebsd.c delete mode 100644 hostapd-0.8/src/l2_packet/l2_packet_linux.c delete mode 100644 hostapd-0.8/src/l2_packet/l2_packet_ndis.c delete mode 100644 hostapd-0.8/src/l2_packet/l2_packet_none.c delete mode 100644 hostapd-0.8/src/l2_packet/l2_packet_pcap.c delete mode 100644 hostapd-0.8/src/l2_packet/l2_packet_privsep.c delete mode 100644 hostapd-0.8/src/l2_packet/l2_packet_winpcap.c delete mode 100644 hostapd-0.8/src/lib.rules delete mode 100644 hostapd-0.8/src/p2p/Makefile delete mode 100644 hostapd-0.8/src/p2p/p2p.c delete mode 100644 hostapd-0.8/src/p2p/p2p.h delete mode 100644 hostapd-0.8/src/p2p/p2p_build.c delete mode 100644 hostapd-0.8/src/p2p/p2p_dev_disc.c delete mode 100644 hostapd-0.8/src/p2p/p2p_go_neg.c delete mode 100644 hostapd-0.8/src/p2p/p2p_group.c delete mode 100644 hostapd-0.8/src/p2p/p2p_i.h delete mode 100644 hostapd-0.8/src/p2p/p2p_invitation.c delete mode 100644 hostapd-0.8/src/p2p/p2p_parse.c delete mode 100644 hostapd-0.8/src/p2p/p2p_pd.c delete mode 100644 hostapd-0.8/src/p2p/p2p_sd.c delete mode 100644 hostapd-0.8/src/p2p/p2p_utils.c delete mode 100644 hostapd-0.8/src/radius/.gitignore delete mode 100644 hostapd-0.8/src/radius/Makefile delete mode 100644 hostapd-0.8/src/radius/radius.c delete mode 100644 hostapd-0.8/src/radius/radius.h delete mode 100644 hostapd-0.8/src/radius/radius_client.c delete mode 100644 hostapd-0.8/src/radius/radius_client.h delete mode 100644 hostapd-0.8/src/radius/radius_server.c delete mode 100644 hostapd-0.8/src/radius/radius_server.h delete mode 100644 hostapd-0.8/src/rsn_supp/Makefile delete mode 100644 hostapd-0.8/src/rsn_supp/peerkey.c delete mode 100644 hostapd-0.8/src/rsn_supp/peerkey.h delete mode 100644 hostapd-0.8/src/rsn_supp/pmksa_cache.c delete mode 100644 hostapd-0.8/src/rsn_supp/pmksa_cache.h delete mode 100644 hostapd-0.8/src/rsn_supp/preauth.c delete mode 100644 hostapd-0.8/src/rsn_supp/preauth.h delete mode 100644 hostapd-0.8/src/rsn_supp/tdls.c delete mode 100644 hostapd-0.8/src/rsn_supp/wpa.c delete mode 100644 hostapd-0.8/src/rsn_supp/wpa.h delete mode 100644 hostapd-0.8/src/rsn_supp/wpa_ft.c delete mode 100644 hostapd-0.8/src/rsn_supp/wpa_i.h delete mode 100644 hostapd-0.8/src/rsn_supp/wpa_ie.c delete mode 100644 hostapd-0.8/src/rsn_supp/wpa_ie.h delete mode 100644 hostapd-0.8/src/tls/.gitignore delete mode 100644 hostapd-0.8/src/tls/Makefile delete mode 100644 hostapd-0.8/src/tls/asn1.c delete mode 100644 hostapd-0.8/src/tls/asn1.h delete mode 100644 hostapd-0.8/src/tls/bignum.c delete mode 100644 hostapd-0.8/src/tls/bignum.h delete mode 100644 hostapd-0.8/src/tls/libtommath.c delete mode 100644 hostapd-0.8/src/tls/pkcs1.c delete mode 100644 hostapd-0.8/src/tls/pkcs1.h delete mode 100644 hostapd-0.8/src/tls/pkcs5.c delete mode 100644 hostapd-0.8/src/tls/pkcs5.h delete mode 100644 hostapd-0.8/src/tls/pkcs8.c delete mode 100644 hostapd-0.8/src/tls/pkcs8.h delete mode 100644 hostapd-0.8/src/tls/rsa.c delete mode 100644 hostapd-0.8/src/tls/rsa.h delete mode 100644 hostapd-0.8/src/tls/tlsv1_client.c delete mode 100644 hostapd-0.8/src/tls/tlsv1_client.h delete mode 100644 hostapd-0.8/src/tls/tlsv1_client_i.h delete mode 100644 hostapd-0.8/src/tls/tlsv1_client_read.c delete mode 100644 hostapd-0.8/src/tls/tlsv1_client_write.c delete mode 100644 hostapd-0.8/src/tls/tlsv1_common.c delete mode 100644 hostapd-0.8/src/tls/tlsv1_common.h delete mode 100644 hostapd-0.8/src/tls/tlsv1_cred.c delete mode 100644 hostapd-0.8/src/tls/tlsv1_cred.h delete mode 100644 hostapd-0.8/src/tls/tlsv1_record.c delete mode 100644 hostapd-0.8/src/tls/tlsv1_record.h delete mode 100644 hostapd-0.8/src/tls/tlsv1_server.c delete mode 100644 hostapd-0.8/src/tls/tlsv1_server.h delete mode 100644 hostapd-0.8/src/tls/tlsv1_server_i.h delete mode 100644 hostapd-0.8/src/tls/tlsv1_server_read.c delete mode 100644 hostapd-0.8/src/tls/tlsv1_server_write.c delete mode 100644 hostapd-0.8/src/tls/x509v3.c delete mode 100644 hostapd-0.8/src/tls/x509v3.h delete mode 100644 hostapd-0.8/src/utils/.gitignore delete mode 100644 hostapd-0.8/src/utils/Makefile delete mode 100644 hostapd-0.8/src/utils/base64.c delete mode 100644 hostapd-0.8/src/utils/base64.h delete mode 100644 hostapd-0.8/src/utils/build_config.h delete mode 100644 hostapd-0.8/src/utils/common.c delete mode 100644 hostapd-0.8/src/utils/common.h delete mode 100644 hostapd-0.8/src/utils/edit.c delete mode 100644 hostapd-0.8/src/utils/edit.h delete mode 100644 hostapd-0.8/src/utils/edit_readline.c delete mode 100644 hostapd-0.8/src/utils/edit_simple.c delete mode 100644 hostapd-0.8/src/utils/eloop.c delete mode 100644 hostapd-0.8/src/utils/eloop.h delete mode 100644 hostapd-0.8/src/utils/eloop_none.c delete mode 100644 hostapd-0.8/src/utils/eloop_win.c delete mode 100644 hostapd-0.8/src/utils/includes.h delete mode 100644 hostapd-0.8/src/utils/ip_addr.c delete mode 100644 hostapd-0.8/src/utils/ip_addr.h delete mode 100644 hostapd-0.8/src/utils/list.h delete mode 100644 hostapd-0.8/src/utils/os.h delete mode 100644 hostapd-0.8/src/utils/os_internal.c delete mode 100644 hostapd-0.8/src/utils/os_none.c delete mode 100644 hostapd-0.8/src/utils/os_unix.c delete mode 100644 hostapd-0.8/src/utils/os_win32.c delete mode 100644 hostapd-0.8/src/utils/pcsc_funcs.c delete mode 100644 hostapd-0.8/src/utils/pcsc_funcs.h delete mode 100644 hostapd-0.8/src/utils/radiotap.c delete mode 100644 hostapd-0.8/src/utils/radiotap.h delete mode 100644 hostapd-0.8/src/utils/radiotap_iter.h delete mode 100644 hostapd-0.8/src/utils/state_machine.h delete mode 100644 hostapd-0.8/src/utils/trace.c delete mode 100644 hostapd-0.8/src/utils/trace.h delete mode 100644 hostapd-0.8/src/utils/uuid.c delete mode 100644 hostapd-0.8/src/utils/uuid.h delete mode 100644 hostapd-0.8/src/utils/wpa_debug.c delete mode 100644 hostapd-0.8/src/utils/wpa_debug.h delete mode 100644 hostapd-0.8/src/utils/wpabuf.c delete mode 100644 hostapd-0.8/src/utils/wpabuf.h delete mode 100644 hostapd-0.8/src/wps/Makefile delete mode 100644 hostapd-0.8/src/wps/http.h delete mode 100644 hostapd-0.8/src/wps/http_client.c delete mode 100644 hostapd-0.8/src/wps/http_client.h delete mode 100644 hostapd-0.8/src/wps/http_server.c delete mode 100644 hostapd-0.8/src/wps/http_server.h delete mode 100644 hostapd-0.8/src/wps/httpread.c delete mode 100644 hostapd-0.8/src/wps/httpread.h delete mode 100644 hostapd-0.8/src/wps/ndef.c delete mode 100644 hostapd-0.8/src/wps/upnp_xml.c delete mode 100644 hostapd-0.8/src/wps/upnp_xml.h delete mode 100644 hostapd-0.8/src/wps/wps.c delete mode 100644 hostapd-0.8/src/wps/wps.h delete mode 100644 hostapd-0.8/src/wps/wps_attr_build.c delete mode 100644 hostapd-0.8/src/wps/wps_attr_parse.c delete mode 100644 hostapd-0.8/src/wps/wps_attr_process.c delete mode 100644 hostapd-0.8/src/wps/wps_common.c delete mode 100644 hostapd-0.8/src/wps/wps_defs.h delete mode 100644 hostapd-0.8/src/wps/wps_dev_attr.c delete mode 100644 hostapd-0.8/src/wps/wps_dev_attr.h delete mode 100644 hostapd-0.8/src/wps/wps_enrollee.c delete mode 100644 hostapd-0.8/src/wps/wps_er.c delete mode 100644 hostapd-0.8/src/wps/wps_er.h delete mode 100644 hostapd-0.8/src/wps/wps_er_ssdp.c delete mode 100644 hostapd-0.8/src/wps/wps_i.h delete mode 100644 hostapd-0.8/src/wps/wps_nfc.c delete mode 100644 hostapd-0.8/src/wps/wps_nfc_pn531.c delete mode 100644 hostapd-0.8/src/wps/wps_registrar.c delete mode 100644 hostapd-0.8/src/wps/wps_ufd.c delete mode 100644 hostapd-0.8/src/wps/wps_upnp.c delete mode 100644 hostapd-0.8/src/wps/wps_upnp.h delete mode 100644 hostapd-0.8/src/wps/wps_upnp_ap.c delete mode 100644 hostapd-0.8/src/wps/wps_upnp_event.c delete mode 100644 hostapd-0.8/src/wps/wps_upnp_i.h delete mode 100644 hostapd-0.8/src/wps/wps_upnp_ssdp.c delete mode 100644 hostapd-0.8/src/wps/wps_upnp_web.c delete mode 100644 hostapd-0.8/src/wps/wps_validate.c rename hal/mp_precomp.h => mp_precomp.h (100%) rename hal/phydm.c => phydm.c (100%) rename hal/phydm.h => phydm.h (100%) rename hal/phydm_acs.c => phydm_acs.c (100%) rename hal/phydm_acs.h => phydm_acs.h (100%) rename hal/phydm_adaptivity.c => phydm_adaptivity.c (100%) rename hal/phydm_adaptivity.h => phydm_adaptivity.h (100%) rename hal/phydm_adc_sampling.c => phydm_adc_sampling.c (100%) rename hal/phydm_adc_sampling.h => phydm_adc_sampling.h (100%) rename hal/phydm_antdect.c => phydm_antdect.c (100%) rename hal/phydm_antdect.h => phydm_antdect.h (100%) rename hal/phydm_antdiv.c => phydm_antdiv.c (100%) rename hal/phydm_antdiv.h => phydm_antdiv.h (100%) rename hal/phydm_beamforming.h => phydm_beamforming.h (100%) rename hal/phydm_ccx.c => phydm_ccx.c (100%) rename hal/phydm_ccx.h => phydm_ccx.h (100%) rename hal/phydm_cfotracking.c => phydm_cfotracking.c (100%) rename hal/phydm_cfotracking.h => phydm_cfotracking.h (100%) rename hal/phydm_debug.c => phydm_debug.c (100%) rename hal/phydm_debug.h => phydm_debug.h (100%) rename hal/phydm_dfs.c => phydm_dfs.c (100%) rename hal/phydm_dfs.h => phydm_dfs.h (100%) rename hal/phydm_dig.c => phydm_dig.c (100%) rename hal/phydm_dig.h => phydm_dig.h (100%) rename hal/phydm_dynamic_rx_path.c => phydm_dynamic_rx_path.c (100%) rename hal/phydm_dynamic_rx_path.h => phydm_dynamic_rx_path.h (100%) rename hal/phydm_dynamicbbpowersaving.c => phydm_dynamicbbpowersaving.c (100%) rename hal/phydm_dynamicbbpowersaving.h => phydm_dynamicbbpowersaving.h (100%) rename hal/phydm_dynamictxpower.c => phydm_dynamictxpower.c (100%) rename hal/phydm_dynamictxpower.h => phydm_dynamictxpower.h (100%) rename hal/phydm_edcaturbocheck.c => phydm_edcaturbocheck.c (100%) rename hal/phydm_edcaturbocheck.h => phydm_edcaturbocheck.h (100%) rename hal/phydm_features.h => phydm_features.h (100%) rename hal/phydm_hal_txbf_api.c => phydm_hal_txbf_api.c (100%) rename hal/phydm_hal_txbf_api.h => phydm_hal_txbf_api.h (100%) rename hal/phydm_hwconfig.c => phydm_hwconfig.c (100%) rename hal/phydm_hwconfig.h => phydm_hwconfig.h (100%) rename hal/phydm_interface.c => phydm_interface.c (100%) rename hal/phydm_interface.h => phydm_interface.h (100%) rename hal/phydm_iqk.h => phydm_iqk.h (100%) rename hal/phydm_kfree.c => phydm_kfree.c (100%) rename hal/phydm_kfree.h => phydm_kfree.h (100%) rename hal/phydm_noisemonitor.c => phydm_noisemonitor.c (100%) rename hal/phydm_noisemonitor.h => phydm_noisemonitor.h (100%) rename hal/phydm_pathdiv.c => phydm_pathdiv.c (100%) rename hal/phydm_pathdiv.h => phydm_pathdiv.h (100%) rename hal/phydm_powertracking_ce.c => phydm_powertracking_ce.c (100%) rename hal/phydm_powertracking_ce.h => phydm_powertracking_ce.h (100%) rename hal/phydm_pre_define.h => phydm_pre_define.h (100%) rename hal/phydm_precomp.h => phydm_precomp.h (100%) rename hal/phydm_rainfo.c => phydm_rainfo.c (100%) rename hal/phydm_rainfo.h => phydm_rainfo.h (100%) rename hal/phydm_reg.h => phydm_reg.h (100%) rename hal/phydm_regconfig8188e.c => phydm_regconfig8188e.c (100%) rename hal/phydm_regconfig8188e.h => phydm_regconfig8188e.h (100%) rename hal/phydm_regdefine11ac.h => phydm_regdefine11ac.h (100%) rename hal/phydm_regdefine11n.h => phydm_regdefine11n.h (100%) rename hal/phydm_rtl8188e.c => phydm_rtl8188e.c (100%) rename hal/phydm_rtl8188e.h => phydm_rtl8188e.h (100%) rename hal/phydm_types.h => phydm_types.h (100%) rename hal/rtchnlplan.c => rtchnlplan.c (100%) rename hal/rtchnlplan.h => rtchnlplan.h (100%) rename hal/rtl8188e_cmd.c => rtl8188e_cmd.c (100%) rename hal/rtl8188e_dm.c => rtl8188e_dm.c (100%) rename hal/rtl8188e_hal_init.c => rtl8188e_hal_init.c (100%) rename hal/rtl8188e_phycfg.c => rtl8188e_phycfg.c (100%) rename hal/rtl8188e_rf6052.c => rtl8188e_rf6052.c (100%) rename hal/rtl8188e_rxdesc.c => rtl8188e_rxdesc.c (100%) rename hal/rtl8188e_sreset.c => rtl8188e_sreset.c (100%) rename hal/rtl8188e_xmit.c => rtl8188e_xmit.c (100%) rename hal/rtl8188eu_led.c => rtl8188eu_led.c (100%) rename hal/rtl8188eu_recv.c => rtl8188eu_recv.c (100%) rename hal/rtl8188eu_xmit.c => rtl8188eu_xmit.c (100%) rename hal/usb_halinit.c => usb_halinit.c (100%) rename hal/usb_ops_linux.c => usb_ops_linux.c (100%) rename hal/version_rtl8188e.h => version_rtl8188e.h (100%) diff --git a/hal/Hal8188EPwrSeq.c b/Hal8188EPwrSeq.c similarity index 100% rename from hal/Hal8188EPwrSeq.c rename to Hal8188EPwrSeq.c diff --git a/hal/HalEfuseMask8188E_USB.c b/HalEfuseMask8188E_USB.c similarity index 100% rename from hal/HalEfuseMask8188E_USB.c rename to HalEfuseMask8188E_USB.c diff --git a/hal/HalEfuseMask8188E_USB.h b/HalEfuseMask8188E_USB.h similarity index 100% rename from hal/HalEfuseMask8188E_USB.h rename to HalEfuseMask8188E_USB.h diff --git a/hal/HalPwrSeqCmd.c b/HalPwrSeqCmd.c similarity index 100% rename from hal/HalPwrSeqCmd.c rename to HalPwrSeqCmd.c diff --git a/Makefile b/Makefile index 6cb9b80..adf1af0 100755 --- a/Makefile +++ b/Makefile @@ -104,80 +104,80 @@ ifeq ($(CONFIG_MP_INCLUDED), y) _OS_INTFS_FILES += os_dep/ioctl_mp.o endif -_HAL_INTFS_FILES := hal/hal_intf.o \ - hal/hal_com.o \ - hal/hal_com_phycfg.o \ - hal/hal_phy.o \ - hal/hal_dm.o \ - hal/hal_btcoex_wifionly.o \ - hal/hal_btcoex.o \ - hal/hal_mp.o \ - hal/hal_mcc.o \ - hal/hal_$(HCI_NAME).o \ - hal/hal_$(HCI_NAME)_led.o +_HAL_INTFS_FILES := hal_intf.o \ + hal_com.o \ + hal_com_phycfg.o \ + hal_phy.o \ + hal_dm.o \ + hal_btcoex_wifionly.o \ + hal_btcoex.o \ + hal_mp.o \ + hal_mcc.o \ + hal_$(HCI_NAME).o \ + hal_$(HCI_NAME)_led.o -_OUTSRC_FILES := hal/phydm_debug.o \ - hal/phydm_antdiv.o\ - hal/phydm_antdect.o\ - hal/phydm_interface.o\ - hal/phydm_hwconfig.o\ - hal/phydm.o\ - hal/halphyrf_ce.o\ - hal/phydm_edcaturbocheck.o\ - hal/phydm_dig.o\ - hal/phydm_pathdiv.o\ - hal/phydm_rainfo.o\ - hal/phydm_dynamicbbpowersaving.o\ - hal/phydm_powertracking_ce.o\ - hal/phydm_dynamictxpower.o\ - hal/phydm_adaptivity.o\ - hal/phydm_cfotracking.o\ - hal/phydm_noisemonitor.o\ - hal/phydm_acs.o\ - hal/phydm_dfs.o\ - hal/phydm_hal_txbf_api.o\ - hal/phydm_adc_sampling.o\ - hal/phydm_kfree.o\ - hal/phydm_ccx.o +_OUTSRC_FILES := phydm_debug.o \ + phydm_antdiv.o\ + phydm_antdect.o\ + phydm_interface.o\ + phydm_hwconfig.o\ + phydm.o\ + halphyrf_ce.o\ + phydm_edcaturbocheck.o\ + phydm_dig.o\ + phydm_pathdiv.o\ + phydm_rainfo.o\ + phydm_dynamicbbpowersaving.o\ + phydm_powertracking_ce.o\ + phydm_dynamictxpower.o\ + phydm_adaptivity.o\ + phydm_cfotracking.o\ + phydm_noisemonitor.o\ + phydm_acs.o\ + phydm_dfs.o\ + phydm_hal_txbf_api.o\ + phydm_adc_sampling.o\ + phydm_kfree.o\ + phydm_ccx.o EXTRA_CFLAGS += -I$(src)/platform -EXTRA_CFLAGS += -I$(src)/hal/btc +EXTRA_CFLAGS += -I$(src)/btc RTL871X = rtl8188e -_HAL_INTFS_FILES += hal/HalPwrSeqCmd.o \ - hal/Hal8188EPwrSeq.o\ - hal/$(RTL871X)_xmit.o\ - hal/$(RTL871X)_sreset.o +_HAL_INTFS_FILES += HalPwrSeqCmd.o \ + Hal8188EPwrSeq.o\ + $(RTL871X)_xmit.o\ + $(RTL871X)_sreset.o -_HAL_INTFS_FILES += hal/$(RTL871X)_hal_init.o \ - hal/$(RTL871X)_phycfg.o \ - hal/$(RTL871X)_rf6052.o \ - hal/$(RTL871X)_dm.o \ - hal/$(RTL871X)_rxdesc.o \ - hal/$(RTL871X)_cmd.o \ - hal/hal8188e_s_fw.o \ - hal/hal8188e_t_fw.o \ - hal/$(HCI_NAME)_halinit.o \ - hal/rtl8188eu_led.o \ - hal/rtl8188eu_xmit.o \ - hal/rtl8188eu_recv.o +_HAL_INTFS_FILES += $(RTL871X)_hal_init.o \ + $(RTL871X)_phycfg.o \ + $(RTL871X)_rf6052.o \ + $(RTL871X)_dm.o \ + $(RTL871X)_rxdesc.o \ + $(RTL871X)_cmd.o \ + hal8188e_s_fw.o \ + hal8188e_t_fw.o \ + $(HCI_NAME)_halinit.o \ + rtl8188eu_led.o \ + rtl8188eu_xmit.o \ + rtl8188eu_recv.o -_HAL_INTFS_FILES += hal/$(HCI_NAME)_ops_linux.o +_HAL_INTFS_FILES += $(HCI_NAME)_ops_linux.o -_HAL_INTFS_FILES +=hal/HalEfuseMask8188E_USB.o +_HAL_INTFS_FILES +=HalEfuseMask8188E_USB.o -#hal/OUTSRC/Hal8188EFWImg_CE.o -_OUTSRC_FILES += hal/halhwimg8188e_mac.o\ - hal/halhwimg8188e_bb.o\ - hal/halhwimg8188e_rf.o\ - hal/halphyrf_8188e_ce.o\ - hal/phydm_regconfig8188e.o\ - hal/hal8188erateadaptive.o\ - hal/phydm_rtl8188e.o +#OUTSRC/Hal8188EFWImg_CE.o +_OUTSRC_FILES += halhwimg8188e_mac.o\ + halhwimg8188e_bb.o\ + halhwimg8188e_rf.o\ + halphyrf_8188e_ce.o\ + phydm_regconfig8188e.o\ + hal8188erateadaptive.o\ + phydm_rtl8188e.o ########### AUTO_CFG ################################# @@ -497,7 +497,7 @@ clean: cd hal ; rm -fr */*/*/*.mod.c */*/*/*.mod */*/*/*.o */*/*/.*.cmd */*/*/*.ko cd hal ; rm -fr */*/*.mod.c */*/*.mod */*/*.o */*/.*.cmd */*/*.ko cd hal ; rm -fr */*.mod.c */*.mod */*.o */.*.cmd */*.ko - cd hal/led ; rm -fr *.mod.c *.mod *.o .*.cmd *.ko .*.cmd + cd led ; rm -fr *.mod.c *.mod *.o .*.cmd *.ko .*.cmd cd core ; rm -fr *.mod.c *.mod *.o .*.cmd *.ko cd os_dep/linux ; rm -fr *.mod.c *.mod *.o .*.cmd *.ko cd os_dep ; rm -fr *.mod.c *.mod *.o .*.cmd *.ko diff --git a/hal/btc/halbtcoutsrc.h b/btc/halbtcoutsrc.h similarity index 100% rename from hal/btc/halbtcoutsrc.h rename to btc/halbtcoutsrc.h diff --git a/hal/btc/mp_precomp.h b/btc/mp_precomp.h similarity index 100% rename from hal/btc/mp_precomp.h rename to btc/mp_precomp.h diff --git a/hal/efuse_mask.h b/efuse_mask.h similarity index 100% rename from hal/efuse_mask.h rename to efuse_mask.h diff --git a/hal/hal8188e_s_fw.c b/hal8188e_s_fw.c similarity index 100% rename from hal/hal8188e_s_fw.c rename to hal8188e_s_fw.c diff --git a/hal/hal8188e_s_fw.h b/hal8188e_s_fw.h similarity index 100% rename from hal/hal8188e_s_fw.h rename to hal8188e_s_fw.h diff --git a/hal/hal8188e_t_fw.c b/hal8188e_t_fw.c similarity index 100% rename from hal/hal8188e_t_fw.c rename to hal8188e_t_fw.c diff --git a/hal/hal8188e_t_fw.h b/hal8188e_t_fw.h similarity index 100% rename from hal/hal8188e_t_fw.h rename to hal8188e_t_fw.h diff --git a/hal/hal8188erateadaptive.c b/hal8188erateadaptive.c similarity index 100% rename from hal/hal8188erateadaptive.c rename to hal8188erateadaptive.c diff --git a/hal/hal8188erateadaptive.h b/hal8188erateadaptive.h similarity index 100% rename from hal/hal8188erateadaptive.h rename to hal8188erateadaptive.h diff --git a/hal/hal8188ereg.h b/hal8188ereg.h similarity index 100% rename from hal/hal8188ereg.h rename to hal8188ereg.h diff --git a/hal/hal_btcoex.c b/hal_btcoex.c similarity index 100% rename from hal/hal_btcoex.c rename to hal_btcoex.c diff --git a/hal/hal_btcoex_wifionly.c b/hal_btcoex_wifionly.c similarity index 100% rename from hal/hal_btcoex_wifionly.c rename to hal_btcoex_wifionly.c diff --git a/hal/hal_com.c b/hal_com.c similarity index 100% rename from hal/hal_com.c rename to hal_com.c diff --git a/hal/hal_com_c2h.h b/hal_com_c2h.h similarity index 100% rename from hal/hal_com_c2h.h rename to hal_com_c2h.h diff --git a/hal/hal_com_phycfg.c b/hal_com_phycfg.c similarity index 100% rename from hal/hal_com_phycfg.c rename to hal_com_phycfg.c diff --git a/hal/hal_dm.c b/hal_dm.c similarity index 100% rename from hal/hal_dm.c rename to hal_dm.c diff --git a/hal/hal_dm.h b/hal_dm.h similarity index 100% rename from hal/hal_dm.h rename to hal_dm.h diff --git a/hal/hal_intf.c b/hal_intf.c similarity index 100% rename from hal/hal_intf.c rename to hal_intf.c diff --git a/hal/hal_mcc.c b/hal_mcc.c similarity index 100% rename from hal/hal_mcc.c rename to hal_mcc.c diff --git a/hal/hal_mp.c b/hal_mp.c similarity index 100% rename from hal/hal_mp.c rename to hal_mp.c diff --git a/hal/hal_phy.c b/hal_phy.c similarity index 100% rename from hal/hal_phy.c rename to hal_phy.c diff --git a/hal/hal_usb.c b/hal_usb.c similarity index 100% rename from hal/hal_usb.c rename to hal_usb.c diff --git a/hal/hal_usb_led.c b/hal_usb_led.c similarity index 100% rename from hal/hal_usb_led.c rename to hal_usb_led.c diff --git a/hal/halcomtxbf.h b/halcomtxbf.h similarity index 100% rename from hal/halcomtxbf.h rename to halcomtxbf.h diff --git a/hal/halhwimg.h b/halhwimg.h similarity index 100% rename from hal/halhwimg.h rename to halhwimg.h diff --git a/hal/halhwimg8188e_bb.c b/halhwimg8188e_bb.c similarity index 100% rename from hal/halhwimg8188e_bb.c rename to halhwimg8188e_bb.c diff --git a/hal/halhwimg8188e_bb.h b/halhwimg8188e_bb.h similarity index 100% rename from hal/halhwimg8188e_bb.h rename to halhwimg8188e_bb.h diff --git a/hal/halhwimg8188e_mac.c b/halhwimg8188e_mac.c similarity index 100% rename from hal/halhwimg8188e_mac.c rename to halhwimg8188e_mac.c diff --git a/hal/halhwimg8188e_mac.h b/halhwimg8188e_mac.h similarity index 100% rename from hal/halhwimg8188e_mac.h rename to halhwimg8188e_mac.h diff --git a/hal/halhwimg8188e_rf.c b/halhwimg8188e_rf.c similarity index 100% rename from hal/halhwimg8188e_rf.c rename to halhwimg8188e_rf.c diff --git a/hal/halhwimg8188e_rf.h b/halhwimg8188e_rf.h similarity index 100% rename from hal/halhwimg8188e_rf.h rename to halhwimg8188e_rf.h diff --git a/hal/halphyrf_8188e_ce.c b/halphyrf_8188e_ce.c similarity index 100% rename from hal/halphyrf_8188e_ce.c rename to halphyrf_8188e_ce.c diff --git a/hal/halphyrf_8188e_ce.h b/halphyrf_8188e_ce.h similarity index 100% rename from hal/halphyrf_8188e_ce.h rename to halphyrf_8188e_ce.h diff --git a/hal/halphyrf_ap.h b/halphyrf_ap.h similarity index 100% rename from hal/halphyrf_ap.h rename to halphyrf_ap.h diff --git a/hal/halphyrf_ce.c b/halphyrf_ce.c similarity index 100% rename from hal/halphyrf_ce.c rename to halphyrf_ce.c diff --git a/hal/halphyrf_ce.h b/halphyrf_ce.h similarity index 100% rename from hal/halphyrf_ce.h rename to halphyrf_ce.h diff --git a/hal/haltxbfinterface.h b/haltxbfinterface.h similarity index 100% rename from hal/haltxbfinterface.h rename to haltxbfinterface.h diff --git a/hal/haltxbfjaguar.h b/haltxbfjaguar.h similarity index 100% rename from hal/haltxbfjaguar.h rename to haltxbfjaguar.h diff --git a/hostapd-0.8/COPYING b/hostapd-0.8/COPYING deleted file mode 100644 index 14f5453..0000000 --- a/hostapd-0.8/COPYING +++ /dev/null @@ -1,340 +0,0 @@ - GNU GENERAL PUBLIC LICENSE - Version 2, June 1991 - - Copyright (C) 1989, 1991 Free Software Foundation, Inc. - 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - Everyone is permitted to copy and distribute verbatim copies - of this license document, but changing it is not allowed. - - Preamble - - The licenses for most software are designed to take away your -freedom to share and change it. By contrast, the GNU General Public -License is intended to guarantee your freedom to share and change free -software--to make sure the software is free for all its users. This -General Public License applies to most of the Free Software -Foundation's software and to any other program whose authors commit to -using it. (Some other Free Software Foundation software is covered by -the GNU Library General Public License instead.) You can apply it to -your programs, too. - - When we speak of free software, we are referring to freedom, not -price. Our General Public Licenses are designed to make sure that you -have the freedom to distribute copies of free software (and charge for -this service if you wish), that you receive source code or can get it -if you want it, that you can change the software or use pieces of it -in new free programs; and that you know you can do these things. - - To protect your rights, we need to make restrictions that forbid -anyone to deny you these rights or to ask you to surrender the rights. -These restrictions translate to certain responsibilities for you if you -distribute copies of the software, or if you modify it. - - For example, if you distribute copies of such a program, whether -gratis or for a fee, you must give the recipients all the rights that -you have. You must make sure that they, too, receive or can get the -source code. And you must show them these terms so they know their -rights. - - We protect your rights with two steps: (1) copyright the software, and -(2) offer you this license which gives you legal permission to copy, -distribute and/or modify the software. - - Also, for each author's protection and ours, we want to make certain -that everyone understands that there is no warranty for this free -software. If the software is modified by someone else and passed on, we -want its recipients to know that what they have is not the original, so -that any problems introduced by others will not reflect on the original -authors' reputations. - - Finally, any free program is threatened constantly by software -patents. We wish to avoid the danger that redistributors of a free -program will individually obtain patent licenses, in effect making the -program proprietary. To prevent this, we have made it clear that any -patent must be licensed for everyone's free use or not licensed at all. - - The precise terms and conditions for copying, distribution and -modification follow. - - GNU GENERAL PUBLIC LICENSE - TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION - - 0. This License applies to any program or other work which contains -a notice placed by the copyright holder saying it may be distributed -under the terms of this General Public License. The "Program", below, -refers to any such program or work, and a "work based on the Program" -means either the Program or any derivative work under copyright law: -that is to say, a work containing the Program or a portion of it, -either verbatim or with modifications and/or translated into another -language. (Hereinafter, translation is included without limitation in -the term "modification".) Each licensee is addressed as "you". - -Activities other than copying, distribution and modification are not -covered by this License; they are outside its scope. The act of -running the Program is not restricted, and the output from the Program -is covered only if its contents constitute a work based on the -Program (independent of having been made by running the Program). -Whether that is true depends on what the Program does. - - 1. You may copy and distribute verbatim copies of the Program's -source code as you receive it, in any medium, provided that you -conspicuously and appropriately publish on each copy an appropriate -copyright notice and disclaimer of warranty; keep intact all the -notices that refer to this License and to the absence of any warranty; -and give any other recipients of the Program a copy of this License -along with the Program. - -You may charge a fee for the physical act of transferring a copy, and -you may at your option offer warranty protection in exchange for a fee. - - 2. You may modify your copy or copies of the Program or any portion -of it, thus forming a work based on the Program, and copy and -distribute such modifications or work under the terms of Section 1 -above, provided that you also meet all of these conditions: - - a) You must cause the modified files to carry prominent notices - stating that you changed the files and the date of any change. - - b) You must cause any work that you distribute or publish, that in - whole or in part contains or is derived from the Program or any - part thereof, to be licensed as a whole at no charge to all third - parties under the terms of this License. - - c) If the modified program normally reads commands interactively - when run, you must cause it, when started running for such - interactive use in the most ordinary way, to print or display an - announcement including an appropriate copyright notice and a - notice that there is no warranty (or else, saying that you provide - a warranty) and that users may redistribute the program under - these conditions, and telling the user how to view a copy of this - License. (Exception: if the Program itself is interactive but - does not normally print such an announcement, your work based on - the Program is not required to print an announcement.) - -These requirements apply to the modified work as a whole. If -identifiable sections of that work are not derived from the Program, -and can be reasonably considered independent and separate works in -themselves, then this License, and its terms, do not apply to those -sections when you distribute them as separate works. But when you -distribute the same sections as part of a whole which is a work based -on the Program, the distribution of the whole must be on the terms of -this License, whose permissions for other licensees extend to the -entire whole, and thus to each and every part regardless of who wrote it. - -Thus, it is not the intent of this section to claim rights or contest -your rights to work written entirely by you; rather, the intent is to -exercise the right to control the distribution of derivative or -collective works based on the Program. - -In addition, mere aggregation of another work not based on the Program -with the Program (or with a work based on the Program) on a volume of -a storage or distribution medium does not bring the other work under -the scope of this License. - - 3. You may copy and distribute the Program (or a work based on it, -under Section 2) in object code or executable form under the terms of -Sections 1 and 2 above provided that you also do one of the following: - - a) Accompany it with the complete corresponding machine-readable - source code, which must be distributed under the terms of Sections - 1 and 2 above on a medium customarily used for software interchange; or, - - b) Accompany it with a written offer, valid for at least three - years, to give any third party, for a charge no more than your - cost of physically performing source distribution, a complete - machine-readable copy of the corresponding source code, to be - distributed under the terms of Sections 1 and 2 above on a medium - customarily used for software interchange; or, - - c) Accompany it with the information you received as to the offer - to distribute corresponding source code. (This alternative is - allowed only for noncommercial distribution and only if you - received the program in object code or executable form with such - an offer, in accord with Subsection b above.) - -The source code for a work means the preferred form of the work for -making modifications to it. For an executable work, complete source -code means all the source code for all modules it contains, plus any -associated interface definition files, plus the scripts used to -control compilation and installation of the executable. However, as a -special exception, the source code distributed need not include -anything that is normally distributed (in either source or binary -form) with the major components (compiler, kernel, and so on) of the -operating system on which the executable runs, unless that component -itself accompanies the executable. - -If distribution of executable or object code is made by offering -access to copy from a designated place, then offering equivalent -access to copy the source code from the same place counts as -distribution of the source code, even though third parties are not -compelled to copy the source along with the object code. - - 4. You may not copy, modify, sublicense, or distribute the Program -except as expressly provided under this License. Any attempt -otherwise to copy, modify, sublicense or distribute the Program is -void, and will automatically terminate your rights under this License. -However, parties who have received copies, or rights, from you under -this License will not have their licenses terminated so long as such -parties remain in full compliance. - - 5. You are not required to accept this License, since you have not -signed it. However, nothing else grants you permission to modify or -distribute the Program or its derivative works. These actions are -prohibited by law if you do not accept this License. Therefore, by -modifying or distributing the Program (or any work based on the -Program), you indicate your acceptance of this License to do so, and -all its terms and conditions for copying, distributing or modifying -the Program or works based on it. - - 6. Each time you redistribute the Program (or any work based on the -Program), the recipient automatically receives a license from the -original licensor to copy, distribute or modify the Program subject to -these terms and conditions. You may not impose any further -restrictions on the recipients' exercise of the rights granted herein. -You are not responsible for enforcing compliance by third parties to -this License. - - 7. If, as a consequence of a court judgment or allegation of patent -infringement or for any other reason (not limited to patent issues), -conditions are imposed on you (whether by court order, agreement or -otherwise) that contradict the conditions of this License, they do not -excuse you from the conditions of this License. If you cannot -distribute so as to satisfy simultaneously your obligations under this -License and any other pertinent obligations, then as a consequence you -may not distribute the Program at all. For example, if a patent -license would not permit royalty-free redistribution of the Program by -all those who receive copies directly or indirectly through you, then -the only way you could satisfy both it and this License would be to -refrain entirely from distribution of the Program. - -If any portion of this section is held invalid or unenforceable under -any particular circumstance, the balance of the section is intended to -apply and the section as a whole is intended to apply in other -circumstances. - -It is not the purpose of this section to induce you to infringe any -patents or other property right claims or to contest validity of any -such claims; this section has the sole purpose of protecting the -integrity of the free software distribution system, which is -implemented by public license practices. Many people have made -generous contributions to the wide range of software distributed -through that system in reliance on consistent application of that -system; it is up to the author/donor to decide if he or she is willing -to distribute software through any other system and a licensee cannot -impose that choice. - -This section is intended to make thoroughly clear what is believed to -be a consequence of the rest of this License. - - 8. If the distribution and/or use of the Program is restricted in -certain countries either by patents or by copyrighted interfaces, the -original copyright holder who places the Program under this License -may add an explicit geographical distribution limitation excluding -those countries, so that distribution is permitted only in or among -countries not thus excluded. In such case, this License incorporates -the limitation as if written in the body of this License. - - 9. The Free Software Foundation may publish revised and/or new versions -of the General Public License from time to time. Such new versions will -be similar in spirit to the present version, but may differ in detail to -address new problems or concerns. - -Each version is given a distinguishing version number. If the Program -specifies a version number of this License which applies to it and "any -later version", you have the option of following the terms and conditions -either of that version or of any later version published by the Free -Software Foundation. If the Program does not specify a version number of -this License, you may choose any version ever published by the Free Software -Foundation. - - 10. If you wish to incorporate parts of the Program into other free -programs whose distribution conditions are different, write to the author -to ask for permission. For software which is copyrighted by the Free -Software Foundation, write to the Free Software Foundation; we sometimes -make exceptions for this. Our decision will be guided by the two goals -of preserving the free status of all derivatives of our free software and -of promoting the sharing and reuse of software generally. - - NO WARRANTY - - 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY -FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN -OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES -PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED -OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS -TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE -PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, -REPAIR OR CORRECTION. - - 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING -WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR -REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, -INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING -OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED -TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY -YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER -PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE -POSSIBILITY OF SUCH DAMAGES. - - END OF TERMS AND CONDITIONS - - How to Apply These Terms to Your New Programs - - If you develop a new program, and you want it to be of the greatest -possible use to the public, the best way to achieve this is to make it -free software which everyone can redistribute and change under these terms. - - To do so, attach the following notices to the program. It is safest -to attach them to the start of each source file to most effectively -convey the exclusion of warranty; and each file should have at least -the "copyright" line and a pointer to where the full notice is found. - - - Copyright (C) 19yy - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - - -Also add information on how to contact you by electronic and paper mail. - -If the program is interactive, make it output a short notice like this -when it starts in an interactive mode: - - Gnomovision version 69, Copyright (C) 19yy name of author - Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. - This is free software, and you are welcome to redistribute it - under certain conditions; type `show c' for details. - -The hypothetical commands `show w' and `show c' should show the appropriate -parts of the General Public License. Of course, the commands you use may -be called something other than `show w' and `show c'; they could even be -mouse-clicks or menu items--whatever suits your program. - -You should also get your employer (if you work as a programmer) or your -school, if any, to sign a "copyright disclaimer" for the program, if -necessary. Here is a sample; alter the names: - - Yoyodyne, Inc., hereby disclaims all copyright interest in the program - `Gnomovision' (which makes passes at compilers) written by James Hacker. - - , 1 April 1989 - Ty Coon, President of Vice - -This General Public License does not permit incorporating your program into -proprietary programs. If your program is a subroutine library, you may -consider it more useful to permit linking proprietary applications with the -library. If this is what you want to do, use the GNU Library General -Public License instead of this License. diff --git a/hostapd-0.8/README b/hostapd-0.8/README deleted file mode 100644 index 94ef1a7..0000000 --- a/hostapd-0.8/README +++ /dev/null @@ -1,72 +0,0 @@ -wpa_supplicant and hostapd --------------------------- - -Copyright (c) 2002-2011, Jouni Malinen and contributors -All Rights Reserved. - -These programs are dual-licensed under both the GPL version 2 and BSD -license (the one with advertisement clause removed). Either license -may be used at your option. - - -This package may include either wpa_supplicant, hostapd, or both. See -README file respective subdirectories (wpa_supplicant/README or -hostapd/README) for more details. - -Source code files were moved around in v0.6.x releases and compared to -earlier releases, the programs are now built by first going to a -subdirectory (wpa_supplicant or hostapd) and creating build -configuration (.config) and running 'make' there (for Linux/BSD/cygwin -builds). - - -License -------- - -GPL v2: - -This program is free software; you can redistribute it and/or modify -it under the terms of the GNU General Public License version 2 as -published by the Free Software Foundation. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - -(this copy of the license is in COPYING file) - - -Alternatively, 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. diff --git a/hostapd-0.8/hostapd/Android.mk b/hostapd-0.8/hostapd/Android.mk deleted file mode 100644 index aa9d5ba..0000000 --- a/hostapd-0.8/hostapd/Android.mk +++ /dev/null @@ -1,816 +0,0 @@ -LOCAL_PATH := $(call my-dir) - -WPA_BUILD_HOSTAPD := false -ifneq ($(TARGET_SIMULATOR),true) - ifneq ($(BOARD_HOSTAPD_DRIVER),) - WPA_BUILD_HOSTAPD := true - CONFIG_DRIVER_$(BOARD_HOSTAPD_DRIVER) := y - endif -endif - -include $(LOCAL_PATH)/.config - -# To ignore possible wrong network configurations -L_CFLAGS = -DWPA_IGNORE_CONFIG_ERRORS - -# To force sizeof(enum) = 4 -ifeq ($(TARGET_ARCH),arm) -L_CFLAGS += -mabi=aapcs-linux -endif - -# To allow non-ASCII characters in SSID -L_CFLAGS += -DWPA_UNICODE_SSID - -# OpenSSL is configured without engines on Android -L_CFLAGS += -DOPENSSL_NO_ENGINE - -INCLUDES = $(LOCAL_PATH) -INCLUDES += $(LOCAL_PATH)/src -INCLUDES += $(LOCAL_PATH)/src/utils -INCLUDES += external/openssl/include -INCLUDES += frameworks/base/cmds/keystore -ifdef CONFIG_DRIVER_NL80211 -INCLUDES += external/libnl_2/include -endif - - -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 - -ifdef CONFIG_NATIVE_WINDOWS -L_CFLAGS += -DCONFIG_NATIVE_WINDOWS -LIBS += -lws2_32 -endif - -OBJS = main.c -OBJS += config_file.c - -OBJS += src/ap/hostapd.c -OBJS += src/ap/wpa_auth_glue.c -OBJS += src/ap/drv_callbacks.c -OBJS += src/ap/ap_drv_ops.c -OBJS += src/ap/utils.c -OBJS += src/ap/authsrv.c -OBJS += src/ap/ieee802_1x.c -OBJS += src/ap/ap_config.c -OBJS += src/ap/ieee802_11_auth.c -OBJS += src/ap/sta_info.c -OBJS += src/ap/wpa_auth.c -OBJS += src/ap/tkip_countermeasures.c -OBJS += src/ap/ap_mlme.c -OBJS += src/ap/wpa_auth_ie.c -OBJS += src/ap/preauth_auth.c -OBJS += src/ap/pmksa_cache_auth.c -OBJS_d = -OBJS_p = -LIBS = -LIBS_c = -HOBJS = -LIBS_h = - -NEED_RC4=y -NEED_AES=y -NEED_MD5=y -NEED_SHA1=y - -OBJS += src/drivers/drivers.c -L_CFLAGS += -DHOSTAPD - -ifdef CONFIG_WPA_TRACE -L_CFLAGS += -DWPA_TRACE -OBJS += src/utils/trace.c -HOBJS += src/utils/trace.c -LDFLAGS += -rdynamic -L_CFLAGS += -funwind-tables -ifdef CONFIG_WPA_TRACE_BFD -L_CFLAGS += -DWPA_TRACE_BFD -LIBS += -lbfd -LIBS_c += -lbfd -LIBS_h += -lbfd -endif -endif - -OBJS += src/utils/eloop.c -OBJS += src/utils/common.c -OBJS += src/utils/wpa_debug.c -OBJS += src/utils/wpabuf.c -OBJS += src/utils/os_$(CONFIG_OS).c -OBJS += src/utils/ip_addr.c - -OBJS += src/common/ieee802_11_common.c -OBJS += src/common/wpa_common.c - -OBJS += src/eapol_auth/eapol_auth_sm.c - - -ifndef CONFIG_NO_DUMP_STATE -# define HOSTAPD_DUMP_STATE to include SIGUSR1 handler for dumping state to -# a file (undefine it, if you want to save in binary size) -L_CFLAGS += -DHOSTAPD_DUMP_STATE -OBJS += dump_state.c -OBJS += src/eapol_auth/eapol_auth_dump.c -endif - -ifdef CONFIG_NO_RADIUS -L_CFLAGS += -DCONFIG_NO_RADIUS -CONFIG_NO_ACCOUNTING=y -else -OBJS += src/radius/radius.c -OBJS += src/radius/radius_client.c -endif - -ifdef CONFIG_NO_ACCOUNTING -L_CFLAGS += -DCONFIG_NO_ACCOUNTING -else -OBJS += src/ap/accounting.c -endif - -ifdef CONFIG_NO_VLAN -L_CFLAGS += -DCONFIG_NO_VLAN -else -OBJS += src/ap/vlan_init.c -endif - -ifdef CONFIG_NO_CTRL_IFACE -L_CFLAGS += -DCONFIG_NO_CTRL_IFACE -else -OBJS += ctrl_iface.c -OBJS += src/ap/ctrl_iface_ap.c -endif - -OBJS += src/crypto/md5.c - -L_CFLAGS += -DCONFIG_CTRL_IFACE -DCONFIG_CTRL_IFACE_UNIX - -ifdef CONFIG_IAPP -L_CFLAGS += -DCONFIG_IAPP -OBJS += src/ap/iapp.c -endif - -ifdef CONFIG_RSN_PREAUTH -L_CFLAGS += -DCONFIG_RSN_PREAUTH -CONFIG_L2_PACKET=y -endif - -ifdef CONFIG_PEERKEY -L_CFLAGS += -DCONFIG_PEERKEY -OBJS += src/ap/peerkey_auth.c -endif - -ifdef CONFIG_IEEE80211W -L_CFLAGS += -DCONFIG_IEEE80211W -NEED_SHA256=y -NEED_AES_OMAC1=y -endif - -ifdef CONFIG_IEEE80211R -L_CFLAGS += -DCONFIG_IEEE80211R -OBJS += src/ap/wpa_auth_ft.c -NEED_SHA256=y -NEED_AES_OMAC1=y -NEED_AES_UNWRAP=y -endif - -ifdef CONFIG_IEEE80211N -L_CFLAGS += -DCONFIG_IEEE80211N -endif - -include $(LOCAL_PATH)/src/drivers/drivers.mk - -OBJS += $(DRV_AP_OBJS) -L_CFLAGS += $(DRV_AP_CFLAGS) -LDFLAGS += $(DRV_AP_LDFLAGS) -LIBS += $(DRV_AP_LIBS) - -ifdef CONFIG_L2_PACKET -ifdef CONFIG_DNET_PCAP -ifdef CONFIG_L2_FREEBSD -LIBS += -lpcap -OBJS += src/l2_packet/l2_packet_freebsd.c -else -LIBS += -ldnet -lpcap -OBJS += src/l2_packet/l2_packet_pcap.c -endif -else -OBJS += src/l2_packet/l2_packet_linux.c -endif -else -OBJS += src/l2_packet/l2_packet_none.c -endif - - -ifdef CONFIG_EAP_MD5 -L_CFLAGS += -DEAP_SERVER_MD5 -OBJS += src/eap_server/eap_server_md5.c -CHAP=y -endif - -ifdef CONFIG_EAP_TLS -L_CFLAGS += -DEAP_SERVER_TLS -OBJS += src/eap_server/eap_server_tls.c -TLS_FUNCS=y -endif - -ifdef CONFIG_EAP_PEAP -L_CFLAGS += -DEAP_SERVER_PEAP -OBJS += src/eap_server/eap_server_peap.c -OBJS += src/eap_common/eap_peap_common.c -TLS_FUNCS=y -CONFIG_EAP_MSCHAPV2=y -endif - -ifdef CONFIG_EAP_TTLS -L_CFLAGS += -DEAP_SERVER_TTLS -OBJS += src/eap_server/eap_server_ttls.c -TLS_FUNCS=y -CHAP=y -endif - -ifdef CONFIG_EAP_MSCHAPV2 -L_CFLAGS += -DEAP_SERVER_MSCHAPV2 -OBJS += src/eap_server/eap_server_mschapv2.c -MS_FUNCS=y -endif - -ifdef CONFIG_EAP_GTC -L_CFLAGS += -DEAP_SERVER_GTC -OBJS += src/eap_server/eap_server_gtc.c -endif - -ifdef CONFIG_EAP_SIM -L_CFLAGS += -DEAP_SERVER_SIM -OBJS += src/eap_server/eap_server_sim.c -CONFIG_EAP_SIM_COMMON=y -NEED_AES_CBC=y -endif - -ifdef CONFIG_EAP_AKA -L_CFLAGS += -DEAP_SERVER_AKA -OBJS += src/eap_server/eap_server_aka.c -CONFIG_EAP_SIM_COMMON=y -NEED_SHA256=y -NEED_AES_CBC=y -endif - -ifdef CONFIG_EAP_AKA_PRIME -L_CFLAGS += -DEAP_SERVER_AKA_PRIME -endif - -ifdef CONFIG_EAP_SIM_COMMON -OBJS += src/eap_common/eap_sim_common.c -# Example EAP-SIM/AKA interface for GSM/UMTS authentication. This can be -# replaced with another file implementating the interface specified in -# eap_sim_db.h. -OBJS += src/eap_server/eap_sim_db.c -NEED_FIPS186_2_PRF=y -endif - -ifdef CONFIG_EAP_PAX -L_CFLAGS += -DEAP_SERVER_PAX -OBJS += src/eap_server/eap_server_pax.c src/eap_common/eap_pax_common.c -endif - -ifdef CONFIG_EAP_PSK -L_CFLAGS += -DEAP_SERVER_PSK -OBJS += src/eap_server/eap_server_psk.c src/eap_common/eap_psk_common.c -NEED_AES_OMAC1=y -NEED_AES_ENCBLOCK=y -NEED_AES_EAX=y -endif - -ifdef CONFIG_EAP_SAKE -L_CFLAGS += -DEAP_SERVER_SAKE -OBJS += src/eap_server/eap_server_sake.c src/eap_common/eap_sake_common.c -endif - -ifdef CONFIG_EAP_GPSK -L_CFLAGS += -DEAP_SERVER_GPSK -OBJS += src/eap_server/eap_server_gpsk.c src/eap_common/eap_gpsk_common.c -ifdef CONFIG_EAP_GPSK_SHA256 -L_CFLAGS += -DEAP_SERVER_GPSK_SHA256 -endif -NEED_SHA256=y -NEED_AES_OMAC1=y -endif - -ifdef CONFIG_EAP_PWD -L_CFLAGS += -DEAP_SERVER_PWD -OBJS += src/eap_server/eap_server_pwd.c src/eap_common/eap_pwd_common.c -NEED_SHA256=y -endif - -ifdef CONFIG_EAP_VENDOR_TEST -L_CFLAGS += -DEAP_SERVER_VENDOR_TEST -OBJS += src/eap_server/eap_server_vendor_test.c -endif - -ifdef CONFIG_EAP_FAST -L_CFLAGS += -DEAP_SERVER_FAST -OBJS += src/eap_server/eap_server_fast.c -OBJS += src/eap_common/eap_fast_common.c -TLS_FUNCS=y -NEED_T_PRF=y -NEED_AES_UNWRAP=y -endif - -ifdef CONFIG_WPS -ifdef CONFIG_WPS2 -L_CFLAGS += -DCONFIG_WPS2 -endif - -L_CFLAGS += -DCONFIG_WPS -DEAP_SERVER_WSC -OBJS += src/utils/uuid.c -OBJS += src/ap/wps_hostapd.c -OBJS += src/eap_server/eap_server_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 -NEED_DH_GROUPS=y -NEED_SHA256=y -NEED_BASE64=y -NEED_AES_CBC=y -NEED_MODEXP=y -CONFIG_EAP=y - -ifdef CONFIG_WPS_UFD -L_CFLAGS += -DCONFIG_WPS_UFD -OBJS += src/wps/wps_ufd.c -NEED_WPS_OOB=y -endif - -ifdef CONFIG_WPS_NFC -L_CFLAGS += -DCONFIG_WPS_NFC -OBJS += src/wps/ndef.c -OBJS += src/wps/wps_nfc.c -NEED_WPS_OOB=y -ifdef CONFIG_WPS_NFC_PN531 -PN531_PATH ?= /usr/local/src/nfc -L_CFLAGS += -DCONFIG_WPS_NFC_PN531 -L_CFLAGS += -I${PN531_PATH}/inc -OBJS += src/wps/wps_nfc_pn531.c -LIBS += ${PN531_PATH}/lib/wpsnfc.dll -LIBS += ${PN531_PATH}/lib/libnfc_mapping_pn53x.dll -endif -endif - -ifdef NEED_WPS_OOB -L_CFLAGS += -DCONFIG_WPS_OOB -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 - -endif - -ifdef CONFIG_EAP_IKEV2 -L_CFLAGS += -DEAP_SERVER_IKEV2 -OBJS += src/eap_server/eap_server_ikev2.c src/eap_server/ikev2.c -OBJS += src/eap_common/eap_ikev2_common.c src/eap_common/ikev2_common.c -NEED_DH_GROUPS=y -NEED_DH_GROUPS_ALL=y -NEED_MODEXP=y -NEED_CIPHER=y -endif - -ifdef CONFIG_EAP_TNC -L_CFLAGS += -DEAP_SERVER_TNC -OBJS += src/eap_server/eap_server_tnc.c -OBJS += src/eap_server/tncs.c -NEED_BASE64=y -ifndef CONFIG_DRIVER_BSD -LIBS += -ldl -endif -endif - -# Basic EAP functionality is needed for EAPOL -OBJS += eap_register.c -OBJS += src/eap_server/eap_server.c -OBJS += src/eap_common/eap_common.c -OBJS += src/eap_server/eap_server_methods.c -OBJS += src/eap_server/eap_server_identity.c -L_CFLAGS += -DEAP_SERVER_IDENTITY - -ifdef CONFIG_EAP -L_CFLAGS += -DEAP_SERVER -endif - -ifdef CONFIG_PKCS12 -L_CFLAGS += -DPKCS12_FUNCS -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, and EAP_TTLS) -L_CFLAGS += -DEAP_TLS_FUNCS -OBJS += src/eap_server/eap_server_tls_common.c -NEED_TLS_PRF=y -endif - -ifndef CONFIG_TLS -CONFIG_TLS=openssl -endif - -ifeq ($(CONFIG_TLS), openssl) -ifdef TLS_FUNCS -OBJS += src/crypto/tls_openssl.c -LIBS += -lssl -endif -OBJS += src/crypto/crypto_openssl.c -HOBJS += src/crypto/crypto_openssl.c -ifdef NEED_FIPS186_2_PRF -OBJS += src/crypto/fips_prf_openssl.c -endif -LIBS += -lcrypto -LIBS_h += -lcrypto -endif - -ifeq ($(CONFIG_TLS), gnutls) -ifdef TLS_FUNCS -OBJS += src/crypto/tls_gnutls.c -LIBS += -lgnutls -lgpg-error -ifdef CONFIG_GNUTLS_EXTRA -L_CFLAGS += -DCONFIG_GNUTLS_EXTRA -LIBS += -lgnutls-extra -endif -endif -OBJS += src/crypto/crypto_gnutls.c -HOBJS += src/crypto/crypto_gnutls.c -ifdef NEED_FIPS186_2_PRF -OBJS += src/crypto/fips_prf_gnutls.c -endif -LIBS += -lgcrypt -LIBS_h += -lgcrypt -CONFIG_INTERNAL_SHA256=y -CONFIG_INTERNAL_RC4=y -CONFIG_INTERNAL_DH_GROUP5=y -endif - -ifeq ($(CONFIG_TLS), schannel) -ifdef TLS_FUNCS -OBJS += src/crypto/tls_schannel.c -endif -OBJS += src/crypto/crypto_cryptoapi.c -OBJS_p += src/crypto/crypto_cryptoapi.c -CONFIG_INTERNAL_SHA256=y -CONFIG_INTERNAL_RC4=y -CONFIG_INTERNAL_DH_GROUP5=y -endif - -ifeq ($(CONFIG_TLS), nss) -ifdef TLS_FUNCS -OBJS += src/crypto/tls_nss.c -LIBS += -lssl3 -endif -OBJS += src/crypto/crypto_nss.c -ifdef NEED_FIPS186_2_PRF -OBJS += src/crypto/fips_prf_nss.c -endif -LIBS += -lnss3 -LIBS_h += -lnss3 -CONFIG_INTERNAL_MD4=y -CONFIG_INTERNAL_DH_GROUP5=y -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_server.c -OBJS += src/tls/tlsv1_server_write.c -OBJS += src/tls/tlsv1_server_read.c -OBJS += src/tls/asn1.c -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_SHA256=y -NEED_BASE64=y -NEED_TLS_PRF=y -NEED_MODEXP=y -NEED_CIPHER=y -L_CFLAGS += -DCONFIG_TLS_INTERNAL -L_CFLAGS += -DCONFIG_TLS_INTERNAL_SERVER -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 -LIBS += -ltomcrypt -ltfm -LIBS_h += -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 -NEED_AES_DEC=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_h += -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_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 - -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 -ifdef CONFIG_INTERNAL_AES -AESOBJS += src/crypto/aes-internal.c src/crypto/aes-internal-enc.c -endif - -AESOBJS += src/crypto/aes-wrap.c -ifdef NEED_AES_EAX -AESOBJS += src/crypto/aes-eax.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 -ifdef NEED_AES_OMAC1 -AESOBJS += src/crypto/aes-omac1.c -endif -ifdef NEED_AES_UNWRAP -NEED_AES_DEC=y -AESOBJS += src/crypto/aes-unwrap.c -endif -ifdef NEED_AES_CBC -NEED_AES_DEC=y -AESOBJS += src/crypto/aes-cbc.c -endif -ifdef NEED_AES_DEC -ifdef CONFIG_INTERNAL_AES -AESOBJS += src/crypto/aes-internal-dec.c -endif -endif -ifdef NEED_AES -OBJS += $(AESOBJS) -endif - -SHA1OBJS = -ifdef NEED_SHA1 -SHA1OBJS += src/crypto/sha1.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 -SHA1OBJS += src/crypto/sha1-pbkdf2.c -ifdef NEED_T_PRF -SHA1OBJS += src/crypto/sha1-tprf.c -endif -ifdef NEED_TLS_PRF -SHA1OBJS += src/crypto/sha1-tlsprf.c -endif -endif - -ifdef NEED_SHA1 -OBJS += $(SHA1OBJS) -endif - -ifdef NEED_MD5 -ifdef CONFIG_INTERNAL_MD5 -OBJS += src/crypto/md5-internal.c -HOBJS += src/crypto/md5-internal.c -endif -endif - -ifdef NEED_MD4 -ifdef CONFIG_INTERNAL_MD4 -OBJS += src/crypto/md4-internal.c -endif -endif - -ifdef NEED_DES -ifdef CONFIG_INTERNAL_DES -OBJS += src/crypto/des-internal.c -endif -endif - -ifdef NEED_RC4 -ifdef CONFIG_INTERNAL_RC4 -OBJS += src/crypto/rc4.c -endif -endif - -ifdef NEED_SHA256 -OBJS += src/crypto/sha256.c -ifdef CONFIG_INTERNAL_SHA256 -OBJS += src/crypto/sha256-internal.c -endif -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 CONFIG_NO_RANDOM_POOL -L_CFLAGS += -DCONFIG_NO_RANDOM_POOL -else -OBJS += src/crypto/random.c -HOBJS += src/crypto/random.c -HOBJS += $(SHA1OBJS) -HOBJS += src/crypto/md5.c -endif - -ifdef CONFIG_RADIUS_SERVER -L_CFLAGS += -DRADIUS_SERVER -OBJS += src/radius/radius_server.c -endif - -ifdef CONFIG_IPV6 -L_CFLAGS += -DCONFIG_IPV6 -endif - -ifdef CONFIG_DRIVER_RADIUS_ACL -L_CFLAGS += -DCONFIG_DRIVER_RADIUS_ACL -endif - -ifdef CONFIG_FULL_DYNAMIC_VLAN -# define CONFIG_FULL_DYNAMIC_VLAN to have hostapd manipulate bridges -# and vlan interfaces for the vlan feature. -L_CFLAGS += -DCONFIG_FULL_DYNAMIC_VLAN -endif - -ifdef NEED_BASE64 -OBJS += src/utils/base64.c -endif - -ifdef NEED_AP_MLME -OBJS += src/ap/beacon.c -OBJS += src/ap/wmm.c -OBJS += src/ap/ap_list.c -OBJS += src/ap/ieee802_11.c -OBJS += src/ap/hw_features.c -L_CFLAGS += -DNEED_AP_MLME -endif -ifdef CONFIG_IEEE80211N -OBJS += src/ap/ieee802_11_ht.c -endif - -ifdef CONFIG_P2P_MANAGER -L_CFLAGS += -DCONFIG_P2P_MANAGER -OBJS += src/ap/p2p_hostapd.c -endif - -ifdef CONFIG_NO_STDOUT_DEBUG -L_CFLAGS += -DCONFIG_NO_STDOUT_DEBUG -endif - -ifdef CONFIG_DEBUG_FILE -L_CFLAGS += -DCONFIG_DEBUG_FILE -endif - -ifdef CONFIG_ANDROID_LOG -L_CFLAGS += -DCONFIG_ANDROID_LOG -endif - -OBJS_c = hostapd_cli.c src/common/wpa_ctrl.c src/utils/os_$(CONFIG_OS).c -ifdef CONFIG_WPA_TRACE -OBJS_c += src/utils/trace.c -OBJS_c += src/utils/wpa_debug.c -endif - -ifeq ($(WPA_BUILD_HOSTAPD),true) - -######################## - -include $(CLEAR_VARS) -LOCAL_MODULE := hostapd_cli -LOCAL_MODULE_TAGS := debug -LOCAL_SHARED_LIBRARIES := libc libcutils -LOCAL_CFLAGS := $(L_CFLAGS) -LOCAL_SRC_FILES := $(OBJS_c) -LOCAL_C_INCLUDES := $(INCLUDES) -include $(BUILD_EXECUTABLE) - -######################## -include $(CLEAR_VARS) -LOCAL_MODULE := hostapd -LOCAL_MODULE_TAGS := optional -ifdef CONFIG_DRIVER_CUSTOM -LOCAL_STATIC_LIBRARIES := libCustomWifi -endif -ifneq ($(BOARD_HOSTAPD_PRIVATE_LIB),) -LOCAL_STATIC_LIBRARIES += $(BOARD_HOSTAPD_PRIVATE_LIB) -endif -LOCAL_SHARED_LIBRARIES := libc libcutils libcrypto libssl -ifdef CONFIG_DRIVER_NL80211 -LOCAL_SHARED_LIBRARIES += libnl_2 -endif -LOCAL_CFLAGS := $(L_CFLAGS) -LOCAL_SRC_FILES := $(OBJS) -LOCAL_C_INCLUDES := $(INCLUDES) -include $(BUILD_EXECUTABLE) - -endif # ifeq ($(WPA_BUILD_HOSTAPD),true) diff --git a/hostapd-0.8/hostapd/ChangeLog b/hostapd-0.8/hostapd/ChangeLog deleted file mode 100644 index a8417d6..0000000 --- a/hostapd-0.8/hostapd/ChangeLog +++ /dev/null @@ -1,647 +0,0 @@ -ChangeLog for hostapd - -2010-04-18 - v0.7.2 - * fix WPS internal Registrar use when an external Registrar is also - active - * bsd: Cleaned up driver wrapper and added various low-level - configuration options - * 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) - * cleaned up driver wrapper API for multi-BSS operations - * nl80211: fix multi-BSS and VLAN operations - * fix number of issues with IEEE 802.11r/FT; this version is not - backwards compatible with old versions - * add SA Query Request processing in AP mode (IEEE 802.11w) - * fix IGTK PN in group rekeying (IEEE 802.11w) - * fix WPS PBC session overlap detection to use correct attribute - * hostapd_notif_Assoc() can now be called with all IEs to simplify - driver wrappers - * work around interoperability issue with some WPS External Registrar - implementations - * nl80211: fix WPS IE update - * hostapd_cli: add support for action script operations (run a script - on hostapd events) - * fix DH padding with internal crypto code (mainly, for WPS) - * fix WPS association with both WPS IE and WPA/RSN IE present with - driver wrappers that use hostapd MLME (e.g., nl80211) - -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 - * fixed HT Capabilities IE with nl80211 drivers - * moved generic AP functionality code into src/ap - * WPS: handle Selected Registrar as union of info from all Registrars - * remove obsolte Prism54.org driver wrapper - * added internal debugging mechanism with backtrace support and memory - allocation/freeing validation, etc. tests (CONFIG_WPA_TRACE=y) - * EAP-FAST server: piggyback Phase 2 start with the end of Phase 1 - * WPS: add support for dynamically selecting whether to provision the - PSK as an ASCII passphrase or PSK - * added support for WDS (4-address frame) mode with per-station virtual - interfaces (wds_sta=1 in config file; only supported with - driver=nl80211 for now) - * fixed WPS Probe Request processing to handle missing required - attribute - * fixed PKCS#12 use with OpenSSL 1.0.0 - * detect bridge interface automatically so that bridge parameter in - hostapd.conf becomes optional (though, it may now be used to - automatically add then WLAN interface into a bridge with - driver=nl80211) - -2009-11-21 - v0.7.0 - * increased hostapd_cli ping interval to 5 seconds and made this - configurable with a new command line options (-G) - * driver_nl80211: use Linux socket filter to improve performance - * added support for external Registrars with WPS (UPnP transport) - * 802.11n: scan for overlapping BSSes before starting 20/40 MHz channel - * driver_nl80211: fixed STA accounting data collection (TX/RX bytes - reported correctly; TX/RX packets not yet available from kernel) - * added support for WPS USBA out-of-band mechanism with USB Flash - Drives (UFD) (CONFIG_WPS_UFD=y) - * fixed EAPOL/EAP reauthentication when using an external RADIUS - authentication server - * fixed TNC with EAP-TTLS - * fixed IEEE 802.11r key derivation function to match with the standard - (note: this breaks interoperability with previous version) [Bug 303] - * 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] - * added number of code size optimizations to remove unnecessary - functionality from the program binary based on build configuration - (part of this automatic; part configurable with CONFIG_NO_* build - options) - * use shared driver wrapper files with wpa_supplicant - * 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 some IEEE 802.11n co-existance rules to disable 40 MHz channels - or modify primary/secondary channels if needed based on neighboring - networks - * added support for NFC out-of-band mechanism with WPS - * added preliminary support for IEEE 802.11r RIC processing - -2009-01-06 - v0.6.7 - * added support for Wi-Fi Protected Setup (WPS) - (hostapd can now be configured to act as an integrated WPS Registrar - and provision credentials for WPS Enrollees using PIN and PBC - methods; external wireless Registrar can configure the AP, but - external WLAN Manager Registrars are not supported); WPS support can - be enabled by adding CONFIG_WPS=y into .config and setting the - runtime configuration variables in hostapd.conf (see WPS section in - the example configuration file); new hostapd_cli commands wps_pin and - wps_pbc are used to configure WPS negotiation; see README-WPS for - more details - * added IEEE 802.11n HT capability configuration (ht_capab) - * added support for generating Country IE based on nl80211 regulatory - information (added if ieee80211d=1 in configuration) - * fixed WEP authentication (both Open System and Shared Key) with - mac80211 - * added support for EAP-AKA' (draft-arkko-eap-aka-kdf) - * added support for using driver_test over UDP socket - * changed EAP-GPSK to use the IANA assigned EAP method type 51 - * updated management frame protection to use IEEE 802.11w/D7.0 - * fixed retransmission of EAP requests if no response is received - -2008-11-23 - v0.6.6 - * added a new configuration option, wpa_ptk_rekey, that can be used to - enforce frequent PTK rekeying, e.g., to mitigate some attacks against - TKIP deficiencies - * 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) - * changed channel flags configuration to read the information from - the driver (e.g., via driver_nl80211 when using mac80211) instead of - using hostapd as the source of the regulatory information (i.e., - information from CRDA is now used with mac80211); this allows 5 GHz - channels to be used with hostapd (if allowed in the current - regulatory domain) - * fixed EAP-TLS message processing for the last TLS message if it is - large enough to require fragmentation (e.g., if a large Session - Ticket data is included) - * fixed listen interval configuration for nl80211 drivers - -2008-11-01 - v0.6.5 - * added support for SHA-256 as X.509 certificate digest when using the - internal X.509/TLSv1 implementation - * fixed EAP-FAST PAC-Opaque padding (0.6.4 broke this for some peer - identity lengths) - * fixed internal TLSv1 implementation for abbreviated handshake (used - by EAP-FAST server) - * added support for setting VLAN ID for STAs based on local MAC ACL - (accept_mac_file) as an alternative for RADIUS server-based - configuration - * updated management frame protection to use IEEE 802.11w/D6.0 - (adds a new association ping to protect against unauthenticated - authenticate or (re)associate request frames dropping association) - * added support for using SHA256-based stronger key derivation for WPA2 - (IEEE 802.11w) - * added new "driver wrapper" for RADIUS-only configuration - (driver=none in hostapd.conf; CONFIG_DRIVER_NONE=y in .config) - * fixed WPA/RSN IE validation to verify that the proto (WPA vs. WPA2) - is enabled in configuration - * changed EAP-FAST configuration to use separate fields for A-ID and - A-ID-Info (eap_fast_a_id_info) to allow A-ID to be set to a fixed - 16-octet len binary value for better interoperability with some peer - implementations; eap_fast_a_id is now configured as a hex string - * driver_nl80211: Updated to match the current Linux mac80211 AP mode - configuration (wireless-testing.git and Linux kernel releases - starting from 2.6.29) - -2008-08-10 - v0.6.4 - * added peer identity into EAP-FAST PAC-Opaque and skip Phase 2 - Identity Request if identity is already known - * added support for EAP Sequences in EAP-FAST Phase 2 - * added support for EAP-TNC (Trusted Network Connect) - (this version implements the EAP-TNC method and EAP-TTLS/EAP-FAST - changes needed to run two methods in sequence (IF-T) and the IF-IMV - and IF-TNCCS interfaces from TNCS) - * added support for optional cryptobinding with PEAPv0 - * added fragmentation support for EAP-TNC - * added support for fragmenting EAP-TTLS/PEAP/FAST Phase 2 (tunneled) - data - * added support for opportunistic key caching (OKC) - -2008-02-22 - v0.6.3 - * fixed Reassociation Response callback processing when using internal - MLME (driver_{hostap,nl80211,test}.c) - * updated FT support to use the latest draft, IEEE 802.11r/D9.0 - * copy optional Proxy-State attributes into RADIUS response when acting - as a RADIUS authentication server - * fixed EAPOL state machine to handle a case in which no response is - received from the RADIUS authentication server; previous version - could have triggered a crash in some cases after a timeout - * fixed EAP-SIM/AKA realm processing to allow decorated usernames to - be used - * added a workaround for EAP-SIM/AKA peers that include incorrect null - termination in the username - * fixed EAP-SIM/AKA protected result indication to include AT_COUNTER - attribute in notification messages only when using fast - reauthentication - * fixed EAP-SIM Start response processing for fast reauthentication - case - * added support for pending EAP processing in EAP-{PEAP,TTLS,FAST} - phase 2 to allow EAP-SIM and EAP-AKA to be used as the Phase 2 method - -2008-01-01 - v0.6.2 - * 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 hostapd 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 (eap_sim_aka_result_ind=1) - * added support for configuring EAP-TTLS phase 2 non-EAP methods in - EAP server configuration; previously all four were enabled for every - phase 2 user, now all four are disabled by default and need to be - enabled with new method names TTLS-PAP, TTLS-CHAP, TTLS-MSCHAP, - TTLS-MSCHAPV2 - * removed old debug printing mechanism and the related 'debug' - parameter in the configuration file; debug verbosity is now set with - -d (or -dd) command line arguments - * 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 experimental, integrated TLSv1 server 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 - * added support for EAP-FAST server method to the integrated EAP - server - * updated EAP Generalized Pre-Shared Key (EAP-GPSK) to use the latest - draft (draft-ietf-emu-eap-gpsk-07.txt) - * added a new configuration parameter, rsn_pairwise, to allow different - pairwise cipher suites to be enabled for WPA and RSN/WPA2 - (note: if wpa_pairwise differs from rsn_pairwise, the driver will - either need to support this or will have to use the WPA/RSN IEs from - hostapd; currently, the included madwifi and bsd driver interfaces do - not have support for this) - * updated FT support to use the latest draft, IEEE 802.11r/D8.0 - -2007-05-28 - v0.6.0 - * 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-PSK bit ordering of the Flags field - * fixed configuration reloading (SIGHUP) to re-initialize WPA PSKs - by reading wpa_psk_file [Bug 181] - * fixed EAP-TTLS AVP parser processing for too short AVP lengths - * fixed IPv6 connection to RADIUS accounting server - * updated EAP Generalized Pre-Shared Key (EAP-GPSK) to use the latest - draft (draft-ietf-emu-eap-gpsk-04.txt) - * hlr_auc_gw: read GSM triplet file into memory and rotate through the - entries instead of only using the same three triplets every time - (this does not work properly with tests using multiple clients, but - provides bit better triplet data for testing a single client; anyway, - if a better quality triplets are needed, GSM-Milenage should be used - instead of hardcoded triplet file) - * fixed EAP-MSCHAPv2 server to use a space between S and M parameters - in Success Request [Bug 203] - * added support for sending EAP-AKA Notifications in error cases - * updated to use IEEE 802.11w/D2.0 for management frame protection - (still experimental) - * RADIUS server: added support for processing duplicate messages - (retransmissions from RADIUS client) by replying with the previous - reply - -2006-11-24 - v0.5.6 - * added support for configuring and controlling multiple BSSes per - radio interface (bss= in hostapd.conf); this is only - available with Devicescape and test driver interfaces - * fixed PMKSA cache update in the end of successful RSN - pre-authentication - * added support for dynamic VLAN configuration (i.e., selecting VLAN-ID - for each STA based on RADIUS Access-Accept attributes); this requires - VLAN support from the kernel driver/802.11 stack and this is - currently only available with Devicescape and test driver interfaces - * driver_madwifi: fixed configuration of unencrypted modes (plaintext - and IEEE 802.1X without WEP) - * 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.) - * hlr_auc_gw: added support for GSM-Milenage (for EAP-SIM) - * hlr_auc_gw: added support for reading per-IMSI Milenage keys and - parameters from a text file to make it possible to implement proper - GSM/UMTS authentication server for multiple SIM/USIM cards using - EAP-SIM/EAP-AKA - * fixed session timeout processing with drivers that do not use - ieee802_11.c (e.g., madwifi) - -2006-08-27 - v0.5.5 - * added 'hostapd_cli new_sta ' command for adding a new STA into - hostapd (e.g., to initialize wired network authentication based on an - external signal) - * fixed hostapd to add PMKID KDE into 4-Way Handshake Message 1 when - using WPA2 even if PMKSA caching is not used - * added -P argument for hostapd to write the current process - id into a file - * added support for RADIUS Authentication Server MIB (RFC 2619) - -2006-06-20 - v0.5.4 - * fixed nt_password_hash build [Bug 144] - * added PeerKey handshake implementation for IEEE 802.11e - direct link setup (DLS) to replace STAKey handshake - * added support for EAP Generalized Pre-Shared Key (EAP-GPSK, - draft-clancy-emu-eap-shared-secret-00.txt) - * fixed a segmentation fault when RSN pre-authentication was completed - successfully [Bug 152] - -2006-04-27 - v0.5.3 - * do not build nt_password_hash and hlr_auc_gw by default to avoid - requiring a TLS library for a successful build; these programs can be - build with 'make nt_password_hash' and 'make hlr_auc_gw' - * added a new configuration option, eapol_version, that can be used to - set EAPOL version to 1 (default is 2) to work around broken client - implementations that drop EAPOL frames which use version number 2 - [Bug 89] - * added support for EAP-SAKE (no EAP method number allocated yet, so - this is using the same experimental type 255 as EAP-PSK) - * fixed EAP-MSCHAPv2 message length validation - -2006-03-19 - v0.5.2 - * fixed stdarg use in hostapd_logger(): if both stdout and syslog - logging was enabled, hostapd could trigger a segmentation fault in - vsyslog on some CPU -- C library combinations - * moved HLR/AuC gateway implementation for EAP-SIM/AKA into an external - program to make it easier to use for implementing real SS7 gateway; - eap_sim_db is not anymore used as a file name for GSM authentication - triplets; instead, it is path to UNIX domain socket that will be used - to communicate with the external gateway program (e.g., hlr_auc_gw) - * added example HLR/AuC gateway implementation, hlr_auc_gw, that uses - local information (GSM authentication triplets from a text file and - hardcoded AKA authentication data); this can be used to test EAP-SIM - and EAP-AKA - * added Milenage algorithm (example 3GPP AKA algorithm) to hlr_auc_gw - to make it possible to test EAP-AKA with real USIM cards (this is - disabled by default; define AKA_USE_MILENAGE when building hlr_auc_gw - to enable this) - * driver_madwifi: added support for getting station RSN IE from - madwifi-ng svn r1453 and newer; this fixes RSN that was apparently - broken with earlier change (r1357) in the driver - * changed EAP method registration to use a dynamic list of methods - instead of a static list generated at build time - * fixed WPA message 3/4 not to encrypt Key Data field (WPA IE) - [Bug 125] - * added ap_max_inactivity configuration parameter - -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 (test_socket=DIR:/tmp/test) - * added support for EAP expanded type (vendor specific EAP methods) - -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) - * added support for EAP methods to use callbacks to external programs - by buffering a pending request and processing it after the EAP method - is ready to continue - * improved EAP-SIM database interface to allow external request to GSM - HLR/AuC without blocking hostapd process - * added support for using EAP-SIM pseudonyms and fast re-authentication - * added support for EAP-AKA in the integrated EAP authenticator - * added support for matching EAP identity prefixes (e.g., "1"*) in EAP - user database to allow EAP-SIM/AKA selection without extra roundtrip - for EAP-Nak negotiation - * added support for storing EAP user password as NtPasswordHash instead - of plaintext password when using MSCHAP or MSCHAPv2 for - authentication (hash:<16-octet hex value>); added nt_password_hash - tool for hashing password to generate NtPasswordHash - -2005-11-20 - v0.4.7 (beginning of 0.4.x stable releases) - * driver_wired: fixed EAPOL sending to optionally use PAE group address - as the destination instead of supplicant MAC address; this is - disabled by default, but should be enabled with use_pae_group_addr=1 - in configuration file if the wired interface is used by only one - device at the time (common switch configuration) - * driver_madwifi: configure driver to use TKIP countermeasures in order - to get correct behavior (IEEE 802.11 association failing; previously, - association succeeded, but hostpad forced disassociation immediately) - * driver_madwifi: added support for madwifi-ng - -2005-10-27 - v0.4.6 - * added support for replacing user identity from EAP with RADIUS - User-Name attribute from Access-Accept message, if that is included, - for the RADIUS accounting messages (e.g., for EAP-PEAP/TTLS to get - tunneled identity into accounting messages when the RADIUS server - does not support better way of doing this with Class attribute) - * driver_madwifi: fixed EAPOL packet receive for configuration where - ath# is part of a bridge interface - * added a configuration file and log analyzer script for logwatch - * fixed EAPOL state machine step function to process all state - transitions before processing new events; this resolves a race - condition in which EAPOL-Start message could trigger hostapd to send - two EAP-Response/Identity frames to the authentication server - -2005-09-25 - v0.4.5 - * added client CA list to the TLS certificate request in order to make - it easier for the client to select which certificate to use - * added experimental support for EAP-PSK - * added support for WE-19 (hostap, madwifi) - -2005-08-21 - v0.4.4 - * fixed build without CONFIG_RSN_PREAUTH - * fixed FreeBSD build - -2005-06-26 - v0.4.3 - * fixed PMKSA caching to copy User-Name and Class attributes so that - RADIUS accounting gets correct information - * start RADIUS accounting only after successful completion of WPA - 4-Way Handshake if WPA-PSK is used - * fixed PMKSA caching for the case where STA (re)associates without - first disassociating - -2005-06-12 - v0.4.2 - * EAP-PAX is now registered as EAP type 46 - * fixed EAP-PAX MAC calculation - * fixed EAP-PAX CK and ICK key derivation - * renamed eap_authenticator configuration variable to eap_server to - better match with RFC 3748 (EAP) terminology - * 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 - * fixed RADIUS server initialization when only auth or acct server - is configured and the other one is left empty - * driver_madwifi: added support for RADIUS accounting - * driver_madwifi: added preliminary support for compiling against 'BSD' - branch of madwifi CVS tree - * driver_madwifi: fixed pairwise key removal to allow WPA reauth - without disassociation - * added support for reading additional certificates from PKCS#12 files - and adding them to the certificate chain - * fixed RADIUS Class attribute processing to only use Access-Accept - packets to update Class; previously, other RADIUS authentication - packets could have cleared Class attribute - * added support for more than one Class attribute in RADIUS packets - * added support for verifying certificate revocation list (CRL) when - using integrated EAP authenticator for EAP-TLS; new hostapd.conf - options 'check_crl'; CRL must be included in the ca_cert file for now - -2005-04-25 - v0.4.0 (beginning of 0.4.x development releases) - * added support for including network information into - EAP-Request/Identity message (ASCII-0 (nul) in eap_message) - (e.g., to implement draft-adrange-eap-network-discovery-07.txt) - * fixed a bug which caused some RSN pre-authentication cases to use - freed memory and potentially crash hostapd - * fixed private key loading for cases where passphrase is not set - * added support for sending TLS alerts and aborting authentication - when receiving a TLS alert - * fixed WPA2 to add PMKSA cache entry when using integrated EAP - authenticator - * fixed PMKSA caching (EAP authentication was not skipped correctly - with the new state machine changes from IEEE 802.1X draft) - * added support for RADIUS over IPv6; own_ip_addr, auth_server_addr, - and acct_server_addr can now be IPv6 addresses (CONFIG_IPV6=y needs - to be added to .config to include IPv6 support); for RADIUS server, - radius_server_ipv6=1 needs to be set in hostapd.conf and addresses - in RADIUS clients file can then use IPv6 format - * added experimental support for EAP-PAX - * replaced hostapd control interface library (hostapd_ctrl.[ch]) with - the same implementation that wpa_supplicant is using (wpa_ctrl.[ch]) - -2005-02-12 - v0.3.7 (beginning of 0.3.x stable releases) - -2005-01-23 - v0.3.5 - * added support for configuring a forced PEAP version based on the - Phase 1 identity - * fixed PEAPv1 to use tunneled EAP-Success/Failure instead of EAP-TLV - to terminate authentication - * fixed EAP identifier duplicate processing with the new IEEE 802.1X - draft - * clear accounting data in the driver when starting a new accounting - session - * driver_madwifi: filter wireless events based on ifindex to allow more - than one network interface to be used - * fixed WPA message 2/4 processing not to cancel timeout for TimeoutEvt - setting if the packet does not pass MIC verification (e.g., due to - incorrect PSK); previously, message 1/4 was not tried again if an - invalid message 2/4 was received - * fixed reconfiguration of RADIUS client retransmission timer when - adding a new message to the pending list; previously, timer was not - updated at this point and if there was a pending message with long - time for the next retry, the new message needed to wait that long for - its first retry, too - -2005-01-09 - v0.3.4 - * added support for configuring multiple allowed EAP types for Phase 2 - authentication (EAP-PEAP, EAP-TTLS) - * fixed EAPOL-Start processing to trigger WPA reauthentication - (previously, only EAPOL authentication was done) - -2005-01-02 - v0.3.3 - * added support for EAP-PEAP in the integrated EAP authenticator - * added support for EAP-GTC in the integrated EAP authenticator - * added support for configuring list of EAP methods for Phase 1 so that - the integrated EAP authenticator can, e.g., use the wildcard entry - for EAP-TLS and EAP-PEAP - * added support for EAP-TTLS in the integrated EAP authenticator - * added support for EAP-SIM in the integrated EAP authenticator - * added support for using hostapd as a RADIUS authentication server - with the integrated EAP authenticator taking care of EAP - authentication (new hostapd.conf options: radius_server_clients and - radius_server_auth_port); this is not included in default build; use - CONFIG_RADIUS_SERVER=y in .config to include - -2004-12-19 - v0.3.2 - * removed 'daemonize' configuration file option since it has not really - been used at all for more than year - * driver_madwifi: fixed group key setup and added get_ssid method - * added support for EAP-MSCHAPv2 in the integrated EAP authenticator - -2004-12-12 - v0.3.1 - * added support for integrated EAP-TLS authentication (new hostapd.conf - variables: ca_cert, server_cert, private_key, private_key_passwd); - this enabled dynamic keying (WPA2/WPA/IEEE 802.1X/WEP) without - external RADIUS server - * added support for reading PKCS#12 (PFX) files (as a replacement for - PEM/DER) to get certificate and private key (CONFIG_PKCS12) - -2004-12-05 - v0.3.0 (beginning of 0.3.x development releases) - * added support for Acct-{Input,Output}-Gigawords - * added support for Event-Timestamp (in RADIUS Accounting-Requests) - * added support for RADIUS Authentication Client MIB (RFC2618) - * added support for RADIUS Accounting Client MIB (RFC2620) - * made EAP re-authentication period configurable (eap_reauth_period) - * fixed EAPOL reauthentication to trigger WPA/WPA2 reauthentication - * fixed EAPOL state machine to stop if STA is removed during - eapol_sm_step(); this fixes at least one segfault triggering bug with - IEEE 802.11i pre-authentication - * added support for multiple WPA pre-shared keys (e.g., one for each - client MAC address or keys shared by a group of clients); - new hostapd.conf field wpa_psk_file for setting path to a text file - containing PSKs, see hostapd.wpa_psk for an example - * added support for multiple driver interfaces to allow hostapd to be - used with other drivers - * added wired authenticator driver interface (driver=wired in - hostapd.conf, see wired.conf for example configuration) - * added madwifi driver interface (driver=madwifi in hostapd.conf, see - madwifi.conf for example configuration; Note: include files from - madwifi project is needed for building and a configuration file, - .config, needs to be created in hostapd directory with - CONFIG_DRIVER_MADWIFI=y to include this driver interface in hostapd - build) - * fixed an alignment issue that could cause SHA-1 to fail on some - platforms (e.g., Intel ixp425 with a compiler that does not 32-bit - align variables) - * fixed RADIUS reconnection after an error in sending interim - accounting packets - * added hostapd control interface for external programs and an example - CLI, hostapd_cli (like wpa_cli for wpa_supplicant) - * started adding dot11, dot1x, radius MIBs ('hostapd_cli mib', - 'hostapd_cli sta ') - * finished update from IEEE 802.1X-2001 to IEEE 802.1X-REV (now d11) - * added support for strict GTK rekeying (wpa_strict_rekey in - hostapd.conf) - * updated IAPP to use UDP port 3517 and multicast address 224.0.1.178 - (instead of broadcast) for IAPP ADD-notify (moved from draft 3 to - IEEE 802.11F-2003) - * added Prism54 driver interface (driver=prism54 in hostapd.conf; - note: .config needs to be created in hostapd directory with - CONFIG_DRIVER_PRISM54=y to include this driver interface in hostapd - build) - * dual-licensed hostapd (GPLv2 and BSD licenses) - * fixed RADIUS accounting to generate a new session id for cases where - a station reassociates without first being complete deauthenticated - * fixed STA disassociation handler to mark next timeout state to - deauthenticate the station, i.e., skip long wait for inactivity poll - and extra disassociation, if the STA disassociates without - deauthenticating - * added integrated EAP authenticator that can be used instead of - external RADIUS authentication server; currently, only EAP-MD5 is - supported, so this cannot yet be used for key distribution; the EAP - method interface is generic, though, so adding new EAP methods should - be straightforward; new hostapd.conf variables: 'eap_authenticator' - and 'eap_user_file'; this obsoletes "minimal authentication server" - ('minimal_eap' in hostapd.conf) which is now removed - * added support for FreeBSD and driver interface for the BSD net80211 - layer (driver=bsd in hostapd.conf and CONFIG_DRIVER_BSD=y in - .config); please note that some of the required kernel mods have not - yet been committed - -2004-07-17 - v0.2.4 (beginning of 0.2.x stable releases) - * fixed some accounting cases where Accounting-Start was sent when - IEEE 802.1X port was being deauthorized - -2004-06-20 - v0.2.3 - * modified RADIUS client to re-connect the socket in case of certain - error codes that are generated when a network interface state is - changes (e.g., when IP address changes or the interface is set UP) - * fixed couple of cases where EAPOL state for a station was freed - twice causing a segfault for hostapd - * fixed couple of bugs in processing WPA deauthentication (freed data - was used) - -2004-05-31 - v0.2.2 - * fixed WPA/WPA2 group rekeying to use key index correctly (GN/GM) - * fixed group rekeying to send zero TSC in EAPOL-Key messages to fix - cases where STAs dropped multicast frames as replay attacks - * added support for copying RADIUS Attribute 'Class' from - authentication messages into accounting messages - * send canned EAP failure if RADIUS server sends Access-Reject without - EAP message (previously, Supplicant was not notified in this case) - * fixed mixed WPA-PSK and WPA-EAP mode to work with WPA-PSK (i.e., do - not start EAPOL state machines if the STA selected to use WPA-PSK) - -2004-05-06 - v0.2.1 - * added WPA and IEEE 802.11i/RSN (WPA2) Authenticator functionality - - based on IEEE 802.11i/D10.0 but modified to interoperate with WPA - (i.e., IEEE 802.11i/D3.0) - - supports WPA-only, RSN-only, and mixed WPA/RSN mode - - both WPA-PSK and WPA-RADIUS/EAP are supported - - PMKSA caching and pre-authentication - - new hostapd.conf variables: wpa, wpa_psk, wpa_passphrase, - wpa_key_mgmt, wpa_pairwise, wpa_group_rekey, wpa_gmk_rekey, - rsn_preauth, rsn_preauth_interfaces - * fixed interim accounting to remove any pending accounting messages - to the STA before sending a new one - -2004-02-15 - v0.2.0 - * added support for Acct-Interim-Interval: - - draft-ietf-radius-acct-interim-01.txt - - use Acct-Interim-Interval attribute from Access-Accept if local - 'radius_acct_interim_interval' is not set - - allow different update intervals for each STA - * fixed event loop to call signal handlers only after returning from - the real signal handler - * reset sta->timeout_next after successful association to make sure - that the previously registered inactivity timer will not remove the - STA immediately (e.g., if STA deauthenticates and re-associates - before the timer is triggered). - * added new hostapd.conf variable, nas_identifier, that can be used to - add an optional RADIUS Attribute, NAS-Identifier, into authentication - and accounting messages - * added support for Accounting-On and Accounting-Off messages - * fixed accounting session handling to send Accounting-Start only once - per session and not to send Accounting-Stop if the session was not - initialized properly - * fixed Accounting-Stop statistics in cases where the message was - previously sent after the kernel entry for the STA (and/or IEEE - 802.1X data) was removed - - -Note: - -Older changes up to and including v0.1.0 are included in the ChangeLog -of the Host AP driver. diff --git a/hostapd-0.8/hostapd/Makefile b/hostapd-0.8/hostapd/Makefile deleted file mode 100644 index d05975b..0000000 --- a/hostapd-0.8/hostapd/Makefile +++ /dev/null @@ -1,836 +0,0 @@ -ifndef CC -CC=gcc -endif - -ifndef CFLAGS -CFLAGS = -MMD -O2 -Wall -g -endif - -CFLAGS += -I../src -CFLAGS += -I../src/utils - -# Uncomment following line and set the path to your kernel tree include -# directory if your C library does not include all header files. -# CFLAGS += -DUSE_KERNEL_HEADERS -I/usr/src/linux/include - --include .config - -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 - -ifdef CONFIG_NATIVE_WINDOWS -CFLAGS += -DCONFIG_NATIVE_WINDOWS -LIBS += -lws2_32 -endif - -OBJS += main.o -OBJS += config_file.o - -OBJS += ../src/ap/hostapd.o -OBJS += ../src/ap/wpa_auth_glue.o -OBJS += ../src/ap/drv_callbacks.o -OBJS += ../src/ap/ap_drv_ops.o -OBJS += ../src/ap/utils.o -OBJS += ../src/ap/authsrv.o -OBJS += ../src/ap/ieee802_1x.o -OBJS += ../src/ap/ap_config.o -OBJS += ../src/ap/ieee802_11_auth.o -OBJS += ../src/ap/sta_info.o -OBJS += ../src/ap/wpa_auth.o -OBJS += ../src/ap/tkip_countermeasures.o -OBJS += ../src/ap/ap_mlme.o -OBJS += ../src/ap/wpa_auth_ie.o -OBJS += ../src/ap/preauth_auth.o -OBJS += ../src/ap/pmksa_cache_auth.o - -NEED_RC4=y -NEED_AES=y -NEED_MD5=y -NEED_SHA1=y - -OBJS += ../src/drivers/drivers.o -CFLAGS += -DHOSTAPD - -ifdef CONFIG_WPA_TRACE -CFLAGS += -DWPA_TRACE -OBJS += ../src/utils/trace.o -HOBJS += ../src/utils/trace.o -LDFLAGS += -rdynamic -CFLAGS += -funwind-tables -ifdef CONFIG_WPA_TRACE_BFD -CFLAGS += -DWPA_TRACE_BFD -LIBS += -lbfd -LIBS_c += -lbfd -LIBS_h += -lbfd -endif -endif - -OBJS += ../src/utils/eloop.o -OBJS += ../src/utils/common.o -OBJS += ../src/utils/wpa_debug.o -OBJS += ../src/utils/wpabuf.o -OBJS += ../src/utils/os_$(CONFIG_OS).o -OBJS += ../src/utils/ip_addr.o - -OBJS += ../src/common/ieee802_11_common.o -OBJS += ../src/common/wpa_common.o - -OBJS += ../src/eapol_auth/eapol_auth_sm.o - - -ifndef CONFIG_NO_DUMP_STATE -# define HOSTAPD_DUMP_STATE to include SIGUSR1 handler for dumping state to -# a file (undefine it, if you want to save in binary size) -CFLAGS += -DHOSTAPD_DUMP_STATE -OBJS += dump_state.o -OBJS += ../src/eapol_auth/eapol_auth_dump.o -endif - -ifdef CONFIG_NO_RADIUS -CFLAGS += -DCONFIG_NO_RADIUS -CONFIG_NO_ACCOUNTING=y -else -OBJS += ../src/radius/radius.o -OBJS += ../src/radius/radius_client.o -endif - -ifdef CONFIG_NO_ACCOUNTING -CFLAGS += -DCONFIG_NO_ACCOUNTING -else -OBJS += ../src/ap/accounting.o -endif - -ifdef CONFIG_NO_VLAN -CFLAGS += -DCONFIG_NO_VLAN -else -OBJS += ../src/ap/vlan_init.o -endif - -ifdef CONFIG_NO_CTRL_IFACE -CFLAGS += -DCONFIG_NO_CTRL_IFACE -else -OBJS += ctrl_iface.o -OBJS += ../src/ap/ctrl_iface_ap.o -endif - -OBJS += ../src/crypto/md5.o - -CFLAGS += -DCONFIG_CTRL_IFACE -DCONFIG_CTRL_IFACE_UNIX - -ifdef CONFIG_IAPP -CFLAGS += -DCONFIG_IAPP -OBJS += ../src/ap/iapp.o -endif - -ifdef CONFIG_RSN_PREAUTH -CFLAGS += -DCONFIG_RSN_PREAUTH -CONFIG_L2_PACKET=y -endif - -ifdef CONFIG_PEERKEY -CFLAGS += -DCONFIG_PEERKEY -OBJS += ../src/ap/peerkey_auth.o -endif - -ifdef CONFIG_IEEE80211W -CFLAGS += -DCONFIG_IEEE80211W -NEED_SHA256=y -NEED_AES_OMAC1=y -endif - -ifdef CONFIG_IEEE80211R -CFLAGS += -DCONFIG_IEEE80211R -OBJS += ../src/ap/wpa_auth_ft.o -NEED_SHA256=y -NEED_AES_OMAC1=y -NEED_AES_UNWRAP=y -endif - -ifdef CONFIG_IEEE80211N -CFLAGS += -DCONFIG_IEEE80211N -endif - -include ../src/drivers/drivers.mak -OBJS += $(DRV_AP_OBJS) -CFLAGS += $(DRV_AP_CFLAGS) -LDFLAGS += $(DRV_AP_LDFLAGS) -LIBS += $(DRV_AP_LIBS) - -ifdef CONFIG_L2_PACKET -ifdef CONFIG_DNET_PCAP -ifdef CONFIG_L2_FREEBSD -LIBS += -lpcap -OBJS += ../src/l2_packet/l2_packet_freebsd.o -else -LIBS += -ldnet -lpcap -OBJS += ../src/l2_packet/l2_packet_pcap.o -endif -else -OBJS += ../src/l2_packet/l2_packet_linux.o -endif -else -OBJS += ../src/l2_packet/l2_packet_none.o -endif - - -ifdef CONFIG_EAP_MD5 -CFLAGS += -DEAP_SERVER_MD5 -OBJS += ../src/eap_server/eap_server_md5.o -CHAP=y -endif - -ifdef CONFIG_EAP_TLS -CFLAGS += -DEAP_SERVER_TLS -OBJS += ../src/eap_server/eap_server_tls.o -TLS_FUNCS=y -endif - -ifdef CONFIG_EAP_PEAP -CFLAGS += -DEAP_SERVER_PEAP -OBJS += ../src/eap_server/eap_server_peap.o -OBJS += ../src/eap_common/eap_peap_common.o -TLS_FUNCS=y -CONFIG_EAP_MSCHAPV2=y -endif - -ifdef CONFIG_EAP_TTLS -CFLAGS += -DEAP_SERVER_TTLS -OBJS += ../src/eap_server/eap_server_ttls.o -TLS_FUNCS=y -CHAP=y -endif - -ifdef CONFIG_EAP_MSCHAPV2 -CFLAGS += -DEAP_SERVER_MSCHAPV2 -OBJS += ../src/eap_server/eap_server_mschapv2.o -MS_FUNCS=y -endif - -ifdef CONFIG_EAP_GTC -CFLAGS += -DEAP_SERVER_GTC -OBJS += ../src/eap_server/eap_server_gtc.o -endif - -ifdef CONFIG_EAP_SIM -CFLAGS += -DEAP_SERVER_SIM -OBJS += ../src/eap_server/eap_server_sim.o -CONFIG_EAP_SIM_COMMON=y -NEED_AES_CBC=y -endif - -ifdef CONFIG_EAP_AKA -CFLAGS += -DEAP_SERVER_AKA -OBJS += ../src/eap_server/eap_server_aka.o -CONFIG_EAP_SIM_COMMON=y -NEED_SHA256=y -NEED_AES_CBC=y -endif - -ifdef CONFIG_EAP_AKA_PRIME -CFLAGS += -DEAP_SERVER_AKA_PRIME -endif - -ifdef CONFIG_EAP_SIM_COMMON -OBJS += ../src/eap_common/eap_sim_common.o -# Example EAP-SIM/AKA interface for GSM/UMTS authentication. This can be -# replaced with another file implementating the interface specified in -# eap_sim_db.h. -OBJS += ../src/eap_server/eap_sim_db.o -NEED_FIPS186_2_PRF=y -endif - -ifdef CONFIG_EAP_PAX -CFLAGS += -DEAP_SERVER_PAX -OBJS += ../src/eap_server/eap_server_pax.o ../src/eap_common/eap_pax_common.o -endif - -ifdef CONFIG_EAP_PSK -CFLAGS += -DEAP_SERVER_PSK -OBJS += ../src/eap_server/eap_server_psk.o ../src/eap_common/eap_psk_common.o -NEED_AES_OMAC1=y -NEED_AES_ENCBLOCK=y -NEED_AES_EAX=y -endif - -ifdef CONFIG_EAP_SAKE -CFLAGS += -DEAP_SERVER_SAKE -OBJS += ../src/eap_server/eap_server_sake.o ../src/eap_common/eap_sake_common.o -endif - -ifdef CONFIG_EAP_GPSK -CFLAGS += -DEAP_SERVER_GPSK -OBJS += ../src/eap_server/eap_server_gpsk.o ../src/eap_common/eap_gpsk_common.o -ifdef CONFIG_EAP_GPSK_SHA256 -CFLAGS += -DEAP_SERVER_GPSK_SHA256 -endif -NEED_SHA256=y -NEED_AES_OMAC1=y -endif - -ifdef CONFIG_EAP_PWD -CFLAGS += -DEAP_SERVER_PWD -OBJS += ../src/eap_server/eap_server_pwd.o ../src/eap_common/eap_pwd_common.o -NEED_SHA256=y -endif - -ifdef CONFIG_EAP_VENDOR_TEST -CFLAGS += -DEAP_SERVER_VENDOR_TEST -OBJS += ../src/eap_server/eap_server_vendor_test.o -endif - -ifdef CONFIG_EAP_FAST -CFLAGS += -DEAP_SERVER_FAST -OBJS += ../src/eap_server/eap_server_fast.o -OBJS += ../src/eap_common/eap_fast_common.o -TLS_FUNCS=y -NEED_T_PRF=y -NEED_AES_UNWRAP=y -endif - -ifdef CONFIG_WPS -ifdef CONFIG_WPS2 -CFLAGS += -DCONFIG_WPS2 -endif - -CFLAGS += -DCONFIG_WPS -DEAP_SERVER_WSC -OBJS += ../src/utils/uuid.o -OBJS += ../src/ap/wps_hostapd.o -OBJS += ../src/eap_server/eap_server_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 -NEED_DH_GROUPS=y -NEED_SHA256=y -NEED_BASE64=y -NEED_AES_CBC=y -NEED_MODEXP=y -CONFIG_EAP=y - -ifdef CONFIG_WPS_UFD -CFLAGS += -DCONFIG_WPS_UFD -OBJS += ../src/wps/wps_ufd.o -NEED_WPS_OOB=y -endif - -ifdef CONFIG_WPS_NFC -CFLAGS += -DCONFIG_WPS_NFC -OBJS += ../src/wps/ndef.o -OBJS += ../src/wps/wps_nfc.o -NEED_WPS_OOB=y -ifdef CONFIG_WPS_NFC_PN531 -PN531_PATH ?= /usr/local/src/nfc -CFLAGS += -DCONFIG_WPS_NFC_PN531 -CFLAGS += -I${PN531_PATH}/inc -OBJS += ../src/wps/wps_nfc_pn531.o -LIBS += ${PN531_PATH}/lib/wpsnfc.dll -LIBS += ${PN531_PATH}/lib/libnfc_mapping_pn53x.dll -endif -endif - -ifdef NEED_WPS_OOB -CFLAGS += -DCONFIG_WPS_OOB -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 - -endif - -ifdef CONFIG_EAP_IKEV2 -CFLAGS += -DEAP_SERVER_IKEV2 -OBJS += ../src/eap_server/eap_server_ikev2.o ../src/eap_server/ikev2.o -OBJS += ../src/eap_common/eap_ikev2_common.o ../src/eap_common/ikev2_common.o -NEED_DH_GROUPS=y -NEED_DH_GROUPS_ALL=y -NEED_MODEXP=y -NEED_CIPHER=y -endif - -ifdef CONFIG_EAP_TNC -CFLAGS += -DEAP_SERVER_TNC -OBJS += ../src/eap_server/eap_server_tnc.o -OBJS += ../src/eap_server/tncs.o -NEED_BASE64=y -ifndef CONFIG_DRIVER_BSD -LIBS += -ldl -endif -endif - -# Basic EAP functionality is needed for EAPOL -OBJS += eap_register.o -OBJS += ../src/eap_server/eap_server.o -OBJS += ../src/eap_common/eap_common.o -OBJS += ../src/eap_server/eap_server_methods.o -OBJS += ../src/eap_server/eap_server_identity.o -CFLAGS += -DEAP_SERVER_IDENTITY - -ifdef CONFIG_EAP -CFLAGS += -DEAP_SERVER -endif - -ifdef CONFIG_PKCS12 -CFLAGS += -DPKCS12_FUNCS -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, and EAP_TTLS) -CFLAGS += -DEAP_TLS_FUNCS -OBJS += ../src/eap_server/eap_server_tls_common.o -NEED_TLS_PRF=y -endif - -ifndef CONFIG_TLS -CONFIG_TLS=openssl -endif - -ifeq ($(CONFIG_TLS), openssl) -ifdef TLS_FUNCS -OBJS += ../src/crypto/tls_openssl.o -LIBS += -lssl -endif -OBJS += ../src/crypto/crypto_openssl.o -HOBJS += ../src/crypto/crypto_openssl.o -ifdef NEED_FIPS186_2_PRF -OBJS += ../src/crypto/fips_prf_openssl.o -endif -LIBS += -lcrypto -LIBS_h += -lcrypto -endif - -ifeq ($(CONFIG_TLS), gnutls) -ifdef TLS_FUNCS -OBJS += ../src/crypto/tls_gnutls.o -LIBS += -lgnutls -lgpg-error -ifdef CONFIG_GNUTLS_EXTRA -CFLAGS += -DCONFIG_GNUTLS_EXTRA -LIBS += -lgnutls-extra -endif -endif -OBJS += ../src/crypto/crypto_gnutls.o -HOBJS += ../src/crypto/crypto_gnutls.o -ifdef NEED_FIPS186_2_PRF -OBJS += ../src/crypto/fips_prf_gnutls.o -endif -LIBS += -lgcrypt -LIBS_h += -lgcrypt -CONFIG_INTERNAL_SHA256=y -CONFIG_INTERNAL_RC4=y -CONFIG_INTERNAL_DH_GROUP5=y -endif - -ifeq ($(CONFIG_TLS), schannel) -ifdef TLS_FUNCS -OBJS += ../src/crypto/tls_schannel.o -endif -OBJS += ../src/crypto/crypto_cryptoapi.o -OBJS_p += ../src/crypto/crypto_cryptoapi.o -CONFIG_INTERNAL_SHA256=y -CONFIG_INTERNAL_RC4=y -CONFIG_INTERNAL_DH_GROUP5=y -endif - -ifeq ($(CONFIG_TLS), nss) -ifdef TLS_FUNCS -OBJS += ../src/crypto/tls_nss.o -LIBS += -lssl3 -endif -OBJS += ../src/crypto/crypto_nss.o -ifdef NEED_FIPS186_2_PRF -OBJS += ../src/crypto/fips_prf_nss.o -endif -LIBS += -lnss3 -LIBS_h += -lnss3 -CONFIG_INTERNAL_MD4=y -CONFIG_INTERNAL_DH_GROUP5=y -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_server.o -OBJS += ../src/tls/tlsv1_server_write.o -OBJS += ../src/tls/tlsv1_server_read.o -OBJS += ../src/tls/asn1.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_SHA256=y -NEED_BASE64=y -NEED_TLS_PRF=y -NEED_MODEXP=y -NEED_CIPHER=y -CFLAGS += -DCONFIG_TLS_INTERNAL -CFLAGS += -DCONFIG_TLS_INTERNAL_SERVER -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 -LIBS += -ltomcrypt -ltfm -LIBS_h += -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 -NEED_AES_DEC=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_h += -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_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), 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 - -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 -ifdef CONFIG_INTERNAL_AES -AESOBJS += ../src/crypto/aes-internal.o ../src/crypto/aes-internal-enc.o -endif - -AESOBJS += ../src/crypto/aes-wrap.o -ifdef NEED_AES_EAX -AESOBJS += ../src/crypto/aes-eax.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 -ifdef NEED_AES_OMAC1 -AESOBJS += ../src/crypto/aes-omac1.o -endif -ifdef NEED_AES_UNWRAP -NEED_AES_DEC=y -AESOBJS += ../src/crypto/aes-unwrap.o -endif -ifdef NEED_AES_CBC -NEED_AES_DEC=y -AESOBJS += ../src/crypto/aes-cbc.o -endif -ifdef NEED_AES_DEC -ifdef CONFIG_INTERNAL_AES -AESOBJS += ../src/crypto/aes-internal-dec.o -endif -endif -ifdef NEED_AES -OBJS += $(AESOBJS) -endif - -ifdef NEED_SHA1 -SHA1OBJS += ../src/crypto/sha1.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 -SHA1OBJS += ../src/crypto/sha1-pbkdf2.o -ifdef NEED_T_PRF -SHA1OBJS += ../src/crypto/sha1-tprf.o -endif -ifdef NEED_TLS_PRF -SHA1OBJS += ../src/crypto/sha1-tlsprf.o -endif -endif - -ifdef NEED_SHA1 -OBJS += $(SHA1OBJS) -endif - -ifdef NEED_MD5 -ifdef CONFIG_INTERNAL_MD5 -OBJS += ../src/crypto/md5-internal.o -HOBJS += ../src/crypto/md5-internal.o -endif -endif - -ifdef NEED_MD4 -ifdef CONFIG_INTERNAL_MD4 -OBJS += ../src/crypto/md4-internal.o -endif -endif - -ifdef NEED_DES -ifdef CONFIG_INTERNAL_DES -OBJS += ../src/crypto/des-internal.o -endif -endif - -ifdef NEED_RC4 -ifdef CONFIG_INTERNAL_RC4 -OBJS += ../src/crypto/rc4.o -endif -endif - -ifdef NEED_SHA256 -OBJS += ../src/crypto/sha256.o -ifdef CONFIG_INTERNAL_SHA256 -OBJS += ../src/crypto/sha256-internal.o -endif -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 CONFIG_NO_RANDOM_POOL -CFLAGS += -DCONFIG_NO_RANDOM_POOL -else -OBJS += ../src/crypto/random.o -HOBJS += ../src/crypto/random.o -HOBJS += $(SHA1OBJS) -HOBJS += ../src/crypto/md5.o -endif - -ifdef CONFIG_RADIUS_SERVER -CFLAGS += -DRADIUS_SERVER -OBJS += ../src/radius/radius_server.o -endif - -ifdef CONFIG_IPV6 -CFLAGS += -DCONFIG_IPV6 -endif - -ifdef CONFIG_DRIVER_RADIUS_ACL -CFLAGS += -DCONFIG_DRIVER_RADIUS_ACL -endif - -ifdef CONFIG_FULL_DYNAMIC_VLAN -# define CONFIG_FULL_DYNAMIC_VLAN to have hostapd manipulate bridges -# and vlan interfaces for the vlan feature. -CFLAGS += -DCONFIG_FULL_DYNAMIC_VLAN -endif - -ifdef NEED_BASE64 -OBJS += ../src/utils/base64.o -endif - -ifdef NEED_AP_MLME -OBJS += ../src/ap/beacon.o -OBJS += ../src/ap/wmm.o -OBJS += ../src/ap/ap_list.o -OBJS += ../src/ap/ieee802_11.o -OBJS += ../src/ap/hw_features.o -CFLAGS += -DNEED_AP_MLME -endif -ifdef CONFIG_IEEE80211N -OBJS += ../src/ap/ieee802_11_ht.o -endif - -ifdef CONFIG_P2P_MANAGER -CFLAGS += -DCONFIG_P2P_MANAGER -OBJS += ../src/ap/p2p_hostapd.o -endif - -ifdef CONFIG_NO_STDOUT_DEBUG -CFLAGS += -DCONFIG_NO_STDOUT_DEBUG -endif - -ifdef CONFIG_DEBUG_FILE -CFLAGS += -DCONFIG_DEBUG_FILE -endif - -ALL=hostapd hostapd_cli - -all: verify_config $(ALL) - -Q=@ -E=echo -ifeq ($(V), 1) -Q= -E=true -endif - -%.o: %.c - $(Q)$(CC) -c -o $@ $(CFLAGS) $< - @$(E) " CC " $< - -verify_config: - @if [ ! -r .config ]; then \ - echo 'Building hostapd requires a configuration file'; \ - echo '(.config). See README for more instructions. You can'; \ - echo 'run "cp defconfig .config" to create an example'; \ - echo 'configuration.'; \ - exit 1; \ - fi - -install: all - mkdir -p $(DESTDIR)/usr/local/bin - for i in $(ALL); do cp -f $$i $(DESTDIR)/usr/local/bin/$$i; done - -../src/drivers/build.hostapd: - @if [ -f ../src/drivers/build.wpa_supplicant ]; then \ - $(MAKE) -C ../src/drivers clean; \ - fi - @touch ../src/drivers/build.hostapd - -BCHECK=../src/drivers/build.hostapd - -hostapd: $(BCHECK) $(OBJS) - $(Q)$(CC) $(LDFLAGS) -o hostapd $(OBJS) $(LIBS) - @$(E) " LD " $@ - -OBJS_c = hostapd_cli.o ../src/common/wpa_ctrl.o ../src/utils/os_$(CONFIG_OS).o -ifdef CONFIG_WPA_TRACE -OBJS_c += ../src/utils/trace.o -OBJS_c += ../src/utils/wpa_debug.o -endif -hostapd_cli: $(OBJS_c) - $(Q)$(CC) $(LDFLAGS) -o hostapd_cli $(OBJS_c) $(LIBS_c) - @$(E) " LD " $@ - -NOBJS = nt_password_hash.o ../src/crypto/ms_funcs.o $(SHA1OBJS) ../src/crypto/md5.o -ifdef NEED_RC4 -ifdef CONFIG_INTERNAL_RC4 -NOBJS += ../src/crypto/rc4.o -endif -endif -ifdef CONFIG_INTERNAL_MD5 -NOBJS += ../src/crypto/md5-internal.o -endif -NOBJS += ../src/crypto/crypto_openssl.o ../src/utils/os_$(CONFIG_OS).o -NOBJS += ../src/utils/wpa_debug.o -NOBJS += ../src/utils/wpabuf.o -ifdef CONFIG_WPA_TRACE -NOBJS += ../src/utils/trace.o -LIBS_n += -lbfd -endif -ifdef TLS_FUNCS -LIBS_n += -lcrypto -endif - -HOBJS += hlr_auc_gw.o ../src/utils/common.o ../src/utils/wpa_debug.o ../src/utils/os_$(CONFIG_OS).o ../src/utils/wpabuf.o ../src/crypto/milenage.o -HOBJS += ../src/crypto/aes-encblock.o -ifdef CONFIG_INTERNAL_AES -HOBJS += ../src/crypto/aes-internal.o -HOBJS += ../src/crypto/aes-internal-enc.o -endif - -nt_password_hash: $(NOBJS) - $(Q)$(CC) $(LDFLAGS) -o nt_password_hash $(NOBJS) $(LIBS_n) - @$(E) " LD " $@ - -hlr_auc_gw: $(HOBJS) - $(Q)$(CC) $(LDFLAGS) -o hlr_auc_gw $(HOBJS) $(LIBS_h) - @$(E) " LD " $@ - -clean: - $(MAKE) -C ../src clean - rm -f core *~ *.o hostapd hostapd_cli nt_password_hash hlr_auc_gw - rm -f *.d - --include $(OBJS:%.o=%.d) diff --git a/hostapd-0.8/hostapd/README b/hostapd-0.8/hostapd/README deleted file mode 100644 index a211cdd..0000000 --- a/hostapd-0.8/hostapd/README +++ /dev/null @@ -1,387 +0,0 @@ -hostapd - user space IEEE 802.11 AP and IEEE 802.1X/WPA/WPA2/EAP - Authenticator and RADIUS authentication server -================================================================ - -Copyright (c) 2002-2011, Jouni Malinen and contributors -All Rights Reserved. - -This program is dual-licensed under both the GPL version 2 and BSD -license. Either license may be used at your option. - - - -License -------- - -GPL v2: - -This program is free software; you can redistribute it and/or modify -it under the terms of the GNU General Public License version 2 as -published by the Free Software Foundation. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - -(this copy of the license is in COPYING file) - - -Alternatively, 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. - - - -Introduction -============ - -Originally, hostapd was an optional user space component for Host AP -driver. It adds more features to the basic IEEE 802.11 management -included in the kernel driver: using external RADIUS authentication -server for MAC address based access control, IEEE 802.1X Authenticator -and dynamic WEP keying, RADIUS accounting, WPA/WPA2 (IEEE 802.11i/RSN) -Authenticator and dynamic TKIP/CCMP keying. - -The current version includes support for other drivers, an integrated -EAP server (i.e., allow full authentication without requiring -an external RADIUS authentication server), and RADIUS authentication -server for EAP authentication. - - -Requirements ------------- - -Current hardware/software requirements: -- drivers: - Host AP driver for Prism2/2.5/3. - (http://hostap.epitest.fi/) - Please note that station firmware version needs to be 1.7.0 or newer - to work in WPA mode. - - madwifi driver for cards based on Atheros chip set (ar521x) - (http://sourceforge.net/projects/madwifi/) - Please note that you will need to add the correct path for - madwifi driver root directory in .config (see defconfig file for - an example: CFLAGS += -I) - - mac80211-based drivers that support AP mode (with driver=nl80211). - This includes drivers for Atheros (ath9k) and Broadcom (b43) - chipsets. - - Any wired Ethernet driver for wired IEEE 802.1X authentication - (experimental code) - - FreeBSD -current (with some kernel mods that have not yet been - committed when hostapd v0.3.0 was released) - BSD net80211 layer (e.g., Atheros driver) - - -Build configuration -------------------- - -In order to be able to build hostapd, you will need to create a build -time configuration file, .config that selects which optional -components are included. See defconfig file for example configuration -and list of available options. - - - -IEEE 802.1X -=========== - -IEEE Std 802.1X-2001 is a standard for port-based network access -control. In case of IEEE 802.11 networks, a "virtual port" is used -between each associated station and the AP. IEEE 802.11 specifies -minimal authentication mechanism for stations, whereas IEEE 802.1X -introduces a extensible mechanism for authenticating and authorizing -users. - -IEEE 802.1X uses elements called Supplicant, Authenticator, Port -Access Entity, and Authentication Server. Supplicant is a component in -a station and it performs the authentication with the Authentication -Server. An access point includes an Authenticator that relays the packets -between a Supplicant and an Authentication Server. In addition, it has a -Port Access Entity (PAE) with Authenticator functionality for -controlling the virtual port authorization, i.e., whether to accept -packets from or to the station. - -IEEE 802.1X uses Extensible Authentication Protocol (EAP). The frames -between a Supplicant and an Authenticator are sent using EAP over LAN -(EAPOL) and the Authenticator relays these frames to the Authentication -Server (and similarly, relays the messages from the Authentication -Server to the Supplicant). The Authentication Server can be colocated with the -Authenticator, in which case there is no need for additional protocol -for EAP frame transmission. However, a more common configuration is to -use an external Authentication Server and encapsulate EAP frame in the -frames used by that server. RADIUS is suitable for this, but IEEE -802.1X would also allow other mechanisms. - -Host AP driver includes PAE functionality in the kernel driver. It -is a relatively simple mechanism for denying normal frames going to -or coming from an unauthorized port. PAE allows IEEE 802.1X related -frames to be passed between the Supplicant and the Authenticator even -on an unauthorized port. - -User space daemon, hostapd, includes Authenticator functionality. It -receives 802.1X (EAPOL) frames from the Supplicant using the wlan#ap -device that is also used with IEEE 802.11 management frames. The -frames to the Supplicant are sent using the same device. - -The normal configuration of the Authenticator would use an external -Authentication Server. hostapd supports RADIUS encapsulation of EAP -packets, so the Authentication Server should be a RADIUS server, like -FreeRADIUS (http://www.freeradius.org/). The Authenticator in hostapd -relays the frames between the Supplicant and the Authentication -Server. It also controls the PAE functionality in the kernel driver by -controlling virtual port authorization, i.e., station-AP -connection, based on the IEEE 802.1X state. - -When a station would like to use the services of an access point, it -will first perform IEEE 802.11 authentication. This is normally done -with open systems authentication, so there is no security. After -this, IEEE 802.11 association is performed. If IEEE 802.1X is -configured to be used, the virtual port for the station is set in -Unauthorized state and only IEEE 802.1X frames are accepted at this -point. The Authenticator will then ask the Supplicant to authenticate -with the Authentication Server. After this is completed successfully, -the virtual port is set to Authorized state and frames from and to the -station are accepted. - -Host AP configuration for IEEE 802.1X -------------------------------------- - -The user space daemon has its own configuration file that can be used to -define AP options. Distribution package contains an example -configuration file (hostapd/hostapd.conf) that can be used as a basis -for configuration. It includes examples of all supported configuration -options and short description of each option. hostapd should be started -with full path to the configuration file as the command line argument, -e.g., './hostapd /etc/hostapd.conf'. If you have more that one wireless -LAN card, you can use one hostapd process for multiple interfaces by -giving a list of configuration files (one per interface) in the command -line. - -hostapd includes a minimal co-located IEEE 802.1X server which can be -used to test IEEE 802.1X authentication. However, it should not be -used in normal use since it does not provide any security. This can be -configured by setting ieee8021x and minimal_eap options in the -configuration file. - -An external Authentication Server (RADIUS) is configured with -auth_server_{addr,port,shared_secret} options. In addition, -ieee8021x and own_ip_addr must be set for this mode. With such -configuration, the co-located Authentication Server is not used and EAP -frames will be relayed using EAPOL between the Supplicant and the -Authenticator and RADIUS encapsulation between the Authenticator and -the Authentication Server. Other than this, the functionality is similar -to the case with the co-located Authentication Server. - -Authentication Server and Supplicant ------------------------------------- - -Any RADIUS server supporting EAP should be usable as an IEEE 802.1X -Authentication Server with hostapd Authenticator. FreeRADIUS -(http://www.freeradius.org/) has been successfully tested with hostapd -Authenticator and both Xsupplicant (http://www.open1x.org) and Windows -XP Supplicants. EAP/TLS was used with Xsupplicant and -EAP/MD5-Challenge with Windows XP. - -http://www.missl.cs.umd.edu/wireless/eaptls/ has useful information -about using EAP/TLS with FreeRADIUS and Xsupplicant (just replace -Cisco access point with Host AP driver, hostapd daemon, and a Prism2 -card ;-). http://www.freeradius.org/doc/EAP-MD5.html has information -about using EAP/MD5 with FreeRADIUS, including instructions for WinXP -configuration. http://www.denobula.com/EAPTLS.pdf has a HOWTO on -EAP/TLS use with WinXP Supplicant. - -Automatic WEP key configuration -------------------------------- - -EAP/TLS generates a session key that can be used to send WEP keys from -an AP to authenticated stations. The Authenticator in hostapd can be -configured to automatically select a random default/broadcast key -(shared by all authenticated stations) with wep_key_len_broadcast -option (5 for 40-bit WEP or 13 for 104-bit WEP). In addition, -wep_key_len_unicast option can be used to configure individual unicast -keys for stations. This requires support for individual keys in the -station driver. - -WEP keys can be automatically updated by configuring rekeying. This -will improve security of the network since same WEP key will only be -used for a limited period of time. wep_rekey_period option sets the -interval for rekeying in seconds. - - -WPA/WPA2 -======== - -Features --------- - -Supported WPA/IEEE 802.11i features: -- WPA-PSK ("WPA-Personal") -- WPA with EAP (e.g., with RADIUS authentication server) ("WPA-Enterprise") -- key management for CCMP, TKIP, WEP104, WEP40 -- RSN/WPA2 (IEEE 802.11i), including PMKSA caching and pre-authentication - -WPA ---- - -The original security mechanism of IEEE 802.11 standard was not -designed to be strong and has proved 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 this amendment is likely -to be 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). - -Some wireless LAN vendors are already providing support for CCMP in -their WPA products. There is no "official" interoperability -certification for CCMP and/or mixed modes using both TKIP and CCMP, so -some interoperability issues can be expected even though many -combinations seem to be working with equipment from different vendors. -Testing for WPA2 is likely to start during the second half of 2004. - -hostapd configuration for WPA/WPA2 ----------------------------------- - -TODO - -# Enable WPA. Setting this variable configures the AP to require WPA (either -# WPA-PSK or WPA-RADIUS/EAP based on other configuration). For WPA-PSK, either -# wpa_psk or wpa_passphrase must be set and wpa_key_mgmt must include WPA-PSK. -# For WPA-RADIUS/EAP, ieee8021x must be set (but without dynamic WEP keys), -# RADIUS authentication server must be configured, and WPA-EAP must be included -# in wpa_key_mgmt. -# This field is a bit field that can be used to enable WPA (IEEE 802.11i/D3.0) -# and/or WPA2 (full IEEE 802.11i/RSN): -# bit0 = WPA -# bit1 = IEEE 802.11i/RSN (WPA2) -#wpa=1 - -# WPA pre-shared keys for WPA-PSK. This can be either entered as a 256-bit -# secret in hex format (64 hex digits), wpa_psk, or as an ASCII passphrase -# (8..63 characters) that will be converted to PSK. This conversion uses SSID -# so the PSK changes when ASCII passphrase is used and the SSID is changed. -#wpa_psk=0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef -#wpa_passphrase=secret passphrase - -# Set of accepted key management algorithms (WPA-PSK, WPA-EAP, or both). The -# entries are separated with a space. -#wpa_key_mgmt=WPA-PSK WPA-EAP - -# Set of accepted cipher suites (encryption algorithms) for pairwise keys -# (unicast packets). This is a space separated list of algorithms: -# CCMP = AES in Counter mode with CBC-MAC [RFC 3610, IEEE 802.11i] -# TKIP = Temporal Key Integrity Protocol [IEEE 802.11i] -# Group cipher suite (encryption algorithm for broadcast and multicast frames) -# is automatically selected based on this configuration. If only CCMP is -# allowed as the pairwise cipher, group cipher will also be CCMP. Otherwise, -# TKIP will be used as the group cipher. -#wpa_pairwise=TKIP CCMP - -# Time interval for rekeying GTK (broadcast/multicast encryption keys) in -# seconds. -#wpa_group_rekey=600 - -# Time interval for rekeying GMK (master key used internally to generate GTKs -# (in seconds). -#wpa_gmk_rekey=86400 - -# Enable IEEE 802.11i/RSN/WPA2 pre-authentication. This is used to speed up -# roaming be pre-authenticating IEEE 802.1X/EAP part of the full RSN -# authentication and key handshake before actually associating with a new AP. -#rsn_preauth=1 -# -# Space separated list of interfaces from which pre-authentication frames are -# accepted (e.g., 'eth0' or 'eth0 wlan0wds0'. This list should include all -# interface that are used for connections to other APs. This could include -# wired interfaces and WDS links. The normal wireless data interface towards -# associated stations (e.g., wlan0) should not be added, since -# pre-authentication is only used with APs other than the currently associated -# one. -#rsn_preauth_interfaces=eth0 diff --git a/hostapd-0.8/hostapd/README-WPS b/hostapd-0.8/hostapd/README-WPS deleted file mode 100644 index 17988d4..0000000 --- a/hostapd-0.8/hostapd/README-WPS +++ /dev/null @@ -1,291 +0,0 @@ -hostapd and Wi-Fi Protected Setup (WPS) -======================================= - -This document describes how the WPS implementation in hostapd can be -configured and how an external component on an AP (e.g., web UI) is -used to enable enrollment of client devices. - - -Introduction to WPS -------------------- - -Wi-Fi Protected Setup (WPS) is a mechanism for easy configuration of a -wireless network. It allows automated generation of random keys (WPA -passphrase/PSK) and configuration of an access point and client -devices. WPS includes number of methods for setting up connections -with PIN method and push-button configuration (PBC) being the most -commonly deployed options. - -While WPS can enable more home networks to use encryption in the -wireless network, it should be noted that the use of the PIN and -especially PBC mechanisms for authenticating the initial key setup is -not very secure. As such, use of WPS may not be suitable for -environments that require secure network access without chance for -allowing outsiders to gain access during the setup phase. - -WPS uses following terms to describe the entities participating in the -network setup: -- access point: the WLAN access point -- Registrar: a device that control a network and can authorize - addition of new devices); this may be either in the AP ("internal - Registrar") or in an external device, e.g., a laptop, ("external - Registrar") -- Enrollee: a device that is being authorized to use the network - -It should also be noted that the AP and a client device may change -roles (i.e., AP acts as an Enrollee and client device as a Registrar) -when WPS is used to configure the access point. - - -More information about WPS is available from Wi-Fi Alliance: -http://www.wi-fi.org/wifi-protected-setup - - -hostapd implementation ----------------------- - -hostapd includes an optional WPS component that can be used as an -internal WPS Registrar to manage addition of new WPS enabled clients -to the network. In addition, WPS Enrollee functionality in hostapd can -be used to allow external WPS Registrars to configure the access -point, e.g., for initial network setup. In addition, hostapd can proxy a -WPS registration between a wireless Enrollee and an external Registrar -(e.g., Microsoft Vista or Atheros JumpStart) with UPnP. - - -hostapd configuration ---------------------- - -WPS is an optional component that needs to be enabled in hostapd build -configuration (.config). Here is an example configuration that -includes WPS support and uses madwifi driver interface: - -CONFIG_DRIVER_MADWIFI=y -CFLAGS += -I/usr/src/madwifi-0.9.3 -CONFIG_WPS=y -CONFIG_WPS2=y -CONFIG_WPS_UPNP=y - - -Following section shows an example runtime configuration -(hostapd.conf) that enables WPS: - -# Configure the driver and network interface -driver=madwifi -interface=ath0 - -# WPA2-Personal configuration for the AP -ssid=wps-test -wpa=2 -wpa_key_mgmt=WPA-PSK -wpa_pairwise=CCMP -# Default WPA passphrase for legacy (non-WPS) clients -wpa_passphrase=12345678 -# Enable random per-device PSK generation for WPS clients -# Please note that the file has to exists for hostapd to start (i.e., create an -# empty file as a starting point). -wpa_psk_file=/etc/hostapd.psk - -# Enable control interface for PBC/PIN entry -ctrl_interface=/var/run/hostapd - -# Enable internal EAP server for EAP-WSC (part of Wi-Fi Protected Setup) -eap_server=1 - -# WPS configuration (AP configured, do not allow external WPS Registrars) -wps_state=2 -ap_setup_locked=1 -# If UUID is not configured, it will be generated based on local MAC address. -uuid=87654321-9abc-def0-1234-56789abc0000 -wps_pin_requests=/var/run/hostapd.pin-req -device_name=Wireless AP -manufacturer=Company -model_name=WAP -model_number=123 -serial_number=12345 -device_type=6-0050F204-1 -os_version=01020300 -config_methods=label display push_button keypad - -# if external Registrars are allowed, UPnP support could be added: -#upnp_iface=br0 -#friendly_name=WPS Access Point - - -External operations -------------------- - -WPS requires either a device PIN code (usually, 8-digit number) or a -pushbutton event (for PBC) to allow a new WPS Enrollee to join the -network. hostapd uses the control interface as an input channel for -these events. - -The PIN value used in the commands must be processed by an UI to -remove non-digit characters and potentially, to verify the checksum -digit. "hostapd_cli wps_check_pin " can be used to do such -processing. It returns FAIL if the PIN is invalid, or FAIL-CHECKSUM if -the checksum digit is incorrect, or the processed PIN (non-digit -characters removed) if the PIN is valid. - -When a client device (WPS Enrollee) connects to hostapd (WPS -Registrar) in order to start PIN mode negotiation for WPS, an -identifier (Enrollee UUID) is sent. hostapd will need to be configured -with a device password (PIN) for this Enrollee. This is an operation -that requires user interaction (assuming there are no pre-configured -PINs on the AP for a set of Enrollee). - -The PIN request with information about the device is appended to the -wps_pin_requests file (/var/run/hostapd.pin-req in this example). In -addition, hostapd control interface event is sent as a notification of -a new device. The AP could use, e.g., a web UI for showing active -Enrollees to the user and request a PIN for an Enrollee. - -The PIN request file has one line for every Enrollee that connected to -the AP, but for which there was no PIN. Following information is -provided for each Enrollee (separated with tabulators): -- timestamp (seconds from 1970-01-01) -- Enrollee UUID -- MAC address -- Device name -- Manufacturer -- Model Name -- Model Number -- Serial Number -- Device category - -Example line in the /var/run/hostapd.pin-req file: -1200188391 53b63a98-d29e-4457-a2ed-094d7e6a669c Intel(R) Centrino(R) Intel Corporation Intel(R) Centrino(R) - - 1-0050F204-1 - -Control interface data: -WPS-PIN-NEEDED [UUID-E|MAC Address|Device Name|Manufacturer|Model Name|Model Number|Serial Number|Device Category] -For example: -<2>WPS-PIN-NEEDED [53b63a98-d29e-4457-a2ed-094d7e6a669c|02:12:34:56:78:9a|Device|Manuf|Model|Model Number|Serial Number|1-0050F204-1] - -When the user enters a PIN for a pending Enrollee, e.g., on the web -UI), hostapd needs to be notified of the new PIN over the control -interface. This can be done either by using the UNIX domain socket --based control interface directly (src/common/wpa_ctrl.c provides -helper functions for using the interface) or by calling hostapd_cli. - -Example command to add a PIN (12345670) for an Enrollee: - -hostapd_cli wps_pin 53b63a98-d29e-4457-a2ed-094d7e6a669c 12345670 - -If the UUID-E is not available (e.g., Enrollee waits for the Registrar -to be selected before connecting), wildcard UUID may be used to allow -the PIN to be used once with any UUID: - -hostapd_cli wps_pin any 12345670 - -To reduce likelihood of PIN being used with other devices or of -forgetting an active PIN available for potential attackers, expiration -time in seconds can be set for the new PIN (value 0 indicates no -expiration): - -hostapd_cli wps_pin any 12345670 300 - -If the MAC address of the enrollee is known, it should be configured -to allow the AP to advertise list of authorized enrollees: - -hostapd_cli wps_pin 53b63a98-d29e-4457-a2ed-094d7e6a669c \ - 12345670 300 00:11:22:33:44:55 - - -After this, the Enrollee can connect to the AP again and complete WPS -negotiation. At that point, a new, random WPA PSK is generated for the -client device and the client can then use that key to connect to the -AP to access the network. - - -If the AP includes a pushbutton, WPS PBC mode can be used. It is -enabled by pushing a button on both the AP and the client at about the -same time (2 minute window). hostapd needs to be notified about the AP -button pushed event over the control interface, e.g., by calling -hostapd_cli: - -hostapd_cli wps_pbc - -At this point, the client has two minutes to complete WPS negotiation -which will generate a new WPA PSK in the same way as the PIN method -described above. - - -When an external Registrar is used, the AP can act as an Enrollee and -use its AP PIN. A static AP PIN (e.g., one one a label in the AP -device) can be configured in hostapd.conf (ap_pin parameter). A more -secure option is to use hostapd_cli wps_ap_pin command to enable the -AP PIN only based on user action (and even better security by using a -random AP PIN for each session, i.e., by using "wps_ap_pin random" -command with a timeout value). Following commands are available for -managing the dynamic AP PIN operations: - -hostapd_cli wps_ap_pin disable -- disable AP PIN (i.e., do not allow external Registrars to use it to - learn the current AP settings or to reconfigure the AP) - -hostapd_cli wps_ap_pin random [timeout] -- generate a random AP PIN and enable it -- if the optional timeout parameter is given, the AP PIN will be enabled - for the specified number of seconds - -hostapd_cli wps_ap_pin get -- fetch the current AP PIN - -hostapd_cli wps_ap_pin set [timeout] -- set the AP PIN and enable it -- if the optional timeout parameter is given, the AP PIN will be enabled - for the specified number of seconds - -hostapd_cli get_config -- display the current configuration - -hostapd_cli wps_config -examples: - hostapd_cli wps_config testing WPA2PSK CCMP 12345678 - hostapd_cli wps_config "no security" OPEN NONE "" - - must be one of the following: OPEN WPAPSK WPA2PSK - must be one of the following: NONE WEP TKIP CCMP - - -Credential generation and configuration changes ------------------------------------------------ - -By default, hostapd generates credentials for Enrollees and processing -AP configuration updates internally. However, it is possible to -control these operations from external programs, if desired. - -The internal credential generation can be disabled with -skip_cred_build=1 option in the configuration. extra_cred option will -then need to be used to provide pre-configured Credential attribute(s) -for hostapd to use. The exact data from this binary file will be sent, -i.e., it will have to include valid WPS attributes. extra_cred can -also be used to add additional networks if the Registrar is used to -configure credentials for multiple networks. - -Processing of received configuration updates can be disabled with -wps_cred_processing=1 option. When this is used, an external program -is responsible for creating hostapd configuration files and processing -configuration updates based on messages received from hostapd over -control interface. This will also include the initial configuration on -first successful registration if the AP is initially set in -unconfigured state. - -Following control interface messages are sent out for external programs: - -WPS-REG-SUCCESS -For example: -<2>WPS-REG-SUCCESS 02:66:a0:ee:17:27 2b7093f1-d6fb-5108-adbb-bea66bb87333 - -This can be used to trigger change from unconfigured to configured -state (random configuration based on the first successful WPS -registration). In addition, this can be used to update AP UI about the -status of WPS registration progress. - - -WPS-NEW-AP-SETTINGS -For example: -<2>WPS-NEW-AP-SETTINGS 10260001011045000c6a6b6d2d7770732d74657374100300020020100f00020008102700403065346230343536633236366665306433396164313535346131663462663731323433376163666462376633393965353466316631623032306164343438623510200006024231cede15101e000844 - -This can be used to update the externally stored AP configuration and -then update hostapd configuration (followed by restarting of hostapd). diff --git a/hostapd-0.8/hostapd/config_file.c b/hostapd-0.8/hostapd/config_file.c deleted file mode 100644 index 11c8bf0..0000000 --- a/hostapd-0.8/hostapd/config_file.c +++ /dev/null @@ -1,2119 +0,0 @@ -/* - * hostapd / Configuration file parser - * Copyright (c) 2003-2009, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#include "utils/includes.h" -#ifndef CONFIG_NATIVE_WINDOWS -#include -#endif /* CONFIG_NATIVE_WINDOWS */ - -#include "utils/common.h" -#include "utils/uuid.h" -#include "common/ieee802_11_defs.h" -#include "drivers/driver.h" -#include "eap_server/eap.h" -#include "radius/radius_client.h" -#include "ap/wpa_auth.h" -#include "ap/ap_config.h" -#include "config_file.h" - - -extern struct wpa_driver_ops *wpa_drivers[]; - - -#ifndef CONFIG_NO_VLAN -static int hostapd_config_read_vlan_file(struct hostapd_bss_config *bss, - const char *fname) -{ - FILE *f; - char buf[128], *pos, *pos2; - int line = 0, vlan_id; - struct hostapd_vlan *vlan; - - f = fopen(fname, "r"); - if (!f) { - wpa_printf(MSG_ERROR, "VLAN file '%s' not readable.", fname); - return -1; - } - - while (fgets(buf, sizeof(buf), f)) { - line++; - - if (buf[0] == '#') - continue; - pos = buf; - while (*pos != '\0') { - if (*pos == '\n') { - *pos = '\0'; - break; - } - pos++; - } - if (buf[0] == '\0') - continue; - - if (buf[0] == '*') { - vlan_id = VLAN_ID_WILDCARD; - pos = buf + 1; - } else { - vlan_id = strtol(buf, &pos, 10); - if (buf == pos || vlan_id < 1 || - vlan_id > MAX_VLAN_ID) { - wpa_printf(MSG_ERROR, "Invalid VLAN ID at " - "line %d in '%s'", line, fname); - fclose(f); - return -1; - } - } - - while (*pos == ' ' || *pos == '\t') - pos++; - pos2 = pos; - while (*pos2 != ' ' && *pos2 != '\t' && *pos2 != '\0') - pos2++; - *pos2 = '\0'; - if (*pos == '\0' || os_strlen(pos) > IFNAMSIZ) { - wpa_printf(MSG_ERROR, "Invalid VLAN ifname at line %d " - "in '%s'", line, fname); - fclose(f); - return -1; - } - - vlan = os_malloc(sizeof(*vlan)); - if (vlan == NULL) { - wpa_printf(MSG_ERROR, "Out of memory while reading " - "VLAN interfaces from '%s'", fname); - fclose(f); - return -1; - } - - os_memset(vlan, 0, sizeof(*vlan)); - vlan->vlan_id = vlan_id; - os_strlcpy(vlan->ifname, pos, sizeof(vlan->ifname)); - if (bss->vlan_tail) - bss->vlan_tail->next = vlan; - else - bss->vlan = vlan; - bss->vlan_tail = vlan; - } - - fclose(f); - - return 0; -} -#endif /* CONFIG_NO_VLAN */ - - -static int hostapd_acl_comp(const void *a, const void *b) -{ - const struct mac_acl_entry *aa = a; - const struct mac_acl_entry *bb = b; - return os_memcmp(aa->addr, bb->addr, sizeof(macaddr)); -} - - -static int hostapd_config_read_maclist(const char *fname, - struct mac_acl_entry **acl, int *num) -{ - FILE *f; - char buf[128], *pos; - int line = 0; - u8 addr[ETH_ALEN]; - struct mac_acl_entry *newacl; - int vlan_id; - - if (!fname) - return 0; - - f = fopen(fname, "r"); - if (!f) { - wpa_printf(MSG_ERROR, "MAC list file '%s' not found.", fname); - return -1; - } - - while (fgets(buf, sizeof(buf), f)) { - line++; - - if (buf[0] == '#') - continue; - pos = buf; - while (*pos != '\0') { - if (*pos == '\n') { - *pos = '\0'; - break; - } - pos++; - } - if (buf[0] == '\0') - continue; - - if (hwaddr_aton(buf, addr)) { - wpa_printf(MSG_ERROR, "Invalid MAC address '%s' at " - "line %d in '%s'", buf, line, fname); - fclose(f); - return -1; - } - - vlan_id = 0; - pos = buf; - while (*pos != '\0' && *pos != ' ' && *pos != '\t') - pos++; - while (*pos == ' ' || *pos == '\t') - pos++; - if (*pos != '\0') - vlan_id = atoi(pos); - - newacl = os_realloc(*acl, (*num + 1) * sizeof(**acl)); - if (newacl == NULL) { - wpa_printf(MSG_ERROR, "MAC list reallocation failed"); - fclose(f); - return -1; - } - - *acl = newacl; - os_memcpy((*acl)[*num].addr, addr, ETH_ALEN); - (*acl)[*num].vlan_id = vlan_id; - (*num)++; - } - - fclose(f); - - qsort(*acl, *num, sizeof(**acl), hostapd_acl_comp); - - return 0; -} - - -#ifdef EAP_SERVER -static int hostapd_config_read_eap_user(const char *fname, - struct hostapd_bss_config *conf) -{ - FILE *f; - char buf[512], *pos, *start, *pos2; - int line = 0, ret = 0, num_methods; - struct hostapd_eap_user *user, *tail = NULL; - - if (!fname) - return 0; - - f = fopen(fname, "r"); - if (!f) { - wpa_printf(MSG_ERROR, "EAP user file '%s' not found.", fname); - return -1; - } - - /* Lines: "user" METHOD,METHOD2 "password" (password optional) */ - while (fgets(buf, sizeof(buf), f)) { - line++; - - if (buf[0] == '#') - continue; - pos = buf; - while (*pos != '\0') { - if (*pos == '\n') { - *pos = '\0'; - break; - } - pos++; - } - if (buf[0] == '\0') - continue; - - user = NULL; - - if (buf[0] != '"' && buf[0] != '*') { - wpa_printf(MSG_ERROR, "Invalid EAP identity (no \" in " - "start) on line %d in '%s'", line, fname); - goto failed; - } - - user = os_zalloc(sizeof(*user)); - if (user == NULL) { - wpa_printf(MSG_ERROR, "EAP user allocation failed"); - goto failed; - } - user->force_version = -1; - - if (buf[0] == '*') { - pos = buf; - } else { - pos = buf + 1; - start = pos; - while (*pos != '"' && *pos != '\0') - pos++; - if (*pos == '\0') { - wpa_printf(MSG_ERROR, "Invalid EAP identity " - "(no \" in end) on line %d in '%s'", - line, fname); - goto failed; - } - - user->identity = os_malloc(pos - start); - if (user->identity == NULL) { - wpa_printf(MSG_ERROR, "Failed to allocate " - "memory for EAP identity"); - goto failed; - } - os_memcpy(user->identity, start, pos - start); - user->identity_len = pos - start; - - if (pos[0] == '"' && pos[1] == '*') { - user->wildcard_prefix = 1; - pos++; - } - } - pos++; - while (*pos == ' ' || *pos == '\t') - pos++; - - if (*pos == '\0') { - wpa_printf(MSG_ERROR, "No EAP method on line %d in " - "'%s'", line, fname); - goto failed; - } - - start = pos; - while (*pos != ' ' && *pos != '\t' && *pos != '\0') - pos++; - if (*pos == '\0') { - pos = NULL; - } else { - *pos = '\0'; - pos++; - } - num_methods = 0; - while (*start) { - char *pos3 = os_strchr(start, ','); - if (pos3) { - *pos3++ = '\0'; - } - user->methods[num_methods].method = - eap_server_get_type( - start, - &user->methods[num_methods].vendor); - if (user->methods[num_methods].vendor == - EAP_VENDOR_IETF && - user->methods[num_methods].method == EAP_TYPE_NONE) - { - if (os_strcmp(start, "TTLS-PAP") == 0) { - user->ttls_auth |= EAP_TTLS_AUTH_PAP; - goto skip_eap; - } - if (os_strcmp(start, "TTLS-CHAP") == 0) { - user->ttls_auth |= EAP_TTLS_AUTH_CHAP; - goto skip_eap; - } - if (os_strcmp(start, "TTLS-MSCHAP") == 0) { - user->ttls_auth |= - EAP_TTLS_AUTH_MSCHAP; - goto skip_eap; - } - if (os_strcmp(start, "TTLS-MSCHAPV2") == 0) { - user->ttls_auth |= - EAP_TTLS_AUTH_MSCHAPV2; - goto skip_eap; - } - wpa_printf(MSG_ERROR, "Unsupported EAP type " - "'%s' on line %d in '%s'", - start, line, fname); - goto failed; - } - - num_methods++; - if (num_methods >= EAP_USER_MAX_METHODS) - break; - skip_eap: - if (pos3 == NULL) - break; - start = pos3; - } - if (num_methods == 0 && user->ttls_auth == 0) { - wpa_printf(MSG_ERROR, "No EAP types configured on " - "line %d in '%s'", line, fname); - goto failed; - } - - if (pos == NULL) - goto done; - - while (*pos == ' ' || *pos == '\t') - pos++; - if (*pos == '\0') - goto done; - - if (os_strncmp(pos, "[ver=0]", 7) == 0) { - user->force_version = 0; - goto done; - } - - if (os_strncmp(pos, "[ver=1]", 7) == 0) { - user->force_version = 1; - goto done; - } - - if (os_strncmp(pos, "[2]", 3) == 0) { - user->phase2 = 1; - goto done; - } - - if (*pos == '"') { - pos++; - start = pos; - while (*pos != '"' && *pos != '\0') - pos++; - if (*pos == '\0') { - wpa_printf(MSG_ERROR, "Invalid EAP password " - "(no \" in end) on line %d in '%s'", - line, fname); - goto failed; - } - - user->password = os_malloc(pos - start); - if (user->password == NULL) { - wpa_printf(MSG_ERROR, "Failed to allocate " - "memory for EAP password"); - goto failed; - } - os_memcpy(user->password, start, pos - start); - user->password_len = pos - start; - - pos++; - } else if (os_strncmp(pos, "hash:", 5) == 0) { - pos += 5; - pos2 = pos; - while (*pos2 != '\0' && *pos2 != ' ' && - *pos2 != '\t' && *pos2 != '#') - pos2++; - if (pos2 - pos != 32) { - wpa_printf(MSG_ERROR, "Invalid password hash " - "on line %d in '%s'", line, fname); - goto failed; - } - user->password = os_malloc(16); - if (user->password == NULL) { - wpa_printf(MSG_ERROR, "Failed to allocate " - "memory for EAP password hash"); - goto failed; - } - if (hexstr2bin(pos, user->password, 16) < 0) { - wpa_printf(MSG_ERROR, "Invalid hash password " - "on line %d in '%s'", line, fname); - goto failed; - } - user->password_len = 16; - user->password_hash = 1; - pos = pos2; - } else { - pos2 = pos; - while (*pos2 != '\0' && *pos2 != ' ' && - *pos2 != '\t' && *pos2 != '#') - pos2++; - if ((pos2 - pos) & 1) { - wpa_printf(MSG_ERROR, "Invalid hex password " - "on line %d in '%s'", line, fname); - goto failed; - } - user->password = os_malloc((pos2 - pos) / 2); - if (user->password == NULL) { - wpa_printf(MSG_ERROR, "Failed to allocate " - "memory for EAP password"); - goto failed; - } - if (hexstr2bin(pos, user->password, - (pos2 - pos) / 2) < 0) { - wpa_printf(MSG_ERROR, "Invalid hex password " - "on line %d in '%s'", line, fname); - goto failed; - } - user->password_len = (pos2 - pos) / 2; - pos = pos2; - } - - while (*pos == ' ' || *pos == '\t') - pos++; - if (os_strncmp(pos, "[2]", 3) == 0) { - user->phase2 = 1; - } - - done: - if (tail == NULL) { - tail = conf->eap_user = user; - } else { - tail->next = user; - tail = user; - } - continue; - - failed: - if (user) { - os_free(user->password); - os_free(user->identity); - os_free(user); - } - ret = -1; - break; - } - - fclose(f); - - return ret; -} -#endif /* EAP_SERVER */ - - -#ifndef CONFIG_NO_RADIUS -static int -hostapd_config_read_radius_addr(struct hostapd_radius_server **server, - int *num_server, const char *val, int def_port, - struct hostapd_radius_server **curr_serv) -{ - struct hostapd_radius_server *nserv; - int ret; - static int server_index = 1; - - nserv = os_realloc(*server, (*num_server + 1) * sizeof(*nserv)); - if (nserv == NULL) - return -1; - - *server = nserv; - nserv = &nserv[*num_server]; - (*num_server)++; - (*curr_serv) = nserv; - - os_memset(nserv, 0, sizeof(*nserv)); - nserv->port = def_port; - ret = hostapd_parse_ip_addr(val, &nserv->addr); - nserv->index = server_index++; - - return ret; -} -#endif /* CONFIG_NO_RADIUS */ - - -static int hostapd_config_parse_key_mgmt(int line, const char *value) -{ - int val = 0, last; - char *start, *end, *buf; - - buf = os_strdup(value); - if (buf == NULL) - return -1; - start = buf; - - while (*start != '\0') { - while (*start == ' ' || *start == '\t') - start++; - if (*start == '\0') - break; - end = start; - while (*end != ' ' && *end != '\t' && *end != '\0') - end++; - last = *end == '\0'; - *end = '\0'; - if (os_strcmp(start, "WPA-PSK") == 0) - val |= WPA_KEY_MGMT_PSK; - else if (os_strcmp(start, "WPA-EAP") == 0) - val |= WPA_KEY_MGMT_IEEE8021X; -#ifdef CONFIG_IEEE80211R - else if (os_strcmp(start, "FT-PSK") == 0) - val |= WPA_KEY_MGMT_FT_PSK; - else if (os_strcmp(start, "FT-EAP") == 0) - val |= WPA_KEY_MGMT_FT_IEEE8021X; -#endif /* CONFIG_IEEE80211R */ -#ifdef CONFIG_IEEE80211W - else if (os_strcmp(start, "WPA-PSK-SHA256") == 0) - val |= WPA_KEY_MGMT_PSK_SHA256; - else if (os_strcmp(start, "WPA-EAP-SHA256") == 0) - val |= WPA_KEY_MGMT_IEEE8021X_SHA256; -#endif /* CONFIG_IEEE80211W */ - else { - wpa_printf(MSG_ERROR, "Line %d: invalid key_mgmt '%s'", - line, start); - os_free(buf); - return -1; - } - - if (last) - break; - start = end + 1; - } - - os_free(buf); - if (val == 0) { - wpa_printf(MSG_ERROR, "Line %d: no key_mgmt values " - "configured.", line); - return -1; - } - - return val; -} - - -static int hostapd_config_parse_cipher(int line, const char *value) -{ - int val = 0, last; - char *start, *end, *buf; - - buf = os_strdup(value); - if (buf == NULL) - return -1; - start = buf; - - while (*start != '\0') { - while (*start == ' ' || *start == '\t') - start++; - if (*start == '\0') - break; - end = start; - while (*end != ' ' && *end != '\t' && *end != '\0') - end++; - last = *end == '\0'; - *end = '\0'; - if (os_strcmp(start, "CCMP") == 0) - val |= WPA_CIPHER_CCMP; - else if (os_strcmp(start, "TKIP") == 0) - val |= WPA_CIPHER_TKIP; - else if (os_strcmp(start, "WEP104") == 0) - val |= WPA_CIPHER_WEP104; - else if (os_strcmp(start, "WEP40") == 0) - val |= WPA_CIPHER_WEP40; - else if (os_strcmp(start, "NONE") == 0) - val |= WPA_CIPHER_NONE; - else { - wpa_printf(MSG_ERROR, "Line %d: invalid cipher '%s'.", - line, start); - os_free(buf); - return -1; - } - - if (last) - break; - start = end + 1; - } - os_free(buf); - - if (val == 0) { - wpa_printf(MSG_ERROR, "Line %d: no cipher values configured.", - line); - return -1; - } - return val; -} - - -static int hostapd_config_read_wep(struct hostapd_wep_keys *wep, int keyidx, - char *val) -{ - size_t len = os_strlen(val); - - if (keyidx < 0 || keyidx > 3 || wep->key[keyidx] != NULL) - return -1; - - if (val[0] == '"') { - if (len < 2 || val[len - 1] != '"') - return -1; - len -= 2; - wep->key[keyidx] = os_malloc(len); - if (wep->key[keyidx] == NULL) - return -1; - os_memcpy(wep->key[keyidx], val + 1, len); - wep->len[keyidx] = len; - } else { - if (len & 1) - return -1; - len /= 2; - wep->key[keyidx] = os_malloc(len); - if (wep->key[keyidx] == NULL) - return -1; - wep->len[keyidx] = len; - if (hexstr2bin(val, wep->key[keyidx], len) < 0) - return -1; - } - - wep->keys_set++; - - return 0; -} - - -static int hostapd_parse_rates(int **rate_list, char *val) -{ - int *list; - int count; - char *pos, *end; - - os_free(*rate_list); - *rate_list = NULL; - - pos = val; - count = 0; - while (*pos != '\0') { - if (*pos == ' ') - count++; - pos++; - } - - list = os_malloc(sizeof(int) * (count + 2)); - if (list == NULL) - return -1; - pos = val; - count = 0; - while (*pos != '\0') { - end = os_strchr(pos, ' '); - if (end) - *end = '\0'; - - list[count++] = atoi(pos); - if (!end) - break; - pos = end + 1; - } - list[count] = -1; - - *rate_list = list; - return 0; -} - - -static int hostapd_config_bss(struct hostapd_config *conf, const char *ifname) -{ - struct hostapd_bss_config *bss; - - if (*ifname == '\0') - return -1; - - bss = os_realloc(conf->bss, (conf->num_bss + 1) * - sizeof(struct hostapd_bss_config)); - if (bss == NULL) { - wpa_printf(MSG_ERROR, "Failed to allocate memory for " - "multi-BSS entry"); - return -1; - } - conf->bss = bss; - - bss = &(conf->bss[conf->num_bss]); - os_memset(bss, 0, sizeof(*bss)); - bss->radius = os_zalloc(sizeof(*bss->radius)); - if (bss->radius == NULL) { - wpa_printf(MSG_ERROR, "Failed to allocate memory for " - "multi-BSS RADIUS data"); - return -1; - } - - conf->num_bss++; - conf->last_bss = bss; - - hostapd_config_defaults_bss(bss); - os_strlcpy(bss->iface, ifname, sizeof(bss->iface)); - os_memcpy(bss->ssid.vlan, bss->iface, IFNAMSIZ + 1); - - return 0; -} - - -/* convert floats with one decimal place to value*10 int, i.e., - * "1.5" will return 15 */ -static int hostapd_config_read_int10(const char *value) -{ - int i, d; - char *pos; - - i = atoi(value); - pos = os_strchr(value, '.'); - d = 0; - if (pos) { - pos++; - if (*pos >= '0' && *pos <= '9') - d = *pos - '0'; - } - - return i * 10 + d; -} - - -static int valid_cw(int cw) -{ - return (cw == 1 || cw == 3 || cw == 7 || cw == 15 || cw == 31 || - cw == 63 || cw == 127 || cw == 255 || cw == 511 || cw == 1023); -} - - -enum { - IEEE80211_TX_QUEUE_DATA0 = 0, /* used for EDCA AC_VO data */ - IEEE80211_TX_QUEUE_DATA1 = 1, /* used for EDCA AC_VI data */ - IEEE80211_TX_QUEUE_DATA2 = 2, /* used for EDCA AC_BE data */ - IEEE80211_TX_QUEUE_DATA3 = 3 /* used for EDCA AC_BK data */ -}; - -static int hostapd_config_tx_queue(struct hostapd_config *conf, char *name, - char *val) -{ - int num; - char *pos; - struct hostapd_tx_queue_params *queue; - - /* skip 'tx_queue_' prefix */ - pos = name + 9; - if (os_strncmp(pos, "data", 4) == 0 && - pos[4] >= '0' && pos[4] <= '9' && pos[5] == '_') { - num = pos[4] - '0'; - pos += 6; - } else if (os_strncmp(pos, "after_beacon_", 13) == 0 || - os_strncmp(pos, "beacon_", 7) == 0) { - wpa_printf(MSG_INFO, "DEPRECATED: '%s' not used", name); - return 0; - } else { - wpa_printf(MSG_ERROR, "Unknown tx_queue name '%s'", pos); - return -1; - } - - if (num >= NUM_TX_QUEUES) { - /* for backwards compatibility, do not trigger failure */ - wpa_printf(MSG_INFO, "DEPRECATED: '%s' not used", name); - return 0; - } - - queue = &conf->tx_queue[num]; - - if (os_strcmp(pos, "aifs") == 0) { - queue->aifs = atoi(val); - if (queue->aifs < 0 || queue->aifs > 255) { - wpa_printf(MSG_ERROR, "Invalid AIFS value %d", - queue->aifs); - return -1; - } - } else if (os_strcmp(pos, "cwmin") == 0) { - queue->cwmin = atoi(val); - if (!valid_cw(queue->cwmin)) { - wpa_printf(MSG_ERROR, "Invalid cwMin value %d", - queue->cwmin); - return -1; - } - } else if (os_strcmp(pos, "cwmax") == 0) { - queue->cwmax = atoi(val); - if (!valid_cw(queue->cwmax)) { - wpa_printf(MSG_ERROR, "Invalid cwMax value %d", - queue->cwmax); - return -1; - } - } else if (os_strcmp(pos, "burst") == 0) { - queue->burst = hostapd_config_read_int10(val); - } else { - wpa_printf(MSG_ERROR, "Unknown tx_queue field '%s'", pos); - return -1; - } - - return 0; -} - - -static int hostapd_config_wmm_ac(struct hostapd_config *conf, char *name, - char *val) -{ - int num, v; - char *pos; - struct hostapd_wmm_ac_params *ac; - - /* skip 'wme_ac_' or 'wmm_ac_' prefix */ - pos = name + 7; - if (os_strncmp(pos, "be_", 3) == 0) { - num = 0; - pos += 3; - } else if (os_strncmp(pos, "bk_", 3) == 0) { - num = 1; - pos += 3; - } else if (os_strncmp(pos, "vi_", 3) == 0) { - num = 2; - pos += 3; - } else if (os_strncmp(pos, "vo_", 3) == 0) { - num = 3; - pos += 3; - } else { - wpa_printf(MSG_ERROR, "Unknown WMM name '%s'", pos); - return -1; - } - - ac = &conf->wmm_ac_params[num]; - - if (os_strcmp(pos, "aifs") == 0) { - v = atoi(val); - if (v < 1 || v > 255) { - wpa_printf(MSG_ERROR, "Invalid AIFS value %d", v); - return -1; - } - ac->aifs = v; - } else if (os_strcmp(pos, "cwmin") == 0) { - v = atoi(val); - if (v < 0 || v > 12) { - wpa_printf(MSG_ERROR, "Invalid cwMin value %d", v); - return -1; - } - ac->cwmin = v; - } else if (os_strcmp(pos, "cwmax") == 0) { - v = atoi(val); - if (v < 0 || v > 12) { - wpa_printf(MSG_ERROR, "Invalid cwMax value %d", v); - return -1; - } - ac->cwmax = v; - } else if (os_strcmp(pos, "txop_limit") == 0) { - v = atoi(val); - if (v < 0 || v > 0xffff) { - wpa_printf(MSG_ERROR, "Invalid txop value %d", v); - return -1; - } - ac->txop_limit = v; - } else if (os_strcmp(pos, "acm") == 0) { - v = atoi(val); - if (v < 0 || v > 1) { - wpa_printf(MSG_ERROR, "Invalid acm value %d", v); - return -1; - } - ac->admission_control_mandatory = v; - } else { - wpa_printf(MSG_ERROR, "Unknown wmm_ac_ field '%s'", pos); - return -1; - } - - return 0; -} - - -#ifdef CONFIG_IEEE80211R -static int add_r0kh(struct hostapd_bss_config *bss, char *value) -{ - struct ft_remote_r0kh *r0kh; - char *pos, *next; - - r0kh = os_zalloc(sizeof(*r0kh)); - if (r0kh == NULL) - return -1; - - /* 02:01:02:03:04:05 a.example.com 000102030405060708090a0b0c0d0e0f */ - pos = value; - next = os_strchr(pos, ' '); - if (next) - *next++ = '\0'; - if (next == NULL || hwaddr_aton(pos, r0kh->addr)) { - wpa_printf(MSG_ERROR, "Invalid R0KH MAC address: '%s'", pos); - os_free(r0kh); - return -1; - } - - pos = next; - next = os_strchr(pos, ' '); - if (next) - *next++ = '\0'; - if (next == NULL || next - pos > FT_R0KH_ID_MAX_LEN) { - wpa_printf(MSG_ERROR, "Invalid R0KH-ID: '%s'", pos); - os_free(r0kh); - return -1; - } - r0kh->id_len = next - pos - 1; - os_memcpy(r0kh->id, pos, r0kh->id_len); - - pos = next; - if (hexstr2bin(pos, r0kh->key, sizeof(r0kh->key))) { - wpa_printf(MSG_ERROR, "Invalid R0KH key: '%s'", pos); - os_free(r0kh); - return -1; - } - - r0kh->next = bss->r0kh_list; - bss->r0kh_list = r0kh; - - return 0; -} - - -static int add_r1kh(struct hostapd_bss_config *bss, char *value) -{ - struct ft_remote_r1kh *r1kh; - char *pos, *next; - - r1kh = os_zalloc(sizeof(*r1kh)); - if (r1kh == NULL) - return -1; - - /* 02:01:02:03:04:05 02:01:02:03:04:05 - * 000102030405060708090a0b0c0d0e0f */ - pos = value; - next = os_strchr(pos, ' '); - if (next) - *next++ = '\0'; - if (next == NULL || hwaddr_aton(pos, r1kh->addr)) { - wpa_printf(MSG_ERROR, "Invalid R1KH MAC address: '%s'", pos); - os_free(r1kh); - return -1; - } - - pos = next; - next = os_strchr(pos, ' '); - if (next) - *next++ = '\0'; - if (next == NULL || hwaddr_aton(pos, r1kh->id)) { - wpa_printf(MSG_ERROR, "Invalid R1KH-ID: '%s'", pos); - os_free(r1kh); - return -1; - } - - pos = next; - if (hexstr2bin(pos, r1kh->key, sizeof(r1kh->key))) { - wpa_printf(MSG_ERROR, "Invalid R1KH key: '%s'", pos); - os_free(r1kh); - return -1; - } - - r1kh->next = bss->r1kh_list; - bss->r1kh_list = r1kh; - - return 0; -} -#endif /* CONFIG_IEEE80211R */ - - -#ifdef CONFIG_IEEE80211N -static int hostapd_config_ht_capab(struct hostapd_config *conf, - const char *capab) -{ - if (os_strstr(capab, "[LDPC]")) - conf->ht_capab |= HT_CAP_INFO_LDPC_CODING_CAP; - if (os_strstr(capab, "[HT40-]")) { - conf->ht_capab |= HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET; - conf->secondary_channel = -1; - } - if (os_strstr(capab, "[HT40+]")) { - conf->ht_capab |= HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET; - conf->secondary_channel = 1; - } - if (os_strstr(capab, "[SMPS-STATIC]")) { - conf->ht_capab &= ~HT_CAP_INFO_SMPS_MASK; - conf->ht_capab |= HT_CAP_INFO_SMPS_STATIC; - } - if (os_strstr(capab, "[SMPS-DYNAMIC]")) { - conf->ht_capab &= ~HT_CAP_INFO_SMPS_MASK; - conf->ht_capab |= HT_CAP_INFO_SMPS_DYNAMIC; - } - if (os_strstr(capab, "[GF]")) - conf->ht_capab |= HT_CAP_INFO_GREEN_FIELD; - if (os_strstr(capab, "[SHORT-GI-20]")) - conf->ht_capab |= HT_CAP_INFO_SHORT_GI20MHZ; - if (os_strstr(capab, "[SHORT-GI-40]")) - conf->ht_capab |= HT_CAP_INFO_SHORT_GI40MHZ; - if (os_strstr(capab, "[TX-STBC]")) - conf->ht_capab |= HT_CAP_INFO_TX_STBC; - if (os_strstr(capab, "[RX-STBC1]")) { - conf->ht_capab &= ~HT_CAP_INFO_RX_STBC_MASK; - conf->ht_capab |= HT_CAP_INFO_RX_STBC_1; - } - if (os_strstr(capab, "[RX-STBC12]")) { - conf->ht_capab &= ~HT_CAP_INFO_RX_STBC_MASK; - conf->ht_capab |= HT_CAP_INFO_RX_STBC_12; - } - if (os_strstr(capab, "[RX-STBC123]")) { - conf->ht_capab &= ~HT_CAP_INFO_RX_STBC_MASK; - conf->ht_capab |= HT_CAP_INFO_RX_STBC_123; - } - if (os_strstr(capab, "[DELAYED-BA]")) - conf->ht_capab |= HT_CAP_INFO_DELAYED_BA; - if (os_strstr(capab, "[MAX-AMSDU-7935]")) - conf->ht_capab |= HT_CAP_INFO_MAX_AMSDU_SIZE; - if (os_strstr(capab, "[DSSS_CCK-40]")) - conf->ht_capab |= HT_CAP_INFO_DSSS_CCK40MHZ; - if (os_strstr(capab, "[PSMP]")) - conf->ht_capab |= HT_CAP_INFO_PSMP_SUPP; - if (os_strstr(capab, "[LSIG-TXOP-PROT]")) - conf->ht_capab |= HT_CAP_INFO_LSIG_TXOP_PROTECT_SUPPORT; - - return 0; -} -#endif /* CONFIG_IEEE80211N */ - - -static int hostapd_config_check_bss(struct hostapd_bss_config *bss, - struct hostapd_config *conf) -{ - if (bss->ieee802_1x && !bss->eap_server && - !bss->radius->auth_servers) { - wpa_printf(MSG_ERROR, "Invalid IEEE 802.1X configuration (no " - "EAP authenticator configured)."); - return -1; - } - - if (bss->wpa && (bss->wpa_key_mgmt & WPA_KEY_MGMT_PSK) && - bss->ssid.wpa_psk == NULL && bss->ssid.wpa_passphrase == NULL && - bss->ssid.wpa_psk_file == NULL) { - wpa_printf(MSG_ERROR, "WPA-PSK enabled, but PSK or passphrase " - "is not configured."); - return -1; - } - - if (hostapd_mac_comp_empty(bss->bssid) != 0) { - size_t i; - - for (i = 0; i < conf->num_bss; i++) { - if ((&conf->bss[i] != bss) && - (hostapd_mac_comp(conf->bss[i].bssid, - bss->bssid) == 0)) { - wpa_printf(MSG_ERROR, "Duplicate BSSID " MACSTR - " on interface '%s' and '%s'.", - MAC2STR(bss->bssid), - conf->bss[i].iface, bss->iface); - return -1; - } - } - } - -#ifdef CONFIG_IEEE80211R - if ((bss->wpa_key_mgmt & - (WPA_KEY_MGMT_FT_PSK | WPA_KEY_MGMT_FT_IEEE8021X)) && - (bss->nas_identifier == NULL || - os_strlen(bss->nas_identifier) < 1 || - os_strlen(bss->nas_identifier) > FT_R0KH_ID_MAX_LEN)) { - wpa_printf(MSG_ERROR, "FT (IEEE 802.11r) requires " - "nas_identifier to be configured as a 1..48 octet " - "string"); - return -1; - } -#endif /* CONFIG_IEEE80211R */ - -#ifdef CONFIG_IEEE80211N - if (conf->ieee80211n && - bss->ssid.security_policy == SECURITY_STATIC_WEP) { - bss->disable_11n = 1; - wpa_printf(MSG_ERROR, "HT (IEEE 802.11n) with WEP is not " - "allowed, disabling HT capabilities"); - } - - if (conf->ieee80211n && bss->wpa && - !(bss->wpa_pairwise & WPA_CIPHER_CCMP) && - !(bss->rsn_pairwise & WPA_CIPHER_CCMP)) { - bss->disable_11n = 1; - wpa_printf(MSG_ERROR, "HT (IEEE 802.11n) with WPA/WPA2 " - "requires CCMP to be enabled, disabling HT " - "capabilities"); - } -#endif /* CONFIG_IEEE80211N */ - -#ifdef CONFIG_WPS2 - if (bss->wps_state && bss->ignore_broadcast_ssid) { - wpa_printf(MSG_INFO, "WPS: ignore_broadcast_ssid " - "configuration forced WPS to be disabled"); - bss->wps_state = 0; - } - - if (bss->wps_state && bss->ssid.wep.keys_set && bss->wpa == 0) { - wpa_printf(MSG_INFO, "WPS: WEP configuration forced WPS to be " - "disabled"); - bss->wps_state = 0; - } -#endif /* CONFIG_WPS2 */ - - return 0; -} - - -static int hostapd_config_check(struct hostapd_config *conf) -{ - size_t i; - - if (conf->ieee80211d && (!conf->country[0] || !conf->country[1])) { - wpa_printf(MSG_ERROR, "Cannot enable IEEE 802.11d without " - "setting the country_code"); - return -1; - } - - for (i = 0; i < conf->num_bss; i++) { - if (hostapd_config_check_bss(&conf->bss[i], conf)) - return -1; - } - - return 0; -} - - -/** - * hostapd_config_read - Read and parse a configuration file - * @fname: Configuration file name (including path, if needed) - * Returns: Allocated configuration data structure - */ -struct hostapd_config * hostapd_config_read(const char *fname) -{ - struct hostapd_config *conf; - struct hostapd_bss_config *bss; - FILE *f; - char buf[256], *pos; - int line = 0; - int errors = 0; - int pairwise; - size_t i; - - f = fopen(fname, "r"); - if (f == NULL) { - wpa_printf(MSG_ERROR, "Could not open configuration file '%s' " - "for reading.", fname); - return NULL; - } - - conf = hostapd_config_defaults(); - if (conf == NULL) { - fclose(f); - return NULL; - } - - /* set default driver based on configuration */ - conf->driver = wpa_drivers[0]; - if (conf->driver == NULL) { - wpa_printf(MSG_ERROR, "No driver wrappers registered!"); - hostapd_config_free(conf); - fclose(f); - return NULL; - } - - bss = conf->last_bss = conf->bss; - - while (fgets(buf, sizeof(buf), f)) { - bss = conf->last_bss; - line++; - - if (buf[0] == '#') - continue; - pos = buf; - while (*pos != '\0') { - if (*pos == '\n') { - *pos = '\0'; - break; - } - pos++; - } - if (buf[0] == '\0') - continue; - - pos = os_strchr(buf, '='); - if (pos == NULL) { - wpa_printf(MSG_ERROR, "Line %d: invalid line '%s'", - line, buf); - errors++; - continue; - } - *pos = '\0'; - pos++; - - if (os_strcmp(buf, "interface") == 0) { - os_strlcpy(conf->bss[0].iface, pos, - sizeof(conf->bss[0].iface)); - } else if (os_strcmp(buf, "bridge") == 0) { - os_strlcpy(bss->bridge, pos, sizeof(bss->bridge)); - } else if (os_strcmp(buf, "wds_bridge") == 0) { - os_strlcpy(bss->wds_bridge, pos, - sizeof(bss->wds_bridge)); - } else if (os_strcmp(buf, "driver") == 0) { - int j; - /* clear to get error below if setting is invalid */ - conf->driver = NULL; - for (j = 0; wpa_drivers[j]; j++) { - if (os_strcmp(pos, wpa_drivers[j]->name) == 0) - { - conf->driver = wpa_drivers[j]; - break; - } - } - if (conf->driver == NULL) { - wpa_printf(MSG_ERROR, "Line %d: invalid/" - "unknown driver '%s'", line, pos); - errors++; - } - } else if (os_strcmp(buf, "debug") == 0) { - wpa_printf(MSG_DEBUG, "Line %d: DEPRECATED: 'debug' " - "configuration variable is not used " - "anymore", line); - } else if (os_strcmp(buf, "logger_syslog_level") == 0) { - bss->logger_syslog_level = atoi(pos); - } else if (os_strcmp(buf, "logger_stdout_level") == 0) { - bss->logger_stdout_level = atoi(pos); - } else if (os_strcmp(buf, "logger_syslog") == 0) { - bss->logger_syslog = atoi(pos); - } else if (os_strcmp(buf, "logger_stdout") == 0) { - bss->logger_stdout = atoi(pos); - } else if (os_strcmp(buf, "dump_file") == 0) { - bss->dump_log_name = os_strdup(pos); - } else if (os_strcmp(buf, "ssid") == 0) { - bss->ssid.ssid_len = os_strlen(pos); - if (bss->ssid.ssid_len > HOSTAPD_MAX_SSID_LEN || - bss->ssid.ssid_len < 1) { - wpa_printf(MSG_ERROR, "Line %d: invalid SSID " - "'%s'", line, pos); - errors++; - } else { - os_memcpy(bss->ssid.ssid, pos, - bss->ssid.ssid_len); - bss->ssid.ssid[bss->ssid.ssid_len] = '\0'; - bss->ssid.ssid_set = 1; - } - } else if (os_strcmp(buf, "macaddr_acl") == 0) { - bss->macaddr_acl = atoi(pos); - if (bss->macaddr_acl != ACCEPT_UNLESS_DENIED && - bss->macaddr_acl != DENY_UNLESS_ACCEPTED && - bss->macaddr_acl != USE_EXTERNAL_RADIUS_AUTH) { - wpa_printf(MSG_ERROR, "Line %d: unknown " - "macaddr_acl %d", - line, bss->macaddr_acl); - } - } else if (os_strcmp(buf, "accept_mac_file") == 0) { - if (hostapd_config_read_maclist(pos, &bss->accept_mac, - &bss->num_accept_mac)) - { - wpa_printf(MSG_ERROR, "Line %d: Failed to " - "read accept_mac_file '%s'", - line, pos); - errors++; - } - } else if (os_strcmp(buf, "deny_mac_file") == 0) { - if (hostapd_config_read_maclist(pos, &bss->deny_mac, - &bss->num_deny_mac)) { - wpa_printf(MSG_ERROR, "Line %d: Failed to " - "read deny_mac_file '%s'", - line, pos); - errors++; - } - } else if (os_strcmp(buf, "wds_sta") == 0) { - bss->wds_sta = atoi(pos); - } else if (os_strcmp(buf, "ap_isolate") == 0) { - bss->isolate = atoi(pos); - } else if (os_strcmp(buf, "ap_max_inactivity") == 0) { - bss->ap_max_inactivity = atoi(pos); - } else if (os_strcmp(buf, "country_code") == 0) { - os_memcpy(conf->country, pos, 2); - /* FIX: make this configurable */ - conf->country[2] = ' '; - } else if (os_strcmp(buf, "ieee80211d") == 0) { - conf->ieee80211d = atoi(pos); - } else if (os_strcmp(buf, "ieee8021x") == 0) { - bss->ieee802_1x = atoi(pos); - } else if (os_strcmp(buf, "eapol_version") == 0) { - bss->eapol_version = atoi(pos); - if (bss->eapol_version < 1 || - bss->eapol_version > 2) { - wpa_printf(MSG_ERROR, "Line %d: invalid EAPOL " - "version (%d): '%s'.", - line, bss->eapol_version, pos); - errors++; - } else - wpa_printf(MSG_DEBUG, "eapol_version=%d", - bss->eapol_version); -#ifdef EAP_SERVER - } else if (os_strcmp(buf, "eap_authenticator") == 0) { - bss->eap_server = atoi(pos); - wpa_printf(MSG_ERROR, "Line %d: obsolete " - "eap_authenticator used; this has been " - "renamed to eap_server", line); - } else if (os_strcmp(buf, "eap_server") == 0) { - bss->eap_server = atoi(pos); - } else if (os_strcmp(buf, "eap_user_file") == 0) { - if (hostapd_config_read_eap_user(pos, bss)) - errors++; - } else if (os_strcmp(buf, "ca_cert") == 0) { - os_free(bss->ca_cert); - bss->ca_cert = os_strdup(pos); - } else if (os_strcmp(buf, "server_cert") == 0) { - os_free(bss->server_cert); - bss->server_cert = os_strdup(pos); - } else if (os_strcmp(buf, "private_key") == 0) { - os_free(bss->private_key); - bss->private_key = os_strdup(pos); - } else if (os_strcmp(buf, "private_key_passwd") == 0) { - os_free(bss->private_key_passwd); - bss->private_key_passwd = os_strdup(pos); - } else if (os_strcmp(buf, "check_crl") == 0) { - bss->check_crl = atoi(pos); - } else if (os_strcmp(buf, "dh_file") == 0) { - os_free(bss->dh_file); - bss->dh_file = os_strdup(pos); - } else if (os_strcmp(buf, "fragment_size") == 0) { - bss->fragment_size = atoi(pos); -#ifdef EAP_SERVER_FAST - } else if (os_strcmp(buf, "pac_opaque_encr_key") == 0) { - os_free(bss->pac_opaque_encr_key); - bss->pac_opaque_encr_key = os_malloc(16); - if (bss->pac_opaque_encr_key == NULL) { - wpa_printf(MSG_ERROR, "Line %d: No memory for " - "pac_opaque_encr_key", line); - errors++; - } else if (hexstr2bin(pos, bss->pac_opaque_encr_key, - 16)) { - wpa_printf(MSG_ERROR, "Line %d: Invalid " - "pac_opaque_encr_key", line); - errors++; - } - } else if (os_strcmp(buf, "eap_fast_a_id") == 0) { - size_t idlen = os_strlen(pos); - if (idlen & 1) { - wpa_printf(MSG_ERROR, "Line %d: Invalid " - "eap_fast_a_id", line); - errors++; - } else { - os_free(bss->eap_fast_a_id); - bss->eap_fast_a_id = os_malloc(idlen / 2); - if (bss->eap_fast_a_id == NULL || - hexstr2bin(pos, bss->eap_fast_a_id, - idlen / 2)) { - wpa_printf(MSG_ERROR, "Line %d: " - "Failed to parse " - "eap_fast_a_id", line); - errors++; - } else - bss->eap_fast_a_id_len = idlen / 2; - } - } else if (os_strcmp(buf, "eap_fast_a_id_info") == 0) { - os_free(bss->eap_fast_a_id_info); - bss->eap_fast_a_id_info = os_strdup(pos); - } else if (os_strcmp(buf, "eap_fast_prov") == 0) { - bss->eap_fast_prov = atoi(pos); - } else if (os_strcmp(buf, "pac_key_lifetime") == 0) { - bss->pac_key_lifetime = atoi(pos); - } else if (os_strcmp(buf, "pac_key_refresh_time") == 0) { - bss->pac_key_refresh_time = atoi(pos); -#endif /* EAP_SERVER_FAST */ -#ifdef EAP_SERVER_SIM - } else if (os_strcmp(buf, "eap_sim_db") == 0) { - os_free(bss->eap_sim_db); - bss->eap_sim_db = os_strdup(pos); - } else if (os_strcmp(buf, "eap_sim_aka_result_ind") == 0) { - bss->eap_sim_aka_result_ind = atoi(pos); -#endif /* EAP_SERVER_SIM */ -#ifdef EAP_SERVER_TNC - } else if (os_strcmp(buf, "tnc") == 0) { - bss->tnc = atoi(pos); -#endif /* EAP_SERVER_TNC */ -#ifdef EAP_SERVER_PWD - } else if (os_strcmp(buf, "pwd_group") == 0) { - bss->pwd_group = atoi(pos); -#endif /* EAP_SERVER_PWD */ -#endif /* EAP_SERVER */ - } else if (os_strcmp(buf, "eap_message") == 0) { - char *term; - bss->eap_req_id_text = os_strdup(pos); - if (bss->eap_req_id_text == NULL) { - wpa_printf(MSG_ERROR, "Line %d: Failed to " - "allocate memory for " - "eap_req_id_text", line); - errors++; - continue; - } - bss->eap_req_id_text_len = - os_strlen(bss->eap_req_id_text); - term = os_strstr(bss->eap_req_id_text, "\\0"); - if (term) { - *term++ = '\0'; - os_memmove(term, term + 1, - bss->eap_req_id_text_len - - (term - bss->eap_req_id_text) - 1); - bss->eap_req_id_text_len--; - } - } else if (os_strcmp(buf, "wep_key_len_broadcast") == 0) { - bss->default_wep_key_len = atoi(pos); - if (bss->default_wep_key_len > 13) { - wpa_printf(MSG_ERROR, "Line %d: invalid WEP " - "key len %lu (= %lu bits)", line, - (unsigned long) - bss->default_wep_key_len, - (unsigned long) - bss->default_wep_key_len * 8); - errors++; - } - } else if (os_strcmp(buf, "wep_key_len_unicast") == 0) { - bss->individual_wep_key_len = atoi(pos); - if (bss->individual_wep_key_len < 0 || - bss->individual_wep_key_len > 13) { - wpa_printf(MSG_ERROR, "Line %d: invalid WEP " - "key len %d (= %d bits)", line, - bss->individual_wep_key_len, - bss->individual_wep_key_len * 8); - errors++; - } - } else if (os_strcmp(buf, "wep_rekey_period") == 0) { - bss->wep_rekeying_period = atoi(pos); - if (bss->wep_rekeying_period < 0) { - wpa_printf(MSG_ERROR, "Line %d: invalid " - "period %d", - line, bss->wep_rekeying_period); - errors++; - } - } else if (os_strcmp(buf, "eap_reauth_period") == 0) { - bss->eap_reauth_period = atoi(pos); - if (bss->eap_reauth_period < 0) { - wpa_printf(MSG_ERROR, "Line %d: invalid " - "period %d", - line, bss->eap_reauth_period); - errors++; - } - } else if (os_strcmp(buf, "eapol_key_index_workaround") == 0) { - bss->eapol_key_index_workaround = atoi(pos); -#ifdef CONFIG_IAPP - } else if (os_strcmp(buf, "iapp_interface") == 0) { - bss->ieee802_11f = 1; - os_strlcpy(bss->iapp_iface, pos, - sizeof(bss->iapp_iface)); -#endif /* CONFIG_IAPP */ - } else if (os_strcmp(buf, "own_ip_addr") == 0) { - if (hostapd_parse_ip_addr(pos, &bss->own_ip_addr)) { - wpa_printf(MSG_ERROR, "Line %d: invalid IP " - "address '%s'", line, pos); - errors++; - } - } else if (os_strcmp(buf, "nas_identifier") == 0) { - bss->nas_identifier = os_strdup(pos); -#ifndef CONFIG_NO_RADIUS - } else if (os_strcmp(buf, "auth_server_addr") == 0) { - if (hostapd_config_read_radius_addr( - &bss->radius->auth_servers, - &bss->radius->num_auth_servers, pos, 1812, - &bss->radius->auth_server)) { - wpa_printf(MSG_ERROR, "Line %d: invalid IP " - "address '%s'", line, pos); - errors++; - } - } else if (bss->radius->auth_server && - os_strcmp(buf, "auth_server_port") == 0) { - bss->radius->auth_server->port = atoi(pos); - } else if (bss->radius->auth_server && - os_strcmp(buf, "auth_server_shared_secret") == 0) { - int len = os_strlen(pos); - if (len == 0) { - /* RFC 2865, Ch. 3 */ - wpa_printf(MSG_ERROR, "Line %d: empty shared " - "secret is not allowed.", line); - errors++; - } - bss->radius->auth_server->shared_secret = - (u8 *) os_strdup(pos); - bss->radius->auth_server->shared_secret_len = len; - } else if (os_strcmp(buf, "acct_server_addr") == 0) { - if (hostapd_config_read_radius_addr( - &bss->radius->acct_servers, - &bss->radius->num_acct_servers, pos, 1813, - &bss->radius->acct_server)) { - wpa_printf(MSG_ERROR, "Line %d: invalid IP " - "address '%s'", line, pos); - errors++; - } - } else if (bss->radius->acct_server && - os_strcmp(buf, "acct_server_port") == 0) { - bss->radius->acct_server->port = atoi(pos); - } else if (bss->radius->acct_server && - os_strcmp(buf, "acct_server_shared_secret") == 0) { - int len = os_strlen(pos); - if (len == 0) { - /* RFC 2865, Ch. 3 */ - wpa_printf(MSG_ERROR, "Line %d: empty shared " - "secret is not allowed.", line); - errors++; - } - bss->radius->acct_server->shared_secret = - (u8 *) os_strdup(pos); - bss->radius->acct_server->shared_secret_len = len; - } else if (os_strcmp(buf, "radius_retry_primary_interval") == - 0) { - bss->radius->retry_primary_interval = atoi(pos); - } else if (os_strcmp(buf, "radius_acct_interim_interval") == 0) - { - bss->acct_interim_interval = atoi(pos); -#endif /* CONFIG_NO_RADIUS */ - } else if (os_strcmp(buf, "auth_algs") == 0) { - bss->auth_algs = atoi(pos); - if (bss->auth_algs == 0) { - wpa_printf(MSG_ERROR, "Line %d: no " - "authentication algorithms allowed", - line); - errors++; - } - } else if (os_strcmp(buf, "max_num_sta") == 0) { - bss->max_num_sta = atoi(pos); - if (bss->max_num_sta < 0 || - bss->max_num_sta > MAX_STA_COUNT) { - wpa_printf(MSG_ERROR, "Line %d: Invalid " - "max_num_sta=%d; allowed range " - "0..%d", line, bss->max_num_sta, - MAX_STA_COUNT); - errors++; - } - } else if (os_strcmp(buf, "wpa") == 0) { - bss->wpa = atoi(pos); - } else if (os_strcmp(buf, "wpa_group_rekey") == 0) { - bss->wpa_group_rekey = atoi(pos); - } else if (os_strcmp(buf, "wpa_strict_rekey") == 0) { - bss->wpa_strict_rekey = atoi(pos); - } else if (os_strcmp(buf, "wpa_gmk_rekey") == 0) { - bss->wpa_gmk_rekey = atoi(pos); - } else if (os_strcmp(buf, "wpa_ptk_rekey") == 0) { - bss->wpa_ptk_rekey = atoi(pos); - } else if (os_strcmp(buf, "wpa_passphrase") == 0) { - int len = os_strlen(pos); - if (len < 8 || len > 63) { - wpa_printf(MSG_ERROR, "Line %d: invalid WPA " - "passphrase length %d (expected " - "8..63)", line, len); - errors++; - } else { - os_free(bss->ssid.wpa_passphrase); - bss->ssid.wpa_passphrase = os_strdup(pos); - } - } else if (os_strcmp(buf, "wpa_psk") == 0) { - os_free(bss->ssid.wpa_psk); - bss->ssid.wpa_psk = - os_zalloc(sizeof(struct hostapd_wpa_psk)); - if (bss->ssid.wpa_psk == NULL) - errors++; - else if (hexstr2bin(pos, bss->ssid.wpa_psk->psk, - PMK_LEN) || - pos[PMK_LEN * 2] != '\0') { - wpa_printf(MSG_ERROR, "Line %d: Invalid PSK " - "'%s'.", line, pos); - errors++; - } else { - bss->ssid.wpa_psk->group = 1; - } - } else if (os_strcmp(buf, "wpa_psk_file") == 0) { - os_free(bss->ssid.wpa_psk_file); - bss->ssid.wpa_psk_file = os_strdup(pos); - if (!bss->ssid.wpa_psk_file) { - wpa_printf(MSG_ERROR, "Line %d: allocation " - "failed", line); - errors++; - } - } else if (os_strcmp(buf, "wpa_key_mgmt") == 0) { - bss->wpa_key_mgmt = - hostapd_config_parse_key_mgmt(line, pos); - if (bss->wpa_key_mgmt == -1) - errors++; - } else if (os_strcmp(buf, "wpa_pairwise") == 0) { - bss->wpa_pairwise = - hostapd_config_parse_cipher(line, pos); - if (bss->wpa_pairwise == -1 || - bss->wpa_pairwise == 0) - errors++; - else if (bss->wpa_pairwise & - (WPA_CIPHER_NONE | WPA_CIPHER_WEP40 | - WPA_CIPHER_WEP104)) { - wpa_printf(MSG_ERROR, "Line %d: unsupported " - "pairwise cipher suite '%s'", - bss->wpa_pairwise, pos); - errors++; - } - } else if (os_strcmp(buf, "rsn_pairwise") == 0) { - bss->rsn_pairwise = - hostapd_config_parse_cipher(line, pos); - if (bss->rsn_pairwise == -1 || - bss->rsn_pairwise == 0) - errors++; - else if (bss->rsn_pairwise & - (WPA_CIPHER_NONE | WPA_CIPHER_WEP40 | - WPA_CIPHER_WEP104)) { - wpa_printf(MSG_ERROR, "Line %d: unsupported " - "pairwise cipher suite '%s'", - bss->rsn_pairwise, pos); - errors++; - } -#ifdef CONFIG_RSN_PREAUTH - } else if (os_strcmp(buf, "rsn_preauth") == 0) { - bss->rsn_preauth = atoi(pos); - } else if (os_strcmp(buf, "rsn_preauth_interfaces") == 0) { - bss->rsn_preauth_interfaces = os_strdup(pos); -#endif /* CONFIG_RSN_PREAUTH */ -#ifdef CONFIG_PEERKEY - } else if (os_strcmp(buf, "peerkey") == 0) { - bss->peerkey = atoi(pos); -#endif /* CONFIG_PEERKEY */ -#ifdef CONFIG_IEEE80211R - } else if (os_strcmp(buf, "mobility_domain") == 0) { - if (os_strlen(pos) != 2 * MOBILITY_DOMAIN_ID_LEN || - hexstr2bin(pos, bss->mobility_domain, - MOBILITY_DOMAIN_ID_LEN) != 0) { - wpa_printf(MSG_DEBUG, "Line %d: Invalid " - "mobility_domain '%s'", line, pos); - errors++; - continue; - } - } else if (os_strcmp(buf, "r1_key_holder") == 0) { - if (os_strlen(pos) != 2 * FT_R1KH_ID_LEN || - hexstr2bin(pos, bss->r1_key_holder, - FT_R1KH_ID_LEN) != 0) { - wpa_printf(MSG_DEBUG, "Line %d: Invalid " - "r1_key_holder '%s'", line, pos); - errors++; - continue; - } - } else if (os_strcmp(buf, "r0_key_lifetime") == 0) { - bss->r0_key_lifetime = atoi(pos); - } else if (os_strcmp(buf, "reassociation_deadline") == 0) { - bss->reassociation_deadline = atoi(pos); - } else if (os_strcmp(buf, "r0kh") == 0) { - if (add_r0kh(bss, pos) < 0) { - wpa_printf(MSG_DEBUG, "Line %d: Invalid " - "r0kh '%s'", line, pos); - errors++; - continue; - } - } else if (os_strcmp(buf, "r1kh") == 0) { - if (add_r1kh(bss, pos) < 0) { - wpa_printf(MSG_DEBUG, "Line %d: Invalid " - "r1kh '%s'", line, pos); - errors++; - continue; - } - } else if (os_strcmp(buf, "pmk_r1_push") == 0) { - bss->pmk_r1_push = atoi(pos); - } else if (os_strcmp(buf, "ft_over_ds") == 0) { - bss->ft_over_ds = atoi(pos); -#endif /* CONFIG_IEEE80211R */ -#ifndef CONFIG_NO_CTRL_IFACE - } else if (os_strcmp(buf, "ctrl_interface") == 0) { - os_free(bss->ctrl_interface); - bss->ctrl_interface = os_strdup(pos); - } else if (os_strcmp(buf, "ctrl_interface_group") == 0) { -#ifndef CONFIG_NATIVE_WINDOWS - struct group *grp; - char *endp; - const char *group = pos; - - grp = getgrnam(group); - if (grp) { - bss->ctrl_interface_gid = grp->gr_gid; - bss->ctrl_interface_gid_set = 1; - wpa_printf(MSG_DEBUG, "ctrl_interface_group=%d" - " (from group name '%s')", - bss->ctrl_interface_gid, group); - continue; - } - - /* Group name not found - try to parse this as gid */ - bss->ctrl_interface_gid = strtol(group, &endp, 10); - if (*group == '\0' || *endp != '\0') { - wpa_printf(MSG_DEBUG, "Line %d: Invalid group " - "'%s'", line, group); - errors++; - continue; - } - bss->ctrl_interface_gid_set = 1; - wpa_printf(MSG_DEBUG, "ctrl_interface_group=%d", - bss->ctrl_interface_gid); -#endif /* CONFIG_NATIVE_WINDOWS */ -#endif /* CONFIG_NO_CTRL_IFACE */ -#ifdef RADIUS_SERVER - } else if (os_strcmp(buf, "radius_server_clients") == 0) { - os_free(bss->radius_server_clients); - bss->radius_server_clients = os_strdup(pos); - } else if (os_strcmp(buf, "radius_server_auth_port") == 0) { - bss->radius_server_auth_port = atoi(pos); - } else if (os_strcmp(buf, "radius_server_ipv6") == 0) { - bss->radius_server_ipv6 = atoi(pos); -#endif /* RADIUS_SERVER */ - } else if (os_strcmp(buf, "test_socket") == 0) { - os_free(bss->test_socket); - bss->test_socket = os_strdup(pos); - } else if (os_strcmp(buf, "use_pae_group_addr") == 0) { - bss->use_pae_group_addr = atoi(pos); - } else if (os_strcmp(buf, "hw_mode") == 0) { - if (os_strcmp(pos, "a") == 0) - conf->hw_mode = HOSTAPD_MODE_IEEE80211A; - else if (os_strcmp(pos, "b") == 0) - conf->hw_mode = HOSTAPD_MODE_IEEE80211B; - else if (os_strcmp(pos, "g") == 0) - conf->hw_mode = HOSTAPD_MODE_IEEE80211G; - else { - wpa_printf(MSG_ERROR, "Line %d: unknown " - "hw_mode '%s'", line, pos); - errors++; - } - } else if (os_strcmp(buf, "channel") == 0) { - conf->channel = atoi(pos); - } else if (os_strcmp(buf, "beacon_int") == 0) { - int val = atoi(pos); - /* MIB defines range as 1..65535, but very small values - * cause problems with the current implementation. - * Since it is unlikely that this small numbers are - * useful in real life scenarios, do not allow beacon - * period to be set below 15 TU. */ - if (val < 15 || val > 65535) { - wpa_printf(MSG_ERROR, "Line %d: invalid " - "beacon_int %d (expected " - "15..65535)", line, val); - errors++; - } else - conf->beacon_int = val; - } else if (os_strcmp(buf, "dtim_period") == 0) { - bss->dtim_period = atoi(pos); - if (bss->dtim_period < 1 || bss->dtim_period > 255) { - wpa_printf(MSG_ERROR, "Line %d: invalid " - "dtim_period %d", - line, bss->dtim_period); - errors++; - } - } else if (os_strcmp(buf, "rts_threshold") == 0) { - conf->rts_threshold = atoi(pos); - if (conf->rts_threshold < 0 || - conf->rts_threshold > 2347) { - wpa_printf(MSG_ERROR, "Line %d: invalid " - "rts_threshold %d", - line, conf->rts_threshold); - errors++; - } - } else if (os_strcmp(buf, "fragm_threshold") == 0) { - conf->fragm_threshold = atoi(pos); - if (conf->fragm_threshold < 256 || - conf->fragm_threshold > 2346) { - wpa_printf(MSG_ERROR, "Line %d: invalid " - "fragm_threshold %d", - line, conf->fragm_threshold); - errors++; - } - } else if (os_strcmp(buf, "send_probe_response") == 0) { - int val = atoi(pos); - if (val != 0 && val != 1) { - wpa_printf(MSG_ERROR, "Line %d: invalid " - "send_probe_response %d (expected " - "0 or 1)", line, val); - } else - conf->send_probe_response = val; - } else if (os_strcmp(buf, "supported_rates") == 0) { - if (hostapd_parse_rates(&conf->supported_rates, pos)) { - wpa_printf(MSG_ERROR, "Line %d: invalid rate " - "list", line); - errors++; - } - } else if (os_strcmp(buf, "basic_rates") == 0) { - if (hostapd_parse_rates(&conf->basic_rates, pos)) { - wpa_printf(MSG_ERROR, "Line %d: invalid rate " - "list", line); - errors++; - } - } else if (os_strcmp(buf, "preamble") == 0) { - if (atoi(pos)) - conf->preamble = SHORT_PREAMBLE; - else - conf->preamble = LONG_PREAMBLE; - } else if (os_strcmp(buf, "ignore_broadcast_ssid") == 0) { - bss->ignore_broadcast_ssid = atoi(pos); - } else if (os_strcmp(buf, "wep_default_key") == 0) { - bss->ssid.wep.idx = atoi(pos); - if (bss->ssid.wep.idx > 3) { - wpa_printf(MSG_ERROR, "Invalid " - "wep_default_key index %d", - bss->ssid.wep.idx); - errors++; - } - } else if (os_strcmp(buf, "wep_key0") == 0 || - os_strcmp(buf, "wep_key1") == 0 || - os_strcmp(buf, "wep_key2") == 0 || - os_strcmp(buf, "wep_key3") == 0) { - if (hostapd_config_read_wep(&bss->ssid.wep, - buf[7] - '0', pos)) { - wpa_printf(MSG_ERROR, "Line %d: invalid WEP " - "key '%s'", line, buf); - errors++; - } -#ifndef CONFIG_NO_VLAN - } else if (os_strcmp(buf, "dynamic_vlan") == 0) { - bss->ssid.dynamic_vlan = atoi(pos); - } else if (os_strcmp(buf, "vlan_file") == 0) { - if (hostapd_config_read_vlan_file(bss, pos)) { - wpa_printf(MSG_ERROR, "Line %d: failed to " - "read VLAN file '%s'", line, pos); - errors++; - } -#ifdef CONFIG_FULL_DYNAMIC_VLAN - } else if (os_strcmp(buf, "vlan_tagged_interface") == 0) { - bss->ssid.vlan_tagged_interface = os_strdup(pos); -#endif /* CONFIG_FULL_DYNAMIC_VLAN */ -#endif /* CONFIG_NO_VLAN */ - } else if (os_strcmp(buf, "ap_table_max_size") == 0) { - conf->ap_table_max_size = atoi(pos); - } else if (os_strcmp(buf, "ap_table_expiration_time") == 0) { - conf->ap_table_expiration_time = atoi(pos); - } else if (os_strncmp(buf, "tx_queue_", 9) == 0) { - if (hostapd_config_tx_queue(conf, buf, pos)) { - wpa_printf(MSG_ERROR, "Line %d: invalid TX " - "queue item", line); - errors++; - } - } else if (os_strcmp(buf, "wme_enabled") == 0 || - os_strcmp(buf, "wmm_enabled") == 0) { - bss->wmm_enabled = atoi(pos); - } else if (os_strcmp(buf, "uapsd_advertisement_enabled") == 0) { - bss->wmm_uapsd = atoi(pos); - } else if (os_strncmp(buf, "wme_ac_", 7) == 0 || - os_strncmp(buf, "wmm_ac_", 7) == 0) { - if (hostapd_config_wmm_ac(conf, buf, pos)) { - wpa_printf(MSG_ERROR, "Line %d: invalid WMM " - "ac item", line); - errors++; - } - } else if (os_strcmp(buf, "bss") == 0) { - if (hostapd_config_bss(conf, pos)) { - wpa_printf(MSG_ERROR, "Line %d: invalid bss " - "item", line); - errors++; - } - } else if (os_strcmp(buf, "bssid") == 0) { - if (hwaddr_aton(pos, bss->bssid)) { - wpa_printf(MSG_ERROR, "Line %d: invalid bssid " - "item", line); - errors++; - } -#ifdef CONFIG_IEEE80211W - } else if (os_strcmp(buf, "ieee80211w") == 0) { - bss->ieee80211w = atoi(pos); - } else if (os_strcmp(buf, "assoc_sa_query_max_timeout") == 0) { - bss->assoc_sa_query_max_timeout = atoi(pos); - if (bss->assoc_sa_query_max_timeout == 0) { - wpa_printf(MSG_ERROR, "Line %d: invalid " - "assoc_sa_query_max_timeout", line); - errors++; - } - } else if (os_strcmp(buf, "assoc_sa_query_retry_timeout") == 0) - { - bss->assoc_sa_query_retry_timeout = atoi(pos); - if (bss->assoc_sa_query_retry_timeout == 0) { - wpa_printf(MSG_ERROR, "Line %d: invalid " - "assoc_sa_query_retry_timeout", - line); - errors++; - } -#endif /* CONFIG_IEEE80211W */ -#ifdef CONFIG_IEEE80211N - } else if (os_strcmp(buf, "ieee80211n") == 0) { - conf->ieee80211n = atoi(pos); - } else if (os_strcmp(buf, "ht_capab") == 0) { - if (hostapd_config_ht_capab(conf, pos) < 0) { - wpa_printf(MSG_ERROR, "Line %d: invalid " - "ht_capab", line); - errors++; - } - } else if (os_strcmp(buf, "require_ht") == 0) { - conf->require_ht = atoi(pos); -#endif /* CONFIG_IEEE80211N */ - } else if (os_strcmp(buf, "max_listen_interval") == 0) { - bss->max_listen_interval = atoi(pos); - } else if (os_strcmp(buf, "okc") == 0) { - bss->okc = atoi(pos); -#ifdef CONFIG_WPS - } else if (os_strcmp(buf, "wps_state") == 0) { - bss->wps_state = atoi(pos); - if (bss->wps_state < 0 || bss->wps_state > 2) { - wpa_printf(MSG_ERROR, "Line %d: invalid " - "wps_state", line); - errors++; - } - } else if (os_strcmp(buf, "ap_setup_locked") == 0) { - bss->ap_setup_locked = atoi(pos); - } else if (os_strcmp(buf, "uuid") == 0) { - if (uuid_str2bin(pos, bss->uuid)) { - wpa_printf(MSG_ERROR, "Line %d: invalid UUID", - line); - errors++; - } - } else if (os_strcmp(buf, "wps_pin_requests") == 0) { - os_free(bss->wps_pin_requests); - bss->wps_pin_requests = os_strdup(pos); - } else if (os_strcmp(buf, "device_name") == 0) { - if (os_strlen(pos) > 32) { - wpa_printf(MSG_ERROR, "Line %d: Too long " - "device_name", line); - errors++; - } - os_free(bss->device_name); - bss->device_name = os_strdup(pos); - } else if (os_strcmp(buf, "manufacturer") == 0) { - if (os_strlen(pos) > 64) { - wpa_printf(MSG_ERROR, "Line %d: Too long " - "manufacturer", line); - errors++; - } - os_free(bss->manufacturer); - bss->manufacturer = os_strdup(pos); - } else if (os_strcmp(buf, "model_name") == 0) { - if (os_strlen(pos) > 32) { - wpa_printf(MSG_ERROR, "Line %d: Too long " - "model_name", line); - errors++; - } - os_free(bss->model_name); - bss->model_name = os_strdup(pos); - } else if (os_strcmp(buf, "model_number") == 0) { - if (os_strlen(pos) > 32) { - wpa_printf(MSG_ERROR, "Line %d: Too long " - "model_number", line); - errors++; - } - os_free(bss->model_number); - bss->model_number = os_strdup(pos); - } else if (os_strcmp(buf, "serial_number") == 0) { - if (os_strlen(pos) > 32) { - wpa_printf(MSG_ERROR, "Line %d: Too long " - "serial_number", line); - errors++; - } - os_free(bss->serial_number); - bss->serial_number = os_strdup(pos); - } else if (os_strcmp(buf, "device_type") == 0) { - if (wps_dev_type_str2bin(pos, bss->device_type)) - errors++; - } else if (os_strcmp(buf, "config_methods") == 0) { - os_free(bss->config_methods); - bss->config_methods = os_strdup(pos); - } else if (os_strcmp(buf, "os_version") == 0) { - if (hexstr2bin(pos, bss->os_version, 4)) { - wpa_printf(MSG_ERROR, "Line %d: invalid " - "os_version", line); - errors++; - } - } else if (os_strcmp(buf, "ap_pin") == 0) { - os_free(bss->ap_pin); - bss->ap_pin = os_strdup(pos); - } else if (os_strcmp(buf, "skip_cred_build") == 0) { - bss->skip_cred_build = atoi(pos); - } else if (os_strcmp(buf, "extra_cred") == 0) { - os_free(bss->extra_cred); - bss->extra_cred = - (u8 *) os_readfile(pos, &bss->extra_cred_len); - if (bss->extra_cred == NULL) { - wpa_printf(MSG_ERROR, "Line %d: could not " - "read Credentials from '%s'", - line, pos); - errors++; - } - } else if (os_strcmp(buf, "wps_cred_processing") == 0) { - bss->wps_cred_processing = atoi(pos); - } else if (os_strcmp(buf, "ap_settings") == 0) { - os_free(bss->ap_settings); - bss->ap_settings = - (u8 *) os_readfile(pos, &bss->ap_settings_len); - if (bss->ap_settings == NULL) { - wpa_printf(MSG_ERROR, "Line %d: could not " - "read AP Settings from '%s'", - line, pos); - errors++; - } - } else if (os_strcmp(buf, "upnp_iface") == 0) { - bss->upnp_iface = os_strdup(pos); - } else if (os_strcmp(buf, "friendly_name") == 0) { - os_free(bss->friendly_name); - bss->friendly_name = os_strdup(pos); - } else if (os_strcmp(buf, "manufacturer_url") == 0) { - os_free(bss->manufacturer_url); - bss->manufacturer_url = os_strdup(pos); - } else if (os_strcmp(buf, "model_description") == 0) { - os_free(bss->model_description); - bss->model_description = os_strdup(pos); - } else if (os_strcmp(buf, "model_url") == 0) { - os_free(bss->model_url); - bss->model_url = os_strdup(pos); - } else if (os_strcmp(buf, "upc") == 0) { - os_free(bss->upc); - bss->upc = os_strdup(pos); -#endif /* CONFIG_WPS */ -#ifdef CONFIG_P2P_MANAGER - } else if (os_strcmp(buf, "manage_p2p") == 0) { - int manage = atoi(pos); - if (manage) - bss->p2p |= P2P_MANAGE; - else - bss->p2p &= ~P2P_MANAGE; - } else if (os_strcmp(buf, "allow_cross_connection") == 0) { - if (atoi(pos)) - bss->p2p |= P2P_ALLOW_CROSS_CONNECTION; - else - bss->p2p &= ~P2P_ALLOW_CROSS_CONNECTION; -#endif /* CONFIG_P2P_MANAGER */ - } else if (os_strcmp(buf, "disassoc_low_ack") == 0) { - bss->disassoc_low_ack = atoi(pos); - } else if (os_strcmp(buf, "tdls_prohibit") == 0) { - int val = atoi(pos); - if (val) - bss->tdls |= TDLS_PROHIBIT; - else - bss->tdls &= ~TDLS_PROHIBIT; - } else if (os_strcmp(buf, "tdls_prohibit_chan_switch") == 0) { - int val = atoi(pos); - if (val) - bss->tdls |= TDLS_PROHIBIT_CHAN_SWITCH; - else - bss->tdls &= ~TDLS_PROHIBIT_CHAN_SWITCH; -#ifdef CONFIG_RSN_TESTING - } else if (os_strcmp(buf, "rsn_testing") == 0) { - extern int rsn_testing; - rsn_testing = atoi(pos); -#endif /* CONFIG_RSN_TESTING */ - } else { - wpa_printf(MSG_ERROR, "Line %d: unknown configuration " - "item '%s'", line, buf); - errors++; - } - } - - fclose(f); - - for (i = 0; i < conf->num_bss; i++) { - bss = &conf->bss[i]; - - if (bss->individual_wep_key_len == 0) { - /* individual keys are not use; can use key idx0 for - * broadcast keys */ - bss->broadcast_key_idx_min = 0; - } - - /* Select group cipher based on the enabled pairwise cipher - * suites */ - pairwise = 0; - if (bss->wpa & 1) - pairwise |= bss->wpa_pairwise; - if (bss->wpa & 2) { - if (bss->rsn_pairwise == 0) - bss->rsn_pairwise = bss->wpa_pairwise; - pairwise |= bss->rsn_pairwise; - } - if (pairwise & WPA_CIPHER_TKIP) - bss->wpa_group = WPA_CIPHER_TKIP; - else - bss->wpa_group = WPA_CIPHER_CCMP; - - bss->radius->auth_server = bss->radius->auth_servers; - bss->radius->acct_server = bss->radius->acct_servers; - - if (bss->wpa && bss->ieee802_1x) { - bss->ssid.security_policy = SECURITY_WPA; - } else if (bss->wpa) { - bss->ssid.security_policy = SECURITY_WPA_PSK; - } else if (bss->ieee802_1x) { - bss->ssid.security_policy = SECURITY_IEEE_802_1X; - bss->ssid.wep.default_len = bss->default_wep_key_len; - } else if (bss->ssid.wep.keys_set) - bss->ssid.security_policy = SECURITY_STATIC_WEP; - else - bss->ssid.security_policy = SECURITY_PLAINTEXT; - } - - if (hostapd_config_check(conf)) - errors++; - -#ifndef WPA_IGNORE_CONFIG_ERRORS - if (errors) { - wpa_printf(MSG_ERROR, "%d errors found in configuration file " - "'%s'", errors, fname); - hostapd_config_free(conf); - conf = NULL; - } -#endif /* WPA_IGNORE_CONFIG_ERRORS */ - - return conf; -} diff --git a/hostapd-0.8/hostapd/config_file.h b/hostapd-0.8/hostapd/config_file.h deleted file mode 100644 index 7111a9a..0000000 --- a/hostapd-0.8/hostapd/config_file.h +++ /dev/null @@ -1,20 +0,0 @@ -/* - * hostapd / Configuration file parser - * Copyright (c) 2003-2009, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#ifndef CONFIG_FILE_H -#define CONFIG_FILE_H - -struct hostapd_config * hostapd_config_read(const char *fname); - -#endif /* CONFIG_FILE_H */ diff --git a/hostapd-0.8/hostapd/ctrl_iface.c b/hostapd-0.8/hostapd/ctrl_iface.c deleted file mode 100644 index 195b8a7..0000000 --- a/hostapd-0.8/hostapd/ctrl_iface.c +++ /dev/null @@ -1,1131 +0,0 @@ -/* - * hostapd / UNIX domain socket -based control interface - * Copyright (c) 2004-2010, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#include "utils/includes.h" - -#ifndef CONFIG_NATIVE_WINDOWS - -#include -#include -#include - -#include "utils/common.h" -#include "utils/eloop.h" -#include "common/version.h" -#include "common/ieee802_11_defs.h" -#include "drivers/driver.h" -#include "radius/radius_client.h" -#include "ap/hostapd.h" -#include "ap/ap_config.h" -#include "ap/ieee802_1x.h" -#include "ap/wpa_auth.h" -#include "ap/ieee802_11.h" -#include "ap/sta_info.h" -#include "ap/accounting.h" -#include "ap/wps_hostapd.h" -#include "ap/ctrl_iface_ap.h" -#include "ap/ap_drv_ops.h" -#include "wps/wps_defs.h" -#include "wps/wps.h" -#include "ctrl_iface.h" - - -struct wpa_ctrl_dst { - struct wpa_ctrl_dst *next; - struct sockaddr_un addr; - socklen_t addrlen; - int debug_level; - int errors; -}; - - -static void hostapd_ctrl_iface_send(struct hostapd_data *hapd, int level, - const char *buf, size_t len); - - -static int hostapd_ctrl_iface_attach(struct hostapd_data *hapd, - struct sockaddr_un *from, - socklen_t fromlen) -{ - struct wpa_ctrl_dst *dst; - - dst = os_zalloc(sizeof(*dst)); - if (dst == NULL) - return -1; - os_memcpy(&dst->addr, from, sizeof(struct sockaddr_un)); - dst->addrlen = fromlen; - dst->debug_level = MSG_INFO; - dst->next = hapd->ctrl_dst; - hapd->ctrl_dst = dst; - wpa_hexdump(MSG_DEBUG, "CTRL_IFACE monitor attached", - (u8 *) from->sun_path, - fromlen - offsetof(struct sockaddr_un, sun_path)); - return 0; -} - - -static int hostapd_ctrl_iface_detach(struct hostapd_data *hapd, - struct sockaddr_un *from, - socklen_t fromlen) -{ - struct wpa_ctrl_dst *dst, *prev = NULL; - - dst = hapd->ctrl_dst; - while (dst) { - if (fromlen == dst->addrlen && - os_memcmp(from->sun_path, dst->addr.sun_path, - fromlen - offsetof(struct sockaddr_un, sun_path)) - == 0) { - if (prev == NULL) - hapd->ctrl_dst = dst->next; - else - prev->next = dst->next; - os_free(dst); - wpa_hexdump(MSG_DEBUG, "CTRL_IFACE monitor detached", - (u8 *) from->sun_path, - fromlen - - offsetof(struct sockaddr_un, sun_path)); - return 0; - } - prev = dst; - dst = dst->next; - } - return -1; -} - - -static int hostapd_ctrl_iface_level(struct hostapd_data *hapd, - struct sockaddr_un *from, - socklen_t fromlen, - char *level) -{ - struct wpa_ctrl_dst *dst; - - wpa_printf(MSG_DEBUG, "CTRL_IFACE LEVEL %s", level); - - dst = hapd->ctrl_dst; - while (dst) { - if (fromlen == dst->addrlen && - os_memcmp(from->sun_path, dst->addr.sun_path, - fromlen - offsetof(struct sockaddr_un, sun_path)) - == 0) { - wpa_hexdump(MSG_DEBUG, "CTRL_IFACE changed monitor " - "level", (u8 *) from->sun_path, fromlen - - offsetof(struct sockaddr_un, sun_path)); - dst->debug_level = atoi(level); - return 0; - } - dst = dst->next; - } - - return -1; -} - - -static int hostapd_ctrl_iface_new_sta(struct hostapd_data *hapd, - const char *txtaddr) -{ - u8 addr[ETH_ALEN]; - struct sta_info *sta; - - wpa_printf(MSG_DEBUG, "CTRL_IFACE NEW_STA %s", txtaddr); - - if (hwaddr_aton(txtaddr, addr)) - return -1; - - sta = ap_get_sta(hapd, addr); - if (sta) - return 0; - - wpa_printf(MSG_DEBUG, "Add new STA " MACSTR " based on ctrl_iface " - "notification", MAC2STR(addr)); - sta = ap_sta_add(hapd, addr); - if (sta == NULL) - return -1; - - hostapd_new_assoc_sta(hapd, sta, 0); - return 0; -} - - -#ifdef CONFIG_P2P_MANAGER -static int p2p_manager_disconnect(struct hostapd_data *hapd, u16 stype, - u8 minor_reason_code, const u8 *addr) -{ - struct ieee80211_mgmt *mgmt; - int ret; - u8 *pos; - - if (hapd->driver->send_frame == NULL) - return -1; - - mgmt = os_zalloc(sizeof(*mgmt) + 100); - if (mgmt == NULL) - return -1; - - wpa_printf(MSG_DEBUG, "P2P: Disconnect STA " MACSTR " with minor " - "reason code %u (stype=%u)", - MAC2STR(addr), minor_reason_code, stype); - - mgmt->frame_control = IEEE80211_FC(WLAN_FC_TYPE_MGMT, stype); - os_memcpy(mgmt->da, addr, ETH_ALEN); - os_memcpy(mgmt->sa, hapd->own_addr, ETH_ALEN); - os_memcpy(mgmt->bssid, hapd->own_addr, ETH_ALEN); - if (stype == WLAN_FC_STYPE_DEAUTH) { - mgmt->u.deauth.reason_code = - host_to_le16(WLAN_REASON_PREV_AUTH_NOT_VALID); - pos = (u8 *) (&mgmt->u.deauth.reason_code + 1); - } else { - mgmt->u.disassoc.reason_code = - host_to_le16(WLAN_REASON_PREV_AUTH_NOT_VALID); - pos = (u8 *) (&mgmt->u.disassoc.reason_code + 1); - } - - *pos++ = WLAN_EID_VENDOR_SPECIFIC; - *pos++ = 4 + 3 + 1; - WPA_PUT_BE24(pos, OUI_WFA); - pos += 3; - *pos++ = P2P_OUI_TYPE; - - *pos++ = P2P_ATTR_MINOR_REASON_CODE; - WPA_PUT_LE16(pos, 1); - pos += 2; - *pos++ = minor_reason_code; - - ret = hapd->driver->send_frame(hapd->drv_priv, (u8 *) mgmt, - pos - (u8 *) mgmt, 1); - os_free(mgmt); - - return ret < 0 ? -1 : 0; -} -#endif /* CONFIG_P2P_MANAGER */ - - -static int hostapd_ctrl_iface_deauthenticate(struct hostapd_data *hapd, - const char *txtaddr) -{ - u8 addr[ETH_ALEN]; - struct sta_info *sta; - const char *pos; - - wpa_printf(MSG_DEBUG, "CTRL_IFACE DEAUTHENTICATE %s", txtaddr); - - if (hwaddr_aton(txtaddr, addr)) - return -1; - - pos = os_strstr(txtaddr, " test="); - if (pos) { - struct ieee80211_mgmt mgmt; - int encrypt; - if (hapd->driver->send_frame == NULL) - return -1; - pos += 6; - encrypt = atoi(pos); - os_memset(&mgmt, 0, sizeof(mgmt)); - mgmt.frame_control = IEEE80211_FC(WLAN_FC_TYPE_MGMT, - WLAN_FC_STYPE_DEAUTH); - os_memcpy(mgmt.da, addr, ETH_ALEN); - os_memcpy(mgmt.sa, hapd->own_addr, ETH_ALEN); - os_memcpy(mgmt.bssid, hapd->own_addr, ETH_ALEN); - mgmt.u.deauth.reason_code = - host_to_le16(WLAN_REASON_PREV_AUTH_NOT_VALID); - if (hapd->driver->send_frame(hapd->drv_priv, (u8 *) &mgmt, - IEEE80211_HDRLEN + - sizeof(mgmt.u.deauth), - encrypt) < 0) - return -1; - return 0; - } - -#ifdef CONFIG_P2P_MANAGER - pos = os_strstr(txtaddr, " p2p="); - if (pos) { - return p2p_manager_disconnect(hapd, WLAN_FC_STYPE_DEAUTH, - atoi(pos + 5), addr); - } -#endif /* CONFIG_P2P_MANAGER */ - - hostapd_drv_sta_deauth(hapd, addr, WLAN_REASON_PREV_AUTH_NOT_VALID); - sta = ap_get_sta(hapd, addr); - if (sta) - ap_sta_deauthenticate(hapd, sta, - WLAN_REASON_PREV_AUTH_NOT_VALID); - else if (addr[0] == 0xff) - hostapd_free_stas(hapd); - - return 0; -} - - -static int hostapd_ctrl_iface_disassociate(struct hostapd_data *hapd, - const char *txtaddr) -{ - u8 addr[ETH_ALEN]; - struct sta_info *sta; - const char *pos; - - wpa_printf(MSG_DEBUG, "CTRL_IFACE DISASSOCIATE %s", txtaddr); - - if (hwaddr_aton(txtaddr, addr)) - return -1; - - pos = os_strstr(txtaddr, " test="); - if (pos) { - struct ieee80211_mgmt mgmt; - int encrypt; - if (hapd->driver->send_frame == NULL) - return -1; - pos += 6; - encrypt = atoi(pos); - os_memset(&mgmt, 0, sizeof(mgmt)); - mgmt.frame_control = IEEE80211_FC(WLAN_FC_TYPE_MGMT, - WLAN_FC_STYPE_DISASSOC); - os_memcpy(mgmt.da, addr, ETH_ALEN); - os_memcpy(mgmt.sa, hapd->own_addr, ETH_ALEN); - os_memcpy(mgmt.bssid, hapd->own_addr, ETH_ALEN); - mgmt.u.disassoc.reason_code = - host_to_le16(WLAN_REASON_PREV_AUTH_NOT_VALID); - if (hapd->driver->send_frame(hapd->drv_priv, (u8 *) &mgmt, - IEEE80211_HDRLEN + - sizeof(mgmt.u.deauth), - encrypt) < 0) - return -1; - return 0; - } - -#ifdef CONFIG_P2P_MANAGER - pos = os_strstr(txtaddr, " p2p="); - if (pos) { - return p2p_manager_disconnect(hapd, WLAN_FC_STYPE_DISASSOC, - atoi(pos + 5), addr); - } -#endif /* CONFIG_P2P_MANAGER */ - - hostapd_drv_sta_disassoc(hapd, addr, WLAN_REASON_PREV_AUTH_NOT_VALID); - sta = ap_get_sta(hapd, addr); - if (sta) - ap_sta_disassociate(hapd, sta, - WLAN_REASON_PREV_AUTH_NOT_VALID); - else if (addr[0] == 0xff) - hostapd_free_stas(hapd); - - return 0; -} - - -#ifdef CONFIG_IEEE80211W -#ifdef NEED_AP_MLME -static int hostapd_ctrl_iface_sa_query(struct hostapd_data *hapd, - const char *txtaddr) -{ - u8 addr[ETH_ALEN]; - u8 trans_id[WLAN_SA_QUERY_TR_ID_LEN]; - - wpa_printf(MSG_DEBUG, "CTRL_IFACE SA_QUERY %s", txtaddr); - - if (hwaddr_aton(txtaddr, addr) || - os_get_random(trans_id, WLAN_SA_QUERY_TR_ID_LEN) < 0) - return -1; - - ieee802_11_send_sa_query_req(hapd, addr, trans_id); - - return 0; -} -#endif /* NEED_AP_MLME */ -#endif /* CONFIG_IEEE80211W */ - - -#ifdef CONFIG_WPS -static int hostapd_ctrl_iface_wps_pin(struct hostapd_data *hapd, char *txt) -{ - char *pin = os_strchr(txt, ' '); - char *timeout_txt; - int timeout; - u8 addr_buf[ETH_ALEN], *addr = NULL; - char *pos; - - if (pin == NULL) - return -1; - *pin++ = '\0'; - - timeout_txt = os_strchr(pin, ' '); - if (timeout_txt) { - *timeout_txt++ = '\0'; - timeout = atoi(timeout_txt); - pos = os_strchr(timeout_txt, ' '); - if (pos) { - *pos++ = '\0'; - if (hwaddr_aton(pos, addr_buf) == 0) - addr = addr_buf; - } - } else - timeout = 0; - - return hostapd_wps_add_pin(hapd, addr, txt, pin, timeout); -} - - -static int hostapd_ctrl_iface_wps_check_pin( - struct hostapd_data *hapd, char *cmd, char *buf, size_t buflen) -{ - char pin[9]; - size_t len; - char *pos; - int ret; - - wpa_hexdump_ascii_key(MSG_DEBUG, "WPS_CHECK_PIN", - (u8 *) cmd, os_strlen(cmd)); - for (pos = cmd, len = 0; *pos != '\0'; pos++) { - if (*pos < '0' || *pos > '9') - continue; - pin[len++] = *pos; - if (len == 9) { - wpa_printf(MSG_DEBUG, "WPS: Too long PIN"); - return -1; - } - } - if (len != 4 && len != 8) { - wpa_printf(MSG_DEBUG, "WPS: Invalid PIN length %d", (int) len); - return -1; - } - pin[len] = '\0'; - - if (len == 8) { - unsigned int pin_val; - pin_val = atoi(pin); - if (!wps_pin_valid(pin_val)) { - wpa_printf(MSG_DEBUG, "WPS: Invalid checksum digit"); - ret = os_snprintf(buf, buflen, "FAIL-CHECKSUM\n"); - if (ret < 0 || (size_t) ret >= buflen) - return -1; - return ret; - } - } - - ret = os_snprintf(buf, buflen, "%s", pin); - if (ret < 0 || (size_t) ret >= buflen) - return -1; - - return ret; -} - - -#ifdef CONFIG_WPS_OOB -static int hostapd_ctrl_iface_wps_oob(struct hostapd_data *hapd, char *txt) -{ - char *path, *method, *name; - - path = os_strchr(txt, ' '); - if (path == NULL) - return -1; - *path++ = '\0'; - - method = os_strchr(path, ' '); - if (method == NULL) - return -1; - *method++ = '\0'; - - name = os_strchr(method, ' '); - if (name != NULL) - *name++ = '\0'; - - return hostapd_wps_start_oob(hapd, txt, path, method, name); -} -#endif /* CONFIG_WPS_OOB */ - - -static int hostapd_ctrl_iface_wps_ap_pin(struct hostapd_data *hapd, char *txt, - char *buf, size_t buflen) -{ - int timeout = 300; - char *pos; - const char *pin_txt; - - pos = os_strchr(txt, ' '); - if (pos) - *pos++ = '\0'; - - if (os_strcmp(txt, "disable") == 0) { - hostapd_wps_ap_pin_disable(hapd); - return os_snprintf(buf, buflen, "OK\n"); - } - - if (os_strcmp(txt, "random") == 0) { - if (pos) - timeout = atoi(pos); - pin_txt = hostapd_wps_ap_pin_random(hapd, timeout); - if (pin_txt == NULL) - return -1; - return os_snprintf(buf, buflen, "%s", pin_txt); - } - - if (os_strcmp(txt, "get") == 0) { - pin_txt = hostapd_wps_ap_pin_get(hapd); - if (pin_txt == NULL) - return -1; - return os_snprintf(buf, buflen, "%s", pin_txt); - } - - if (os_strcmp(txt, "set") == 0) { - char *pin; - if (pos == NULL) - return -1; - pin = pos; - pos = os_strchr(pos, ' '); - if (pos) { - *pos++ = '\0'; - timeout = atoi(pos); - } - if (os_strlen(pin) > buflen) - return -1; - if (hostapd_wps_ap_pin_set(hapd, pin, timeout) < 0) - return -1; - return os_snprintf(buf, buflen, "%s", pin); - } - - return -1; -} - - -static int hostapd_ctrl_iface_wps_config(struct hostapd_data *hapd, char *txt) -{ - char *pos; - char *ssid, *auth, *encr = NULL, *key = NULL; - - ssid = txt; - pos = os_strchr(txt, ' '); - if (!pos) - return -1; - *pos++ = '\0'; - - auth = pos; - pos = os_strchr(pos, ' '); - if (pos) { - *pos++ = '\0'; - encr = pos; - pos = os_strchr(pos, ' '); - if (pos) { - *pos++ = '\0'; - key = pos; - } - } - - return hostapd_wps_config_ap(hapd, ssid, auth, encr, key); -} -#endif /* CONFIG_WPS */ - - -static int hostapd_ctrl_iface_get_config(struct hostapd_data *hapd, - char *buf, size_t buflen) -{ - int ret; - char *pos, *end; - - pos = buf; - end = buf + buflen; - - ret = os_snprintf(pos, end - pos, "bssid=" MACSTR "\n" - "ssid=%s\n", - MAC2STR(hapd->own_addr), - hapd->conf->ssid.ssid); - if (ret < 0 || ret >= end - pos) - return pos - buf; - pos += ret; - -#ifdef CONFIG_WPS - ret = os_snprintf(pos, end - pos, "wps_state=%s\n", - hapd->conf->wps_state == 0 ? "disabled" : - (hapd->conf->wps_state == 1 ? "not configured" : - "configured")); - if (ret < 0 || ret >= end - pos) - return pos - buf; - pos += ret; - - if (hapd->conf->wps_state && hapd->conf->wpa && - hapd->conf->ssid.wpa_passphrase) { - ret = os_snprintf(pos, end - pos, "passphrase=%s\n", - hapd->conf->ssid.wpa_passphrase); - if (ret < 0 || ret >= end - pos) - return pos - buf; - pos += ret; - } - - if (hapd->conf->wps_state && hapd->conf->wpa && - hapd->conf->ssid.wpa_psk && - hapd->conf->ssid.wpa_psk->group) { - char hex[PMK_LEN * 2 + 1]; - wpa_snprintf_hex(hex, sizeof(hex), - hapd->conf->ssid.wpa_psk->psk, PMK_LEN); - ret = os_snprintf(pos, end - pos, "psk=%s\n", hex); - if (ret < 0 || ret >= end - pos) - return pos - buf; - pos += ret; - } -#endif /* CONFIG_WPS */ - - if (hapd->conf->wpa && hapd->conf->wpa_key_mgmt) { - ret = os_snprintf(pos, end - pos, "key_mgmt="); - if (ret < 0 || ret >= end - pos) - return pos - buf; - pos += ret; - - if (hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_PSK) { - ret = os_snprintf(pos, end - pos, "WPA-PSK "); - if (ret < 0 || ret >= end - pos) - return pos - buf; - pos += ret; - } - if (hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_IEEE8021X) { - ret = os_snprintf(pos, end - pos, "WPA-EAP "); - if (ret < 0 || ret >= end - pos) - return pos - buf; - pos += ret; - } -#ifdef CONFIG_IEEE80211R - if (hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_FT_PSK) { - ret = os_snprintf(pos, end - pos, "FT-PSK "); - if (ret < 0 || ret >= end - pos) - return pos - buf; - pos += ret; - } - if (hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_FT_IEEE8021X) { - ret = os_snprintf(pos, end - pos, "FT-EAP "); - if (ret < 0 || ret >= end - pos) - return pos - buf; - pos += ret; - } -#endif /* CONFIG_IEEE80211R */ -#ifdef CONFIG_IEEE80211W - if (hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_PSK_SHA256) { - ret = os_snprintf(pos, end - pos, "WPA-PSK-SHA256 "); - if (ret < 0 || ret >= end - pos) - return pos - buf; - pos += ret; - } - if (hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_IEEE8021X_SHA256) { - ret = os_snprintf(pos, end - pos, "WPA-EAP-SHA256 "); - if (ret < 0 || ret >= end - pos) - return pos - buf; - pos += ret; - } -#endif /* CONFIG_IEEE80211W */ - - ret = os_snprintf(pos, end - pos, "\n"); - if (ret < 0 || ret >= end - pos) - return pos - buf; - pos += ret; - } - - if (hapd->conf->wpa && hapd->conf->wpa_group == WPA_CIPHER_CCMP) { - ret = os_snprintf(pos, end - pos, "group_cipher=CCMP\n"); - if (ret < 0 || ret >= end - pos) - return pos - buf; - pos += ret; - } else if (hapd->conf->wpa && - hapd->conf->wpa_group == WPA_CIPHER_TKIP) { - ret = os_snprintf(pos, end - pos, "group_cipher=TKIP\n"); - if (ret < 0 || ret >= end - pos) - return pos - buf; - pos += ret; - } - - if ((hapd->conf->wpa & WPA_PROTO_RSN) && hapd->conf->rsn_pairwise) { - ret = os_snprintf(pos, end - pos, "rsn_pairwise_cipher="); - if (ret < 0 || ret >= end - pos) - return pos - buf; - pos += ret; - - if (hapd->conf->rsn_pairwise & WPA_CIPHER_CCMP) { - ret = os_snprintf(pos, end - pos, "CCMP "); - if (ret < 0 || ret >= end - pos) - return pos - buf; - pos += ret; - } - if (hapd->conf->rsn_pairwise & WPA_CIPHER_TKIP) { - ret = os_snprintf(pos, end - pos, "TKIP "); - if (ret < 0 || ret >= end - pos) - return pos - buf; - pos += ret; - } - - ret = os_snprintf(pos, end - pos, "\n"); - if (ret < 0 || ret >= end - pos) - return pos - buf; - pos += ret; - } - - if ((hapd->conf->wpa & WPA_PROTO_WPA) && hapd->conf->wpa_pairwise) { - ret = os_snprintf(pos, end - pos, "wpa_pairwise_cipher="); - if (ret < 0 || ret >= end - pos) - return pos - buf; - pos += ret; - - if (hapd->conf->wpa_pairwise & WPA_CIPHER_CCMP) { - ret = os_snprintf(pos, end - pos, "CCMP "); - if (ret < 0 || ret >= end - pos) - return pos - buf; - pos += ret; - } - if (hapd->conf->wpa_pairwise & WPA_CIPHER_TKIP) { - ret = os_snprintf(pos, end - pos, "TKIP "); - if (ret < 0 || ret >= end - pos) - return pos - buf; - pos += ret; - } - - ret = os_snprintf(pos, end - pos, "\n"); - if (ret < 0 || ret >= end - pos) - return pos - buf; - pos += ret; - } - - return pos - buf; -} - - -static int hostapd_ctrl_iface_set(struct hostapd_data *hapd, char *cmd) -{ - char *value; - int ret = 0; - - value = os_strchr(cmd, ' '); - if (value == NULL) - return -1; - *value++ = '\0'; - - wpa_printf(MSG_DEBUG, "CTRL_IFACE SET '%s'='%s'", cmd, value); - if (0) { -#ifdef CONFIG_WPS_TESTING - } else if (os_strcasecmp(cmd, "wps_version_number") == 0) { - long int val; - val = strtol(value, NULL, 0); - if (val < 0 || val > 0xff) { - ret = -1; - wpa_printf(MSG_DEBUG, "WPS: Invalid " - "wps_version_number %ld", val); - } else { - wps_version_number = val; - wpa_printf(MSG_DEBUG, "WPS: Testing - force WPS " - "version %u.%u", - (wps_version_number & 0xf0) >> 4, - wps_version_number & 0x0f); - hostapd_wps_update_ie(hapd); - } - } else if (os_strcasecmp(cmd, "wps_testing_dummy_cred") == 0) { - wps_testing_dummy_cred = atoi(value); - wpa_printf(MSG_DEBUG, "WPS: Testing - dummy_cred=%d", - wps_testing_dummy_cred); -#endif /* CONFIG_WPS_TESTING */ - } else { - ret = -1; - } - - return ret; -} - - -static int hostapd_ctrl_iface_get(struct hostapd_data *hapd, char *cmd, - char *buf, size_t buflen) -{ - int res; - - wpa_printf(MSG_DEBUG, "CTRL_IFACE GET '%s'", cmd); - - if (os_strcmp(cmd, "version") == 0) { - res = os_snprintf(buf, buflen, "%s", VERSION_STR); - if (res < 0 || (unsigned int) res >= buflen) - return -1; - return res; - } - - return -1; -} - - -static void hostapd_ctrl_iface_receive(int sock, void *eloop_ctx, - void *sock_ctx) -{ - struct hostapd_data *hapd = eloop_ctx; - char buf[256]; - int res; - struct sockaddr_un from; - socklen_t fromlen = sizeof(from); - char *reply; - const int reply_size = 4096; - int reply_len; - int level = MSG_DEBUG; - - res = recvfrom(sock, buf, sizeof(buf) - 1, 0, - (struct sockaddr *) &from, &fromlen); - if (res < 0) { - perror("recvfrom(ctrl_iface)"); - return; - } - buf[res] = '\0'; - if (os_strcmp(buf, "PING") == 0) - level = MSG_EXCESSIVE; - wpa_hexdump_ascii(level, "RX ctrl_iface", (u8 *) buf, res); - - reply = os_malloc(reply_size); - if (reply == NULL) { - sendto(sock, "FAIL\n", 5, 0, (struct sockaddr *) &from, - fromlen); - return; - } - - os_memcpy(reply, "OK\n", 3); - reply_len = 3; - - if (os_strcmp(buf, "PING") == 0) { - os_memcpy(reply, "PONG\n", 5); - reply_len = 5; - } else if (os_strncmp(buf, "RELOG", 5) == 0) { - if (wpa_debug_reopen_file() < 0) - reply_len = -1; - } else if (os_strcmp(buf, "MIB") == 0) { - reply_len = ieee802_11_get_mib(hapd, reply, reply_size); - if (reply_len >= 0) { - res = wpa_get_mib(hapd->wpa_auth, reply + reply_len, - reply_size - reply_len); - if (res < 0) - reply_len = -1; - else - reply_len += res; - } - if (reply_len >= 0) { - res = ieee802_1x_get_mib(hapd, reply + reply_len, - reply_size - reply_len); - if (res < 0) - reply_len = -1; - else - reply_len += res; - } -#ifndef CONFIG_NO_RADIUS - if (reply_len >= 0) { - res = radius_client_get_mib(hapd->radius, - reply + reply_len, - reply_size - reply_len); - if (res < 0) - reply_len = -1; - else - reply_len += res; - } -#endif /* CONFIG_NO_RADIUS */ - } else if (os_strcmp(buf, "STA-FIRST") == 0) { - reply_len = hostapd_ctrl_iface_sta_first(hapd, reply, - reply_size); - } else if (os_strncmp(buf, "STA ", 4) == 0) { - reply_len = hostapd_ctrl_iface_sta(hapd, buf + 4, reply, - reply_size); - } else if (os_strncmp(buf, "STA-NEXT ", 9) == 0) { - reply_len = hostapd_ctrl_iface_sta_next(hapd, buf + 9, reply, - reply_size); - } else if (os_strcmp(buf, "ATTACH") == 0) { - if (hostapd_ctrl_iface_attach(hapd, &from, fromlen)) - reply_len = -1; - } else if (os_strcmp(buf, "DETACH") == 0) { - if (hostapd_ctrl_iface_detach(hapd, &from, fromlen)) - reply_len = -1; - } else if (os_strncmp(buf, "LEVEL ", 6) == 0) { - if (hostapd_ctrl_iface_level(hapd, &from, fromlen, - buf + 6)) - reply_len = -1; - } else if (os_strncmp(buf, "NEW_STA ", 8) == 0) { - if (hostapd_ctrl_iface_new_sta(hapd, buf + 8)) - reply_len = -1; - } else if (os_strncmp(buf, "DEAUTHENTICATE ", 15) == 0) { - if (hostapd_ctrl_iface_deauthenticate(hapd, buf + 15)) - reply_len = -1; - } else if (os_strncmp(buf, "DISASSOCIATE ", 13) == 0) { - if (hostapd_ctrl_iface_disassociate(hapd, buf + 13)) - reply_len = -1; -#ifdef CONFIG_IEEE80211W -#ifdef NEED_AP_MLME - } else if (os_strncmp(buf, "SA_QUERY ", 9) == 0) { - if (hostapd_ctrl_iface_sa_query(hapd, buf + 9)) - reply_len = -1; -#endif /* NEED_AP_MLME */ -#endif /* CONFIG_IEEE80211W */ -#ifdef CONFIG_WPS - } else if (os_strncmp(buf, "WPS_PIN ", 8) == 0) { - if (hostapd_ctrl_iface_wps_pin(hapd, buf + 8)) - reply_len = -1; - } else if (os_strncmp(buf, "WPS_CHECK_PIN ", 14) == 0) { - reply_len = hostapd_ctrl_iface_wps_check_pin( - hapd, buf + 14, reply, reply_size); - } else if (os_strcmp(buf, "WPS_PBC") == 0) { - if (hostapd_wps_button_pushed(hapd, NULL)) - reply_len = -1; -#ifdef CONFIG_WPS_OOB - } else if (os_strncmp(buf, "WPS_OOB ", 8) == 0) { - if (hostapd_ctrl_iface_wps_oob(hapd, buf + 8)) - reply_len = -1; -#endif /* CONFIG_WPS_OOB */ - } else if (os_strncmp(buf, "WPS_AP_PIN ", 11) == 0) { - reply_len = hostapd_ctrl_iface_wps_ap_pin(hapd, buf + 11, - reply, reply_size); - } else if (os_strncmp(buf, "WPS_CONFIG ", 11) == 0) { - if (hostapd_ctrl_iface_wps_config(hapd, buf + 11) < 0) - reply_len = -1; -#endif /* CONFIG_WPS */ - } else if (os_strcmp(buf, "GET_CONFIG") == 0) { - reply_len = hostapd_ctrl_iface_get_config(hapd, reply, - reply_size); - } else if (os_strncmp(buf, "SET ", 4) == 0) { - if (hostapd_ctrl_iface_set(hapd, buf + 4)) - reply_len = -1; - } else if (os_strncmp(buf, "GET ", 4) == 0) { - reply_len = hostapd_ctrl_iface_get(hapd, buf + 4, reply, - reply_size); - } else { - os_memcpy(reply, "UNKNOWN COMMAND\n", 16); - reply_len = 16; - } - - if (reply_len < 0) { - os_memcpy(reply, "FAIL\n", 5); - reply_len = 5; - } - sendto(sock, reply, reply_len, 0, (struct sockaddr *) &from, fromlen); - os_free(reply); -} - - -static char * hostapd_ctrl_iface_path(struct hostapd_data *hapd) -{ - char *buf; - size_t len; - - if (hapd->conf->ctrl_interface == NULL) - return NULL; - - len = os_strlen(hapd->conf->ctrl_interface) + - os_strlen(hapd->conf->iface) + 2; - buf = os_malloc(len); - if (buf == NULL) - return NULL; - - os_snprintf(buf, len, "%s/%s", - hapd->conf->ctrl_interface, hapd->conf->iface); - buf[len - 1] = '\0'; - return buf; -} - - -static void hostapd_ctrl_iface_msg_cb(void *ctx, int level, - const char *txt, size_t len) -{ - struct hostapd_data *hapd = ctx; - if (hapd == NULL) - return; - hostapd_ctrl_iface_send(hapd, level, txt, len); -} - - -int hostapd_ctrl_iface_init(struct hostapd_data *hapd) -{ - struct sockaddr_un addr; - int s = -1; - char *fname = NULL; - - hapd->ctrl_sock = -1; - - if (hapd->conf->ctrl_interface == NULL) - return 0; - - if (mkdir(hapd->conf->ctrl_interface, S_IRWXU | S_IRWXG) < 0) { - if (errno == EEXIST) { - wpa_printf(MSG_DEBUG, "Using existing control " - "interface directory."); - } else { - perror("mkdir[ctrl_interface]"); - goto fail; - } - } - - if (hapd->conf->ctrl_interface_gid_set && - chown(hapd->conf->ctrl_interface, 0, - hapd->conf->ctrl_interface_gid) < 0) { - perror("chown[ctrl_interface]"); - return -1; - } - - if (os_strlen(hapd->conf->ctrl_interface) + 1 + - os_strlen(hapd->conf->iface) >= sizeof(addr.sun_path)) - goto fail; - - s = socket(PF_UNIX, SOCK_DGRAM, 0); - if (s < 0) { - perror("socket(PF_UNIX)"); - goto fail; - } - - os_memset(&addr, 0, sizeof(addr)); -#ifdef __FreeBSD__ - addr.sun_len = sizeof(addr); -#endif /* __FreeBSD__ */ - addr.sun_family = AF_UNIX; - fname = hostapd_ctrl_iface_path(hapd); - if (fname == NULL) - goto fail; - os_strlcpy(addr.sun_path, fname, sizeof(addr.sun_path)); - if (bind(s, (struct sockaddr *) &addr, sizeof(addr)) < 0) { - wpa_printf(MSG_DEBUG, "ctrl_iface bind(PF_UNIX) failed: %s", - strerror(errno)); - if (connect(s, (struct sockaddr *) &addr, sizeof(addr)) < 0) { - wpa_printf(MSG_DEBUG, "ctrl_iface exists, but does not" - " allow connections - assuming it was left" - "over from forced program termination"); - if (unlink(fname) < 0) { - perror("unlink[ctrl_iface]"); - wpa_printf(MSG_ERROR, "Could not unlink " - "existing ctrl_iface socket '%s'", - fname); - goto fail; - } - if (bind(s, (struct sockaddr *) &addr, sizeof(addr)) < - 0) { - perror("bind(PF_UNIX)"); - goto fail; - } - wpa_printf(MSG_DEBUG, "Successfully replaced leftover " - "ctrl_iface socket '%s'", fname); - } else { - wpa_printf(MSG_INFO, "ctrl_iface exists and seems to " - "be in use - cannot override it"); - wpa_printf(MSG_INFO, "Delete '%s' manually if it is " - "not used anymore", fname); - os_free(fname); - fname = NULL; - goto fail; - } - } - - if (hapd->conf->ctrl_interface_gid_set && - chown(fname, 0, hapd->conf->ctrl_interface_gid) < 0) { - perror("chown[ctrl_interface/ifname]"); - goto fail; - } - - if (chmod(fname, S_IRWXU | S_IRWXG) < 0) { - perror("chmod[ctrl_interface/ifname]"); - goto fail; - } - os_free(fname); - - hapd->ctrl_sock = s; - eloop_register_read_sock(s, hostapd_ctrl_iface_receive, hapd, - NULL); - hapd->msg_ctx = hapd; - wpa_msg_register_cb(hostapd_ctrl_iface_msg_cb); - - return 0; - -fail: - if (s >= 0) - close(s); - if (fname) { - unlink(fname); - os_free(fname); - } - return -1; -} - - -void hostapd_ctrl_iface_deinit(struct hostapd_data *hapd) -{ - struct wpa_ctrl_dst *dst, *prev; - - if (hapd->ctrl_sock > -1) { - char *fname; - eloop_unregister_read_sock(hapd->ctrl_sock); - close(hapd->ctrl_sock); - hapd->ctrl_sock = -1; - fname = hostapd_ctrl_iface_path(hapd); - if (fname) - unlink(fname); - os_free(fname); - - if (hapd->conf->ctrl_interface && - rmdir(hapd->conf->ctrl_interface) < 0) { - if (errno == ENOTEMPTY) { - wpa_printf(MSG_DEBUG, "Control interface " - "directory not empty - leaving it " - "behind"); - } else { - perror("rmdir[ctrl_interface]"); - } - } - } - - dst = hapd->ctrl_dst; - while (dst) { - prev = dst; - dst = dst->next; - os_free(prev); - } -} - - -static void hostapd_ctrl_iface_send(struct hostapd_data *hapd, int level, - const char *buf, size_t len) -{ - struct wpa_ctrl_dst *dst, *next; - struct msghdr msg; - int idx; - struct iovec io[2]; - char levelstr[10]; - - dst = hapd->ctrl_dst; - if (hapd->ctrl_sock < 0 || dst == NULL) - return; - - os_snprintf(levelstr, sizeof(levelstr), "<%d>", level); - io[0].iov_base = levelstr; - io[0].iov_len = os_strlen(levelstr); - io[1].iov_base = (char *) buf; - io[1].iov_len = len; - os_memset(&msg, 0, sizeof(msg)); - msg.msg_iov = io; - msg.msg_iovlen = 2; - - idx = 0; - while (dst) { - next = dst->next; - if (level >= dst->debug_level) { - wpa_hexdump(MSG_DEBUG, "CTRL_IFACE monitor send", - (u8 *) dst->addr.sun_path, dst->addrlen - - offsetof(struct sockaddr_un, sun_path)); - msg.msg_name = &dst->addr; - msg.msg_namelen = dst->addrlen; - if (sendmsg(hapd->ctrl_sock, &msg, 0) < 0) { - int _errno = errno; - wpa_printf(MSG_INFO, "CTRL_IFACE monitor[%d]: " - "%d - %s", - idx, errno, strerror(errno)); - dst->errors++; - if (dst->errors > 10 || _errno == ENOENT) { - hostapd_ctrl_iface_detach( - hapd, &dst->addr, - dst->addrlen); - } - } else - dst->errors = 0; - } - idx++; - dst = next; - } -} - -#endif /* CONFIG_NATIVE_WINDOWS */ diff --git a/hostapd-0.8/hostapd/ctrl_iface.h b/hostapd-0.8/hostapd/ctrl_iface.h deleted file mode 100644 index c997141..0000000 --- a/hostapd-0.8/hostapd/ctrl_iface.h +++ /dev/null @@ -1,32 +0,0 @@ -/* - * hostapd / UNIX domain socket -based control interface - * Copyright (c) 2004, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#ifndef CTRL_IFACE_H -#define CTRL_IFACE_H - -#ifndef CONFIG_NO_CTRL_IFACE -int hostapd_ctrl_iface_init(struct hostapd_data *hapd); -void hostapd_ctrl_iface_deinit(struct hostapd_data *hapd); -#else /* CONFIG_NO_CTRL_IFACE */ -static inline int hostapd_ctrl_iface_init(struct hostapd_data *hapd) -{ - return 0; -} - -static inline void hostapd_ctrl_iface_deinit(struct hostapd_data *hapd) -{ -} -#endif /* CONFIG_NO_CTRL_IFACE */ - -#endif /* CTRL_IFACE_H */ diff --git a/hostapd-0.8/hostapd/defconfig b/hostapd-0.8/hostapd/defconfig deleted file mode 100644 index 47d1a6f..0000000 --- a/hostapd-0.8/hostapd/defconfig +++ /dev/null @@ -1,208 +0,0 @@ -# Example hostapd build time configuration -# -# This file lists the configuration options that are used when building the -# hostapd binary. All lines starting with # are ignored. Configuration option -# lines must be commented out complete, if they are not to be included, i.e., -# just setting VARIABLE=n is not disabling that variable. -# -# This file is included in Makefile, so variables like CFLAGS and LIBS can also -# be modified from here. In most cass, these lines should use += in order not -# to override previous values of the variables. - -# Driver interface for Host AP driver -#CONFIG_DRIVER_HOSTAP=y -CONFIG_DRIVER_RTW=y - -# Driver interface for wired authenticator -#CONFIG_DRIVER_WIRED=y - -# Driver interface for madwifi driver -#CONFIG_DRIVER_MADWIFI=y -#CFLAGS += -I../../madwifi # change to the madwifi source directory - -# Driver interface for drivers using the nl80211 kernel interface -#CONFIG_DRIVER_NL80211=y - -# Driver interface for FreeBSD net80211 layer (e.g., Atheros driver) -#CONFIG_DRIVER_BSD=y -#CFLAGS += -I/usr/local/include -#LIBS += -L/usr/local/lib -#LIBS_p += -L/usr/local/lib -#LIBS_c += -L/usr/local/lib - -# Driver interface for no driver (e.g., RADIUS server only) -#CONFIG_DRIVER_NONE=y - -# IEEE 802.11F/IAPP -#CONFIG_IAPP=y - -# WPA2/IEEE 802.11i RSN pre-authentication -#CONFIG_RSN_PREAUTH=y - -# PeerKey handshake for Station to Station Link (IEEE 802.11e DLS) -#CONFIG_PEERKEY=y - -# IEEE 802.11w (management frame protection) -# This version is an experimental implementation based on IEEE 802.11w/D1.0 -# draft and is subject to change since the standard has not yet been finalized. -# Driver support is also needed for IEEE 802.11w. -#CONFIG_IEEE80211W=y - -# Integrated EAP server -CONFIG_EAP=y - -# EAP-MD5 for the integrated EAP server -#CONFIG_EAP_MD5=y - -# EAP-TLS for the integrated EAP server -#CONFIG_EAP_TLS=y - -# EAP-MSCHAPv2 for the integrated EAP server -#CONFIG_EAP_MSCHAPV2=y - -# EAP-PEAP for the integrated EAP server -#CONFIG_EAP_PEAP=y - -# EAP-GTC for the integrated EAP server -#CONFIG_EAP_GTC=y - -# EAP-TTLS for the integrated EAP server -#CONFIG_EAP_TTLS=y - -# EAP-SIM for the integrated EAP server -#CONFIG_EAP_SIM=y - -# EAP-AKA for the integrated EAP server -#CONFIG_EAP_AKA=y - -# EAP-AKA' for the integrated EAP server -# This requires CONFIG_EAP_AKA to be enabled, too. -#CONFIG_EAP_AKA_PRIME=y - -# EAP-PAX for the integrated EAP server -#CONFIG_EAP_PAX=y - -# EAP-PSK for the integrated EAP server (this is _not_ needed for WPA-PSK) -#CONFIG_EAP_PSK=y - -# EAP-SAKE for the integrated EAP server -#CONFIG_EAP_SAKE=y - -# EAP-GPSK for the integrated EAP server -#CONFIG_EAP_GPSK=y -# Include support for optional SHA256 cipher suite in EAP-GPSK -#CONFIG_EAP_GPSK_SHA256=y - -# EAP-FAST for the integrated EAP server -# Note: Default OpenSSL package does not include support for all the -# functionality needed for EAP-FAST. If EAP-FAST is enabled with OpenSSL, -# the OpenSSL library must be patched (openssl-0.9.9-session-ticket.patch) -# to add the needed functions. -#CONFIG_EAP_FAST=y - -# Wi-Fi Protected Setup (WPS) -CONFIG_WPS=y -# Enable WSC 2.0 support -CONFIG_WPS2=y -# Enable UPnP support for external WPS Registrars -#CONFIG_WPS_UPNP=y - -CONFIG_TLS=internal -CONFIG_INTERNAL_LIBTOMMATH=y - -# EAP-IKEv2 -#CONFIG_EAP_IKEV2=y - -# Trusted Network Connect (EAP-TNC) -#CONFIG_EAP_TNC=y - -# PKCS#12 (PFX) support (used to read private key and certificate file from -# a file that usually has extension .p12 or .pfx) -#CONFIG_PKCS12=y - -# RADIUS authentication server. This provides access to the integrated EAP -# server from external hosts using RADIUS. -#CONFIG_RADIUS_SERVER=y - -# Build IPv6 support for RADIUS operations -#CONFIG_IPV6=y - -# IEEE Std 802.11r-2008 (Fast BSS Transition) -#CONFIG_IEEE80211R=y - -# Use the hostapd's IEEE 802.11 authentication (ACL), but without -# the IEEE 802.11 Management capability (e.g., madwifi or FreeBSD/net80211) -#CONFIG_DRIVER_RADIUS_ACL=y - -# IEEE 802.11n (High Throughput) support -CONFIG_IEEE80211N=y - -# Remove debugging code that is printing out debug messages to stdout. -# This can be used to reduce the size of the hostapd considerably if debugging -# code is not needed. -#CONFIG_NO_STDOUT_DEBUG=y - -# Add support for writing debug log to a file: -f /tmp/hostapd.log -# Disabled by default. -#CONFIG_DEBUG_FILE=y - -# Remove support for RADIUS accounting -#CONFIG_NO_ACCOUNTING=y - -# Remove support for RADIUS -#CONFIG_NO_RADIUS=y - -# Remove support for VLANs -#CONFIG_NO_VLAN=y - -# Enable support for fully dynamic VLANs. This enables hostapd to -# automatically create bridge and VLAN interfaces if necessary. -#CONFIG_FULL_DYNAMIC_VLAN=y - -# Remove support for dumping state into a file on SIGUSR1 signal -# This can be used to reduce binary size at the cost of disabling a debugging -# option. -#CONFIG_NO_DUMP_STATE=y - -# Enable tracing code for developer debugging -# This tracks use of memory allocations and other registrations and reports -# incorrect use with a backtrace of call (or allocation) location. -#CONFIG_WPA_TRACE=y -# For BSD, comment out these. -#LIBS += -lexecinfo -#LIBS_p += -lexecinfo -#LIBS_c += -lexecinfo - -# Use libbfd to get more details for developer debugging -# This enables use of libbfd to get more detailed symbols for the backtraces -# generated by CONFIG_WPA_TRACE=y. -#CONFIG_WPA_TRACE_BFD=y -# For BSD, comment out these. -#LIBS += -lbfd -liberty -lz -#LIBS_p += -lbfd -liberty -lz -#LIBS_c += -lbfd -liberty -lz - -# hostapd depends on strong random number generation being available from the -# operating system. os_get_random() function is used to fetch random data when -# needed, e.g., for key generation. On Linux and BSD systems, this works by -# reading /dev/urandom. It should be noted that the OS entropy pool needs to be -# properly initialized before hostapd is started. This is important especially -# on embedded devices that do not have a hardware random number generator and -# may by default start up with minimal entropy available for random number -# generation. -# -# As a safety net, hostapd is by default trying to internally collect -# additional entropy for generating random data to mix in with the data -# fetched from the OS. This by itself is not considered to be very strong, but -# it may help in cases where the system pool is not initialized properly. -# However, it is very strongly recommended that the system pool is initialized -# with enough entropy either by using hardware assisted random number -# generatior or by storing state over device reboots. -# -# If the os_get_random() is known to provide strong ramdom data (e.g., on -# Linux/BSD, the board in question is known to have reliable source of random -# data from /dev/urandom), the internal hostapd random pool can be disabled. -# This will save some in binary size and CPU use. However, this should only be -# considered for builds that are known to be used on devices that meet the -# requirements described above. -#CONFIG_NO_RANDOM_POOL=y diff --git a/hostapd-0.8/hostapd/dump_state.c b/hostapd-0.8/hostapd/dump_state.c deleted file mode 100644 index 73aa93d..0000000 --- a/hostapd-0.8/hostapd/dump_state.c +++ /dev/null @@ -1,183 +0,0 @@ -/* - * hostapd / State dump - * Copyright (c) 2002-2009, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#include "utils/includes.h" - -#include "utils/common.h" -#include "radius/radius_client.h" -#include "radius/radius_server.h" -#include "eapol_auth/eapol_auth_sm.h" -#include "eapol_auth/eapol_auth_sm_i.h" -#include "eap_server/eap.h" -#include "ap/hostapd.h" -#include "ap/ap_config.h" -#include "ap/sta_info.h" -#include "dump_state.h" - - -static void fprint_char(FILE *f, char c) -{ - if (c >= 32 && c < 127) - fprintf(f, "%c", c); - else - fprintf(f, "<%02x>", c); -} - - -static void ieee802_1x_dump_state(FILE *f, const char *prefix, - struct sta_info *sta) -{ - struct eapol_state_machine *sm = sta->eapol_sm; - if (sm == NULL) - return; - - fprintf(f, "%sIEEE 802.1X:\n", prefix); - - if (sm->identity) { - size_t i; - fprintf(f, "%sidentity=", prefix); - for (i = 0; i < sm->identity_len; i++) - fprint_char(f, sm->identity[i]); - fprintf(f, "\n"); - } - - fprintf(f, "%slast EAP type: Authentication Server: %d (%s) " - "Supplicant: %d (%s)\n", prefix, - sm->eap_type_authsrv, - eap_server_get_name(0, sm->eap_type_authsrv), - sm->eap_type_supp, eap_server_get_name(0, sm->eap_type_supp)); - - fprintf(f, "%scached_packets=%s\n", prefix, - sm->last_recv_radius ? "[RX RADIUS]" : ""); - - eapol_auth_dump_state(f, prefix, sm); -} - - -/** - * hostapd_dump_state - SIGUSR1 handler to dump hostapd state to a text file - */ -static void hostapd_dump_state(struct hostapd_data *hapd) -{ - FILE *f; - time_t now; - struct sta_info *sta; - int i; -#ifndef CONFIG_NO_RADIUS - char *buf; -#endif /* CONFIG_NO_RADIUS */ - - if (!hapd->conf->dump_log_name) { - wpa_printf(MSG_DEBUG, "Dump file not defined - ignoring dump " - "request"); - return; - } - - wpa_printf(MSG_DEBUG, "Dumping hostapd state to '%s'", - hapd->conf->dump_log_name); - f = fopen(hapd->conf->dump_log_name, "w"); - if (f == NULL) { - wpa_printf(MSG_WARNING, "Could not open dump file '%s' for " - "writing.", hapd->conf->dump_log_name); - return; - } - - time(&now); - fprintf(f, "hostapd state dump - %s", ctime(&now)); - fprintf(f, "num_sta=%d num_sta_non_erp=%d " - "num_sta_no_short_slot_time=%d\n" - "num_sta_no_short_preamble=%d\n", - hapd->num_sta, hapd->iface->num_sta_non_erp, - hapd->iface->num_sta_no_short_slot_time, - hapd->iface->num_sta_no_short_preamble); - - for (sta = hapd->sta_list; sta != NULL; sta = sta->next) { - fprintf(f, "\nSTA=" MACSTR "\n", MAC2STR(sta->addr)); - - fprintf(f, - " AID=%d flags=0x%x %s%s%s%s%s%s%s%s%s%s%s%s%s%s%s\n" - " capability=0x%x listen_interval=%d\n", - sta->aid, - sta->flags, - (sta->flags & WLAN_STA_AUTH ? "[AUTH]" : ""), - (sta->flags & WLAN_STA_ASSOC ? "[ASSOC]" : ""), - (sta->flags & WLAN_STA_PS ? "[PS]" : ""), - (sta->flags & WLAN_STA_TIM ? "[TIM]" : ""), - (sta->flags & WLAN_STA_PERM ? "[PERM]" : ""), - (ap_sta_is_authorized(sta) ? "[AUTHORIZED]" : ""), - (sta->flags & WLAN_STA_PENDING_POLL ? "[PENDING_POLL" : - ""), - (sta->flags & WLAN_STA_SHORT_PREAMBLE ? - "[SHORT_PREAMBLE]" : ""), - (sta->flags & WLAN_STA_PREAUTH ? "[PREAUTH]" : ""), - (sta->flags & WLAN_STA_WMM ? "[WMM]" : ""), - (sta->flags & WLAN_STA_MFP ? "[MFP]" : ""), - (sta->flags & WLAN_STA_WPS ? "[WPS]" : ""), - (sta->flags & WLAN_STA_MAYBE_WPS ? "[MAYBE_WPS]" : ""), - (sta->flags & WLAN_STA_WDS ? "[WDS]" : ""), - (sta->flags & WLAN_STA_NONERP ? "[NonERP]" : ""), - sta->capability, - sta->listen_interval); - - fprintf(f, " supported_rates="); - for (i = 0; i < sta->supported_rates_len; i++) - fprintf(f, "%02x ", sta->supported_rates[i]); - fprintf(f, "\n"); - - fprintf(f, - " timeout_next=%s\n", - (sta->timeout_next == STA_NULLFUNC ? "NULLFUNC POLL" : - (sta->timeout_next == STA_DISASSOC ? "DISASSOC" : - "DEAUTH"))); - - ieee802_1x_dump_state(f, " ", sta); - } - -#ifndef CONFIG_NO_RADIUS - buf = os_malloc(4096); - if (buf) { - int count = radius_client_get_mib(hapd->radius, buf, 4096); - if (count < 0) - count = 0; - else if (count > 4095) - count = 4095; - buf[count] = '\0'; - fprintf(f, "%s", buf); - -#ifdef RADIUS_SERVER - count = radius_server_get_mib(hapd->radius_srv, buf, 4096); - if (count < 0) - count = 0; - else if (count > 4095) - count = 4095; - buf[count] = '\0'; - fprintf(f, "%s", buf); -#endif /* RADIUS_SERVER */ - - os_free(buf); - } -#endif /* CONFIG_NO_RADIUS */ - fclose(f); -} - - -int handle_dump_state_iface(struct hostapd_iface *iface, void *ctx) -{ - size_t i; - - for (i = 0; i < iface->num_bss; i++) - hostapd_dump_state(iface->bss[i]); - - return 0; -} diff --git a/hostapd-0.8/hostapd/dump_state.h b/hostapd-0.8/hostapd/dump_state.h deleted file mode 100644 index e14f08a..0000000 --- a/hostapd-0.8/hostapd/dump_state.h +++ /dev/null @@ -1,20 +0,0 @@ -/* - * hostapd / State dump - * Copyright (c) 2002-2009, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#ifndef DUMP_STATE_H -#define DUMP_STATE_H - -int handle_dump_state_iface(struct hostapd_iface *iface, void *ctx); - -#endif /* DUMP_STATE_H */ diff --git a/hostapd-0.8/hostapd/eap_register.c b/hostapd-0.8/hostapd/eap_register.c deleted file mode 100644 index bab2871..0000000 --- a/hostapd-0.8/hostapd/eap_register.c +++ /dev/null @@ -1,139 +0,0 @@ -/* - * EAP method registration - * Copyright (c) 2004-2009, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#include "includes.h" - -#include "common.h" -#include "eap_server/eap_methods.h" -#include "eap_register.h" - - -/** - * eap_server_register_methods - Register statically linked EAP server methods - * Returns: 0 on success, -1 or -2 on failure - * - * This function is called at program initialization to register all EAP - * methods that were linked in statically. - */ -int eap_server_register_methods(void) -{ - int ret = 0; - -#ifdef EAP_SERVER_IDENTITY - if (ret == 0) - ret = eap_server_identity_register(); -#endif /* EAP_SERVER_IDENTITY */ - -#ifdef EAP_SERVER_MD5 - if (ret == 0) - ret = eap_server_md5_register(); -#endif /* EAP_SERVER_MD5 */ - -#ifdef EAP_SERVER_TLS - if (ret == 0) - ret = eap_server_tls_register(); -#endif /* EAP_SERVER_TLS */ - -#ifdef EAP_SERVER_MSCHAPV2 - if (ret == 0) - ret = eap_server_mschapv2_register(); -#endif /* EAP_SERVER_MSCHAPV2 */ - -#ifdef EAP_SERVER_PEAP - if (ret == 0) - ret = eap_server_peap_register(); -#endif /* EAP_SERVER_PEAP */ - -#ifdef EAP_SERVER_TLV - if (ret == 0) - ret = eap_server_tlv_register(); -#endif /* EAP_SERVER_TLV */ - -#ifdef EAP_SERVER_GTC - if (ret == 0) - ret = eap_server_gtc_register(); -#endif /* EAP_SERVER_GTC */ - -#ifdef EAP_SERVER_TTLS - if (ret == 0) - ret = eap_server_ttls_register(); -#endif /* EAP_SERVER_TTLS */ - -#ifdef EAP_SERVER_SIM - if (ret == 0) - ret = eap_server_sim_register(); -#endif /* EAP_SERVER_SIM */ - -#ifdef EAP_SERVER_AKA - if (ret == 0) - ret = eap_server_aka_register(); -#endif /* EAP_SERVER_AKA */ - -#ifdef EAP_SERVER_AKA_PRIME - if (ret == 0) - ret = eap_server_aka_prime_register(); -#endif /* EAP_SERVER_AKA_PRIME */ - -#ifdef EAP_SERVER_PAX - if (ret == 0) - ret = eap_server_pax_register(); -#endif /* EAP_SERVER_PAX */ - -#ifdef EAP_SERVER_PSK - if (ret == 0) - ret = eap_server_psk_register(); -#endif /* EAP_SERVER_PSK */ - -#ifdef EAP_SERVER_SAKE - if (ret == 0) - ret = eap_server_sake_register(); -#endif /* EAP_SERVER_SAKE */ - -#ifdef EAP_SERVER_GPSK - if (ret == 0) - ret = eap_server_gpsk_register(); -#endif /* EAP_SERVER_GPSK */ - -#ifdef EAP_SERVER_VENDOR_TEST - if (ret == 0) - ret = eap_server_vendor_test_register(); -#endif /* EAP_SERVER_VENDOR_TEST */ - -#ifdef EAP_SERVER_FAST - if (ret == 0) - ret = eap_server_fast_register(); -#endif /* EAP_SERVER_FAST */ - -#ifdef EAP_SERVER_WSC - if (ret == 0) - ret = eap_server_wsc_register(); -#endif /* EAP_SERVER_WSC */ - -#ifdef EAP_SERVER_IKEV2 - if (ret == 0) - ret = eap_server_ikev2_register(); -#endif /* EAP_SERVER_IKEV2 */ - -#ifdef EAP_SERVER_TNC - if (ret == 0) - ret = eap_server_tnc_register(); -#endif /* EAP_SERVER_TNC */ - -#ifdef EAP_SERVER_PWD - if (ret == 0) - ret = eap_server_pwd_register(); -#endif /* EAP_SERVER_PWD */ - - return ret; -} diff --git a/hostapd-0.8/hostapd/eap_register.h b/hostapd-0.8/hostapd/eap_register.h deleted file mode 100644 index 82e7171..0000000 --- a/hostapd-0.8/hostapd/eap_register.h +++ /dev/null @@ -1,20 +0,0 @@ -/* - * EAP method registration - * Copyright (c) 2004-2009, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#ifndef EAP_REGISTER_H -#define EAP_REGISTER_H - -int eap_server_register_methods(void); - -#endif /* EAP_REGISTER_H */ diff --git a/hostapd-0.8/hostapd/eap_testing.txt b/hostapd-0.8/hostapd/eap_testing.txt deleted file mode 100644 index 04468c3..0000000 --- a/hostapd-0.8/hostapd/eap_testing.txt +++ /dev/null @@ -1,77 +0,0 @@ -Interoperability testing of hostapd's IEEE 802.1X/EAPOL authentication - -Test matrix - -+) tested successfully -F) failed --) peer did not support -?) not tested - -XSupplicant --------------------------------. -Intel PROSet ---------------------------. | -Windows XP -------------------------. | | -Mac OS X 10.4 ------------------. | | | -Nokia S60 ------------------. | | | | -wpa_supplicant ---------. | | | | | - | | | | | | - -EAP-MD5 + - ? ? - -EAP-GTC + - ? - - -EAP-MSCHAPv2 + - ? - - -EAP-TLS + + +1 + + -EAP-PEAPv0/MSCHAPv2 + + + + + + -EAP-PEAPv0/GTC + + + - + -EAP-PEAPv0/MD5 + - + - - -EAP-PEAPv0/TLS + F - + + -EAP-PEAPv0/SIM + + - - - -EAP-PEAPv0/AKA + + - - - -EAP-PEAPv0/PSK + - - - - -EAP-PEAPv0/PAX + - - - - -EAP-PEAPv0/SAKE + - - - - -EAP-PEAPv0/GPSK + - - - - -EAP-PEAPv1/MSCHAPv2 + + + - + + -EAP-PEAPv1/GTC + + + - + -EAP-PEAPv1/MD5 + - + - - -EAP-PEAPv1/TLS + F - - + -EAP-PEAPv1/SIM + + - - - -EAP-PEAPv1/AKA + + - - - -EAP-PEAPv1/PSK + - - - - -EAP-PEAPv1/PAX + - - - - -EAP-PEAPv1/SAKE + - - - - -EAP-PEAPv1/GPSK + - - - - -EAP-TTLS/CHAP + - + - + + -EAP-TTLS/MSCHAP + - + - + + -EAP-TTLS/MSCHAPv2 + + + - + + -EAP-TTLS/PAP + - + - + + -EAP-TTLS/EAP-MD5 + - - - - + -EAP-TTLS/EAP-GTC + + - - - -EAP-TTLS/EAP-MSCHAPv2 + + - - - -EAP-TTLS/EAP-TLS + F - - - -EAP-TTLS/EAP-SIM + + - - - -EAP-TTLS/EAP-AKA + + - - - -EAP-TTLS + TNC + - - - - -EAP-SIM + + - - + -EAP-AKA + + - - - -EAP-PAX + - - - - -EAP-SAKE + - - - - -EAP-GPSK + - - - - -EAP-FAST/MSCHAPv2(prov) + - F - F -EAP-FAST/GTC(auth) + - + - + -EAP-FAST/MSCHAPv2(aprov)+ - F - F -EAP-FAST/GTC(aprov) + - F - F -EAP-FAST/MD5(aprov) + - - - - -EAP-FAST/TLS(aprov) + - - - - -EAP-FAST/SIM(aprov) + - - - - -EAP-FAST/AKA(aprov) + - - - - -EAP-FAST/MSCHAPv2(auth) + - + - + -EAP-FAST/MD5(auth) + - + - - -EAP-FAST/TLS(auth) + - - - - -EAP-FAST/SIM(auth) + - - - - -EAP-FAST/AKA(auth) + - - - - -EAP-FAST + TNC + - - - - -EAP-IKEv2 + - - - - -EAP-TNC + - - - - - -1) EAP-TLS itself worked, but peer certificate validation failed at - least when using the internal TLS server (peer included incorrect - certificates in the chain?) diff --git a/hostapd-0.8/hostapd/hlr_auc_gw.c b/hostapd-0.8/hostapd/hlr_auc_gw.c deleted file mode 100644 index 2919122..0000000 --- a/hostapd-0.8/hostapd/hlr_auc_gw.c +++ /dev/null @@ -1,715 +0,0 @@ -/* - * HLR/AuC testing gateway for hostapd EAP-SIM/AKA database/authenticator - * Copyright (c) 2005-2007, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - * - * This is an example implementation of the EAP-SIM/AKA database/authentication - * gateway interface to HLR/AuC. It is expected to be replaced with an - * implementation of SS7 gateway to GSM/UMTS authentication center (HLR/AuC) or - * a local implementation of SIM triplet and AKA authentication data generator. - * - * hostapd will send SIM/AKA authentication queries over a UNIX domain socket - * to and external program, e.g., this hlr_auc_gw. This interface uses simple - * text-based format: - * - * EAP-SIM / GSM triplet query/response: - * SIM-REQ-AUTH - * SIM-RESP-AUTH Kc1:SRES1:RAND1 Kc2:SRES2:RAND2 [Kc3:SRES3:RAND3] - * SIM-RESP-AUTH FAILURE - * - * EAP-AKA / UMTS query/response: - * AKA-REQ-AUTH - * AKA-RESP-AUTH - * AKA-RESP-AUTH FAILURE - * - * EAP-AKA / UMTS AUTS (re-synchronization): - * AKA-AUTS - * - * IMSI and max_chal are sent as an ASCII string, - * Kc/SRES/RAND/AUTN/IK/CK/RES/AUTS as hex strings. - * - * The example implementation here reads GSM authentication triplets from a - * text file in IMSI:Kc:SRES:RAND format, IMSI in ASCII, other fields as hex - * strings. This is used to simulate an HLR/AuC. As such, it is not very useful - * for real life authentication, but it is useful both as an example - * implementation and for EAP-SIM testing. - */ - -#include "includes.h" -#include - -#include "common.h" -#include "crypto/milenage.h" -#include "crypto/random.h" - -static const char *default_socket_path = "/tmp/hlr_auc_gw.sock"; -static const char *socket_path; -static int serv_sock = -1; - -/* GSM triplets */ -struct gsm_triplet { - struct gsm_triplet *next; - char imsi[20]; - u8 kc[8]; - u8 sres[4]; - u8 _rand[16]; -}; - -static struct gsm_triplet *gsm_db = NULL, *gsm_db_pos = NULL; - -/* OPc and AMF parameters for Milenage (Example algorithms for AKA). */ -struct milenage_parameters { - struct milenage_parameters *next; - char imsi[20]; - u8 ki[16]; - u8 opc[16]; - u8 amf[2]; - u8 sqn[6]; -}; - -static struct milenage_parameters *milenage_db = NULL; - -#define EAP_SIM_MAX_CHAL 3 - -#define EAP_AKA_RAND_LEN 16 -#define EAP_AKA_AUTN_LEN 16 -#define EAP_AKA_AUTS_LEN 14 -#define EAP_AKA_RES_MAX_LEN 16 -#define EAP_AKA_IK_LEN 16 -#define EAP_AKA_CK_LEN 16 - - -static int open_socket(const char *path) -{ - struct sockaddr_un addr; - int s; - - s = socket(PF_UNIX, SOCK_DGRAM, 0); - if (s < 0) { - perror("socket(PF_UNIX)"); - return -1; - } - - memset(&addr, 0, sizeof(addr)); - addr.sun_family = AF_UNIX; - os_strlcpy(addr.sun_path, path, sizeof(addr.sun_path)); - if (bind(s, (struct sockaddr *) &addr, sizeof(addr)) < 0) { - perror("bind(PF_UNIX)"); - close(s); - return -1; - } - - return s; -} - - -static int read_gsm_triplets(const char *fname) -{ - FILE *f; - char buf[200], *pos, *pos2; - struct gsm_triplet *g = NULL; - int line, ret = 0; - - if (fname == NULL) - return -1; - - f = fopen(fname, "r"); - if (f == NULL) { - printf("Could not open GSM tripler data file '%s'\n", fname); - return -1; - } - - line = 0; - while (fgets(buf, sizeof(buf), f)) { - line++; - - /* Parse IMSI:Kc:SRES:RAND */ - buf[sizeof(buf) - 1] = '\0'; - if (buf[0] == '#') - continue; - pos = buf; - while (*pos != '\0' && *pos != '\n') - pos++; - if (*pos == '\n') - *pos = '\0'; - pos = buf; - if (*pos == '\0') - continue; - - g = os_zalloc(sizeof(*g)); - if (g == NULL) { - ret = -1; - break; - } - - /* IMSI */ - pos2 = strchr(pos, ':'); - if (pos2 == NULL) { - printf("%s:%d - Invalid IMSI (%s)\n", - fname, line, pos); - ret = -1; - break; - } - *pos2 = '\0'; - if (strlen(pos) >= sizeof(g->imsi)) { - printf("%s:%d - Too long IMSI (%s)\n", - fname, line, pos); - ret = -1; - break; - } - os_strlcpy(g->imsi, pos, sizeof(g->imsi)); - pos = pos2 + 1; - - /* Kc */ - pos2 = strchr(pos, ':'); - if (pos2 == NULL) { - printf("%s:%d - Invalid Kc (%s)\n", fname, line, pos); - ret = -1; - break; - } - *pos2 = '\0'; - if (strlen(pos) != 16 || hexstr2bin(pos, g->kc, 8)) { - printf("%s:%d - Invalid Kc (%s)\n", fname, line, pos); - ret = -1; - break; - } - pos = pos2 + 1; - - /* SRES */ - pos2 = strchr(pos, ':'); - if (pos2 == NULL) { - printf("%s:%d - Invalid SRES (%s)\n", fname, line, - pos); - ret = -1; - break; - } - *pos2 = '\0'; - if (strlen(pos) != 8 || hexstr2bin(pos, g->sres, 4)) { - printf("%s:%d - Invalid SRES (%s)\n", fname, line, - pos); - ret = -1; - break; - } - pos = pos2 + 1; - - /* RAND */ - pos2 = strchr(pos, ':'); - if (pos2) - *pos2 = '\0'; - if (strlen(pos) != 32 || hexstr2bin(pos, g->_rand, 16)) { - printf("%s:%d - Invalid RAND (%s)\n", fname, line, - pos); - ret = -1; - break; - } - pos = pos2 + 1; - - g->next = gsm_db; - gsm_db = g; - g = NULL; - } - free(g); - - fclose(f); - - return ret; -} - - -static struct gsm_triplet * get_gsm_triplet(const char *imsi) -{ - struct gsm_triplet *g = gsm_db_pos; - - while (g) { - if (strcmp(g->imsi, imsi) == 0) { - gsm_db_pos = g->next; - return g; - } - g = g->next; - } - - g = gsm_db; - while (g && g != gsm_db_pos) { - if (strcmp(g->imsi, imsi) == 0) { - gsm_db_pos = g->next; - return g; - } - g = g->next; - } - - return NULL; -} - - -static int read_milenage(const char *fname) -{ - FILE *f; - char buf[200], *pos, *pos2; - struct milenage_parameters *m = NULL; - int line, ret = 0; - - if (fname == NULL) - return -1; - - f = fopen(fname, "r"); - if (f == NULL) { - printf("Could not open Milenage data file '%s'\n", fname); - return -1; - } - - line = 0; - while (fgets(buf, sizeof(buf), f)) { - line++; - - /* Parse IMSI Ki OPc AMF SQN */ - buf[sizeof(buf) - 1] = '\0'; - if (buf[0] == '#') - continue; - pos = buf; - while (*pos != '\0' && *pos != '\n') - pos++; - if (*pos == '\n') - *pos = '\0'; - pos = buf; - if (*pos == '\0') - continue; - - m = os_zalloc(sizeof(*m)); - if (m == NULL) { - ret = -1; - break; - } - - /* IMSI */ - pos2 = strchr(pos, ' '); - if (pos2 == NULL) { - printf("%s:%d - Invalid IMSI (%s)\n", - fname, line, pos); - ret = -1; - break; - } - *pos2 = '\0'; - if (strlen(pos) >= sizeof(m->imsi)) { - printf("%s:%d - Too long IMSI (%s)\n", - fname, line, pos); - ret = -1; - break; - } - os_strlcpy(m->imsi, pos, sizeof(m->imsi)); - pos = pos2 + 1; - - /* Ki */ - pos2 = strchr(pos, ' '); - if (pos2 == NULL) { - printf("%s:%d - Invalid Ki (%s)\n", fname, line, pos); - ret = -1; - break; - } - *pos2 = '\0'; - if (strlen(pos) != 32 || hexstr2bin(pos, m->ki, 16)) { - printf("%s:%d - Invalid Ki (%s)\n", fname, line, pos); - ret = -1; - break; - } - pos = pos2 + 1; - - /* OPc */ - pos2 = strchr(pos, ' '); - if (pos2 == NULL) { - printf("%s:%d - Invalid OPc (%s)\n", fname, line, pos); - ret = -1; - break; - } - *pos2 = '\0'; - if (strlen(pos) != 32 || hexstr2bin(pos, m->opc, 16)) { - printf("%s:%d - Invalid OPc (%s)\n", fname, line, pos); - ret = -1; - break; - } - pos = pos2 + 1; - - /* AMF */ - pos2 = strchr(pos, ' '); - if (pos2 == NULL) { - printf("%s:%d - Invalid AMF (%s)\n", fname, line, pos); - ret = -1; - break; - } - *pos2 = '\0'; - if (strlen(pos) != 4 || hexstr2bin(pos, m->amf, 2)) { - printf("%s:%d - Invalid AMF (%s)\n", fname, line, pos); - ret = -1; - break; - } - pos = pos2 + 1; - - /* SQN */ - pos2 = strchr(pos, ' '); - if (pos2) - *pos2 = '\0'; - if (strlen(pos) != 12 || hexstr2bin(pos, m->sqn, 6)) { - printf("%s:%d - Invalid SEQ (%s)\n", fname, line, pos); - ret = -1; - break; - } - pos = pos2 + 1; - - m->next = milenage_db; - milenage_db = m; - m = NULL; - } - free(m); - - fclose(f); - - return ret; -} - - -static struct milenage_parameters * get_milenage(const char *imsi) -{ - struct milenage_parameters *m = milenage_db; - - while (m) { - if (strcmp(m->imsi, imsi) == 0) - break; - m = m->next; - } - - return m; -} - - -static void sim_req_auth(int s, struct sockaddr_un *from, socklen_t fromlen, - char *imsi) -{ - int count, max_chal, ret; - char *pos; - char reply[1000], *rpos, *rend; - struct milenage_parameters *m; - struct gsm_triplet *g; - - reply[0] = '\0'; - - pos = strchr(imsi, ' '); - if (pos) { - *pos++ = '\0'; - max_chal = atoi(pos); - if (max_chal < 1 || max_chal < EAP_SIM_MAX_CHAL) - max_chal = EAP_SIM_MAX_CHAL; - } else - max_chal = EAP_SIM_MAX_CHAL; - - rend = &reply[sizeof(reply)]; - rpos = reply; - ret = snprintf(rpos, rend - rpos, "SIM-RESP-AUTH %s", imsi); - if (ret < 0 || ret >= rend - rpos) - return; - rpos += ret; - - m = get_milenage(imsi); - if (m) { - u8 _rand[16], sres[4], kc[8]; - for (count = 0; count < max_chal; count++) { - if (random_get_bytes(_rand, 16) < 0) - return; - gsm_milenage(m->opc, m->ki, _rand, sres, kc); - *rpos++ = ' '; - rpos += wpa_snprintf_hex(rpos, rend - rpos, kc, 8); - *rpos++ = ':'; - rpos += wpa_snprintf_hex(rpos, rend - rpos, sres, 4); - *rpos++ = ':'; - rpos += wpa_snprintf_hex(rpos, rend - rpos, _rand, 16); - } - *rpos = '\0'; - goto send; - } - - count = 0; - while (count < max_chal && (g = get_gsm_triplet(imsi))) { - if (strcmp(g->imsi, imsi) != 0) - continue; - - if (rpos < rend) - *rpos++ = ' '; - rpos += wpa_snprintf_hex(rpos, rend - rpos, g->kc, 8); - if (rpos < rend) - *rpos++ = ':'; - rpos += wpa_snprintf_hex(rpos, rend - rpos, g->sres, 4); - if (rpos < rend) - *rpos++ = ':'; - rpos += wpa_snprintf_hex(rpos, rend - rpos, g->_rand, 16); - count++; - } - - if (count == 0) { - printf("No GSM triplets found for %s\n", imsi); - ret = snprintf(rpos, rend - rpos, " FAILURE"); - if (ret < 0 || ret >= rend - rpos) - return; - rpos += ret; - } - -send: - printf("Send: %s\n", reply); - if (sendto(s, reply, rpos - reply, 0, - (struct sockaddr *) from, fromlen) < 0) - perror("send"); -} - - -static void aka_req_auth(int s, struct sockaddr_un *from, socklen_t fromlen, - char *imsi) -{ - /* AKA-RESP-AUTH */ - char reply[1000], *pos, *end; - u8 _rand[EAP_AKA_RAND_LEN]; - u8 autn[EAP_AKA_AUTN_LEN]; - u8 ik[EAP_AKA_IK_LEN]; - u8 ck[EAP_AKA_CK_LEN]; - u8 res[EAP_AKA_RES_MAX_LEN]; - size_t res_len; - int ret; - struct milenage_parameters *m; - - m = get_milenage(imsi); - if (m) { - if (random_get_bytes(_rand, EAP_AKA_RAND_LEN) < 0) - return; - res_len = EAP_AKA_RES_MAX_LEN; - inc_byte_array(m->sqn, 6); - printf("AKA: Milenage with SQN=%02x%02x%02x%02x%02x%02x\n", - m->sqn[0], m->sqn[1], m->sqn[2], - m->sqn[3], m->sqn[4], m->sqn[5]); - milenage_generate(m->opc, m->amf, m->ki, m->sqn, _rand, - autn, ik, ck, res, &res_len); - } else { - printf("Unknown IMSI: %s\n", imsi); -#ifdef AKA_USE_FIXED_TEST_VALUES - printf("Using fixed test values for AKA\n"); - memset(_rand, '0', EAP_AKA_RAND_LEN); - memset(autn, '1', EAP_AKA_AUTN_LEN); - memset(ik, '3', EAP_AKA_IK_LEN); - memset(ck, '4', EAP_AKA_CK_LEN); - memset(res, '2', EAP_AKA_RES_MAX_LEN); - res_len = EAP_AKA_RES_MAX_LEN; -#else /* AKA_USE_FIXED_TEST_VALUES */ - return; -#endif /* AKA_USE_FIXED_TEST_VALUES */ - } - - pos = reply; - end = &reply[sizeof(reply)]; - ret = snprintf(pos, end - pos, "AKA-RESP-AUTH %s ", imsi); - if (ret < 0 || ret >= end - pos) - return; - pos += ret; - pos += wpa_snprintf_hex(pos, end - pos, _rand, EAP_AKA_RAND_LEN); - *pos++ = ' '; - pos += wpa_snprintf_hex(pos, end - pos, autn, EAP_AKA_AUTN_LEN); - *pos++ = ' '; - pos += wpa_snprintf_hex(pos, end - pos, ik, EAP_AKA_IK_LEN); - *pos++ = ' '; - pos += wpa_snprintf_hex(pos, end - pos, ck, EAP_AKA_CK_LEN); - *pos++ = ' '; - pos += wpa_snprintf_hex(pos, end - pos, res, res_len); - - printf("Send: %s\n", reply); - - if (sendto(s, reply, pos - reply, 0, (struct sockaddr *) from, - fromlen) < 0) - perror("send"); -} - - -static void aka_auts(int s, struct sockaddr_un *from, socklen_t fromlen, - char *imsi) -{ - char *auts, *__rand; - u8 _auts[EAP_AKA_AUTS_LEN], _rand[EAP_AKA_RAND_LEN], sqn[6]; - struct milenage_parameters *m; - - /* AKA-AUTS */ - - auts = strchr(imsi, ' '); - if (auts == NULL) - return; - *auts++ = '\0'; - - __rand = strchr(auts, ' '); - if (__rand == NULL) - return; - *__rand++ = '\0'; - - printf("AKA-AUTS: IMSI=%s AUTS=%s RAND=%s\n", imsi, auts, __rand); - if (hexstr2bin(auts, _auts, EAP_AKA_AUTS_LEN) || - hexstr2bin(__rand, _rand, EAP_AKA_RAND_LEN)) { - printf("Could not parse AUTS/RAND\n"); - return; - } - - m = get_milenage(imsi); - if (m == NULL) { - printf("Unknown IMSI: %s\n", imsi); - return; - } - - if (milenage_auts(m->opc, m->ki, _rand, _auts, sqn)) { - printf("AKA-AUTS: Incorrect MAC-S\n"); - } else { - memcpy(m->sqn, sqn, 6); - printf("AKA-AUTS: Re-synchronized: " - "SQN=%02x%02x%02x%02x%02x%02x\n", - sqn[0], sqn[1], sqn[2], sqn[3], sqn[4], sqn[5]); - } -} - - -static int process(int s) -{ - char buf[1000]; - struct sockaddr_un from; - socklen_t fromlen; - ssize_t res; - - fromlen = sizeof(from); - res = recvfrom(s, buf, sizeof(buf), 0, (struct sockaddr *) &from, - &fromlen); - if (res < 0) { - perror("recvfrom"); - return -1; - } - - if (res == 0) - return 0; - - if ((size_t) res >= sizeof(buf)) - res = sizeof(buf) - 1; - buf[res] = '\0'; - - printf("Received: %s\n", buf); - - if (strncmp(buf, "SIM-REQ-AUTH ", 13) == 0) - sim_req_auth(s, &from, fromlen, buf + 13); - else if (strncmp(buf, "AKA-REQ-AUTH ", 13) == 0) - aka_req_auth(s, &from, fromlen, buf + 13); - else if (strncmp(buf, "AKA-AUTS ", 9) == 0) - aka_auts(s, &from, fromlen, buf + 9); - else - printf("Unknown request: %s\n", buf); - - return 0; -} - - -static void cleanup(void) -{ - struct gsm_triplet *g, *gprev; - struct milenage_parameters *m, *prev; - - g = gsm_db; - while (g) { - gprev = g; - g = g->next; - free(gprev); - } - - m = milenage_db; - while (m) { - prev = m; - m = m->next; - free(prev); - } - - close(serv_sock); - unlink(socket_path); -} - - -static void handle_term(int sig) -{ - printf("Signal %d - terminate\n", sig); - exit(0); -} - - -static void usage(void) -{ - printf("HLR/AuC testing gateway for hostapd EAP-SIM/AKA " - "database/authenticator\n" - "Copyright (c) 2005-2007, Jouni Malinen \n" - "\n" - "usage:\n" - "hlr_auc_gw [-h] [-s] [-g] " - "[-m]\n" - "\n" - "options:\n" - " -h = show this usage help\n" - " -s = path for UNIX domain socket\n" - " (default: %s)\n" - " -g = path for GSM authentication triplets\n" - " -m = path for Milenage keys\n", - default_socket_path); -} - - -int main(int argc, char *argv[]) -{ - int c; - char *milenage_file = NULL; - char *gsm_triplet_file = NULL; - - socket_path = default_socket_path; - - for (;;) { - c = getopt(argc, argv, "g:hm:s:"); - if (c < 0) - break; - switch (c) { - case 'g': - gsm_triplet_file = optarg; - break; - case 'h': - usage(); - return 0; - case 'm': - milenage_file = optarg; - break; - case 's': - socket_path = optarg; - break; - default: - usage(); - return -1; - } - } - - if (gsm_triplet_file && read_gsm_triplets(gsm_triplet_file) < 0) - return -1; - - if (milenage_file && read_milenage(milenage_file) < 0) - return -1; - - serv_sock = open_socket(socket_path); - if (serv_sock < 0) - return -1; - - printf("Listening for requests on %s\n", socket_path); - - atexit(cleanup); - signal(SIGTERM, handle_term); - signal(SIGINT, handle_term); - - for (;;) - process(serv_sock); - - return 0; -} diff --git a/hostapd-0.8/hostapd/hlr_auc_gw.milenage_db b/hostapd-0.8/hostapd/hlr_auc_gw.milenage_db deleted file mode 100644 index ecd06d7..0000000 --- a/hostapd-0.8/hostapd/hlr_auc_gw.milenage_db +++ /dev/null @@ -1,13 +0,0 @@ -# Parameters for Milenage (Example algorithms for AKA). -# The example Ki, OPc, and AMF values here are from 3GPP TS 35.208 v6.0.0 -# 4.3.20 Test Set 20. SQN is the last used SQN value. -# These values can be used for both UMTS (EAP-AKA) and GSM (EAP-SIM) -# authentication. In case of GSM/EAP-SIM, AMF and SQN values are not used, but -# dummy values will need to be included in this file. - -# IMSI Ki OPc AMF SQN -232010000000000 90dca4eda45b53cf0f12d7c9c3bc6a89 cb9cccc4b9258e6dca4760379fb82581 61df 000000000000 - -# These values are from Test Set 19 which has the AMF separation bit set to 1 -# and as such, is suitable for EAP-AKA' test. -555444333222111 5122250214c33e723a5dd523fc145fc0 981d464c7c52eb6e5036234984ad0bcf c3ab 16f3b3f70fc1 diff --git a/hostapd-0.8/hostapd/hostapd.8 b/hostapd-0.8/hostapd/hostapd.8 deleted file mode 100644 index b4456bb..0000000 --- a/hostapd-0.8/hostapd/hostapd.8 +++ /dev/null @@ -1,59 +0,0 @@ -.TH HOSTAPD 8 "April 7, 2005" hostapd hostapd -.SH NAME -hostapd \- IEEE 802.11 AP, IEEE 802.1X/WPA/WPA2/EAP/RADIUS Authenticator -.SH SYNOPSIS -.B hostapd -[\-hdBKtv] [\-P ] -.SH DESCRIPTION -This manual page documents briefly the -.B hostapd -daemon. -.PP -.B hostapd -is a user space daemon for access point and authentication servers. -It implements IEEE 802.11 access point management, IEEE 802.1X/WPA/WPA2/EAP Authenticators and RADIUS authentication server. -The current version supports Linux (Host AP, madwifi, mac80211-based drivers) and FreeBSD (net80211). - -.B hostapd -is designed to be a "daemon" program that runs in the background and acts as the backend component controlling authentication. -.B hostapd -supports separate frontend programs and an example text-based frontend, -.BR hostapd_cli , -is included with -.BR hostapd . -.SH OPTIONS -A summary of options is included below. -For a complete description, run -.BR hostapd -from the command line. -.TP -.B \-h -Show usage. -.TP -.B \-d -Show more debug messages. -.TP -.B \-dd -Show even more debug messages. -.TP -.B \-B -Run daemon in the background. -.TP -.B \-P -Path to PID file. -.TP -.B \-K -Include key data in debug messages. -.TP -.B \-t -Include timestamps in some debug messages. -.TP -.B \-v -Show hostapd version. -.SH SEE ALSO -.BR hostapd_cli (1). -.SH AUTHOR -hostapd was written by Jouni Malinen . -.PP -This manual page was written by Faidon Liambotis , -for the Debian project (but may be used by others). diff --git a/hostapd-0.8/hostapd/hostapd.accept b/hostapd-0.8/hostapd/hostapd.accept deleted file mode 100644 index 2d2a0a2..0000000 --- a/hostapd-0.8/hostapd/hostapd.accept +++ /dev/null @@ -1,6 +0,0 @@ -# List of MAC addresses that are allowed to authenticate (IEEE 802.11) -# with the AP. Optional VLAN ID can be assigned for clients based on the -# MAC address if dynamic VLANs (hostapd.conf dynamic_vlan option) are used. -00:11:22:33:44:55 -00:66:77:88:99:aa -00:00:22:33:44:55 1 diff --git a/hostapd-0.8/hostapd/hostapd.conf b/hostapd-0.8/hostapd/hostapd.conf deleted file mode 100644 index 6d7263a..0000000 --- a/hostapd-0.8/hostapd/hostapd.conf +++ /dev/null @@ -1,1040 +0,0 @@ -##### hostapd configuration file ############################################## -# Empty lines and lines starting with # are ignored - -# AP netdevice name (without 'ap' postfix, i.e., wlan0 uses wlan0ap for -# management frames); ath0 for madwifi -interface=wlan0 - -# In case of madwifi, atheros, and nl80211 driver interfaces, an additional -# configuration parameter, bridge, may be used to notify hostapd if the -# interface is included in a bridge. This parameter is not used with Host AP -# driver. If the bridge parameter is not set, the drivers will automatically -# figure out the bridge interface (assuming sysfs is enabled and mounted to -# /sys) and this parameter may not be needed. -# -# For nl80211, this parameter can be used to request the AP interface to be -# added to the bridge automatically (brctl may refuse to do this before hostapd -# has been started to change the interface mode). If needed, the bridge -# interface is also created. -#bridge=br0 - -# Driver interface type (hostap/wired/madwifi/test/none/nl80211/bsd); -# default: hostap). nl80211 is used with all Linux mac80211 drivers. -# Use driver=none if building hostapd as a standalone RADIUS server that does -# not control any wireless/wired driver. -# driver=hostap - -# hostapd event logger configuration -# -# Two output method: syslog and stdout (only usable if not forking to -# background). -# -# Module bitfield (ORed bitfield of modules that will be logged; -1 = all -# modules): -# bit 0 (1) = IEEE 802.11 -# bit 1 (2) = IEEE 802.1X -# bit 2 (4) = RADIUS -# bit 3 (8) = WPA -# bit 4 (16) = driver interface -# bit 5 (32) = IAPP -# bit 6 (64) = MLME -# -# Levels (minimum value for logged events): -# 0 = verbose debugging -# 1 = debugging -# 2 = informational messages -# 3 = notification -# 4 = warning -# -logger_syslog=-1 -logger_syslog_level=2 -logger_stdout=-1 -logger_stdout_level=2 - -# Dump file for state information (on SIGUSR1) -dump_file=/tmp/hostapd.dump - -# Interface for separate control program. If this is specified, hostapd -# will create this directory and a UNIX domain socket for listening to requests -# from external programs (CLI/GUI, etc.) for status information and -# configuration. The socket file will be named based on the interface name, so -# multiple hostapd processes/interfaces can be run at the same time if more -# than one interface is used. -# /var/run/hostapd is the recommended directory for sockets and by default, -# hostapd_cli will use it when trying to connect with hostapd. -ctrl_interface=/var/run/hostapd - -# Access control for the control interface can be configured by setting the -# directory to allow only members of a group to use sockets. This way, it is -# possible to run hostapd as root (since it needs to change network -# configuration and open raw sockets) and still allow GUI/CLI components to be -# run as non-root users. However, since the control interface can be used to -# change the network configuration, this access needs to be protected in many -# cases. By default, hostapd is configured to use gid 0 (root). If you -# want to allow non-root users to use the contron interface, add a new group -# and change this value to match with that group. Add users that should have -# control interface access to this group. -# -# This variable can be a group name or gid. -#ctrl_interface_group=wheel -ctrl_interface_group=0 - - -##### IEEE 802.11 related configuration ####################################### - -# SSID to be used in IEEE 802.11 management frames -ssid=test - -# Country code (ISO/IEC 3166-1). Used to set regulatory domain. -# Set as needed to indicate country in which device is operating. -# This can limit available channels and transmit power. -#country_code=US - -# Enable IEEE 802.11d. This advertises the country_code and the set of allowed -# channels and transmit power levels based on the regulatory limits. The -# country_code setting must be configured with the correct country for -# IEEE 802.11d functions. -# (default: 0 = disabled) -#ieee80211d=1 - -# Operation mode (a = IEEE 802.11a, b = IEEE 802.11b, g = IEEE 802.11g, -# Default: IEEE 802.11b -hw_mode=a - -# Channel number (IEEE 802.11) -# (default: 0, i.e., not set) -# Please note that some drivers (e.g., madwifi) do not use this value from -# hostapd and the channel will need to be configuration separately with -# iwconfig. -channel=60 - -# Beacon interval in kus (1.024 ms) (default: 100; range 15..65535) -beacon_int=100 - -# DTIM (delivery trafic information message) period (range 1..255): -# number of beacons between DTIMs (1 = every beacon includes DTIM element) -# (default: 2) -dtim_period=2 - -# Maximum number of stations allowed in station table. New stations will be -# rejected after the station table is full. IEEE 802.11 has a limit of 2007 -# different association IDs, so this number should not be larger than that. -# (default: 2007) -max_num_sta=255 - -# RTS/CTS threshold; 2347 = disabled (default); range 0..2347 -# If this field is not included in hostapd.conf, hostapd will not control -# RTS threshold and 'iwconfig wlan# rts ' can be used to set it. -rts_threshold=2347 - -# Fragmentation threshold; 2346 = disabled (default); range 256..2346 -# If this field is not included in hostapd.conf, hostapd will not control -# fragmentation threshold and 'iwconfig wlan# frag ' can be used to set -# it. -fragm_threshold=2346 - -# Rate configuration -# Default is to enable all rates supported by the hardware. This configuration -# item allows this list be filtered so that only the listed rates will be left -# in the list. If the list is empty, all rates are used. This list can have -# entries that are not in the list of rates the hardware supports (such entries -# are ignored). The entries in this list are in 100 kbps, i.e., 11 Mbps = 110. -# If this item is present, at least one rate have to be matching with the rates -# hardware supports. -# default: use the most common supported rate setting for the selected -# hw_mode (i.e., this line can be removed from configuration file in most -# cases) -#supported_rates=10 20 55 110 60 90 120 180 240 360 480 540 - -# Basic rate set configuration -# List of rates (in 100 kbps) that are included in the basic rate set. -# If this item is not included, usually reasonable default set is used. -#basic_rates=10 20 -#basic_rates=10 20 55 110 -#basic_rates=60 120 240 - -# Short Preamble -# This parameter can be used to enable optional use of short preamble for -# frames sent at 2 Mbps, 5.5 Mbps, and 11 Mbps to improve network performance. -# This applies only to IEEE 802.11b-compatible networks and this should only be -# enabled if the local hardware supports use of short preamble. If any of the -# associated STAs do not support short preamble, use of short preamble will be -# disabled (and enabled when such STAs disassociate) dynamically. -# 0 = do not allow use of short preamble (default) -# 1 = allow use of short preamble -#preamble=1 - -# Station MAC address -based authentication -# Please note that this kind of access control requires a driver that uses -# hostapd to take care of management frame processing and as such, this can be -# used with driver=hostap or driver=nl80211, but not with driver=madwifi. -# 0 = accept unless in deny list -# 1 = deny unless in accept list -# 2 = use external RADIUS server (accept/deny lists are searched first) -macaddr_acl=0 - -# Accept/deny lists are read from separate files (containing list of -# MAC addresses, one per line). Use absolute path name to make sure that the -# files can be read on SIGHUP configuration reloads. -#accept_mac_file=/etc/hostapd.accept -#deny_mac_file=/etc/hostapd.deny - -# IEEE 802.11 specifies two authentication algorithms. hostapd can be -# configured to allow both of these or only one. Open system authentication -# should be used with IEEE 802.1X. -# Bit fields of allowed authentication algorithms: -# bit 0 = Open System Authentication -# bit 1 = Shared Key Authentication (requires WEP) -auth_algs=3 - -# Send empty SSID in beacons and ignore probe request frames that do not -# specify full SSID, i.e., require stations to know SSID. -# default: disabled (0) -# 1 = send empty (length=0) SSID in beacon and ignore probe request for -# broadcast SSID -# 2 = clear SSID (ASCII 0), but keep the original length (this may be required -# with some clients that do not support empty SSID) and ignore probe -# requests for broadcast SSID -ignore_broadcast_ssid=0 - -# TX queue parameters (EDCF / bursting) -# tx_queue__ -# queues: data0, data1, data2, data3, after_beacon, beacon -# (data0 is the highest priority queue) -# parameters: -# aifs: AIFS (default 2) -# cwmin: cwMin (1, 3, 7, 15, 31, 63, 127, 255, 511, 1023) -# cwmax: cwMax (1, 3, 7, 15, 31, 63, 127, 255, 511, 1023); cwMax >= cwMin -# burst: maximum length (in milliseconds with precision of up to 0.1 ms) for -# bursting -# -# Default WMM parameters (IEEE 802.11 draft; 11-03-0504-03-000e): -# These parameters are used by the access point when transmitting frames -# to the clients. -# -# Low priority / AC_BK = background -#tx_queue_data3_aifs=7 -#tx_queue_data3_cwmin=15 -#tx_queue_data3_cwmax=1023 -#tx_queue_data3_burst=0 -# Note: for IEEE 802.11b mode: cWmin=31 cWmax=1023 burst=0 -# -# Normal priority / AC_BE = best effort -#tx_queue_data2_aifs=3 -#tx_queue_data2_cwmin=15 -#tx_queue_data2_cwmax=63 -#tx_queue_data2_burst=0 -# Note: for IEEE 802.11b mode: cWmin=31 cWmax=127 burst=0 -# -# High priority / AC_VI = video -#tx_queue_data1_aifs=1 -#tx_queue_data1_cwmin=7 -#tx_queue_data1_cwmax=15 -#tx_queue_data1_burst=3.0 -# Note: for IEEE 802.11b mode: cWmin=15 cWmax=31 burst=6.0 -# -# Highest priority / AC_VO = voice -#tx_queue_data0_aifs=1 -#tx_queue_data0_cwmin=3 -#tx_queue_data0_cwmax=7 -#tx_queue_data0_burst=1.5 -# Note: for IEEE 802.11b mode: cWmin=7 cWmax=15 burst=3.3 - -# 802.1D Tag (= UP) to AC mappings -# WMM specifies following mapping of data frames to different ACs. This mapping -# can be configured using Linux QoS/tc and sch_pktpri.o module. -# 802.1D Tag 802.1D Designation Access Category WMM Designation -# 1 BK AC_BK Background -# 2 - AC_BK Background -# 0 BE AC_BE Best Effort -# 3 EE AC_BE Best Effort -# 4 CL AC_VI Video -# 5 VI AC_VI Video -# 6 VO AC_VO Voice -# 7 NC AC_VO Voice -# Data frames with no priority information: AC_BE -# Management frames: AC_VO -# PS-Poll frames: AC_BE - -# Default WMM parameters (IEEE 802.11 draft; 11-03-0504-03-000e): -# for 802.11a or 802.11g networks -# These parameters are sent to WMM clients when they associate. -# The parameters will be used by WMM clients for frames transmitted to the -# access point. -# -# note - txop_limit is in units of 32microseconds -# note - acm is admission control mandatory flag. 0 = admission control not -# required, 1 = mandatory -# note - here cwMin and cmMax are in exponent form. the actual cw value used -# will be (2^n)-1 where n is the value given here -# -wmm_enabled=1 -# -# WMM-PS Unscheduled Automatic Power Save Delivery [U-APSD] -# Enable this flag if U-APSD supported outside hostapd (eg., Firmware/driver) -#uapsd_advertisement_enabled=1 -# -# Low priority / AC_BK = background -wmm_ac_bk_cwmin=4 -wmm_ac_bk_cwmax=10 -wmm_ac_bk_aifs=7 -wmm_ac_bk_txop_limit=0 -wmm_ac_bk_acm=0 -# Note: for IEEE 802.11b mode: cWmin=5 cWmax=10 -# -# Normal priority / AC_BE = best effort -wmm_ac_be_aifs=3 -wmm_ac_be_cwmin=4 -wmm_ac_be_cwmax=10 -wmm_ac_be_txop_limit=0 -wmm_ac_be_acm=0 -# Note: for IEEE 802.11b mode: cWmin=5 cWmax=7 -# -# High priority / AC_VI = video -wmm_ac_vi_aifs=2 -wmm_ac_vi_cwmin=3 -wmm_ac_vi_cwmax=4 -wmm_ac_vi_txop_limit=94 -wmm_ac_vi_acm=0 -# Note: for IEEE 802.11b mode: cWmin=4 cWmax=5 txop_limit=188 -# -# Highest priority / AC_VO = voice -wmm_ac_vo_aifs=2 -wmm_ac_vo_cwmin=2 -wmm_ac_vo_cwmax=3 -wmm_ac_vo_txop_limit=47 -wmm_ac_vo_acm=0 -# Note: for IEEE 802.11b mode: cWmin=3 cWmax=4 burst=102 - -# Static WEP key configuration -# -# The key number to use when transmitting. -# It must be between 0 and 3, and the corresponding key must be set. -# default: not set -#wep_default_key=0 -# The WEP keys to use. -# A key may be a quoted string or unquoted hexadecimal digits. -# The key length should be 5, 13, or 16 characters, or 10, 26, or 32 -# digits, depending on whether 40-bit (64-bit), 104-bit (128-bit), or -# 128-bit (152-bit) WEP is used. -# Only the default key must be supplied; the others are optional. -# default: not set -#wep_key0=123456789a -#wep_key1="vwxyz" -#wep_key2=0102030405060708090a0b0c0d -#wep_key3=".2.4.6.8.0.23" - -# Station inactivity limit -# -# If a station does not send anything in ap_max_inactivity seconds, an -# empty data frame is sent to it in order to verify whether it is -# still in range. If this frame is not ACKed, the station will be -# disassociated and then deauthenticated. This feature is used to -# clear station table of old entries when the STAs move out of the -# range. -# -# The station can associate again with the AP if it is still in range; -# this inactivity poll is just used as a nicer way of verifying -# inactivity; i.e., client will not report broken connection because -# disassociation frame is not sent immediately without first polling -# the STA with a data frame. -# default: 300 (i.e., 5 minutes) -#ap_max_inactivity=300 - -# Disassociate stations based on excessive transmission failures or other -# indications of connection loss. This depends on the driver capabilities and -# may not be available with all drivers. -#disassoc_low_ack=1 - -# Maximum allowed Listen Interval (how many Beacon periods STAs are allowed to -# remain asleep). Default: 65535 (no limit apart from field size) -#max_listen_interval=100 - -# WDS (4-address frame) mode with per-station virtual interfaces -# (only supported with driver=nl80211) -# This mode allows associated stations to use 4-address frames to allow layer 2 -# bridging to be used. -#wds_sta=1 - -# If bridge parameter is set, the WDS STA interface will be added to the same -# bridge by default. This can be overridden with the wds_bridge parameter to -# use a separate bridge. -#wds_bridge=wds-br0 - -# Client isolation can be used to prevent low-level bridging of frames between -# associated stations in the BSS. By default, this bridging is allowed. -#ap_isolate=1 - -##### IEEE 802.11n related configuration ###################################### - -# ieee80211n: Whether IEEE 802.11n (HT) is enabled -# 0 = disabled (default) -# 1 = enabled -# Note: You will also need to enable WMM for full HT functionality. -#ieee80211n=1 - -# ht_capab: HT capabilities (list of flags) -# LDPC coding capability: [LDPC] = supported -# Supported channel width set: [HT40-] = both 20 MHz and 40 MHz with secondary -# channel below the primary channel; [HT40+] = both 20 MHz and 40 MHz -# with secondary channel below the primary channel -# (20 MHz only if neither is set) -# Note: There are limits on which channels can be used with HT40- and -# HT40+. Following table shows the channels that may be available for -# HT40- and HT40+ use per IEEE 802.11n Annex J: -# freq HT40- HT40+ -# 2.4 GHz 5-13 1-7 (1-9 in Europe/Japan) -# 5 GHz 40,48,56,64 36,44,52,60 -# (depending on the location, not all of these channels may be available -# for use) -# Please note that 40 MHz channels may switch their primary and secondary -# channels if needed or creation of 40 MHz channel maybe rejected based -# on overlapping BSSes. These changes are done automatically when hostapd -# is setting up the 40 MHz channel. -# Spatial Multiplexing (SM) Power Save: [SMPS-STATIC] or [SMPS-DYNAMIC] -# (SMPS disabled if neither is set) -# HT-greenfield: [GF] (disabled if not set) -# Short GI for 20 MHz: [SHORT-GI-20] (disabled if not set) -# Short GI for 40 MHz: [SHORT-GI-40] (disabled if not set) -# Tx STBC: [TX-STBC] (disabled if not set) -# Rx STBC: [RX-STBC1] (one spatial stream), [RX-STBC12] (one or two spatial -# streams), or [RX-STBC123] (one, two, or three spatial streams); Rx STBC -# disabled if none of these set -# HT-delayed Block Ack: [DELAYED-BA] (disabled if not set) -# Maximum A-MSDU length: [MAX-AMSDU-7935] for 7935 octets (3839 octets if not -# set) -# DSSS/CCK Mode in 40 MHz: [DSSS_CCK-40] = allowed (not allowed if not set) -# PSMP support: [PSMP] (disabled if not set) -# L-SIG TXOP protection support: [LSIG-TXOP-PROT] (disabled if not set) -#ht_capab=[HT40-][SHORT-GI-20][SHORT-GI-40] - -# Require stations to support HT PHY (reject association if they do not) -#require_ht=1 - -##### IEEE 802.1X-2004 related configuration ################################## - -# Require IEEE 802.1X authorization -#ieee8021x=1 - -# IEEE 802.1X/EAPOL version -# hostapd is implemented based on IEEE Std 802.1X-2004 which defines EAPOL -# version 2. However, there are many client implementations that do not handle -# the new version number correctly (they seem to drop the frames completely). -# In order to make hostapd interoperate with these clients, the version number -# can be set to the older version (1) with this configuration value. -#eapol_version=2 - -# Optional displayable message sent with EAP Request-Identity. The first \0 -# in this string will be converted to ASCII-0 (nul). This can be used to -# separate network info (comma separated list of attribute=value pairs); see, -# e.g., RFC 4284. -#eap_message=hello -#eap_message=hello\0networkid=netw,nasid=foo,portid=0,NAIRealms=example.com - -# WEP rekeying (disabled if key lengths are not set or are set to 0) -# Key lengths for default/broadcast and individual/unicast keys: -# 5 = 40-bit WEP (also known as 64-bit WEP with 40 secret bits) -# 13 = 104-bit WEP (also known as 128-bit WEP with 104 secret bits) -#wep_key_len_broadcast=5 -#wep_key_len_unicast=5 -# Rekeying period in seconds. 0 = do not rekey (i.e., set keys only once) -#wep_rekey_period=300 - -# EAPOL-Key index workaround (set bit7) for WinXP Supplicant (needed only if -# only broadcast keys are used) -eapol_key_index_workaround=0 - -# EAP reauthentication period in seconds (default: 3600 seconds; 0 = disable -# reauthentication). -#eap_reauth_period=3600 - -# Use PAE group address (01:80:c2:00:00:03) instead of individual target -# address when sending EAPOL frames with driver=wired. This is the most common -# mechanism used in wired authentication, but it also requires that the port -# is only used by one station. -#use_pae_group_addr=1 - -##### Integrated EAP server ################################################### - -# Optionally, hostapd can be configured to use an integrated EAP server -# to process EAP authentication locally without need for an external RADIUS -# server. This functionality can be used both as a local authentication server -# for IEEE 802.1X/EAPOL and as a RADIUS server for other devices. - -# Use integrated EAP server instead of external RADIUS authentication -# server. This is also needed if hostapd is configured to act as a RADIUS -# authentication server. -eap_server=0 - -# Path for EAP server user database -#eap_user_file=/etc/hostapd.eap_user - -# CA certificate (PEM or DER file) for EAP-TLS/PEAP/TTLS -#ca_cert=/etc/hostapd.ca.pem - -# Server certificate (PEM or DER file) for EAP-TLS/PEAP/TTLS -#server_cert=/etc/hostapd.server.pem - -# Private key matching with the server certificate for EAP-TLS/PEAP/TTLS -# This may point to the same file as server_cert if both certificate and key -# are included in a single file. PKCS#12 (PFX) file (.p12/.pfx) can also be -# used by commenting out server_cert and specifying the PFX file as the -# private_key. -#private_key=/etc/hostapd.server.prv - -# Passphrase for private key -#private_key_passwd=secret passphrase - -# Enable CRL verification. -# Note: hostapd does not yet support CRL downloading based on CDP. Thus, a -# valid CRL signed by the CA is required to be included in the ca_cert file. -# This can be done by using PEM format for CA certificate and CRL and -# concatenating these into one file. Whenever CRL changes, hostapd needs to be -# restarted to take the new CRL into use. -# 0 = do not verify CRLs (default) -# 1 = check the CRL of the user certificate -# 2 = check all CRLs in the certificate path -#check_crl=1 - -# dh_file: File path to DH/DSA parameters file (in PEM format) -# This is an optional configuration file for setting parameters for an -# ephemeral DH key exchange. In most cases, the default RSA authentication does -# not use this configuration. However, it is possible setup RSA to use -# ephemeral DH key exchange. In addition, ciphers with DSA keys always use -# ephemeral DH keys. This can be used to achieve forward secrecy. If the file -# is in DSA parameters format, it will be automatically converted into DH -# params. This parameter is required if anonymous EAP-FAST is used. -# You can generate DH parameters file with OpenSSL, e.g., -# "openssl dhparam -out /etc/hostapd.dh.pem 1024" -#dh_file=/etc/hostapd.dh.pem - -# Fragment size for EAP methods -#fragment_size=1400 - -# Configuration data for EAP-SIM database/authentication gateway interface. -# This is a text string in implementation specific format. The example -# implementation in eap_sim_db.c uses this as the UNIX domain socket name for -# the HLR/AuC gateway (e.g., hlr_auc_gw). In this case, the path uses "unix:" -# prefix. -#eap_sim_db=unix:/tmp/hlr_auc_gw.sock - -# Encryption key for EAP-FAST PAC-Opaque values. This key must be a secret, -# random value. It is configured as a 16-octet value in hex format. It can be -# generated, e.g., with the following command: -# od -tx1 -v -N16 /dev/random | colrm 1 8 | tr -d ' ' -#pac_opaque_encr_key=000102030405060708090a0b0c0d0e0f - -# EAP-FAST authority identity (A-ID) -# A-ID indicates the identity of the authority that issues PACs. The A-ID -# should be unique across all issuing servers. In theory, this is a variable -# length field, but due to some existing implementations requiring A-ID to be -# 16 octets in length, it is strongly recommended to use that length for the -# field to provid interoperability with deployed peer implementations. This -# field is configured in hex format. -#eap_fast_a_id=101112131415161718191a1b1c1d1e1f - -# EAP-FAST authority identifier information (A-ID-Info) -# This is a user-friendly name for the A-ID. For example, the enterprise name -# and server name in a human-readable format. This field is encoded as UTF-8. -#eap_fast_a_id_info=test server - -# Enable/disable different EAP-FAST provisioning modes: -#0 = provisioning disabled -#1 = only anonymous provisioning allowed -#2 = only authenticated provisioning allowed -#3 = both provisioning modes allowed (default) -#eap_fast_prov=3 - -# EAP-FAST PAC-Key lifetime in seconds (hard limit) -#pac_key_lifetime=604800 - -# EAP-FAST PAC-Key refresh time in seconds (soft limit on remaining hard -# limit). The server will generate a new PAC-Key when this number of seconds -# (or fewer) of the lifetime remains. -#pac_key_refresh_time=86400 - -# EAP-SIM and EAP-AKA protected success/failure indication using AT_RESULT_IND -# (default: 0 = disabled). -#eap_sim_aka_result_ind=1 - -# Trusted Network Connect (TNC) -# If enabled, TNC validation will be required before the peer is allowed to -# connect. Note: This is only used with EAP-TTLS and EAP-FAST. If any other -# EAP method is enabled, the peer will be allowed to connect without TNC. -#tnc=1 - - -##### IEEE 802.11f - Inter-Access Point Protocol (IAPP) ####################### - -# Interface to be used for IAPP broadcast packets -#iapp_interface=eth0 - - -##### RADIUS client configuration ############################################# -# for IEEE 802.1X with external Authentication Server, IEEE 802.11 -# authentication with external ACL for MAC addresses, and accounting - -# The own IP address of the access point (used as NAS-IP-Address) -own_ip_addr=127.0.0.1 - -# Optional NAS-Identifier string for RADIUS messages. When used, this should be -# a unique to the NAS within the scope of the RADIUS server. For example, a -# fully qualified domain name can be used here. -# When using IEEE 802.11r, nas_identifier must be set and must be between 1 and -# 48 octets long. -#nas_identifier=ap.example.com - -# RADIUS authentication server -#auth_server_addr=127.0.0.1 -#auth_server_port=1812 -#auth_server_shared_secret=secret - -# RADIUS accounting server -#acct_server_addr=127.0.0.1 -#acct_server_port=1813 -#acct_server_shared_secret=secret - -# Secondary RADIUS servers; to be used if primary one does not reply to -# RADIUS packets. These are optional and there can be more than one secondary -# server listed. -#auth_server_addr=127.0.0.2 -#auth_server_port=1812 -#auth_server_shared_secret=secret2 -# -#acct_server_addr=127.0.0.2 -#acct_server_port=1813 -#acct_server_shared_secret=secret2 - -# Retry interval for trying to return to the primary RADIUS server (in -# seconds). RADIUS client code will automatically try to use the next server -# when the current server is not replying to requests. If this interval is set, -# primary server will be retried after configured amount of time even if the -# currently used secondary server is still working. -#radius_retry_primary_interval=600 - - -# Interim accounting update interval -# If this is set (larger than 0) and acct_server is configured, hostapd will -# send interim accounting updates every N seconds. Note: if set, this overrides -# possible Acct-Interim-Interval attribute in Access-Accept message. Thus, this -# value should not be configured in hostapd.conf, if RADIUS server is used to -# control the interim interval. -# This value should not be less 600 (10 minutes) and must not be less than -# 60 (1 minute). -#radius_acct_interim_interval=600 - -# Dynamic VLAN mode; allow RADIUS authentication server to decide which VLAN -# is used for the stations. This information is parsed from following RADIUS -# attributes based on RFC 3580 and RFC 2868: Tunnel-Type (value 13 = VLAN), -# Tunnel-Medium-Type (value 6 = IEEE 802), Tunnel-Private-Group-ID (value -# VLANID as a string). vlan_file option below must be configured if dynamic -# VLANs are used. Optionally, the local MAC ACL list (accept_mac_file) can be -# used to set static client MAC address to VLAN ID mapping. -# 0 = disabled (default) -# 1 = option; use default interface if RADIUS server does not include VLAN ID -# 2 = required; reject authentication if RADIUS server does not include VLAN ID -#dynamic_vlan=0 - -# VLAN interface list for dynamic VLAN mode is read from a separate text file. -# This list is used to map VLAN ID from the RADIUS server to a network -# interface. Each station is bound to one interface in the same way as with -# multiple BSSIDs or SSIDs. Each line in this text file is defining a new -# interface and the line must include VLAN ID and interface name separated by -# white space (space or tab). -#vlan_file=/etc/hostapd.vlan - -# Interface where 802.1q tagged packets should appear when a RADIUS server is -# used to determine which VLAN a station is on. hostapd creates a bridge for -# each VLAN. Then hostapd adds a VLAN interface (associated with the interface -# indicated by 'vlan_tagged_interface') and the appropriate wireless interface -# to the bridge. -#vlan_tagged_interface=eth0 - - -##### RADIUS authentication server configuration ############################## - -# hostapd can be used as a RADIUS authentication server for other hosts. This -# requires that the integrated EAP server is also enabled and both -# authentication services are sharing the same configuration. - -# File name of the RADIUS clients configuration for the RADIUS server. If this -# commented out, RADIUS server is disabled. -#radius_server_clients=/etc/hostapd.radius_clients - -# The UDP port number for the RADIUS authentication server -#radius_server_auth_port=1812 - -# Use IPv6 with RADIUS server (IPv4 will also be supported using IPv6 API) -#radius_server_ipv6=1 - - -##### WPA/IEEE 802.11i configuration ########################################## - -# Enable WPA. Setting this variable configures the AP to require WPA (either -# WPA-PSK or WPA-RADIUS/EAP based on other configuration). For WPA-PSK, either -# wpa_psk or wpa_passphrase must be set and wpa_key_mgmt must include WPA-PSK. -# For WPA-RADIUS/EAP, ieee8021x must be set (but without dynamic WEP keys), -# RADIUS authentication server must be configured, and WPA-EAP must be included -# in wpa_key_mgmt. -# This field is a bit field that can be used to enable WPA (IEEE 802.11i/D3.0) -# and/or WPA2 (full IEEE 802.11i/RSN): -# bit0 = WPA -# bit1 = IEEE 802.11i/RSN (WPA2) (dot11RSNAEnabled) -#wpa=1 - -# WPA pre-shared keys for WPA-PSK. This can be either entered as a 256-bit -# secret in hex format (64 hex digits), wpa_psk, or as an ASCII passphrase -# (8..63 characters) that will be converted to PSK. This conversion uses SSID -# so the PSK changes when ASCII passphrase is used and the SSID is changed. -# wpa_psk (dot11RSNAConfigPSKValue) -# wpa_passphrase (dot11RSNAConfigPSKPassPhrase) -#wpa_psk=0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef -#wpa_passphrase=secret passphrase - -# Optionally, WPA PSKs can be read from a separate text file (containing list -# of (PSK,MAC address) pairs. This allows more than one PSK to be configured. -# Use absolute path name to make sure that the files can be read on SIGHUP -# configuration reloads. -#wpa_psk_file=/etc/hostapd.wpa_psk - -# Set of accepted key management algorithms (WPA-PSK, WPA-EAP, or both). The -# entries are separated with a space. WPA-PSK-SHA256 and WPA-EAP-SHA256 can be -# added to enable SHA256-based stronger algorithms. -# (dot11RSNAConfigAuthenticationSuitesTable) -#wpa_key_mgmt=WPA-PSK WPA-EAP - -# Set of accepted cipher suites (encryption algorithms) for pairwise keys -# (unicast packets). This is a space separated list of algorithms: -# CCMP = AES in Counter mode with CBC-MAC [RFC 3610, IEEE 802.11i/D7.0] -# TKIP = Temporal Key Integrity Protocol [IEEE 802.11i/D7.0] -# Group cipher suite (encryption algorithm for broadcast and multicast frames) -# is automatically selected based on this configuration. If only CCMP is -# allowed as the pairwise cipher, group cipher will also be CCMP. Otherwise, -# TKIP will be used as the group cipher. -# (dot11RSNAConfigPairwiseCiphersTable) -# Pairwise cipher for WPA (v1) (default: TKIP) -#wpa_pairwise=TKIP CCMP -# Pairwise cipher for RSN/WPA2 (default: use wpa_pairwise value) -#rsn_pairwise=CCMP - -# Time interval for rekeying GTK (broadcast/multicast encryption keys) in -# seconds. (dot11RSNAConfigGroupRekeyTime) -#wpa_group_rekey=600 - -# Rekey GTK when any STA that possesses the current GTK is leaving the BSS. -# (dot11RSNAConfigGroupRekeyStrict) -#wpa_strict_rekey=1 - -# Time interval for rekeying GMK (master key used internally to generate GTKs -# (in seconds). -#wpa_gmk_rekey=86400 - -# Maximum lifetime for PTK in seconds. This can be used to enforce rekeying of -# PTK to mitigate some attacks against TKIP deficiencies. -#wpa_ptk_rekey=600 - -# Enable IEEE 802.11i/RSN/WPA2 pre-authentication. This is used to speed up -# roaming be pre-authenticating IEEE 802.1X/EAP part of the full RSN -# authentication and key handshake before actually associating with a new AP. -# (dot11RSNAPreauthenticationEnabled) -#rsn_preauth=1 -# -# Space separated list of interfaces from which pre-authentication frames are -# accepted (e.g., 'eth0' or 'eth0 wlan0wds0'. This list should include all -# interface that are used for connections to other APs. This could include -# wired interfaces and WDS links. The normal wireless data interface towards -# associated stations (e.g., wlan0) should not be added, since -# pre-authentication is only used with APs other than the currently associated -# one. -#rsn_preauth_interfaces=eth0 - -# peerkey: Whether PeerKey negotiation for direct links (IEEE 802.11e) is -# allowed. This is only used with RSN/WPA2. -# 0 = disabled (default) -# 1 = enabled -#peerkey=1 - -# ieee80211w: Whether management frame protection (MFP) is enabled -# 0 = disabled (default) -# 1 = optional -# 2 = required -#ieee80211w=0 - -# Association SA Query maximum timeout (in TU = 1.024 ms; for MFP) -# (maximum time to wait for a SA Query response) -# dot11AssociationSAQueryMaximumTimeout, 1...4294967295 -#assoc_sa_query_max_timeout=1000 - -# Association SA Query retry timeout (in TU = 1.024 ms; for MFP) -# (time between two subsequent SA Query requests) -# dot11AssociationSAQueryRetryTimeout, 1...4294967295 -#assoc_sa_query_retry_timeout=201 - - -# okc: Opportunistic Key Caching (aka Proactive Key Caching) -# Allow PMK cache to be shared opportunistically among configured interfaces -# and BSSes (i.e., all configurations within a single hostapd process). -# 0 = disabled (default) -# 1 = enabled -#okc=1 - - -##### IEEE 802.11r configuration ############################################## - -# Mobility Domain identifier (dot11FTMobilityDomainID, MDID) -# MDID is used to indicate a group of APs (within an ESS, i.e., sharing the -# same SSID) between which a STA can use Fast BSS Transition. -# 2-octet identifier as a hex string. -#mobility_domain=a1b2 - -# PMK-R0 Key Holder identifier (dot11FTR0KeyHolderID) -# 1 to 48 octet identifier. -# This is configured with nas_identifier (see RADIUS client section above). - -# Default lifetime of the PMK-RO in minutes; range 1..65535 -# (dot11FTR0KeyLifetime) -#r0_key_lifetime=10000 - -# PMK-R1 Key Holder identifier (dot11FTR1KeyHolderID) -# 6-octet identifier as a hex string. -#r1_key_holder=000102030405 - -# Reassociation deadline in time units (TUs / 1.024 ms; range 1000..65535) -# (dot11FTReassociationDeadline) -#reassociation_deadline=1000 - -# List of R0KHs in the same Mobility Domain -# format: <128-bit key as hex string> -# This list is used to map R0KH-ID (NAS Identifier) to a destination MAC -# address when requesting PMK-R1 key from the R0KH that the STA used during the -# Initial Mobility Domain Association. -#r0kh=02:01:02:03:04:05 r0kh-1.example.com 000102030405060708090a0b0c0d0e0f -#r0kh=02:01:02:03:04:06 r0kh-2.example.com 00112233445566778899aabbccddeeff -# And so on.. One line per R0KH. - -# List of R1KHs in the same Mobility Domain -# format: <128-bit key as hex string> -# This list is used to map R1KH-ID to a destination MAC address when sending -# PMK-R1 key from the R0KH. This is also the list of authorized R1KHs in the MD -# that can request PMK-R1 keys. -#r1kh=02:01:02:03:04:05 02:11:22:33:44:55 000102030405060708090a0b0c0d0e0f -#r1kh=02:01:02:03:04:06 02:11:22:33:44:66 00112233445566778899aabbccddeeff -# And so on.. One line per R1KH. - -# Whether PMK-R1 push is enabled at R0KH -# 0 = do not push PMK-R1 to all configured R1KHs (default) -# 1 = push PMK-R1 to all configured R1KHs whenever a new PMK-R0 is derived -#pmk_r1_push=1 - -##### Neighbor table ########################################################## -# Maximum number of entries kept in AP table (either for neigbor table or for -# detecting Overlapping Legacy BSS Condition). The oldest entry will be -# removed when adding a new entry that would make the list grow over this -# limit. Note! WFA certification for IEEE 802.11g requires that OLBC is -# enabled, so this field should not be set to 0 when using IEEE 802.11g. -# default: 255 -#ap_table_max_size=255 - -# Number of seconds of no frames received after which entries may be deleted -# from the AP table. Since passive scanning is not usually performed frequently -# this should not be set to very small value. In addition, there is no -# guarantee that every scan cycle will receive beacon frames from the -# neighboring APs. -# default: 60 -#ap_table_expiration_time=3600 - - -##### Wi-Fi Protected Setup (WPS) ############################################# - -# WPS state -# 0 = WPS disabled (default) -# 1 = WPS enabled, not configured -# 2 = WPS enabled, configured -#wps_state=2 - -# AP can be configured into a locked state where new WPS Registrar are not -# accepted, but previously authorized Registrars (including the internal one) -# can continue to add new Enrollees. -#ap_setup_locked=1 - -# Universally Unique IDentifier (UUID; see RFC 4122) of the device -# This value is used as the UUID for the internal WPS Registrar. If the AP -# is also using UPnP, this value should be set to the device's UPnP UUID. -# If not configured, UUID will be generated based on the local MAC address. -#uuid=12345678-9abc-def0-1234-56789abcdef0 - -# Note: If wpa_psk_file is set, WPS is used to generate random, per-device PSKs -# that will be appended to the wpa_psk_file. If wpa_psk_file is not set, the -# default PSK (wpa_psk/wpa_passphrase) will be delivered to Enrollees. Use of -# per-device PSKs is recommended as the more secure option (i.e., make sure to -# set wpa_psk_file when using WPS with WPA-PSK). - -# When an Enrollee requests access to the network with PIN method, the Enrollee -# PIN will need to be entered for the Registrar. PIN request notifications are -# sent to hostapd ctrl_iface monitor. In addition, they can be written to a -# text file that could be used, e.g., to populate the AP administration UI with -# pending PIN requests. If the following variable is set, the PIN requests will -# be written to the configured file. -#wps_pin_requests=/var/run/hostapd_wps_pin_requests - -# Device Name -# User-friendly description of device; up to 32 octets encoded in UTF-8 -#device_name=Wireless AP - -# Manufacturer -# The manufacturer of the device (up to 64 ASCII characters) -#manufacturer=Company - -# Model Name -# Model of the device (up to 32 ASCII characters) -#model_name=WAP - -# Model Number -# Additional device description (up to 32 ASCII characters) -#model_number=123 - -# Serial Number -# Serial number of the device (up to 32 characters) -#serial_number=12345 - -# Primary Device Type -# Used format: -- -# categ = Category as an integer value -# OUI = OUI and type octet as a 4-octet hex-encoded value; 0050F204 for -# default WPS OUI -# subcateg = OUI-specific Sub Category as an integer value -# Examples: -# 1-0050F204-1 (Computer / PC) -# 1-0050F204-2 (Computer / Server) -# 5-0050F204-1 (Storage / NAS) -# 6-0050F204-1 (Network Infrastructure / AP) -#device_type=6-0050F204-1 - -# OS Version -# 4-octet operating system version number (hex string) -#os_version=01020300 - -# Config Methods -# List of the supported configuration methods -# Available methods: usba ethernet label display ext_nfc_token int_nfc_token -# nfc_interface push_button keypad virtual_display physical_display -# virtual_push_button physical_push_button -#config_methods=label virtual_display virtual_push_button keypad - -# Static access point PIN for initial configuration and adding Registrars -# If not set, hostapd will not allow external WPS Registrars to control the -# access point. The AP PIN can also be set at runtime with hostapd_cli -# wps_ap_pin command. Use of temporary (enabled by user action) and random -# AP PIN is much more secure than configuring a static AP PIN here. As such, -# use of the ap_pin parameter is not recommended if the AP device has means for -# displaying a random PIN. -#ap_pin=12345670 - -# Skip building of automatic WPS credential -# This can be used to allow the automatically generated Credential attribute to -# be replaced with pre-configured Credential(s). -#skip_cred_build=1 - -# Additional Credential attribute(s) -# This option can be used to add pre-configured Credential attributes into M8 -# message when acting as a Registrar. If skip_cred_build=1, this data will also -# be able to override the Credential attribute that would have otherwise been -# automatically generated based on network configuration. This configuration -# option points to an external file that much contain the WPS Credential -# attribute(s) as binary data. -#extra_cred=hostapd.cred - -# Credential processing -# 0 = process received credentials internally (default) -# 1 = do not process received credentials; just pass them over ctrl_iface to -# external program(s) -# 2 = process received credentials internally and pass them over ctrl_iface -# to external program(s) -# Note: With wps_cred_processing=1, skip_cred_build should be set to 1 and -# extra_cred be used to provide the Credential data for Enrollees. -# -# wps_cred_processing=1 will disabled automatic updates of hostapd.conf file -# both for Credential processing and for marking AP Setup Locked based on -# validation failures of AP PIN. An external program is responsible on updating -# the configuration appropriately in this case. -#wps_cred_processing=0 - -# AP Settings Attributes for M7 -# By default, hostapd generates the AP Settings Attributes for M7 based on the -# current configuration. It is possible to override this by providing a file -# with pre-configured attributes. This is similar to extra_cred file format, -# but the AP Settings attributes are not encapsulated in a Credential -# attribute. -#ap_settings=hostapd.ap_settings - -# WPS UPnP interface -# If set, support for external Registrars is enabled. -#upnp_iface=br0 - -# Friendly Name (required for UPnP) -# Short description for end use. Should be less than 64 characters. -#friendly_name=WPS Access Point - -# Manufacturer URL (optional for UPnP) -#manufacturer_url=http://www.example.com/ - -# Model Description (recommended for UPnP) -# Long description for end user. Should be less than 128 characters. -#model_description=Wireless Access Point - -# Model URL (optional for UPnP) -#model_url=http://www.example.com/model/ - -# Universal Product Code (optional for UPnP) -# 12-digit, all-numeric code that identifies the consumer package. -#upc=123456789012 - -##### Wi-Fi Direct (P2P) ###################################################### - -# Enable P2P Device management -#manage_p2p=1 - -# Allow cross connection -#allow_cross_connection=1 - -#### TDLS (IEEE 802.11z-2010) ################################################# - -# Prohibit use of TDLS in this BSS -#tdls_prohibit=1 - -# Prohibit use of TDLS Channel Switching in this BSS -#tdls_prohibit_chan_switch=1 - -##### Multiple BSSID support ################################################## -# -# Above configuration is using the default interface (wlan#, or multi-SSID VLAN -# interfaces). Other BSSIDs can be added by using separator 'bss' with -# default interface name to be allocated for the data packets of the new BSS. -# -# hostapd will generate BSSID mask based on the BSSIDs that are -# configured. hostapd will verify that dev_addr & MASK == dev_addr. If this is -# not the case, the MAC address of the radio must be changed before starting -# hostapd (ifconfig wlan0 hw ether ). If a BSSID is configured for -# every secondary BSS, this limitation is not applied at hostapd and other -# masks may be used if the driver supports them (e.g., swap the locally -# administered bit) -# -# BSSIDs are assigned in order to each BSS, unless an explicit BSSID is -# specified using the 'bssid' parameter. -# If an explicit BSSID is specified, it must be chosen such that it: -# - results in a valid MASK that covers it and the dev_addr -# - is not the same as the MAC address of the radio -# - is not the same as any other explicitly specified BSSID -# -# Please note that hostapd uses some of the values configured for the first BSS -# as the defaults for the following BSSes. However, it is recommended that all -# BSSes include explicit configuration of all relevant configuration items. -# -#bss=wlan0_0 -#ssid=test2 -# most of the above items can be used here (apart from radio interface specific -# items, like channel) - -#bss=wlan0_1 -#bssid=00:13:10:95:fe:0b -# ... diff --git a/hostapd-0.8/hostapd/hostapd.deny b/hostapd-0.8/hostapd/hostapd.deny deleted file mode 100644 index 1616678..0000000 --- a/hostapd-0.8/hostapd/hostapd.deny +++ /dev/null @@ -1,5 +0,0 @@ -# List of MAC addresses that are not allowed to authenticate (IEEE 802.11) -# with the AP. -00:20:30:40:50:60 -00:ab:cd:ef:12:34 -00:00:30:40:50:60 diff --git a/hostapd-0.8/hostapd/hostapd.eap_user b/hostapd-0.8/hostapd/hostapd.eap_user deleted file mode 100644 index ac9a5d8..0000000 --- a/hostapd-0.8/hostapd/hostapd.eap_user +++ /dev/null @@ -1,91 +0,0 @@ -# hostapd user database for integrated EAP server - -# Each line must contain an identity, EAP method(s), and an optional password -# separated with whitespace (space or tab). The identity and password must be -# double quoted ("user"). Password can alternatively be stored as -# NtPasswordHash (16-byte MD4 hash of the unicode presentation of the password -# in unicode) if it is used for MSCHAP or MSCHAPv2 authentication. This means -# that the plaintext password does not need to be included in the user file. -# Password hash is stored as hash:<16-octets of hex data> without quotation -# marks. - -# [2] flag in the end of the line can be used to mark users for tunneled phase -# 2 authentication (e.g., within EAP-PEAP). In these cases, an anonymous -# identity can be used in the unencrypted phase 1 and the real user identity -# is transmitted only within the encrypted tunnel in phase 2. If non-anonymous -# access is needed, two user entries is needed, one for phase 1 and another -# with the same username for phase 2. -# -# EAP-TLS, EAP-PEAP, EAP-TTLS, EAP-FAST, EAP-SIM, and EAP-AKA do not use -# password option. -# EAP-MD5, EAP-MSCHAPV2, EAP-GTC, EAP-PAX, EAP-PSK, and EAP-SAKE require a -# password. -# EAP-PEAP, EAP-TTLS, and EAP-FAST require Phase 2 configuration. -# -# * can be used as a wildcard to match any user identity. The main purposes for -# this are to set anonymous phase 1 identity for EAP-PEAP and EAP-TTLS and to -# avoid having to configure every certificate for EAP-TLS authentication. The -# first matching entry is selected, so * should be used as the last phase 1 -# user entry. -# -# "prefix"* can be used to match the given prefix and anything after this. The -# main purpose for this is to be able to avoid EAP method negotiation when the -# method is using known prefix in identities (e.g., EAP-SIM and EAP-AKA). This -# is only allowed for phase 1 identities. -# -# Multiple methods can be configured to make the authenticator try them one by -# one until the peer accepts one. The method names are separated with a -# comma (,). -# -# [ver=0] and [ver=1] flags after EAP type PEAP can be used to force PEAP -# version based on the Phase 1 identity. Without this flag, the EAP -# authenticator advertises the highest supported version and select the version -# based on the first PEAP packet from the supplicant. -# -# EAP-TTLS supports both EAP and non-EAP authentication inside the tunnel. -# Tunneled EAP methods are configured with standard EAP method name and [2] -# flag. Non-EAP methods can be enabled by following method names: TTLS-PAP, -# TTLS-CHAP, TTLS-MSCHAP, TTLS-MSCHAPV2. TTLS-PAP and TTLS-CHAP require a -# plaintext password while TTLS-MSCHAP and TTLS-MSCHAPV2 can use NT password -# hash. - -# Phase 1 users -"user" MD5 "password" -"test user" MD5 "secret" -"example user" TLS -"DOMAIN\user" MSCHAPV2 "password" -"gtc user" GTC "password" -"pax user" PAX "unknown" -"pax.user@example.com" PAX 0123456789abcdef0123456789abcdef -"psk user" PSK "unknown" -"psk.user@example.com" PSK 0123456789abcdef0123456789abcdef -"sake.user@example.com" SAKE 0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef -"ttls" TTLS -"not anonymous" PEAP -# Default to EAP-SIM and EAP-AKA based on fixed identity prefixes -"0"* AKA,TTLS,TLS,PEAP,SIM -"1"* SIM,TTLS,TLS,PEAP,AKA -"2"* AKA,TTLS,TLS,PEAP,SIM -"3"* SIM,TTLS,TLS,PEAP,AKA -"4"* AKA,TTLS,TLS,PEAP,SIM -"5"* SIM,TTLS,TLS,PEAP,AKA - -# Wildcard for all other identities -* PEAP,TTLS,TLS,SIM,AKA - -# Phase 2 (tunnelled within EAP-PEAP or EAP-TTLS) users -"t-md5" MD5 "password" [2] -"DOMAIN\t-mschapv2" MSCHAPV2 "password" [2] -"t-gtc" GTC "password" [2] -"not anonymous" MSCHAPV2 "password" [2] -"user" MD5,GTC,MSCHAPV2 "password" [2] -"test user" MSCHAPV2 hash:000102030405060708090a0b0c0d0e0f [2] -"ttls-user" TTLS-PAP,TTLS-CHAP,TTLS-MSCHAP,TTLS-MSCHAPV2 "password" [2] - -# Default to EAP-SIM and EAP-AKA based on fixed identity prefixes in phase 2 -"0"* AKA [2] -"1"* SIM [2] -"2"* AKA [2] -"3"* SIM [2] -"4"* AKA [2] -"5"* SIM [2] diff --git a/hostapd-0.8/hostapd/hostapd.radius_clients b/hostapd-0.8/hostapd/hostapd.radius_clients deleted file mode 100644 index 3980427..0000000 --- a/hostapd-0.8/hostapd/hostapd.radius_clients +++ /dev/null @@ -1,4 +0,0 @@ -# RADIUS client configuration for the RADIUS server -10.1.2.3 secret passphrase -192.168.1.0/24 another very secret passphrase -0.0.0.0/0 radius diff --git a/hostapd-0.8/hostapd/hostapd.sim_db b/hostapd-0.8/hostapd/hostapd.sim_db deleted file mode 100644 index 01c593d..0000000 --- a/hostapd-0.8/hostapd/hostapd.sim_db +++ /dev/null @@ -1,9 +0,0 @@ -# Example GSM authentication triplet file for EAP-SIM authenticator -# IMSI:Kc:SRES:RAND -# IMSI: ASCII string (numbers) -# Kc: hex, 8 octets -# SRES: hex, 4 octets -# RAND: hex, 16 octets -234567898765432:A0A1A2A3A4A5A6A7:D1D2D3D4:AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA -234567898765432:B0B1B2B3B4B5B6B7:E1E2E3E4:BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB -234567898765432:C0C1C2C3C4C5C6C7:F1F2F3F4:CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC diff --git a/hostapd-0.8/hostapd/hostapd.vlan b/hostapd-0.8/hostapd/hostapd.vlan deleted file mode 100644 index 98254fa..0000000 --- a/hostapd-0.8/hostapd/hostapd.vlan +++ /dev/null @@ -1,9 +0,0 @@ -# VLAN ID to network interface mapping -1 vlan1 -2 vlan2 -3 vlan3 -100 guest -# Optional wildcard entry matching all VLAN IDs. The first # in the interface -# name will be replaced with the VLAN ID. The network interfaces are created -# (and removed) dynamically based on the use. -* vlan# diff --git a/hostapd-0.8/hostapd/hostapd.wpa_psk b/hostapd-0.8/hostapd/hostapd.wpa_psk deleted file mode 100644 index 0a9499a..0000000 --- a/hostapd-0.8/hostapd/hostapd.wpa_psk +++ /dev/null @@ -1,9 +0,0 @@ -# List of WPA PSKs. Each line, except for empty lines and lines starting -# with #, must contain a MAC address and PSK separated with a space. -# Special MAC address 00:00:00:00:00:00 can be used to configure PSKs that -# anyone can use. PSK can be configured as an ASCII passphrase of 8..63 -# characters or as a 256-bit hex PSK (64 hex digits). -00:00:00:00:00:00 secret passphrase -00:11:22:33:44:55 another passphrase -00:22:33:44:55:66 0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef -00:00:00:00:00:00 another passphrase for all STAs diff --git a/hostapd-0.8/hostapd/hostapd_cli.1 b/hostapd-0.8/hostapd/hostapd_cli.1 deleted file mode 100644 index 218ea15..0000000 --- a/hostapd-0.8/hostapd/hostapd_cli.1 +++ /dev/null @@ -1,89 +0,0 @@ -.TH HOSTAPD_CLI 1 "April 7, 2005" hostapd_cli "hostapd command-line interface" -.SH NAME -hostapd_cli \- hostapd command-line interface -.SH SYNOPSIS -.B hostapd_cli -[\-p] [\-i] [\-a] [\-hvB] [command..] -.SH DESCRIPTION -This manual page documents briefly the -.B hostapd_cli -utility. -.PP -.B hostapd_cli -is a command-line interface for the -.B hostapd -daemon. - -.B hostapd -is a user space daemon for access point and authentication servers. -It implements IEEE 802.11 access point management, IEEE 802.1X/WPA/WPA2/EAP Authenticators and RADIUS authentication server. -For more information about -.B hostapd -refer to the -.BR hostapd (8) -man page. -.SH OPTIONS -A summary of options is included below. -For a complete description, run -.BR hostapd_cli -from the command line. -.TP -.B \-p -Path to find control sockets. - -Default: /var/run/hostapd -.TP -.B \-i -Interface to listen on. - -Default: first interface found in socket path. -.TP -.B \-a -Run in daemon mode executing the action file based on events from hostapd. -.TP -.B \-B -Run a daemon in the background. -.TP -.B \-h -Show usage. -.TP -.B \-v -Show hostapd_cli version. -.SH COMMANDS -A summary of commands is included below. -For a complete description, run -.BR hostapd_cli -from the command line. -.TP -.B mib -Get MIB variables (dot1x, dot11, radius). -.TP -.B sta -Get MIB variables for one station. -.TP -.B all_sta -Get MIB variables for all stations. -.TP -.B help -Get usage help. -.TP -.B interface [ifname] -Show interfaces/select interface. -.TP -.B level -Change debug level. -.TP -.B license -Show full -.B hostapd_cli -license. -.TP -.B quit -Exit hostapd_cli. -.SH SEE ALSO -.BR hostapd (8). -.SH AUTHOR -hostapd_cli was written by Jouni Malinen . -.PP -This manual page was written by Faidon Liambotis , -for the Debian project (but may be used by others). diff --git a/hostapd-0.8/hostapd/hostapd_cli.c b/hostapd-0.8/hostapd/hostapd_cli.c deleted file mode 100644 index a48d773..0000000 --- a/hostapd-0.8/hostapd/hostapd_cli.c +++ /dev/null @@ -1,1044 +0,0 @@ -/* - * hostapd - command line interface for hostapd daemon - * Copyright (c) 2004-2011, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#include "includes.h" -#include - -#include "common/wpa_ctrl.h" -#include "common.h" -#include "common/version.h" - - -static const char *hostapd_cli_version = -"hostapd_cli v" VERSION_STR "\n" -"Copyright (c) 2004-2011, Jouni Malinen and contributors"; - - -static const char *hostapd_cli_license = -"This program is free software. You can distribute it and/or modify it\n" -"under the terms of the GNU General Public License version 2.\n" -"\n" -"Alternatively, this software may be distributed under the terms of the\n" -"BSD license. See README and COPYING for more details.\n"; - -static const char *hostapd_cli_full_license = -"This program is free software; you can redistribute it and/or modify\n" -"it under the terms of the GNU General Public License version 2 as\n" -"published by the Free Software Foundation.\n" -"\n" -"This program is distributed in the hope that it will be useful,\n" -"but WITHOUT ANY WARRANTY; without even the implied warranty of\n" -"MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n" -"GNU General Public License for more details.\n" -"\n" -"You should have received a copy of the GNU General Public License\n" -"along with this program; if not, write to the Free Software\n" -"Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA\n" -"\n" -"Alternatively, this software may be distributed under the terms of the\n" -"BSD license.\n" -"\n" -"Redistribution and use in source and binary forms, with or without\n" -"modification, are permitted provided that the following conditions are\n" -"met:\n" -"\n" -"1. Redistributions of source code must retain the above copyright\n" -" notice, this list of conditions and the following disclaimer.\n" -"\n" -"2. Redistributions in binary form must reproduce the above copyright\n" -" notice, this list of conditions and the following disclaimer in the\n" -" documentation and/or other materials provided with the distribution.\n" -"\n" -"3. Neither the name(s) of the above-listed copyright holder(s) nor the\n" -" names of its contributors may be used to endorse or promote products\n" -" derived from this software without specific prior written permission.\n" -"\n" -"THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n" -"\"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n" -"LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n" -"A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n" -"OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n" -"SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n" -"LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n" -"DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n" -"THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n" -"(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n" -"OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n" -"\n"; - -static const char *commands_help = -"Commands:\n" -" mib get MIB variables (dot1x, dot11, radius)\n" -" sta get MIB variables for one station\n" -" all_sta get MIB variables for all stations\n" -" new_sta add a new station\n" -" deauthenticate deauthenticate a station\n" -" disassociate disassociate a station\n" -#ifdef CONFIG_IEEE80211W -" sa_query send SA Query to a station\n" -#endif /* CONFIG_IEEE80211W */ -#ifdef CONFIG_WPS -" wps_pin [timeout] [addr] add WPS Enrollee PIN\n" -" wps_check_pin verify PIN checksum\n" -" wps_pbc indicate button pushed to initiate PBC\n" -#ifdef CONFIG_WPS_OOB -" wps_oob use WPS with out-of-band (UFD)\n" -#endif /* CONFIG_WPS_OOB */ -" wps_ap_pin [params..] enable/disable AP PIN\n" -" wps_config configure AP\n" -#endif /* CONFIG_WPS */ -" get_config show current configuration\n" -" help show this usage help\n" -" interface [ifname] show interfaces/select interface\n" -" level change debug level\n" -" license show full hostapd_cli license\n" -" quit exit hostapd_cli\n"; - -static struct wpa_ctrl *ctrl_conn; -static int hostapd_cli_quit = 0; -static int hostapd_cli_attached = 0; -static const char *ctrl_iface_dir = "/var/run/hostapd"; -static char *ctrl_ifname = NULL; -static const char *pid_file = NULL; -static const char *action_file = NULL; -static int ping_interval = 5; - - -static void usage(void) -{ - fprintf(stderr, "%s\n", hostapd_cli_version); - fprintf(stderr, - "\n" - "usage: hostapd_cli [-p] [-i] [-hvB] " - "[-a] \\\n" - " [-G] [command..]\n" - "\n" - "Options:\n" - " -h help (show this usage text)\n" - " -v shown version information\n" - " -p path to find control sockets (default: " - "/var/run/hostapd)\n" - " -a run in daemon mode executing the action file " - "based on events\n" - " from hostapd\n" - " -B run a daemon in the background\n" - " -i Interface to listen on (default: first " - "interface found in the\n" - " socket path)\n\n" - "%s", - commands_help); -} - - -static struct wpa_ctrl * hostapd_cli_open_connection(const char *ifname) -{ - char *cfile; - int flen; - - if (ifname == NULL) - return NULL; - - flen = strlen(ctrl_iface_dir) + strlen(ifname) + 2; - cfile = malloc(flen); - if (cfile == NULL) - return NULL; - snprintf(cfile, flen, "%s/%s", ctrl_iface_dir, ifname); - - ctrl_conn = wpa_ctrl_open(cfile); - free(cfile); - return ctrl_conn; -} - - -static void hostapd_cli_close_connection(void) -{ - if (ctrl_conn == NULL) - return; - - if (hostapd_cli_attached) { - wpa_ctrl_detach(ctrl_conn); - hostapd_cli_attached = 0; - } - wpa_ctrl_close(ctrl_conn); - ctrl_conn = NULL; -} - - -static void hostapd_cli_msg_cb(char *msg, size_t len) -{ - printf("%s\n", msg); -} - - -static int _wpa_ctrl_command(struct wpa_ctrl *ctrl, char *cmd, int print) -{ - char buf[4096]; - size_t len; - int ret; - - if (ctrl_conn == NULL) { - printf("Not connected to hostapd - command dropped.\n"); - return -1; - } - len = sizeof(buf) - 1; - ret = wpa_ctrl_request(ctrl, cmd, strlen(cmd), buf, &len, - hostapd_cli_msg_cb); - if (ret == -2) { - printf("'%s' command timed out.\n", cmd); - return -2; - } else if (ret < 0) { - printf("'%s' command failed.\n", cmd); - return -1; - } - if (print) { - buf[len] = '\0'; - printf("%s", buf); - } - return 0; -} - - -static inline int wpa_ctrl_command(struct wpa_ctrl *ctrl, char *cmd) -{ - return _wpa_ctrl_command(ctrl, cmd, 1); -} - - -static int hostapd_cli_cmd_ping(struct wpa_ctrl *ctrl, int argc, char *argv[]) -{ - return wpa_ctrl_command(ctrl, "PING"); -} - - -static int hostapd_cli_cmd_relog(struct wpa_ctrl *ctrl, int argc, char *argv[]) -{ - return wpa_ctrl_command(ctrl, "RELOG"); -} - - -static int hostapd_cli_cmd_mib(struct wpa_ctrl *ctrl, int argc, char *argv[]) -{ - return wpa_ctrl_command(ctrl, "MIB"); -} - - -static int hostapd_cli_exec(const char *program, const char *arg1, - const char *arg2) -{ - char *cmd; - size_t len; - int res; - int ret = 0; - - len = os_strlen(program) + os_strlen(arg1) + os_strlen(arg2) + 3; - cmd = os_malloc(len); - if (cmd == NULL) - return -1; - res = os_snprintf(cmd, len, "%s %s %s", program, arg1, arg2); - if (res < 0 || (size_t) res >= len) { - os_free(cmd); - return -1; - } - cmd[len - 1] = '\0'; -#ifndef _WIN32_WCE - if (system(cmd) < 0) - ret = -1; -#endif /* _WIN32_WCE */ - os_free(cmd); - - return ret; -} - - -static void hostapd_cli_action_process(char *msg, size_t len) -{ - const char *pos; - - pos = msg; - if (*pos == '<') { - pos = os_strchr(pos, '>'); - if (pos) - pos++; - else - pos = msg; - } - - hostapd_cli_exec(action_file, ctrl_ifname, pos); -} - - -static int hostapd_cli_cmd_sta(struct wpa_ctrl *ctrl, int argc, char *argv[]) -{ - char buf[64]; - if (argc != 1) { - printf("Invalid 'sta' command - exactly one argument, STA " - "address, is required.\n"); - return -1; - } - snprintf(buf, sizeof(buf), "STA %s", argv[0]); - return wpa_ctrl_command(ctrl, buf); -} - - -static int hostapd_cli_cmd_new_sta(struct wpa_ctrl *ctrl, int argc, - char *argv[]) -{ - char buf[64]; - if (argc != 1) { - printf("Invalid 'new_sta' command - exactly one argument, STA " - "address, is required.\n"); - return -1; - } - snprintf(buf, sizeof(buf), "NEW_STA %s", argv[0]); - return wpa_ctrl_command(ctrl, buf); -} - - -static int hostapd_cli_cmd_deauthenticate(struct wpa_ctrl *ctrl, int argc, - char *argv[]) -{ - char buf[64]; - if (argc < 1) { - printf("Invalid 'deauthenticate' command - exactly one " - "argument, STA address, is required.\n"); - return -1; - } - if (argc > 1) - os_snprintf(buf, sizeof(buf), "DEAUTHENTICATE %s %s", - argv[0], argv[1]); - else - os_snprintf(buf, sizeof(buf), "DEAUTHENTICATE %s", argv[0]); - return wpa_ctrl_command(ctrl, buf); -} - - -static int hostapd_cli_cmd_disassociate(struct wpa_ctrl *ctrl, int argc, - char *argv[]) -{ - char buf[64]; - if (argc < 1) { - printf("Invalid 'disassociate' command - exactly one " - "argument, STA address, is required.\n"); - return -1; - } - if (argc > 1) - os_snprintf(buf, sizeof(buf), "DISASSOCIATE %s %s", - argv[0], argv[1]); - else - os_snprintf(buf, sizeof(buf), "DISASSOCIATE %s", argv[0]); - return wpa_ctrl_command(ctrl, buf); -} - - -#ifdef CONFIG_IEEE80211W -static int hostapd_cli_cmd_sa_query(struct wpa_ctrl *ctrl, int argc, - char *argv[]) -{ - char buf[64]; - if (argc != 1) { - printf("Invalid 'sa_query' command - exactly one argument, " - "STA address, is required.\n"); - return -1; - } - snprintf(buf, sizeof(buf), "SA_QUERY %s", argv[0]); - return wpa_ctrl_command(ctrl, buf); -} -#endif /* CONFIG_IEEE80211W */ - - -#ifdef CONFIG_WPS -static int hostapd_cli_cmd_wps_pin(struct wpa_ctrl *ctrl, int argc, - char *argv[]) -{ - char buf[256]; - if (argc < 2) { - printf("Invalid 'wps_pin' command - at least two arguments, " - "UUID and PIN, are required.\n"); - return -1; - } - if (argc > 3) - snprintf(buf, sizeof(buf), "WPS_PIN %s %s %s %s", - argv[0], argv[1], argv[2], argv[3]); - else if (argc > 2) - snprintf(buf, sizeof(buf), "WPS_PIN %s %s %s", - argv[0], argv[1], argv[2]); - else - snprintf(buf, sizeof(buf), "WPS_PIN %s %s", argv[0], argv[1]); - return wpa_ctrl_command(ctrl, buf); -} - - -static int hostapd_cli_cmd_wps_check_pin(struct wpa_ctrl *ctrl, int argc, - char *argv[]) -{ - char cmd[256]; - int res; - - if (argc != 1 && argc != 2) { - printf("Invalid WPS_CHECK_PIN command: needs one argument:\n" - "- PIN to be verified\n"); - return -1; - } - - if (argc == 2) - res = os_snprintf(cmd, sizeof(cmd), "WPS_CHECK_PIN %s %s", - argv[0], argv[1]); - else - res = os_snprintf(cmd, sizeof(cmd), "WPS_CHECK_PIN %s", - argv[0]); - if (res < 0 || (size_t) res >= sizeof(cmd) - 1) { - printf("Too long WPS_CHECK_PIN command.\n"); - return -1; - } - return wpa_ctrl_command(ctrl, cmd); -} - - -static int hostapd_cli_cmd_wps_pbc(struct wpa_ctrl *ctrl, int argc, - char *argv[]) -{ - return wpa_ctrl_command(ctrl, "WPS_PBC"); -} - - -#ifdef CONFIG_WPS_OOB -static int hostapd_cli_cmd_wps_oob(struct wpa_ctrl *ctrl, int argc, - char *argv[]) -{ - char cmd[256]; - int res; - - if (argc != 3 && argc != 4) { - printf("Invalid WPS_OOB command: need three or four " - "arguments:\n" - "- DEV_TYPE: use 'ufd' or 'nfc'\n" - "- PATH: path of OOB device like '/mnt'\n" - "- METHOD: OOB method 'pin-e' or 'pin-r', " - "'cred'\n" - "- DEV_NAME: (only for NFC) device name like " - "'pn531'\n"); - return -1; - } - - if (argc == 3) - res = os_snprintf(cmd, sizeof(cmd), "WPS_OOB %s %s %s", - argv[0], argv[1], argv[2]); - else - res = os_snprintf(cmd, sizeof(cmd), "WPS_OOB %s %s %s %s", - argv[0], argv[1], argv[2], argv[3]); - if (res < 0 || (size_t) res >= sizeof(cmd) - 1) { - printf("Too long WPS_OOB command.\n"); - return -1; - } - return wpa_ctrl_command(ctrl, cmd); -} -#endif /* CONFIG_WPS_OOB */ - - -static int hostapd_cli_cmd_wps_ap_pin(struct wpa_ctrl *ctrl, int argc, - char *argv[]) -{ - char buf[64]; - if (argc < 1) { - printf("Invalid 'wps_ap_pin' command - at least one argument " - "is required.\n"); - return -1; - } - if (argc > 2) - snprintf(buf, sizeof(buf), "WPS_AP_PIN %s %s %s", - argv[0], argv[1], argv[2]); - else if (argc > 1) - snprintf(buf, sizeof(buf), "WPS_AP_PIN %s %s", - argv[0], argv[1]); - else - snprintf(buf, sizeof(buf), "WPS_AP_PIN %s", argv[0]); - return wpa_ctrl_command(ctrl, buf); -} - - -static int hostapd_cli_cmd_wps_config(struct wpa_ctrl *ctrl, int argc, - char *argv[]) -{ - char buf[256]; - char ssid_hex[2 * 32 + 1]; - char key_hex[2 * 64 + 1]; - int i; - - if (argc < 1) { - printf("Invalid 'wps_config' command - at least two arguments " - "are required.\n"); - return -1; - } - - ssid_hex[0] = '\0'; - for (i = 0; i < 32; i++) { - if (argv[0][i] == '\0') - break; - os_snprintf(&ssid_hex[i * 2], 3, "%02x", argv[0][i]); - } - - key_hex[0] = '\0'; - if (argc > 3) { - for (i = 0; i < 64; i++) { - if (argv[3][i] == '\0') - break; - os_snprintf(&key_hex[i * 2], 3, "%02x", - argv[3][i]); - } - } - - if (argc > 3) - snprintf(buf, sizeof(buf), "WPS_CONFIG %s %s %s %s", - ssid_hex, argv[1], argv[2], key_hex); - else if (argc > 2) - snprintf(buf, sizeof(buf), "WPS_CONFIG %s %s %s", - ssid_hex, argv[1], argv[2]); - else - snprintf(buf, sizeof(buf), "WPS_CONFIG %s %s", - ssid_hex, argv[1]); - return wpa_ctrl_command(ctrl, buf); -} -#endif /* CONFIG_WPS */ - - -static int hostapd_cli_cmd_get_config(struct wpa_ctrl *ctrl, int argc, - char *argv[]) -{ - return wpa_ctrl_command(ctrl, "GET_CONFIG"); -} - - -static int wpa_ctrl_command_sta(struct wpa_ctrl *ctrl, char *cmd, - char *addr, size_t addr_len) -{ - char buf[4096], *pos; - size_t len; - int ret; - - if (ctrl_conn == NULL) { - printf("Not connected to hostapd - command dropped.\n"); - return -1; - } - len = sizeof(buf) - 1; - ret = wpa_ctrl_request(ctrl, cmd, strlen(cmd), buf, &len, - hostapd_cli_msg_cb); - if (ret == -2) { - printf("'%s' command timed out.\n", cmd); - return -2; - } else if (ret < 0) { - printf("'%s' command failed.\n", cmd); - return -1; - } - - buf[len] = '\0'; - if (memcmp(buf, "FAIL", 4) == 0) - return -1; - printf("%s", buf); - - pos = buf; - while (*pos != '\0' && *pos != '\n') - pos++; - *pos = '\0'; - os_strlcpy(addr, buf, addr_len); - return 0; -} - - -static int hostapd_cli_cmd_all_sta(struct wpa_ctrl *ctrl, int argc, - char *argv[]) -{ - char addr[32], cmd[64]; - - if (wpa_ctrl_command_sta(ctrl, "STA-FIRST", addr, sizeof(addr))) - return 0; - do { - snprintf(cmd, sizeof(cmd), "STA-NEXT %s", addr); - } while (wpa_ctrl_command_sta(ctrl, cmd, addr, sizeof(addr)) == 0); - - return -1; -} - - -static int hostapd_cli_cmd_help(struct wpa_ctrl *ctrl, int argc, char *argv[]) -{ - printf("%s", commands_help); - return 0; -} - - -static int hostapd_cli_cmd_license(struct wpa_ctrl *ctrl, int argc, - char *argv[]) -{ - printf("%s\n\n%s\n", hostapd_cli_version, hostapd_cli_full_license); - return 0; -} - - -static int hostapd_cli_cmd_quit(struct wpa_ctrl *ctrl, int argc, char *argv[]) -{ - hostapd_cli_quit = 1; - return 0; -} - - -static int hostapd_cli_cmd_level(struct wpa_ctrl *ctrl, int argc, char *argv[]) -{ - char cmd[256]; - if (argc != 1) { - printf("Invalid LEVEL command: needs one argument (debug " - "level)\n"); - return 0; - } - snprintf(cmd, sizeof(cmd), "LEVEL %s", argv[0]); - return wpa_ctrl_command(ctrl, cmd); -} - - -static void hostapd_cli_list_interfaces(struct wpa_ctrl *ctrl) -{ - struct dirent *dent; - DIR *dir; - - dir = opendir(ctrl_iface_dir); - if (dir == NULL) { - printf("Control interface directory '%s' could not be " - "openned.\n", ctrl_iface_dir); - return; - } - - printf("Available interfaces:\n"); - while ((dent = readdir(dir))) { - if (strcmp(dent->d_name, ".") == 0 || - strcmp(dent->d_name, "..") == 0) - continue; - printf("%s\n", dent->d_name); - } - closedir(dir); -} - - -static int hostapd_cli_cmd_interface(struct wpa_ctrl *ctrl, int argc, - char *argv[]) -{ - if (argc < 1) { - hostapd_cli_list_interfaces(ctrl); - return 0; - } - - hostapd_cli_close_connection(); - free(ctrl_ifname); - ctrl_ifname = strdup(argv[0]); - - if (hostapd_cli_open_connection(ctrl_ifname)) { - printf("Connected to interface '%s.\n", ctrl_ifname); - if (wpa_ctrl_attach(ctrl_conn) == 0) { - hostapd_cli_attached = 1; - } else { - printf("Warning: Failed to attach to " - "hostapd.\n"); - } - } else { - printf("Could not connect to interface '%s' - re-trying\n", - ctrl_ifname); - } - return 0; -} - - -static int hostapd_cli_cmd_set(struct wpa_ctrl *ctrl, int argc, char *argv[]) -{ - char cmd[256]; - int res; - - if (argc != 2) { - printf("Invalid SET command: needs two arguments (variable " - "name and value)\n"); - return -1; - } - - res = os_snprintf(cmd, sizeof(cmd), "SET %s %s", argv[0], argv[1]); - if (res < 0 || (size_t) res >= sizeof(cmd) - 1) { - printf("Too long SET command.\n"); - return -1; - } - return wpa_ctrl_command(ctrl, cmd); -} - - -static int hostapd_cli_cmd_get(struct wpa_ctrl *ctrl, int argc, char *argv[]) -{ - char cmd[256]; - int res; - - if (argc != 1) { - printf("Invalid GET command: needs one argument (variable " - "name)\n"); - return -1; - } - - res = os_snprintf(cmd, sizeof(cmd), "GET %s", argv[0]); - if (res < 0 || (size_t) res >= sizeof(cmd) - 1) { - printf("Too long GET command.\n"); - return -1; - } - return wpa_ctrl_command(ctrl, cmd); -} - - -struct hostapd_cli_cmd { - const char *cmd; - int (*handler)(struct wpa_ctrl *ctrl, int argc, char *argv[]); -}; - -static struct hostapd_cli_cmd hostapd_cli_commands[] = { - { "ping", hostapd_cli_cmd_ping }, - { "mib", hostapd_cli_cmd_mib }, - { "relog", hostapd_cli_cmd_relog }, - { "sta", hostapd_cli_cmd_sta }, - { "all_sta", hostapd_cli_cmd_all_sta }, - { "new_sta", hostapd_cli_cmd_new_sta }, - { "deauthenticate", hostapd_cli_cmd_deauthenticate }, - { "disassociate", hostapd_cli_cmd_disassociate }, -#ifdef CONFIG_IEEE80211W - { "sa_query", hostapd_cli_cmd_sa_query }, -#endif /* CONFIG_IEEE80211W */ -#ifdef CONFIG_WPS - { "wps_pin", hostapd_cli_cmd_wps_pin }, - { "wps_check_pin", hostapd_cli_cmd_wps_check_pin }, - { "wps_pbc", hostapd_cli_cmd_wps_pbc }, -#ifdef CONFIG_WPS_OOB - { "wps_oob", hostapd_cli_cmd_wps_oob }, -#endif /* CONFIG_WPS_OOB */ - { "wps_ap_pin", hostapd_cli_cmd_wps_ap_pin }, - { "wps_config", hostapd_cli_cmd_wps_config }, -#endif /* CONFIG_WPS */ - { "get_config", hostapd_cli_cmd_get_config }, - { "help", hostapd_cli_cmd_help }, - { "interface", hostapd_cli_cmd_interface }, - { "level", hostapd_cli_cmd_level }, - { "license", hostapd_cli_cmd_license }, - { "quit", hostapd_cli_cmd_quit }, - { "set", hostapd_cli_cmd_set }, - { "get", hostapd_cli_cmd_get }, - { NULL, NULL } -}; - - -static void wpa_request(struct wpa_ctrl *ctrl, int argc, char *argv[]) -{ - struct hostapd_cli_cmd *cmd, *match = NULL; - int count; - - count = 0; - cmd = hostapd_cli_commands; - while (cmd->cmd) { - if (strncasecmp(cmd->cmd, argv[0], strlen(argv[0])) == 0) { - match = cmd; - if (os_strcasecmp(cmd->cmd, argv[0]) == 0) { - /* we have an exact match */ - count = 1; - break; - } - count++; - } - cmd++; - } - - if (count > 1) { - printf("Ambiguous command '%s'; possible commands:", argv[0]); - cmd = hostapd_cli_commands; - while (cmd->cmd) { - if (strncasecmp(cmd->cmd, argv[0], strlen(argv[0])) == - 0) { - printf(" %s", cmd->cmd); - } - cmd++; - } - printf("\n"); - } else if (count == 0) { - printf("Unknown command '%s'\n", argv[0]); - } else { - match->handler(ctrl, argc - 1, &argv[1]); - } -} - - -static void hostapd_cli_recv_pending(struct wpa_ctrl *ctrl, int in_read, - int action_monitor) -{ - int first = 1; - if (ctrl_conn == NULL) - return; - while (wpa_ctrl_pending(ctrl)) { - char buf[256]; - size_t len = sizeof(buf) - 1; - if (wpa_ctrl_recv(ctrl, buf, &len) == 0) { - buf[len] = '\0'; - if (action_monitor) - hostapd_cli_action_process(buf, len); - else { - if (in_read && first) - printf("\n"); - first = 0; - printf("%s\n", buf); - } - } else { - printf("Could not read pending message.\n"); - break; - } - } -} - - -static void hostapd_cli_interactive(void) -{ - const int max_args = 10; - char cmd[256], *res, *argv[max_args], *pos; - int argc; - - printf("\nInteractive mode\n\n"); - - do { - hostapd_cli_recv_pending(ctrl_conn, 0, 0); - printf("> "); - alarm(ping_interval); - res = fgets(cmd, sizeof(cmd), stdin); - alarm(0); - if (res == NULL) - break; - pos = cmd; - while (*pos != '\0') { - if (*pos == '\n') { - *pos = '\0'; - break; - } - pos++; - } - argc = 0; - pos = cmd; - for (;;) { - while (*pos == ' ') - pos++; - if (*pos == '\0') - break; - argv[argc] = pos; - argc++; - if (argc == max_args) - break; - while (*pos != '\0' && *pos != ' ') - pos++; - if (*pos == ' ') - *pos++ = '\0'; - } - if (argc) - wpa_request(ctrl_conn, argc, argv); - } while (!hostapd_cli_quit); -} - - -static void hostapd_cli_cleanup(void) -{ - hostapd_cli_close_connection(); - if (pid_file) - os_daemonize_terminate(pid_file); - - os_program_deinit(); -} - - -static void hostapd_cli_terminate(int sig) -{ - hostapd_cli_cleanup(); - exit(0); -} - - -static void hostapd_cli_alarm(int sig) -{ - if (ctrl_conn && _wpa_ctrl_command(ctrl_conn, "PING", 0)) { - printf("Connection to hostapd lost - trying to reconnect\n"); - hostapd_cli_close_connection(); - } - if (!ctrl_conn) { - ctrl_conn = hostapd_cli_open_connection(ctrl_ifname); - if (ctrl_conn) { - printf("Connection to hostapd re-established\n"); - if (wpa_ctrl_attach(ctrl_conn) == 0) { - hostapd_cli_attached = 1; - } else { - printf("Warning: Failed to attach to " - "hostapd.\n"); - } - } - } - if (ctrl_conn) - hostapd_cli_recv_pending(ctrl_conn, 1, 0); - alarm(ping_interval); -} - - -static void hostapd_cli_action(struct wpa_ctrl *ctrl) -{ - fd_set rfds; - int fd, res; - struct timeval tv; - char buf[256]; - size_t len; - - fd = wpa_ctrl_get_fd(ctrl); - - while (!hostapd_cli_quit) { - FD_ZERO(&rfds); - FD_SET(fd, &rfds); - tv.tv_sec = ping_interval; - tv.tv_usec = 0; - res = select(fd + 1, &rfds, NULL, NULL, &tv); - if (res < 0 && errno != EINTR) { - perror("select"); - break; - } - - if (FD_ISSET(fd, &rfds)) - hostapd_cli_recv_pending(ctrl, 0, 1); - else { - len = sizeof(buf) - 1; - if (wpa_ctrl_request(ctrl, "PING", 4, buf, &len, - hostapd_cli_action_process) < 0 || - len < 4 || os_memcmp(buf, "PONG", 4) != 0) { - printf("hostapd did not reply to PING " - "command - exiting\n"); - break; - } - } - } -} - - -int main(int argc, char *argv[]) -{ - int interactive; - int warning_displayed = 0; - int c; - int daemonize = 0; - - if (os_program_init()) - return -1; - - for (;;) { - c = getopt(argc, argv, "a:BhG:i:p:v"); - if (c < 0) - break; - switch (c) { - case 'a': - action_file = optarg; - break; - case 'B': - daemonize = 1; - break; - case 'G': - ping_interval = atoi(optarg); - break; - case 'h': - usage(); - return 0; - case 'v': - printf("%s\n", hostapd_cli_version); - return 0; - case 'i': - os_free(ctrl_ifname); - ctrl_ifname = os_strdup(optarg); - break; - case 'p': - ctrl_iface_dir = optarg; - break; - default: - usage(); - return -1; - } - } - - interactive = (argc == optind) && (action_file == NULL); - - if (interactive) { - printf("%s\n\n%s\n\n", hostapd_cli_version, - hostapd_cli_license); - } - - for (;;) { - if (ctrl_ifname == NULL) { - struct dirent *dent; - DIR *dir = opendir(ctrl_iface_dir); - if (dir) { - while ((dent = readdir(dir))) { - if (os_strcmp(dent->d_name, ".") == 0 - || - os_strcmp(dent->d_name, "..") == 0) - continue; - printf("Selected interface '%s'\n", - dent->d_name); - ctrl_ifname = os_strdup(dent->d_name); - break; - } - closedir(dir); - } - } - ctrl_conn = hostapd_cli_open_connection(ctrl_ifname); - if (ctrl_conn) { - if (warning_displayed) - printf("Connection established.\n"); - break; - } - - if (!interactive) { - perror("Failed to connect to hostapd - " - "wpa_ctrl_open"); - return -1; - } - - if (!warning_displayed) { - printf("Could not connect to hostapd - re-trying\n"); - warning_displayed = 1; - } - os_sleep(1, 0); - continue; - } - - signal(SIGINT, hostapd_cli_terminate); - signal(SIGTERM, hostapd_cli_terminate); - signal(SIGALRM, hostapd_cli_alarm); - - if (interactive || action_file) { - if (wpa_ctrl_attach(ctrl_conn) == 0) { - hostapd_cli_attached = 1; - } else { - printf("Warning: Failed to attach to hostapd.\n"); - if (action_file) - return -1; - } - } - - if (daemonize && os_daemonize(pid_file)) - return -1; - - if (interactive) - hostapd_cli_interactive(); - else if (action_file) - hostapd_cli_action(ctrl_conn); - else - wpa_request(ctrl_conn, argc - optind, &argv[optind]); - - os_free(ctrl_ifname); - hostapd_cli_cleanup(); - return 0; -} diff --git a/hostapd-0.8/hostapd/logwatch/README b/hostapd-0.8/hostapd/logwatch/README deleted file mode 100644 index 3cba511..0000000 --- a/hostapd-0.8/hostapd/logwatch/README +++ /dev/null @@ -1,9 +0,0 @@ -Logwatch is a utility for analyzing system logs and provide a human -readable summary. This directory has a configuration file and a log -analyzer script for parsing hostapd system log entries for logwatch. -These files can be installed by copying them to following locations: - -/etc/log.d/conf/services/hostapd.conf -/etc/log.d/scripts/services/hostapd - -More information about logwatch is available from http://www.logwatch.org/ diff --git a/hostapd-0.8/hostapd/logwatch/hostapd b/hostapd-0.8/hostapd/logwatch/hostapd deleted file mode 100644 index 97b24ef..0000000 --- a/hostapd-0.8/hostapd/logwatch/hostapd +++ /dev/null @@ -1,65 +0,0 @@ -#!/usr/bin/perl -w -# -# Logwatch script for hostapd -# -# Copyright 2005 Henrik Brix Andersen -# Distributed under the terms of the GNU General Public License v2 -# Alternatively, this file may be distributed under the terms of the BSD License - -use strict; - -my $debug = $ENV{'LOGWATCH_DEBUG'} || 0; -my $detail = $ENV{'LOGWATCH_DETAIL_LEVEL'} || 0; -my $debugcounter = 1; - -my %hostapd; -my @unmatched; - -if ($debug >= 5) { - print STDERR "\n\nDEBUG: Inside HOSTAPD Filter\n\n"; -} - -while (defined(my $line = )) { - if ($debug >= 5) { - print STDERR "DEBUG($debugcounter): $line"; - $debugcounter++; - } - chomp($line); - - if (my ($iface,$mac,$layer,$details) = ($line =~ /(.*?): STA (.*?) (.*?): (.*?)$/i)) { - unless ($detail == 10) { - # collapse association events - $details =~ s/^(associated) .*$/$1/i; - } - $hostapd{$iface}->{$mac}->{$layer}->{$details}++; - } else { - push @unmatched, "$line\n"; - } -} - -if (keys %hostapd) { - foreach my $iface (sort keys %hostapd) { - print "Interface $iface:\n"; - foreach my $mac (sort keys %{$hostapd{$iface}}) { - print " Client MAC Address $mac:\n"; - foreach my $layer (sort keys %{$hostapd{$iface}->{$mac}}) { - print " $layer:\n"; - foreach my $details (sort keys %{$hostapd{$iface}->{$mac}->{$layer}}) { - print " $details"; - my $count = $hostapd{$iface}->{$mac}->{$layer}->{$details}; - if ($count > 1) { - print ": " . $count . " Times"; - } - print "\n"; - } - } - } - } -} - -if ($#unmatched >= 0) { - print "\n**Unmatched Entries**\n"; - print @unmatched; -} - -exit(0); diff --git a/hostapd-0.8/hostapd/logwatch/hostapd.conf b/hostapd-0.8/hostapd/logwatch/hostapd.conf deleted file mode 100644 index 5bebe6a..0000000 --- a/hostapd-0.8/hostapd/logwatch/hostapd.conf +++ /dev/null @@ -1,10 +0,0 @@ -# Logwatch configuration for hostapd -# -# Copyright 2005 Henrik Brix Andersen -# Distributed under the terms of the GNU General Public License v2 -# Alternatively, this file may be distributed under the terms of the BSD License - -Title = "hostapd" -LogFile = messages -*OnlyService = hostapd -*RemoveHeaders diff --git a/hostapd-0.8/hostapd/main.c b/hostapd-0.8/hostapd/main.c deleted file mode 100644 index 7a4cfb0..0000000 --- a/hostapd-0.8/hostapd/main.c +++ /dev/null @@ -1,599 +0,0 @@ -/* - * hostapd / main() - * Copyright (c) 2002-2011, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#include "utils/includes.h" -#ifndef CONFIG_NATIVE_WINDOWS -#include -#endif /* CONFIG_NATIVE_WINDOWS */ - -#include "utils/common.h" -#include "utils/eloop.h" -#include "crypto/random.h" -#include "crypto/tls.h" -#include "common/version.h" -#include "drivers/driver.h" -#include "eap_server/eap.h" -#include "eap_server/tncs.h" -#include "ap/hostapd.h" -#include "ap/ap_config.h" -#include "config_file.h" -#include "eap_register.h" -#include "dump_state.h" -#include "ctrl_iface.h" - - -extern int wpa_debug_level; -extern int wpa_debug_show_keys; -extern int wpa_debug_timestamp; - - -struct hapd_interfaces { - size_t count; - struct hostapd_iface **iface; -}; - - -static int hostapd_for_each_interface(struct hapd_interfaces *interfaces, - int (*cb)(struct hostapd_iface *iface, - void *ctx), void *ctx) -{ - size_t i; - int ret; - - for (i = 0; i < interfaces->count; i++) { - ret = cb(interfaces->iface[i], ctx); - if (ret) - return ret; - } - - return 0; -} - - -#ifndef CONFIG_NO_HOSTAPD_LOGGER -static void hostapd_logger_cb(void *ctx, const u8 *addr, unsigned int module, - int level, const char *txt, size_t len) -{ - struct hostapd_data *hapd = ctx; - char *format, *module_str; - int maxlen; - int conf_syslog_level, conf_stdout_level; - unsigned int conf_syslog, conf_stdout; - - maxlen = len + 100; - format = os_malloc(maxlen); - if (!format) - return; - - if (hapd && hapd->conf) { - conf_syslog_level = hapd->conf->logger_syslog_level; - conf_stdout_level = hapd->conf->logger_stdout_level; - conf_syslog = hapd->conf->logger_syslog; - conf_stdout = hapd->conf->logger_stdout; - } else { - conf_syslog_level = conf_stdout_level = 0; - conf_syslog = conf_stdout = (unsigned int) -1; - } - - switch (module) { - case HOSTAPD_MODULE_IEEE80211: - module_str = "IEEE 802.11"; - break; - case HOSTAPD_MODULE_IEEE8021X: - module_str = "IEEE 802.1X"; - break; - case HOSTAPD_MODULE_RADIUS: - module_str = "RADIUS"; - break; - case HOSTAPD_MODULE_WPA: - module_str = "WPA"; - break; - case HOSTAPD_MODULE_DRIVER: - module_str = "DRIVER"; - break; - case HOSTAPD_MODULE_IAPP: - module_str = "IAPP"; - break; - case HOSTAPD_MODULE_MLME: - module_str = "MLME"; - break; - default: - module_str = NULL; - break; - } - - if (hapd && hapd->conf && addr) - os_snprintf(format, maxlen, "%s: STA " MACSTR "%s%s: %s", - hapd->conf->iface, MAC2STR(addr), - module_str ? " " : "", module_str, txt); - else if (hapd && hapd->conf) - os_snprintf(format, maxlen, "%s:%s%s %s", - hapd->conf->iface, module_str ? " " : "", - module_str, txt); - else if (addr) - os_snprintf(format, maxlen, "STA " MACSTR "%s%s: %s", - MAC2STR(addr), module_str ? " " : "", - module_str, txt); - else - os_snprintf(format, maxlen, "%s%s%s", - module_str, module_str ? ": " : "", txt); - - if ((conf_stdout & module) && level >= conf_stdout_level) { - wpa_debug_print_timestamp(); - printf("%s\n", format); - } - -#ifndef CONFIG_NATIVE_WINDOWS - if ((conf_syslog & module) && level >= conf_syslog_level) { - int priority; - switch (level) { - case HOSTAPD_LEVEL_DEBUG_VERBOSE: - case HOSTAPD_LEVEL_DEBUG: - priority = LOG_DEBUG; - break; - case HOSTAPD_LEVEL_INFO: - priority = LOG_INFO; - break; - case HOSTAPD_LEVEL_NOTICE: - priority = LOG_NOTICE; - break; - case HOSTAPD_LEVEL_WARNING: - priority = LOG_WARNING; - break; - default: - priority = LOG_INFO; - break; - } - syslog(priority, "%s", format); - } -#endif /* CONFIG_NATIVE_WINDOWS */ - - os_free(format); -} -#endif /* CONFIG_NO_HOSTAPD_LOGGER */ - - -/** - * hostapd_init - Allocate and initialize per-interface data - * @config_file: Path to the configuration file - * Returns: Pointer to the allocated interface data or %NULL on failure - * - * This function is used to allocate main data structures for per-interface - * data. The allocated data buffer will be freed by calling - * hostapd_cleanup_iface(). - */ -static struct hostapd_iface * hostapd_init(const char *config_file) -{ - struct hostapd_iface *hapd_iface = NULL; - struct hostapd_config *conf = NULL; - struct hostapd_data *hapd; - size_t i; - - hapd_iface = os_zalloc(sizeof(*hapd_iface)); - if (hapd_iface == NULL) - goto fail; - - hapd_iface->reload_config = hostapd_reload_config; - hapd_iface->config_read_cb = hostapd_config_read; - hapd_iface->config_fname = os_strdup(config_file); - if (hapd_iface->config_fname == NULL) - goto fail; - hapd_iface->ctrl_iface_init = hostapd_ctrl_iface_init; - hapd_iface->ctrl_iface_deinit = hostapd_ctrl_iface_deinit; - hapd_iface->for_each_interface = hostapd_for_each_interface; - - conf = hostapd_config_read(hapd_iface->config_fname); - if (conf == NULL) - goto fail; - hapd_iface->conf = conf; - - hapd_iface->num_bss = conf->num_bss; - hapd_iface->bss = os_zalloc(conf->num_bss * - sizeof(struct hostapd_data *)); - if (hapd_iface->bss == NULL) - goto fail; - - for (i = 0; i < conf->num_bss; i++) { - hapd = hapd_iface->bss[i] = - hostapd_alloc_bss_data(hapd_iface, conf, - &conf->bss[i]); - if (hapd == NULL) - goto fail; - hapd->msg_ctx = hapd; - } - - return hapd_iface; - -fail: - if (conf) - hostapd_config_free(conf); - if (hapd_iface) { - os_free(hapd_iface->config_fname); - os_free(hapd_iface->bss); - os_free(hapd_iface); - } - return NULL; -} - - -static int hostapd_driver_init(struct hostapd_iface *iface) -{ - struct wpa_init_params params; - size_t i; - struct hostapd_data *hapd = iface->bss[0]; - struct hostapd_bss_config *conf = hapd->conf; - u8 *b = conf->bssid; - struct wpa_driver_capa capa; - - if (hapd->driver == NULL || hapd->driver->hapd_init == NULL) { - wpa_printf(MSG_ERROR, "No hostapd driver wrapper available"); - return -1; - } - - /* Initialize the driver interface */ - if (!(b[0] | b[1] | b[2] | b[3] | b[4] | b[5])) - b = NULL; - - os_memset(¶ms, 0, sizeof(params)); - params.bssid = b; - params.ifname = hapd->conf->iface; - params.ssid = (const u8 *) hapd->conf->ssid.ssid; - params.ssid_len = hapd->conf->ssid.ssid_len; - params.test_socket = hapd->conf->test_socket; - params.use_pae_group_addr = hapd->conf->use_pae_group_addr; - - params.num_bridge = hapd->iface->num_bss; - params.bridge = os_zalloc(hapd->iface->num_bss * sizeof(char *)); - if (params.bridge == NULL) - return -1; - for (i = 0; i < hapd->iface->num_bss; i++) { - struct hostapd_data *bss = hapd->iface->bss[i]; - if (bss->conf->bridge[0]) - params.bridge[i] = bss->conf->bridge; - } - - params.own_addr = hapd->own_addr; - - hapd->drv_priv = hapd->driver->hapd_init(hapd, ¶ms); - os_free(params.bridge); - if (hapd->drv_priv == NULL) { - wpa_printf(MSG_ERROR, "%s driver initialization failed.", - hapd->driver->name); - hapd->driver = NULL; - return -1; - } - - if (hapd->driver->get_capa && - hapd->driver->get_capa(hapd->drv_priv, &capa) == 0) - iface->drv_flags = capa.flags; - - return 0; -} - - -static void hostapd_interface_deinit_free(struct hostapd_iface *iface) -{ - const struct wpa_driver_ops *driver; - void *drv_priv; - if (iface == NULL) - return; - driver = iface->bss[0]->driver; - drv_priv = iface->bss[0]->drv_priv; - hostapd_interface_deinit(iface); - if (driver && driver->hapd_deinit) - driver->hapd_deinit(drv_priv); - hostapd_interface_free(iface); -} - - -static struct hostapd_iface * -hostapd_interface_init(struct hapd_interfaces *interfaces, - const char *config_fname, int debug) -{ - struct hostapd_iface *iface; - int k; - - wpa_printf(MSG_ERROR, "Configuration file: %s", config_fname); - iface = hostapd_init(config_fname); - if (!iface) - return NULL; - iface->interfaces = interfaces; - - for (k = 0; k < debug; k++) { - if (iface->bss[0]->conf->logger_stdout_level > 0) - iface->bss[0]->conf->logger_stdout_level--; - } - - if (hostapd_driver_init(iface) || - hostapd_setup_interface(iface)) { - hostapd_interface_deinit_free(iface); - return NULL; - } - - return iface; -} - - -/** - * handle_term - SIGINT and SIGTERM handler to terminate hostapd process - */ -static void handle_term(int sig, void *signal_ctx) -{ - wpa_printf(MSG_DEBUG, "Signal %d received - terminating", sig); - eloop_terminate(); -} - - -#ifndef CONFIG_NATIVE_WINDOWS - -static int handle_reload_iface(struct hostapd_iface *iface, void *ctx) -{ - if (hostapd_reload_config(iface) < 0) { - wpa_printf(MSG_WARNING, "Failed to read new configuration " - "file - continuing with old."); - } - return 0; -} - - -/** - * handle_reload - SIGHUP handler to reload configuration - */ -static void handle_reload(int sig, void *signal_ctx) -{ - struct hapd_interfaces *interfaces = signal_ctx; - wpa_printf(MSG_DEBUG, "Signal %d received - reloading configuration", - sig); - hostapd_for_each_interface(interfaces, handle_reload_iface, NULL); -} - - -static void handle_dump_state(int sig, void *signal_ctx) -{ -#ifdef HOSTAPD_DUMP_STATE - struct hapd_interfaces *interfaces = signal_ctx; - hostapd_for_each_interface(interfaces, handle_dump_state_iface, NULL); -#endif /* HOSTAPD_DUMP_STATE */ -} -#endif /* CONFIG_NATIVE_WINDOWS */ - - -static int hostapd_global_init(struct hapd_interfaces *interfaces) -{ - hostapd_logger_register_cb(hostapd_logger_cb); - - if (eap_server_register_methods()) { - wpa_printf(MSG_ERROR, "Failed to register EAP methods"); - return -1; - } - - if (eloop_init()) { - wpa_printf(MSG_ERROR, "Failed to initialize event loop"); - return -1; - } - - random_init(); - -#ifndef CONFIG_NATIVE_WINDOWS - eloop_register_signal(SIGHUP, handle_reload, interfaces); - eloop_register_signal(SIGUSR1, handle_dump_state, interfaces); -#endif /* CONFIG_NATIVE_WINDOWS */ - eloop_register_signal_terminate(handle_term, interfaces); - -#ifndef CONFIG_NATIVE_WINDOWS - openlog("hostapd", 0, LOG_DAEMON); -#endif /* CONFIG_NATIVE_WINDOWS */ - - return 0; -} - - -static void hostapd_global_deinit(const char *pid_file) -{ -#ifdef EAP_SERVER_TNC - tncs_global_deinit(); -#endif /* EAP_SERVER_TNC */ - - random_deinit(); - - eloop_destroy(); - -#ifndef CONFIG_NATIVE_WINDOWS - closelog(); -#endif /* CONFIG_NATIVE_WINDOWS */ - - eap_server_unregister_methods(); - - os_daemonize_terminate(pid_file); -} - - -static int hostapd_global_run(struct hapd_interfaces *ifaces, int daemonize, - const char *pid_file) -{ -#ifdef EAP_SERVER_TNC - int tnc = 0; - size_t i, k; - - for (i = 0; !tnc && i < ifaces->count; i++) { - for (k = 0; k < ifaces->iface[i]->num_bss; k++) { - if (ifaces->iface[i]->bss[0]->conf->tnc) { - tnc++; - break; - } - } - } - - if (tnc && tncs_global_init() < 0) { - wpa_printf(MSG_ERROR, "Failed to initialize TNCS"); - return -1; - } -#endif /* EAP_SERVER_TNC */ - - if (daemonize && os_daemonize(pid_file)) { - perror("daemon"); - return -1; - } - - eloop_run(); - - return 0; -} - - -static void show_version(void) -{ - fprintf(stderr, - "hostapd v" VERSION_STR "\n" - "User space daemon for IEEE 802.11 AP management,\n" - "IEEE 802.1X/WPA/WPA2/EAP/RADIUS Authenticator\n" - "Copyright (c) 2002-2011, Jouni Malinen " - "and contributors\n"); -} - - -static void usage(void) -{ - show_version(); - fprintf(stderr, - "\n" - "usage: hostapd [-hdBKtv] [-P ] " - "\n" - "\n" - "options:\n" - " -h show this usage\n" - " -d show more debug messages (-dd for even more)\n" - " -B run daemon in the background\n" - " -P PID file\n" - " -K include key data in debug messages\n" -#ifdef CONFIG_DEBUG_FILE - " -f log output to debug file instead of stdout\n" -#endif /* CONFIG_DEBUG_FILE */ - " -t include timestamps in some debug messages\n" - " -v show hostapd version\n"); - - exit(1); -} - - -static const char * hostapd_msg_ifname_cb(void *ctx) -{ - struct hostapd_data *hapd = ctx; - if (hapd && hapd->iconf && hapd->iconf->bss) - return hapd->iconf->bss->iface; - return NULL; -} - - -int main(int argc, char *argv[]) -{ - struct hapd_interfaces interfaces; - int ret = 1; - size_t i; - int c, debug = 0, daemonize = 0; - char *pid_file = NULL; - const char *log_file = NULL; - - if (os_program_init()) - return -1; - - for (;;) { - c = getopt(argc, argv, "Bdf:hKP:tv"); - if (c < 0) - break; - switch (c) { - case 'h': - usage(); - break; - case 'd': - debug++; - if (wpa_debug_level > 0) - wpa_debug_level--; - break; - case 'B': - daemonize++; - break; - case 'f': - log_file = optarg; - break; - case 'K': - wpa_debug_show_keys++; - break; - case 'P': - os_free(pid_file); - pid_file = os_rel2abs_path(optarg); - break; - case 't': - wpa_debug_timestamp++; - break; - case 'v': - show_version(); - exit(1); - break; - - default: - usage(); - break; - } - } - - if (optind == argc) - usage(); - - wpa_msg_register_ifname_cb(hostapd_msg_ifname_cb); - - if (log_file) - wpa_debug_open_file(log_file); - - interfaces.count = argc - optind; - interfaces.iface = os_zalloc(interfaces.count * - sizeof(struct hostapd_iface *)); - if (interfaces.iface == NULL) { - wpa_printf(MSG_ERROR, "malloc failed"); - return -1; - } - - if (hostapd_global_init(&interfaces)) - return -1; - - /* Initialize interfaces */ - for (i = 0; i < interfaces.count; i++) { - interfaces.iface[i] = hostapd_interface_init(&interfaces, - argv[optind + i], - debug); - if (!interfaces.iface[i]) - goto out; - } - - if (hostapd_global_run(&interfaces, daemonize, pid_file)) - goto out; - - ret = 0; - - out: - /* Deinitialize all interfaces */ - for (i = 0; i < interfaces.count; i++) - hostapd_interface_deinit_free(interfaces.iface[i]); - os_free(interfaces.iface); - - hostapd_global_deinit(pid_file); - os_free(pid_file); - - if (log_file) - wpa_debug_close_file(); - - os_program_deinit(); - - return ret; -} diff --git a/hostapd-0.8/hostapd/nt_password_hash.c b/hostapd-0.8/hostapd/nt_password_hash.c deleted file mode 100644 index 839802a..0000000 --- a/hostapd-0.8/hostapd/nt_password_hash.c +++ /dev/null @@ -1,53 +0,0 @@ -/* - * hostapd - Plaintext password to NtPasswordHash - * Copyright (c) 2005, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#include "includes.h" - -#include "common.h" -#include "crypto/ms_funcs.h" - - -int main(int argc, char *argv[]) -{ - unsigned char password_hash[16]; - size_t i; - char *password, buf[64], *pos; - - if (argc > 1) - password = argv[1]; - else { - if (fgets(buf, sizeof(buf), stdin) == NULL) { - printf("Failed to read password\n"); - return 1; - } - buf[sizeof(buf) - 1] = '\0'; - pos = buf; - while (*pos != '\0') { - if (*pos == '\r' || *pos == '\n') { - *pos = '\0'; - break; - } - pos++; - } - password = buf; - } - - if (nt_password_hash((u8 *) password, strlen(password), password_hash)) - return -1; - for (i = 0; i < sizeof(password_hash); i++) - printf("%02x", password_hash[i]); - printf("\n"); - - return 0; -} diff --git a/hostapd-0.8/hostapd/wired.conf b/hostapd-0.8/hostapd/wired.conf deleted file mode 100644 index 956f8c5..0000000 --- a/hostapd-0.8/hostapd/wired.conf +++ /dev/null @@ -1,40 +0,0 @@ -##### hostapd configuration file ############################################## -# Empty lines and lines starting with # are ignored - -# Example configuration file for wired authenticator. See hostapd.conf for -# more details. - -interface=eth0 -driver=wired -logger_stdout=-1 -logger_stdout_level=1 -debug=2 -dump_file=/tmp/hostapd.dump - -ieee8021x=1 -eap_reauth_period=3600 - -use_pae_group_addr=1 - - -##### RADIUS configuration #################################################### -# for IEEE 802.1X with external Authentication Server, IEEE 802.11 -# authentication with external ACL for MAC addresses, and accounting - -# The own IP address of the access point (used as NAS-IP-Address) -own_ip_addr=127.0.0.1 - -# Optional NAS-Identifier string for RADIUS messages. When used, this should be -# a unique to the NAS within the scope of the RADIUS server. For example, a -# fully qualified domain name can be used here. -nas_identifier=ap.example.com - -# RADIUS authentication server -auth_server_addr=127.0.0.1 -auth_server_port=1812 -auth_server_shared_secret=radius - -# RADIUS accounting server -acct_server_addr=127.0.0.1 -acct_server_port=1813 -acct_server_shared_secret=radius diff --git a/hostapd-0.8/src/Makefile b/hostapd-0.8/src/Makefile deleted file mode 100644 index d73a175..0000000 --- a/hostapd-0.8/src/Makefile +++ /dev/null @@ -1,11 +0,0 @@ -SUBDIRS=ap common crypto drivers eapol_auth eapol_supp eap_common eap_peer eap_server l2_packet p2p radius rsn_supp tls utils wps - -all: - for d in $(SUBDIRS); do [ -d $$d ] && $(MAKE) -C $$d; done - -clean: - for d in $(SUBDIRS); do [ -d $$d ] && $(MAKE) -C $$d clean; done - rm -f *~ - -install: - for d in $(SUBDIRS); do [ -d $$d ] && $(MAKE) -C $$d install; done diff --git a/hostapd-0.8/src/ap/Makefile b/hostapd-0.8/src/ap/Makefile deleted file mode 100644 index 9c41962..0000000 --- a/hostapd-0.8/src/ap/Makefile +++ /dev/null @@ -1,8 +0,0 @@ -all: - @echo Nothing to be made. - -clean: - rm -f *~ *.o *.d - -install: - @echo Nothing to be made. diff --git a/hostapd-0.8/src/ap/accounting.c b/hostapd-0.8/src/ap/accounting.c deleted file mode 100644 index dbfb058..0000000 --- a/hostapd-0.8/src/ap/accounting.c +++ /dev/null @@ -1,505 +0,0 @@ -/* - * hostapd / RADIUS Accounting - * Copyright (c) 2002-2009, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#include "utils/includes.h" - -#include "utils/common.h" -#include "utils/eloop.h" -#include "drivers/driver.h" -#include "radius/radius.h" -#include "radius/radius_client.h" -#include "hostapd.h" -#include "ieee802_1x.h" -#include "ap_config.h" -#include "sta_info.h" -#include "ap_drv_ops.h" -#include "accounting.h" - - -/* Default interval in seconds for polling TX/RX octets from the driver if - * STA is not using interim accounting. This detects wrap arounds for - * input/output octets and updates Acct-{Input,Output}-Gigawords. */ -#define ACCT_DEFAULT_UPDATE_INTERVAL 300 - -static void accounting_sta_get_id(struct hostapd_data *hapd, - struct sta_info *sta); - - -static struct radius_msg * accounting_msg(struct hostapd_data *hapd, - struct sta_info *sta, - int status_type) -{ - struct radius_msg *msg; - char buf[128]; - u8 *val; - size_t len; - int i; - - msg = radius_msg_new(RADIUS_CODE_ACCOUNTING_REQUEST, - radius_client_get_id(hapd->radius)); - if (msg == NULL) { - printf("Could not create net RADIUS packet\n"); - return NULL; - } - - if (sta) { - radius_msg_make_authenticator(msg, (u8 *) sta, sizeof(*sta)); - - os_snprintf(buf, sizeof(buf), "%08X-%08X", - sta->acct_session_id_hi, sta->acct_session_id_lo); - if (!radius_msg_add_attr(msg, RADIUS_ATTR_ACCT_SESSION_ID, - (u8 *) buf, os_strlen(buf))) { - printf("Could not add Acct-Session-Id\n"); - goto fail; - } - } else { - radius_msg_make_authenticator(msg, (u8 *) hapd, sizeof(*hapd)); - } - - if (!radius_msg_add_attr_int32(msg, RADIUS_ATTR_ACCT_STATUS_TYPE, - status_type)) { - printf("Could not add Acct-Status-Type\n"); - goto fail; - } - - if (!radius_msg_add_attr_int32(msg, RADIUS_ATTR_ACCT_AUTHENTIC, - hapd->conf->ieee802_1x ? - RADIUS_ACCT_AUTHENTIC_RADIUS : - RADIUS_ACCT_AUTHENTIC_LOCAL)) { - printf("Could not add Acct-Authentic\n"); - goto fail; - } - - if (sta) { - val = ieee802_1x_get_identity(sta->eapol_sm, &len); - if (!val) { - os_snprintf(buf, sizeof(buf), RADIUS_ADDR_FORMAT, - MAC2STR(sta->addr)); - val = (u8 *) buf; - len = os_strlen(buf); - } - - if (!radius_msg_add_attr(msg, RADIUS_ATTR_USER_NAME, val, - len)) { - printf("Could not add User-Name\n"); - goto fail; - } - } - - if (hapd->conf->own_ip_addr.af == AF_INET && - !radius_msg_add_attr(msg, RADIUS_ATTR_NAS_IP_ADDRESS, - (u8 *) &hapd->conf->own_ip_addr.u.v4, 4)) { - printf("Could not add NAS-IP-Address\n"); - goto fail; - } - -#ifdef CONFIG_IPV6 - if (hapd->conf->own_ip_addr.af == AF_INET6 && - !radius_msg_add_attr(msg, RADIUS_ATTR_NAS_IPV6_ADDRESS, - (u8 *) &hapd->conf->own_ip_addr.u.v6, 16)) { - printf("Could not add NAS-IPv6-Address\n"); - goto fail; - } -#endif /* CONFIG_IPV6 */ - - if (hapd->conf->nas_identifier && - !radius_msg_add_attr(msg, RADIUS_ATTR_NAS_IDENTIFIER, - (u8 *) hapd->conf->nas_identifier, - os_strlen(hapd->conf->nas_identifier))) { - printf("Could not add NAS-Identifier\n"); - goto fail; - } - - if (sta && - !radius_msg_add_attr_int32(msg, RADIUS_ATTR_NAS_PORT, sta->aid)) { - printf("Could not add NAS-Port\n"); - goto fail; - } - - os_snprintf(buf, sizeof(buf), RADIUS_802_1X_ADDR_FORMAT ":%s", - MAC2STR(hapd->own_addr), hapd->conf->ssid.ssid); - if (!radius_msg_add_attr(msg, RADIUS_ATTR_CALLED_STATION_ID, - (u8 *) buf, os_strlen(buf))) { - printf("Could not add Called-Station-Id\n"); - goto fail; - } - - if (sta) { - os_snprintf(buf, sizeof(buf), RADIUS_802_1X_ADDR_FORMAT, - MAC2STR(sta->addr)); - if (!radius_msg_add_attr(msg, RADIUS_ATTR_CALLING_STATION_ID, - (u8 *) buf, os_strlen(buf))) { - printf("Could not add Calling-Station-Id\n"); - goto fail; - } - - if (!radius_msg_add_attr_int32( - msg, RADIUS_ATTR_NAS_PORT_TYPE, - RADIUS_NAS_PORT_TYPE_IEEE_802_11)) { - printf("Could not add NAS-Port-Type\n"); - goto fail; - } - - os_snprintf(buf, sizeof(buf), "CONNECT %d%sMbps %s", - radius_sta_rate(hapd, sta) / 2, - (radius_sta_rate(hapd, sta) & 1) ? ".5" : "", - radius_mode_txt(hapd)); - if (!radius_msg_add_attr(msg, RADIUS_ATTR_CONNECT_INFO, - (u8 *) buf, os_strlen(buf))) { - printf("Could not add Connect-Info\n"); - goto fail; - } - - for (i = 0; ; i++) { - val = ieee802_1x_get_radius_class(sta->eapol_sm, &len, - i); - if (val == NULL) - break; - - if (!radius_msg_add_attr(msg, RADIUS_ATTR_CLASS, - val, len)) { - printf("Could not add Class\n"); - goto fail; - } - } - } - - return msg; - - fail: - radius_msg_free(msg); - return NULL; -} - - -static int accounting_sta_update_stats(struct hostapd_data *hapd, - struct sta_info *sta, - struct hostap_sta_driver_data *data) -{ - if (hostapd_drv_read_sta_data(hapd, data, sta->addr)) - return -1; - - if (sta->last_rx_bytes > data->rx_bytes) - sta->acct_input_gigawords++; - if (sta->last_tx_bytes > data->tx_bytes) - sta->acct_output_gigawords++; - sta->last_rx_bytes = data->rx_bytes; - sta->last_tx_bytes = data->tx_bytes; - - hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_RADIUS, - HOSTAPD_LEVEL_DEBUG, "updated TX/RX stats: " - "Acct-Input-Octets=%lu Acct-Input-Gigawords=%u " - "Acct-Output-Octets=%lu Acct-Output-Gigawords=%u", - sta->last_rx_bytes, sta->acct_input_gigawords, - sta->last_tx_bytes, sta->acct_output_gigawords); - - return 0; -} - - -static void accounting_interim_update(void *eloop_ctx, void *timeout_ctx) -{ - struct hostapd_data *hapd = eloop_ctx; - struct sta_info *sta = timeout_ctx; - int interval; - - if (sta->acct_interim_interval) { - accounting_sta_interim(hapd, sta); - interval = sta->acct_interim_interval; - } else { - struct hostap_sta_driver_data data; - accounting_sta_update_stats(hapd, sta, &data); - interval = ACCT_DEFAULT_UPDATE_INTERVAL; - } - - eloop_register_timeout(interval, 0, accounting_interim_update, - hapd, sta); -} - - -/** - * accounting_sta_start - Start STA accounting - * @hapd: hostapd BSS data - * @sta: The station - */ -void accounting_sta_start(struct hostapd_data *hapd, struct sta_info *sta) -{ - struct radius_msg *msg; - int interval; - - if (sta->acct_session_started) - return; - - accounting_sta_get_id(hapd, sta); - hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_RADIUS, - HOSTAPD_LEVEL_INFO, - "starting accounting session %08X-%08X", - sta->acct_session_id_hi, sta->acct_session_id_lo); - - time(&sta->acct_session_start); - sta->last_rx_bytes = sta->last_tx_bytes = 0; - sta->acct_input_gigawords = sta->acct_output_gigawords = 0; - hostapd_drv_sta_clear_stats(hapd, sta->addr); - - if (!hapd->conf->radius->acct_server) - return; - - if (sta->acct_interim_interval) - interval = sta->acct_interim_interval; - else - interval = ACCT_DEFAULT_UPDATE_INTERVAL; - eloop_register_timeout(interval, 0, accounting_interim_update, - hapd, sta); - - msg = accounting_msg(hapd, sta, RADIUS_ACCT_STATUS_TYPE_START); - if (msg) - radius_client_send(hapd->radius, msg, RADIUS_ACCT, sta->addr); - - sta->acct_session_started = 1; -} - - -static void accounting_sta_report(struct hostapd_data *hapd, - struct sta_info *sta, int stop) -{ - struct radius_msg *msg; - int cause = sta->acct_terminate_cause; - struct hostap_sta_driver_data data; - struct os_time now; - u32 gigawords; - - if (!hapd->conf->radius->acct_server) - return; - - msg = accounting_msg(hapd, sta, - stop ? RADIUS_ACCT_STATUS_TYPE_STOP : - RADIUS_ACCT_STATUS_TYPE_INTERIM_UPDATE); - if (!msg) { - printf("Could not create RADIUS Accounting message\n"); - return; - } - - os_get_time(&now); - if (!radius_msg_add_attr_int32(msg, RADIUS_ATTR_ACCT_SESSION_TIME, - now.sec - sta->acct_session_start)) { - printf("Could not add Acct-Session-Time\n"); - goto fail; - } - - if (accounting_sta_update_stats(hapd, sta, &data) == 0) { - if (!radius_msg_add_attr_int32(msg, - RADIUS_ATTR_ACCT_INPUT_PACKETS, - data.rx_packets)) { - printf("Could not add Acct-Input-Packets\n"); - goto fail; - } - if (!radius_msg_add_attr_int32(msg, - RADIUS_ATTR_ACCT_OUTPUT_PACKETS, - data.tx_packets)) { - printf("Could not add Acct-Output-Packets\n"); - goto fail; - } - if (!radius_msg_add_attr_int32(msg, - RADIUS_ATTR_ACCT_INPUT_OCTETS, - data.rx_bytes)) { - printf("Could not add Acct-Input-Octets\n"); - goto fail; - } - gigawords = sta->acct_input_gigawords; -#if __WORDSIZE == 64 - gigawords += data.rx_bytes >> 32; -#endif - if (gigawords && - !radius_msg_add_attr_int32( - msg, RADIUS_ATTR_ACCT_INPUT_GIGAWORDS, - gigawords)) { - printf("Could not add Acct-Input-Gigawords\n"); - goto fail; - } - if (!radius_msg_add_attr_int32(msg, - RADIUS_ATTR_ACCT_OUTPUT_OCTETS, - data.tx_bytes)) { - printf("Could not add Acct-Output-Octets\n"); - goto fail; - } - gigawords = sta->acct_output_gigawords; -#if __WORDSIZE == 64 - gigawords += data.tx_bytes >> 32; -#endif - if (gigawords && - !radius_msg_add_attr_int32( - msg, RADIUS_ATTR_ACCT_OUTPUT_GIGAWORDS, - gigawords)) { - printf("Could not add Acct-Output-Gigawords\n"); - goto fail; - } - } - - if (!radius_msg_add_attr_int32(msg, RADIUS_ATTR_EVENT_TIMESTAMP, - now.sec)) { - printf("Could not add Event-Timestamp\n"); - goto fail; - } - - if (eloop_terminated()) - cause = RADIUS_ACCT_TERMINATE_CAUSE_ADMIN_REBOOT; - - if (stop && cause && - !radius_msg_add_attr_int32(msg, RADIUS_ATTR_ACCT_TERMINATE_CAUSE, - cause)) { - printf("Could not add Acct-Terminate-Cause\n"); - goto fail; - } - - radius_client_send(hapd->radius, msg, - stop ? RADIUS_ACCT : RADIUS_ACCT_INTERIM, - sta->addr); - return; - - fail: - radius_msg_free(msg); -} - - -/** - * accounting_sta_interim - Send a interim STA accounting report - * @hapd: hostapd BSS data - * @sta: The station - */ -void accounting_sta_interim(struct hostapd_data *hapd, struct sta_info *sta) -{ - if (sta->acct_session_started) - accounting_sta_report(hapd, sta, 0); -} - - -/** - * accounting_sta_stop - Stop STA accounting - * @hapd: hostapd BSS data - * @sta: The station - */ -void accounting_sta_stop(struct hostapd_data *hapd, struct sta_info *sta) -{ - if (sta->acct_session_started) { - accounting_sta_report(hapd, sta, 1); - eloop_cancel_timeout(accounting_interim_update, hapd, sta); - hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_RADIUS, - HOSTAPD_LEVEL_INFO, - "stopped accounting session %08X-%08X", - sta->acct_session_id_hi, - sta->acct_session_id_lo); - sta->acct_session_started = 0; - } -} - - -static void accounting_sta_get_id(struct hostapd_data *hapd, - struct sta_info *sta) -{ - sta->acct_session_id_lo = hapd->acct_session_id_lo++; - if (hapd->acct_session_id_lo == 0) { - hapd->acct_session_id_hi++; - } - sta->acct_session_id_hi = hapd->acct_session_id_hi; -} - - -/** - * accounting_receive - Process the RADIUS frames from Accounting Server - * @msg: RADIUS response message - * @req: RADIUS request message - * @shared_secret: RADIUS shared secret - * @shared_secret_len: Length of shared_secret in octets - * @data: Context data (struct hostapd_data *) - * Returns: Processing status - */ -static RadiusRxResult -accounting_receive(struct radius_msg *msg, struct radius_msg *req, - const u8 *shared_secret, size_t shared_secret_len, - void *data) -{ - if (radius_msg_get_hdr(msg)->code != RADIUS_CODE_ACCOUNTING_RESPONSE) { - printf("Unknown RADIUS message code\n"); - return RADIUS_RX_UNKNOWN; - } - - if (radius_msg_verify(msg, shared_secret, shared_secret_len, req, 0)) { - printf("Incoming RADIUS packet did not have correct " - "Authenticator - dropped\n"); - return RADIUS_RX_INVALID_AUTHENTICATOR; - } - - return RADIUS_RX_PROCESSED; -} - - -static void accounting_report_state(struct hostapd_data *hapd, int on) -{ - struct radius_msg *msg; - - if (!hapd->conf->radius->acct_server || hapd->radius == NULL) - return; - - /* Inform RADIUS server that accounting will start/stop so that the - * server can close old accounting sessions. */ - msg = accounting_msg(hapd, NULL, - on ? RADIUS_ACCT_STATUS_TYPE_ACCOUNTING_ON : - RADIUS_ACCT_STATUS_TYPE_ACCOUNTING_OFF); - if (!msg) - return; - - if (!radius_msg_add_attr_int32(msg, RADIUS_ATTR_ACCT_TERMINATE_CAUSE, - RADIUS_ACCT_TERMINATE_CAUSE_NAS_REBOOT)) - { - printf("Could not add Acct-Terminate-Cause\n"); - radius_msg_free(msg); - return; - } - - radius_client_send(hapd->radius, msg, RADIUS_ACCT, NULL); -} - - -/** - * accounting_init: Initialize accounting - * @hapd: hostapd BSS data - * Returns: 0 on success, -1 on failure - */ -int accounting_init(struct hostapd_data *hapd) -{ - struct os_time now; - - /* Acct-Session-Id should be unique over reboots. If reliable clock is - * not available, this could be replaced with reboot counter, etc. */ - os_get_time(&now); - hapd->acct_session_id_hi = now.sec; - - if (radius_client_register(hapd->radius, RADIUS_ACCT, - accounting_receive, hapd)) - return -1; - - accounting_report_state(hapd, 1); - - return 0; -} - - -/** - * accounting_deinit: Deinitilize accounting - * @hapd: hostapd BSS data - */ -void accounting_deinit(struct hostapd_data *hapd) -{ - accounting_report_state(hapd, 0); -} diff --git a/hostapd-0.8/src/ap/accounting.h b/hostapd-0.8/src/ap/accounting.h deleted file mode 100644 index f3d60f0..0000000 --- a/hostapd-0.8/src/ap/accounting.h +++ /dev/null @@ -1,45 +0,0 @@ -/* - * hostapd / RADIUS Accounting - * Copyright (c) 2002-2005, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#ifndef ACCOUNTING_H -#define ACCOUNTING_H - -void accounting_sta_interim(struct hostapd_data *hapd, struct sta_info *sta); -#ifdef CONFIG_NO_ACCOUNTING -static inline void accounting_sta_start(struct hostapd_data *hapd, - struct sta_info *sta) -{ -} - -static inline void accounting_sta_stop(struct hostapd_data *hapd, - struct sta_info *sta) -{ -} - -static inline int accounting_init(struct hostapd_data *hapd) -{ - return 0; -} - -static inline void accounting_deinit(struct hostapd_data *hapd) -{ -} -#else /* CONFIG_NO_ACCOUNTING */ -void accounting_sta_start(struct hostapd_data *hapd, struct sta_info *sta); -void accounting_sta_stop(struct hostapd_data *hapd, struct sta_info *sta); -int accounting_init(struct hostapd_data *hapd); -void accounting_deinit(struct hostapd_data *hapd); -#endif /* CONFIG_NO_ACCOUNTING */ - -#endif /* ACCOUNTING_H */ diff --git a/hostapd-0.8/src/ap/ap_config.c b/hostapd-0.8/src/ap/ap_config.c deleted file mode 100644 index e77716b..0000000 --- a/hostapd-0.8/src/ap/ap_config.c +++ /dev/null @@ -1,627 +0,0 @@ -/* - * hostapd / Configuration helper functions - * Copyright (c) 2003-2009, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#include "utils/includes.h" - -#include "utils/common.h" -#include "crypto/sha1.h" -#include "radius/radius_client.h" -#include "common/ieee802_11_defs.h" -#include "common/eapol_common.h" -#include "eap_common/eap_wsc_common.h" -#include "eap_server/eap.h" -#include "wpa_auth.h" -#include "sta_info.h" -#include "ap_config.h" - - -static void hostapd_config_free_vlan(struct hostapd_bss_config *bss) -{ - struct hostapd_vlan *vlan, *prev; - - vlan = bss->vlan; - prev = NULL; - while (vlan) { - prev = vlan; - vlan = vlan->next; - os_free(prev); - } - - bss->vlan = NULL; -} - - -void hostapd_config_defaults_bss(struct hostapd_bss_config *bss) -{ - bss->logger_syslog_level = HOSTAPD_LEVEL_INFO; - bss->logger_stdout_level = HOSTAPD_LEVEL_INFO; - bss->logger_syslog = (unsigned int) -1; - bss->logger_stdout = (unsigned int) -1; - - bss->auth_algs = WPA_AUTH_ALG_OPEN | WPA_AUTH_ALG_SHARED; - - bss->wep_rekeying_period = 300; - /* use key0 in individual key and key1 in broadcast key */ - bss->broadcast_key_idx_min = 1; - bss->broadcast_key_idx_max = 2; - bss->eap_reauth_period = 3600; - - bss->wpa_group_rekey = 600; - bss->wpa_gmk_rekey = 86400; - bss->wpa_key_mgmt = WPA_KEY_MGMT_PSK; - bss->wpa_pairwise = WPA_CIPHER_TKIP; - bss->wpa_group = WPA_CIPHER_TKIP; - bss->rsn_pairwise = 0; - - bss->max_num_sta = MAX_STA_COUNT; - - bss->dtim_period = 2; - - bss->radius_server_auth_port = 1812; - bss->ap_max_inactivity = AP_MAX_INACTIVITY; - bss->eapol_version = EAPOL_VERSION; - - bss->max_listen_interval = 65535; - - bss->pwd_group = 19; /* ECC: GF(p=256) */ - -#ifdef CONFIG_IEEE80211W - bss->assoc_sa_query_max_timeout = 1000; - bss->assoc_sa_query_retry_timeout = 201; -#endif /* CONFIG_IEEE80211W */ -#ifdef EAP_SERVER_FAST - /* both anonymous and authenticated provisioning */ - bss->eap_fast_prov = 3; - bss->pac_key_lifetime = 7 * 24 * 60 * 60; - bss->pac_key_refresh_time = 1 * 24 * 60 * 60; -#endif /* EAP_SERVER_FAST */ - - /* Set to -1 as defaults depends on HT in setup */ - bss->wmm_enabled = -1; - -#ifdef CONFIG_IEEE80211R - bss->ft_over_ds = 1; -#endif /* CONFIG_IEEE80211R */ -} - - -struct hostapd_config * hostapd_config_defaults(void) -{ -#define ecw2cw(ecw) ((1 << (ecw)) - 1) - - struct hostapd_config *conf; - struct hostapd_bss_config *bss; - const int aCWmin = 4, aCWmax = 10; - const struct hostapd_wmm_ac_params ac_bk = - { aCWmin, aCWmax, 7, 0, 0 }; /* background traffic */ - const struct hostapd_wmm_ac_params ac_be = - { aCWmin, aCWmax, 3, 0, 0 }; /* best effort traffic */ - const struct hostapd_wmm_ac_params ac_vi = /* video traffic */ - { aCWmin - 1, aCWmin, 2, 3000 / 32, 1 }; - const struct hostapd_wmm_ac_params ac_vo = /* voice traffic */ - { aCWmin - 2, aCWmin - 1, 2, 1500 / 32, 1 }; - const struct hostapd_tx_queue_params txq_bk = - { 7, ecw2cw(aCWmin), ecw2cw(aCWmax), 0 }; - const struct hostapd_tx_queue_params txq_be = - { 3, ecw2cw(aCWmin), 4 * (ecw2cw(aCWmin) + 1) - 1, 0}; - const struct hostapd_tx_queue_params txq_vi = - { 1, (ecw2cw(aCWmin) + 1) / 2 - 1, ecw2cw(aCWmin), 30}; - const struct hostapd_tx_queue_params txq_vo = - { 1, (ecw2cw(aCWmin) + 1) / 4 - 1, - (ecw2cw(aCWmin) + 1) / 2 - 1, 15}; - -#undef ecw2cw - - conf = os_zalloc(sizeof(*conf)); - bss = os_zalloc(sizeof(*bss)); - if (conf == NULL || bss == NULL) { - wpa_printf(MSG_ERROR, "Failed to allocate memory for " - "configuration data."); - os_free(conf); - os_free(bss); - return NULL; - } - - bss->radius = os_zalloc(sizeof(*bss->radius)); - if (bss->radius == NULL) { - os_free(conf); - os_free(bss); - return NULL; - } - - hostapd_config_defaults_bss(bss); - - conf->num_bss = 1; - conf->bss = bss; - - conf->beacon_int = 100; - conf->rts_threshold = -1; /* use driver default: 2347 */ - conf->fragm_threshold = -1; /* user driver default: 2346 */ - conf->send_probe_response = 1; - - conf->wmm_ac_params[0] = ac_be; - conf->wmm_ac_params[1] = ac_bk; - conf->wmm_ac_params[2] = ac_vi; - conf->wmm_ac_params[3] = ac_vo; - - conf->tx_queue[0] = txq_vo; - conf->tx_queue[1] = txq_vi; - conf->tx_queue[2] = txq_be; - conf->tx_queue[3] = txq_bk; - - conf->ht_capab = HT_CAP_INFO_SMPS_DISABLED; - - return conf; -} - - -int hostapd_mac_comp(const void *a, const void *b) -{ - return os_memcmp(a, b, sizeof(macaddr)); -} - - -int hostapd_mac_comp_empty(const void *a) -{ - macaddr empty = { 0 }; - return os_memcmp(a, empty, sizeof(macaddr)); -} - - -static int hostapd_config_read_wpa_psk(const char *fname, - struct hostapd_ssid *ssid) -{ - FILE *f; - char buf[128], *pos; - int line = 0, ret = 0, len, ok; - u8 addr[ETH_ALEN]; - struct hostapd_wpa_psk *psk; - - if (!fname) - return 0; - - f = fopen(fname, "r"); - if (!f) { - wpa_printf(MSG_ERROR, "WPA PSK file '%s' not found.", fname); - return -1; - } - - while (fgets(buf, sizeof(buf), f)) { - line++; - - if (buf[0] == '#') - continue; - pos = buf; - while (*pos != '\0') { - if (*pos == '\n') { - *pos = '\0'; - break; - } - pos++; - } - if (buf[0] == '\0') - continue; - - if (hwaddr_aton(buf, addr)) { - wpa_printf(MSG_ERROR, "Invalid MAC address '%s' on " - "line %d in '%s'", buf, line, fname); - ret = -1; - break; - } - - psk = os_zalloc(sizeof(*psk)); - if (psk == NULL) { - wpa_printf(MSG_ERROR, "WPA PSK allocation failed"); - ret = -1; - break; - } - if (is_zero_ether_addr(addr)) - psk->group = 1; - else - os_memcpy(psk->addr, addr, ETH_ALEN); - - pos = buf + 17; - if (*pos == '\0') { - wpa_printf(MSG_ERROR, "No PSK on line %d in '%s'", - line, fname); - os_free(psk); - ret = -1; - break; - } - pos++; - - ok = 0; - len = os_strlen(pos); - if (len == 64 && hexstr2bin(pos, psk->psk, PMK_LEN) == 0) - ok = 1; - else if (len >= 8 && len < 64) { - pbkdf2_sha1(pos, ssid->ssid, ssid->ssid_len, - 4096, psk->psk, PMK_LEN); - ok = 1; - } - if (!ok) { - wpa_printf(MSG_ERROR, "Invalid PSK '%s' on line %d in " - "'%s'", pos, line, fname); - os_free(psk); - ret = -1; - break; - } - - psk->next = ssid->wpa_psk; - ssid->wpa_psk = psk; - } - - fclose(f); - - return ret; -} - - -static int hostapd_derive_psk(struct hostapd_ssid *ssid) -{ - ssid->wpa_psk = os_zalloc(sizeof(struct hostapd_wpa_psk)); - if (ssid->wpa_psk == NULL) { - wpa_printf(MSG_ERROR, "Unable to alloc space for PSK"); - return -1; - } - wpa_hexdump_ascii(MSG_DEBUG, "SSID", - (u8 *) ssid->ssid, ssid->ssid_len); - wpa_hexdump_ascii_key(MSG_DEBUG, "PSK (ASCII passphrase)", - (u8 *) ssid->wpa_passphrase, - os_strlen(ssid->wpa_passphrase)); - pbkdf2_sha1(ssid->wpa_passphrase, - ssid->ssid, ssid->ssid_len, - 4096, ssid->wpa_psk->psk, PMK_LEN); - wpa_hexdump_key(MSG_DEBUG, "PSK (from passphrase)", - ssid->wpa_psk->psk, PMK_LEN); - return 0; -} - - -int hostapd_setup_wpa_psk(struct hostapd_bss_config *conf) -{ - struct hostapd_ssid *ssid = &conf->ssid; - - if (ssid->wpa_passphrase != NULL) { - if (ssid->wpa_psk != NULL) { - wpa_printf(MSG_DEBUG, "Using pre-configured WPA PSK " - "instead of passphrase"); - } else { - wpa_printf(MSG_DEBUG, "Deriving WPA PSK based on " - "passphrase"); - if (hostapd_derive_psk(ssid) < 0) - return -1; - } - ssid->wpa_psk->group = 1; - } - - if (ssid->wpa_psk_file) { - if (hostapd_config_read_wpa_psk(ssid->wpa_psk_file, - &conf->ssid)) - return -1; - } - - return 0; -} - - -int hostapd_wep_key_cmp(struct hostapd_wep_keys *a, struct hostapd_wep_keys *b) -{ - int i; - - if (a->idx != b->idx || a->default_len != b->default_len) - return 1; - for (i = 0; i < NUM_WEP_KEYS; i++) - if (a->len[i] != b->len[i] || - os_memcmp(a->key[i], b->key[i], a->len[i]) != 0) - return 1; - return 0; -} - - -static void hostapd_config_free_radius(struct hostapd_radius_server *servers, - int num_servers) -{ - int i; - - for (i = 0; i < num_servers; i++) { - os_free(servers[i].shared_secret); - } - os_free(servers); -} - - -static void hostapd_config_free_eap_user(struct hostapd_eap_user *user) -{ - os_free(user->identity); - os_free(user->password); - os_free(user); -} - - -static void hostapd_config_free_wep(struct hostapd_wep_keys *keys) -{ - int i; - for (i = 0; i < NUM_WEP_KEYS; i++) { - os_free(keys->key[i]); - keys->key[i] = NULL; - } -} - - -static void hostapd_config_free_bss(struct hostapd_bss_config *conf) -{ - struct hostapd_wpa_psk *psk, *prev; - struct hostapd_eap_user *user, *prev_user; - - if (conf == NULL) - return; - - psk = conf->ssid.wpa_psk; - while (psk) { - prev = psk; - psk = psk->next; - os_free(prev); - } - - os_free(conf->ssid.wpa_passphrase); - os_free(conf->ssid.wpa_psk_file); - hostapd_config_free_wep(&conf->ssid.wep); -#ifdef CONFIG_FULL_DYNAMIC_VLAN - os_free(conf->ssid.vlan_tagged_interface); -#endif /* CONFIG_FULL_DYNAMIC_VLAN */ - - user = conf->eap_user; - while (user) { - prev_user = user; - user = user->next; - hostapd_config_free_eap_user(prev_user); - } - - os_free(conf->dump_log_name); - os_free(conf->eap_req_id_text); - os_free(conf->accept_mac); - os_free(conf->deny_mac); - os_free(conf->nas_identifier); - hostapd_config_free_radius(conf->radius->auth_servers, - conf->radius->num_auth_servers); - hostapd_config_free_radius(conf->radius->acct_servers, - conf->radius->num_acct_servers); - os_free(conf->rsn_preauth_interfaces); - os_free(conf->ctrl_interface); - os_free(conf->ca_cert); - os_free(conf->server_cert); - os_free(conf->private_key); - os_free(conf->private_key_passwd); - os_free(conf->dh_file); - os_free(conf->pac_opaque_encr_key); - os_free(conf->eap_fast_a_id); - os_free(conf->eap_fast_a_id_info); - os_free(conf->eap_sim_db); - os_free(conf->radius_server_clients); - os_free(conf->test_socket); - os_free(conf->radius); - hostapd_config_free_vlan(conf); - if (conf->ssid.dyn_vlan_keys) { - struct hostapd_ssid *ssid = &conf->ssid; - size_t i; - for (i = 0; i <= ssid->max_dyn_vlan_keys; i++) { - if (ssid->dyn_vlan_keys[i] == NULL) - continue; - hostapd_config_free_wep(ssid->dyn_vlan_keys[i]); - os_free(ssid->dyn_vlan_keys[i]); - } - os_free(ssid->dyn_vlan_keys); - ssid->dyn_vlan_keys = NULL; - } - -#ifdef CONFIG_IEEE80211R - { - struct ft_remote_r0kh *r0kh, *r0kh_prev; - struct ft_remote_r1kh *r1kh, *r1kh_prev; - - r0kh = conf->r0kh_list; - conf->r0kh_list = NULL; - while (r0kh) { - r0kh_prev = r0kh; - r0kh = r0kh->next; - os_free(r0kh_prev); - } - - r1kh = conf->r1kh_list; - conf->r1kh_list = NULL; - while (r1kh) { - r1kh_prev = r1kh; - r1kh = r1kh->next; - os_free(r1kh_prev); - } - } -#endif /* CONFIG_IEEE80211R */ - -#ifdef CONFIG_WPS - os_free(conf->wps_pin_requests); - os_free(conf->device_name); - os_free(conf->manufacturer); - os_free(conf->model_name); - os_free(conf->model_number); - os_free(conf->serial_number); - os_free(conf->config_methods); - os_free(conf->ap_pin); - os_free(conf->extra_cred); - os_free(conf->ap_settings); - os_free(conf->upnp_iface); - os_free(conf->friendly_name); - os_free(conf->manufacturer_url); - os_free(conf->model_description); - os_free(conf->model_url); - os_free(conf->upc); -#endif /* CONFIG_WPS */ -} - - -/** - * hostapd_config_free - Free hostapd configuration - * @conf: Configuration data from hostapd_config_read(). - */ -void hostapd_config_free(struct hostapd_config *conf) -{ - size_t i; - - if (conf == NULL) - return; - - for (i = 0; i < conf->num_bss; i++) - hostapd_config_free_bss(&conf->bss[i]); - os_free(conf->bss); - os_free(conf->supported_rates); - os_free(conf->basic_rates); - - os_free(conf); -} - - -/** - * hostapd_maclist_found - Find a MAC address from a list - * @list: MAC address list - * @num_entries: Number of addresses in the list - * @addr: Address to search for - * @vlan_id: Buffer for returning VLAN ID or %NULL if not needed - * Returns: 1 if address is in the list or 0 if not. - * - * Perform a binary search for given MAC address from a pre-sorted list. - */ -int hostapd_maclist_found(struct mac_acl_entry *list, int num_entries, - const u8 *addr, int *vlan_id) -{ - int start, end, middle, res; - - start = 0; - end = num_entries - 1; - - while (start <= end) { - middle = (start + end) / 2; - res = os_memcmp(list[middle].addr, addr, ETH_ALEN); - if (res == 0) { - if (vlan_id) - *vlan_id = list[middle].vlan_id; - return 1; - } - if (res < 0) - start = middle + 1; - else - end = middle - 1; - } - - return 0; -} - - -int hostapd_rate_found(int *list, int rate) -{ - int i; - - if (list == NULL) - return 0; - - for (i = 0; list[i] >= 0; i++) - if (list[i] == rate) - return 1; - - return 0; -} - - -const char * hostapd_get_vlan_id_ifname(struct hostapd_vlan *vlan, int vlan_id) -{ - struct hostapd_vlan *v = vlan; - while (v) { - if (v->vlan_id == vlan_id || v->vlan_id == VLAN_ID_WILDCARD) - return v->ifname; - v = v->next; - } - return NULL; -} - - -const u8 * hostapd_get_psk(const struct hostapd_bss_config *conf, - const u8 *addr, const u8 *prev_psk) -{ - struct hostapd_wpa_psk *psk; - int next_ok = prev_psk == NULL; - - for (psk = conf->ssid.wpa_psk; psk != NULL; psk = psk->next) { - if (next_ok && - (psk->group || os_memcmp(psk->addr, addr, ETH_ALEN) == 0)) - return psk->psk; - - if (psk->psk == prev_psk) - next_ok = 1; - } - - return NULL; -} - - -const struct hostapd_eap_user * -hostapd_get_eap_user(const struct hostapd_bss_config *conf, const u8 *identity, - size_t identity_len, int phase2) -{ - struct hostapd_eap_user *user = conf->eap_user; - -#ifdef CONFIG_WPS - if (conf->wps_state && identity_len == WSC_ID_ENROLLEE_LEN && - os_memcmp(identity, WSC_ID_ENROLLEE, WSC_ID_ENROLLEE_LEN) == 0) { - static struct hostapd_eap_user wsc_enrollee; - os_memset(&wsc_enrollee, 0, sizeof(wsc_enrollee)); - wsc_enrollee.methods[0].method = eap_server_get_type( - "WSC", &wsc_enrollee.methods[0].vendor); - return &wsc_enrollee; - } - - if (conf->wps_state && identity_len == WSC_ID_REGISTRAR_LEN && - os_memcmp(identity, WSC_ID_REGISTRAR, WSC_ID_REGISTRAR_LEN) == 0) { - static struct hostapd_eap_user wsc_registrar; - os_memset(&wsc_registrar, 0, sizeof(wsc_registrar)); - wsc_registrar.methods[0].method = eap_server_get_type( - "WSC", &wsc_registrar.methods[0].vendor); - wsc_registrar.password = (u8 *) conf->ap_pin; - wsc_registrar.password_len = conf->ap_pin ? - os_strlen(conf->ap_pin) : 0; - return &wsc_registrar; - } -#endif /* CONFIG_WPS */ - - while (user) { - if (!phase2 && user->identity == NULL) { - /* Wildcard match */ - break; - } - - if (user->phase2 == !!phase2 && user->wildcard_prefix && - identity_len >= user->identity_len && - os_memcmp(user->identity, identity, user->identity_len) == - 0) { - /* Wildcard prefix match */ - break; - } - - if (user->phase2 == !!phase2 && - user->identity_len == identity_len && - os_memcmp(user->identity, identity, identity_len) == 0) - break; - user = user->next; - } - - return user; -} diff --git a/hostapd-0.8/src/ap/ap_config.h b/hostapd-0.8/src/ap/ap_config.h deleted file mode 100644 index 25720b8..0000000 --- a/hostapd-0.8/src/ap/ap_config.h +++ /dev/null @@ -1,417 +0,0 @@ -/* - * hostapd / Configuration definitions and helpers functions - * Copyright (c) 2003-2009, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#ifndef HOSTAPD_CONFIG_H -#define HOSTAPD_CONFIG_H - -#include "common/defs.h" -#include "ip_addr.h" -#include "common/wpa_common.h" -#include "wps/wps.h" - -#define MAX_STA_COUNT 2007 -#define MAX_VLAN_ID 4094 - -typedef u8 macaddr[ETH_ALEN]; - -struct mac_acl_entry { - macaddr addr; - int vlan_id; -}; - -struct hostapd_radius_servers; -struct ft_remote_r0kh; -struct ft_remote_r1kh; - -#define HOSTAPD_MAX_SSID_LEN 32 - -#define NUM_WEP_KEYS 4 -struct hostapd_wep_keys { - u8 idx; - u8 *key[NUM_WEP_KEYS]; - size_t len[NUM_WEP_KEYS]; - int keys_set; - size_t default_len; /* key length used for dynamic key generation */ -}; - -typedef enum hostap_security_policy { - SECURITY_PLAINTEXT = 0, - SECURITY_STATIC_WEP = 1, - SECURITY_IEEE_802_1X = 2, - SECURITY_WPA_PSK = 3, - SECURITY_WPA = 4 -} secpolicy; - -struct hostapd_ssid { - char ssid[HOSTAPD_MAX_SSID_LEN + 1]; - size_t ssid_len; - int ssid_set; - - char vlan[IFNAMSIZ + 1]; - secpolicy security_policy; - - struct hostapd_wpa_psk *wpa_psk; - char *wpa_passphrase; - char *wpa_psk_file; - - struct hostapd_wep_keys wep; - -#define DYNAMIC_VLAN_DISABLED 0 -#define DYNAMIC_VLAN_OPTIONAL 1 -#define DYNAMIC_VLAN_REQUIRED 2 - int dynamic_vlan; -#ifdef CONFIG_FULL_DYNAMIC_VLAN - char *vlan_tagged_interface; -#endif /* CONFIG_FULL_DYNAMIC_VLAN */ - struct hostapd_wep_keys **dyn_vlan_keys; - size_t max_dyn_vlan_keys; -}; - - -#define VLAN_ID_WILDCARD -1 - -struct hostapd_vlan { - struct hostapd_vlan *next; - int vlan_id; /* VLAN ID or -1 (VLAN_ID_WILDCARD) for wildcard entry */ - char ifname[IFNAMSIZ + 1]; - int dynamic_vlan; -#ifdef CONFIG_FULL_DYNAMIC_VLAN - -#define DVLAN_CLEAN_BR 0x1 -#define DVLAN_CLEAN_VLAN 0x2 -#define DVLAN_CLEAN_VLAN_PORT 0x4 -#define DVLAN_CLEAN_WLAN_PORT 0x8 - int clean; -#endif /* CONFIG_FULL_DYNAMIC_VLAN */ -}; - -#define PMK_LEN 32 -struct hostapd_wpa_psk { - struct hostapd_wpa_psk *next; - int group; - u8 psk[PMK_LEN]; - u8 addr[ETH_ALEN]; -}; - -#define EAP_USER_MAX_METHODS 8 -struct hostapd_eap_user { - struct hostapd_eap_user *next; - u8 *identity; - size_t identity_len; - struct { - int vendor; - u32 method; - } methods[EAP_USER_MAX_METHODS]; - u8 *password; - size_t password_len; - int phase2; - int force_version; - unsigned int wildcard_prefix:1; - unsigned int password_hash:1; /* whether password is hashed with - * nt_password_hash() */ - int ttls_auth; /* EAP_TTLS_AUTH_* bitfield */ -}; - - -#define NUM_TX_QUEUES 4 - -struct hostapd_tx_queue_params { - int aifs; - int cwmin; - int cwmax; - int burst; /* maximum burst time in 0.1 ms, i.e., 10 = 1 ms */ -}; - -struct hostapd_wmm_ac_params { - int cwmin; - int cwmax; - int aifs; - int txop_limit; /* in units of 32us */ - int admission_control_mandatory; -}; - - -/** - * struct hostapd_bss_config - Per-BSS configuration - */ -struct hostapd_bss_config { - char iface[IFNAMSIZ + 1]; - char bridge[IFNAMSIZ + 1]; - char wds_bridge[IFNAMSIZ + 1]; - - enum hostapd_logger_level logger_syslog_level, logger_stdout_level; - - unsigned int logger_syslog; /* module bitfield */ - unsigned int logger_stdout; /* module bitfield */ - - char *dump_log_name; /* file name for state dump (SIGUSR1) */ - - int max_num_sta; /* maximum number of STAs in station table */ - - int dtim_period; - - int ieee802_1x; /* use IEEE 802.1X */ - int eapol_version; - int eap_server; /* Use internal EAP server instead of external - * RADIUS server */ - struct hostapd_eap_user *eap_user; - char *eap_sim_db; - struct hostapd_ip_addr own_ip_addr; - char *nas_identifier; - struct hostapd_radius_servers *radius; - int acct_interim_interval; - - struct hostapd_ssid ssid; - - char *eap_req_id_text; /* optional displayable message sent with - * EAP Request-Identity */ - size_t eap_req_id_text_len; - int eapol_key_index_workaround; - - size_t default_wep_key_len; - int individual_wep_key_len; - int wep_rekeying_period; - int broadcast_key_idx_min, broadcast_key_idx_max; - int eap_reauth_period; - - int ieee802_11f; /* use IEEE 802.11f (IAPP) */ - char iapp_iface[IFNAMSIZ + 1]; /* interface used with IAPP broadcast - * frames */ - - enum { - ACCEPT_UNLESS_DENIED = 0, - DENY_UNLESS_ACCEPTED = 1, - USE_EXTERNAL_RADIUS_AUTH = 2 - } macaddr_acl; - struct mac_acl_entry *accept_mac; - int num_accept_mac; - struct mac_acl_entry *deny_mac; - int num_deny_mac; - int wds_sta; - int isolate; - - int auth_algs; /* bitfield of allowed IEEE 802.11 authentication - * algorithms, WPA_AUTH_ALG_{OPEN,SHARED,LEAP} */ - - int wpa; /* bitfield of WPA_PROTO_WPA, WPA_PROTO_RSN */ - int wpa_key_mgmt; -#ifdef CONFIG_IEEE80211W - enum mfp_options ieee80211w; - /* dot11AssociationSAQueryMaximumTimeout (in TUs) */ - unsigned int assoc_sa_query_max_timeout; - /* dot11AssociationSAQueryRetryTimeout (in TUs) */ - int assoc_sa_query_retry_timeout; -#endif /* CONFIG_IEEE80211W */ - int wpa_pairwise; - int wpa_group; - int wpa_group_rekey; - int wpa_strict_rekey; - int wpa_gmk_rekey; - int wpa_ptk_rekey; - int rsn_pairwise; - int rsn_preauth; - char *rsn_preauth_interfaces; - int peerkey; - -#ifdef CONFIG_IEEE80211R - /* IEEE 802.11r - Fast BSS Transition */ - u8 mobility_domain[MOBILITY_DOMAIN_ID_LEN]; - u8 r1_key_holder[FT_R1KH_ID_LEN]; - u32 r0_key_lifetime; - u32 reassociation_deadline; - struct ft_remote_r0kh *r0kh_list; - struct ft_remote_r1kh *r1kh_list; - int pmk_r1_push; - int ft_over_ds; -#endif /* CONFIG_IEEE80211R */ - - char *ctrl_interface; /* directory for UNIX domain sockets */ -#ifndef CONFIG_NATIVE_WINDOWS - gid_t ctrl_interface_gid; -#endif /* CONFIG_NATIVE_WINDOWS */ - int ctrl_interface_gid_set; - - char *ca_cert; - char *server_cert; - char *private_key; - char *private_key_passwd; - int check_crl; - char *dh_file; - u8 *pac_opaque_encr_key; - u8 *eap_fast_a_id; - size_t eap_fast_a_id_len; - char *eap_fast_a_id_info; - int eap_fast_prov; - int pac_key_lifetime; - int pac_key_refresh_time; - int eap_sim_aka_result_ind; - int tnc; - int fragment_size; - u16 pwd_group; - - char *radius_server_clients; - int radius_server_auth_port; - int radius_server_ipv6; - - char *test_socket; /* UNIX domain socket path for driver_test */ - - int use_pae_group_addr; /* Whether to send EAPOL frames to PAE group - * address instead of individual address - * (for driver_wired.c). - */ - - int ap_max_inactivity; - int ignore_broadcast_ssid; - - int wmm_enabled; - int wmm_uapsd; - - struct hostapd_vlan *vlan, *vlan_tail; - - macaddr bssid; - - /* - * Maximum listen interval that STAs can use when associating with this - * BSS. If a STA tries to use larger value, the association will be - * denied with status code 51. - */ - u16 max_listen_interval; - - int okc; /* Opportunistic Key Caching */ - - int wps_state; -#ifdef CONFIG_WPS - int ap_setup_locked; - u8 uuid[16]; - char *wps_pin_requests; - char *device_name; - char *manufacturer; - char *model_name; - char *model_number; - char *serial_number; - u8 device_type[WPS_DEV_TYPE_LEN]; - char *config_methods; - u8 os_version[4]; - char *ap_pin; - int skip_cred_build; - u8 *extra_cred; - size_t extra_cred_len; - int wps_cred_processing; - u8 *ap_settings; - size_t ap_settings_len; - char *upnp_iface; - char *friendly_name; - char *manufacturer_url; - char *model_description; - char *model_url; - char *upc; - struct wpabuf *wps_vendor_ext[MAX_WPS_VENDOR_EXTENSIONS]; -#endif /* CONFIG_WPS */ - -#define P2P_ENABLED BIT(0) -#define P2P_GROUP_OWNER BIT(1) -#define P2P_GROUP_FORMATION BIT(2) -#define P2P_MANAGE BIT(3) -#define P2P_ALLOW_CROSS_CONNECTION BIT(4) - int p2p; - - int disassoc_low_ack; - -#define TDLS_PROHIBIT BIT(0) -#define TDLS_PROHIBIT_CHAN_SWITCH BIT(1) - int tdls; - int disable_11n; -}; - - -/** - * struct hostapd_config - Per-radio interface configuration - */ -struct hostapd_config { - struct hostapd_bss_config *bss, *last_bss; - size_t num_bss; - - u16 beacon_int; - int rts_threshold; - int fragm_threshold; - u8 send_probe_response; - u8 channel; - enum hostapd_hw_mode hw_mode; /* HOSTAPD_MODE_IEEE80211A, .. */ - enum { - LONG_PREAMBLE = 0, - SHORT_PREAMBLE = 1 - } preamble; - enum { - CTS_PROTECTION_AUTOMATIC = 0, - CTS_PROTECTION_FORCE_ENABLED = 1, - CTS_PROTECTION_FORCE_DISABLED = 2, - CTS_PROTECTION_AUTOMATIC_NO_OLBC = 3, - } cts_protection_type; - - int *supported_rates; - int *basic_rates; - - const struct wpa_driver_ops *driver; - - int ap_table_max_size; - int ap_table_expiration_time; - - char country[3]; /* first two octets: country code as described in - * ISO/IEC 3166-1. Third octet: - * ' ' (ascii 32): all environments - * 'O': Outdoor environemnt only - * 'I': Indoor environment only - */ - - int ieee80211d; - - struct hostapd_tx_queue_params tx_queue[NUM_TX_QUEUES]; - - /* - * WMM AC parameters, in same order as 802.1D, i.e. - * 0 = BE (best effort) - * 1 = BK (background) - * 2 = VI (video) - * 3 = VO (voice) - */ - struct hostapd_wmm_ac_params wmm_ac_params[4]; - - int ht_op_mode_fixed; - u16 ht_capab; - int ieee80211n; - int secondary_channel; - int require_ht; -}; - - -int hostapd_mac_comp(const void *a, const void *b); -int hostapd_mac_comp_empty(const void *a); -struct hostapd_config * hostapd_config_defaults(void); -void hostapd_config_defaults_bss(struct hostapd_bss_config *bss); -void hostapd_config_free(struct hostapd_config *conf); -int hostapd_maclist_found(struct mac_acl_entry *list, int num_entries, - const u8 *addr, int *vlan_id); -int hostapd_rate_found(int *list, int rate); -int hostapd_wep_key_cmp(struct hostapd_wep_keys *a, - struct hostapd_wep_keys *b); -const u8 * hostapd_get_psk(const struct hostapd_bss_config *conf, - const u8 *addr, const u8 *prev_psk); -int hostapd_setup_wpa_psk(struct hostapd_bss_config *conf); -const char * hostapd_get_vlan_id_ifname(struct hostapd_vlan *vlan, - int vlan_id); -const struct hostapd_eap_user * -hostapd_get_eap_user(const struct hostapd_bss_config *conf, const u8 *identity, - size_t identity_len, int phase2); - -#endif /* HOSTAPD_CONFIG_H */ diff --git a/hostapd-0.8/src/ap/ap_drv_ops.c b/hostapd-0.8/src/ap/ap_drv_ops.c deleted file mode 100644 index 0b6836c..0000000 --- a/hostapd-0.8/src/ap/ap_drv_ops.c +++ /dev/null @@ -1,632 +0,0 @@ -/* - * hostapd - Driver operations - * Copyright (c) 2009-2010, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#include "utils/includes.h" - -#include "utils/common.h" -#include "drivers/driver.h" -#include "common/ieee802_11_defs.h" -#include "wps/wps.h" -#include "hostapd.h" -#include "ieee802_11.h" -#include "sta_info.h" -#include "ap_config.h" -#include "p2p_hostapd.h" -#include "ap_drv_ops.h" - - -u32 hostapd_sta_flags_to_drv(u32 flags) -{ - int res = 0; - if (flags & WLAN_STA_AUTHORIZED) - res |= WPA_STA_AUTHORIZED; - if (flags & WLAN_STA_WMM) - res |= WPA_STA_WMM; - if (flags & WLAN_STA_SHORT_PREAMBLE) - res |= WPA_STA_SHORT_PREAMBLE; - if (flags & WLAN_STA_MFP) - res |= WPA_STA_MFP; - return res; -} - - -int hostapd_set_ap_wps_ie(struct hostapd_data *hapd) -{ - struct wpabuf *beacon, *proberesp, *assocresp = NULL; - int ret; - - if (hapd->driver == NULL || hapd->driver->set_ap_wps_ie == NULL) - return 0; - - beacon = hapd->wps_beacon_ie; - proberesp = hapd->wps_probe_resp_ie; - -#ifdef CONFIG_P2P - if (hapd->wps_beacon_ie == NULL && hapd->p2p_beacon_ie == NULL) - beacon = NULL; - else { - beacon = wpabuf_alloc((hapd->wps_beacon_ie ? - wpabuf_len(hapd->wps_beacon_ie) : 0) + - (hapd->p2p_beacon_ie ? - wpabuf_len(hapd->p2p_beacon_ie) : 0)); - if (beacon == NULL) - return -1; - if (hapd->wps_beacon_ie) - wpabuf_put_buf(beacon, hapd->wps_beacon_ie); - if (hapd->p2p_beacon_ie) - wpabuf_put_buf(beacon, hapd->p2p_beacon_ie); - } - - if (hapd->wps_probe_resp_ie == NULL && hapd->p2p_probe_resp_ie == NULL) - proberesp = NULL; - else { - proberesp = wpabuf_alloc( - (hapd->wps_probe_resp_ie ? - wpabuf_len(hapd->wps_probe_resp_ie) : 0) + - (hapd->p2p_probe_resp_ie ? - wpabuf_len(hapd->p2p_probe_resp_ie) : 0)); - if (proberesp == NULL) { - wpabuf_free(beacon); - return -1; - } - if (hapd->wps_probe_resp_ie) - wpabuf_put_buf(proberesp, hapd->wps_probe_resp_ie); - if (hapd->p2p_probe_resp_ie) - wpabuf_put_buf(proberesp, hapd->p2p_probe_resp_ie); - } -#endif /* CONFIG_P2P */ - -#ifdef CONFIG_P2P_MANAGER - if (hapd->conf->p2p & P2P_MANAGE) { - struct wpabuf *a; - - a = wpabuf_alloc(100 + (beacon ? wpabuf_len(beacon) : 0)); - if (a) { - u8 *start, *p; - if (beacon) - wpabuf_put_buf(a, beacon); - if (beacon != hapd->wps_beacon_ie) - wpabuf_free(beacon); - start = wpabuf_put(a, 0); - p = hostapd_eid_p2p_manage(hapd, start); - wpabuf_put(a, p - start); - beacon = a; - } - - a = wpabuf_alloc(100 + (proberesp ? wpabuf_len(proberesp) : - 0)); - if (a) { - u8 *start, *p; - if (proberesp) - wpabuf_put_buf(a, proberesp); - if (proberesp != hapd->wps_probe_resp_ie) - wpabuf_free(proberesp); - start = wpabuf_put(a, 0); - p = hostapd_eid_p2p_manage(hapd, start); - wpabuf_put(a, p - start); - proberesp = a; - } - } -#endif /* CONFIG_P2P_MANAGER */ - -#ifdef CONFIG_WPS2 - if (hapd->conf->wps_state) - assocresp = wps_build_assoc_resp_ie(); -#endif /* CONFIG_WPS2 */ - -#ifdef CONFIG_P2P_MANAGER - if (hapd->conf->p2p & P2P_MANAGE) { - struct wpabuf *a; - a = wpabuf_alloc(100 + (assocresp ? wpabuf_len(assocresp) : - 0)); - if (a) { - u8 *start, *p; - start = wpabuf_put(a, 0); - p = hostapd_eid_p2p_manage(hapd, start); - wpabuf_put(a, p - start); - if (assocresp) { - wpabuf_put_buf(a, assocresp); - wpabuf_free(assocresp); - } - assocresp = a; - } - } -#endif /* CONFIG_P2P_MANAGER */ - - ret = hapd->driver->set_ap_wps_ie(hapd->drv_priv, beacon, proberesp, - assocresp); - - if (beacon != hapd->wps_beacon_ie) - wpabuf_free(beacon); - if (proberesp != hapd->wps_probe_resp_ie) - wpabuf_free(proberesp); - wpabuf_free(assocresp); - - return ret; -} - - -int hostapd_set_authorized(struct hostapd_data *hapd, - struct sta_info *sta, int authorized) -{ - if (authorized) { - return hostapd_sta_set_flags(hapd, sta->addr, - hostapd_sta_flags_to_drv( - sta->flags), - WPA_STA_AUTHORIZED, ~0); - } - - return hostapd_sta_set_flags(hapd, sta->addr, - hostapd_sta_flags_to_drv(sta->flags), - 0, ~WPA_STA_AUTHORIZED); -} - - -int hostapd_set_sta_flags(struct hostapd_data *hapd, struct sta_info *sta) -{ - int set_flags, total_flags, flags_and, flags_or; - total_flags = hostapd_sta_flags_to_drv(sta->flags); - set_flags = WPA_STA_SHORT_PREAMBLE | WPA_STA_WMM | WPA_STA_MFP; - if (((!hapd->conf->ieee802_1x && !hapd->conf->wpa) || - sta->auth_alg == WLAN_AUTH_FT) && - sta->flags & WLAN_STA_AUTHORIZED) - set_flags |= WPA_STA_AUTHORIZED; - flags_or = total_flags & set_flags; - flags_and = total_flags | ~set_flags; - return hostapd_sta_set_flags(hapd, sta->addr, total_flags, - flags_or, flags_and); -} - - -int hostapd_set_drv_ieee8021x(struct hostapd_data *hapd, const char *ifname, - int enabled) -{ - struct wpa_bss_params params; - os_memset(¶ms, 0, sizeof(params)); - params.ifname = ifname; - params.enabled = enabled; - if (enabled) { - params.wpa = hapd->conf->wpa; - params.ieee802_1x = hapd->conf->ieee802_1x; - params.wpa_group = hapd->conf->wpa_group; - params.wpa_pairwise = hapd->conf->wpa_pairwise; - params.wpa_key_mgmt = hapd->conf->wpa_key_mgmt; - params.rsn_preauth = hapd->conf->rsn_preauth; -#ifdef CONFIG_IEEE80211W - params.ieee80211w = hapd->conf->ieee80211w; -#endif /* CONFIG_IEEE80211W */ - } - return hostapd_set_ieee8021x(hapd, ¶ms); -} - - -static int hostapd_set_ap_isolate(struct hostapd_data *hapd, int value) -{ - if (hapd->driver == NULL || hapd->driver->set_intra_bss == NULL) - return 0; - return hapd->driver->set_intra_bss(hapd->drv_priv, !value); -} - - -int hostapd_set_bss_params(struct hostapd_data *hapd, int use_protection) -{ - int ret = 0; - int preamble; -#ifdef CONFIG_IEEE80211N - u8 buf[60], *ht_capab, *ht_oper, *pos; - - pos = buf; - ht_capab = pos; - pos = hostapd_eid_ht_capabilities(hapd, pos); - ht_oper = pos; - pos = hostapd_eid_ht_operation(hapd, pos); - if (pos > ht_oper && ht_oper > ht_capab && - hostapd_set_ht_params(hapd, ht_capab + 2, ht_capab[1], - ht_oper + 2, ht_oper[1])) { - wpa_printf(MSG_ERROR, "Could not set HT capabilities " - "for kernel driver"); - ret = -1; - } - -#endif /* CONFIG_IEEE80211N */ - - if (hostapd_set_cts_protect(hapd, use_protection)) { - wpa_printf(MSG_ERROR, "Failed to set CTS protect in kernel " - "driver"); - ret = -1; - } - - if (hapd->iface->current_mode && - hapd->iface->current_mode->mode == HOSTAPD_MODE_IEEE80211G && - hostapd_set_short_slot_time(hapd, - hapd->iface->num_sta_no_short_slot_time - > 0 ? 0 : 1)) { - wpa_printf(MSG_ERROR, "Failed to set Short Slot Time option " - "in kernel driver"); - ret = -1; - } - - if (hapd->iface->num_sta_no_short_preamble == 0 && - hapd->iconf->preamble == SHORT_PREAMBLE) - preamble = SHORT_PREAMBLE; - else - preamble = LONG_PREAMBLE; - if (hostapd_set_preamble(hapd, preamble)) { - wpa_printf(MSG_ERROR, "Could not set preamble for kernel " - "driver"); - ret = -1; - } - - if (hostapd_set_ap_isolate(hapd, hapd->conf->isolate) && - hapd->conf->isolate) { - wpa_printf(MSG_ERROR, "Could not enable AP isolation in " - "kernel driver"); - ret = -1; - } - - return ret; -} - - -int hostapd_vlan_if_add(struct hostapd_data *hapd, const char *ifname) -{ - char force_ifname[IFNAMSIZ]; - u8 if_addr[ETH_ALEN]; - return hostapd_if_add(hapd, WPA_IF_AP_VLAN, ifname, hapd->own_addr, - NULL, NULL, force_ifname, if_addr, NULL); -} - - -int hostapd_vlan_if_remove(struct hostapd_data *hapd, const char *ifname) -{ - return hostapd_if_remove(hapd, WPA_IF_AP_VLAN, ifname); -} - - -int hostapd_set_wds_sta(struct hostapd_data *hapd, const u8 *addr, int aid, - int val) -{ - const char *bridge = NULL; - - if (hapd->driver == NULL || hapd->driver->set_wds_sta == NULL) - return 0; - if (hapd->conf->wds_bridge[0]) - bridge = hapd->conf->wds_bridge; - else if (hapd->conf->bridge[0]) - bridge = hapd->conf->bridge; - return hapd->driver->set_wds_sta(hapd->drv_priv, addr, aid, val, - bridge); -} - - -int hostapd_sta_add(struct hostapd_data *hapd, - const u8 *addr, u16 aid, u16 capability, - const u8 *supp_rates, size_t supp_rates_len, - u16 listen_interval, - const struct ieee80211_ht_capabilities *ht_capab) -{ - struct hostapd_sta_add_params params; - - if (hapd->driver == NULL) - return 0; - if (hapd->driver->sta_add == NULL) - return 0; - - os_memset(¶ms, 0, sizeof(params)); - params.addr = addr; - params.aid = aid; - params.capability = capability; - params.supp_rates = supp_rates; - params.supp_rates_len = supp_rates_len; - params.listen_interval = listen_interval; - params.ht_capabilities = ht_capab; - return hapd->driver->sta_add(hapd->drv_priv, ¶ms); -} - - -int hostapd_set_privacy(struct hostapd_data *hapd, int enabled) -{ - if (hapd->driver == NULL || hapd->driver->set_privacy == NULL) - return 0; - return hapd->driver->set_privacy(hapd->drv_priv, enabled); -} - - -int hostapd_set_generic_elem(struct hostapd_data *hapd, const u8 *elem, - size_t elem_len) -{ - if (hapd->driver == NULL || hapd->driver->set_generic_elem == NULL) - return 0; - return hapd->driver->set_generic_elem(hapd->drv_priv, elem, elem_len); -} - - -int hostapd_get_ssid(struct hostapd_data *hapd, u8 *buf, size_t len) -{ - if (hapd->driver == NULL || hapd->driver->hapd_get_ssid == NULL) - return 0; - return hapd->driver->hapd_get_ssid(hapd->drv_priv, buf, len); -} - - -int hostapd_set_ssid(struct hostapd_data *hapd, const u8 *buf, size_t len) -{ - if (hapd->driver == NULL || hapd->driver->hapd_set_ssid == NULL) - return 0; - return hapd->driver->hapd_set_ssid(hapd->drv_priv, buf, len); -} - - -int hostapd_if_add(struct hostapd_data *hapd, enum wpa_driver_if_type type, - const char *ifname, const u8 *addr, void *bss_ctx, - void **drv_priv, char *force_ifname, u8 *if_addr, - const char *bridge) -{ - if (hapd->driver == NULL || hapd->driver->if_add == NULL) - return -1; - return hapd->driver->if_add(hapd->drv_priv, type, ifname, addr, - bss_ctx, drv_priv, force_ifname, if_addr, - bridge); -} - - -int hostapd_if_remove(struct hostapd_data *hapd, enum wpa_driver_if_type type, - const char *ifname) -{ - if (hapd->driver == NULL || hapd->driver->if_remove == NULL) - return -1; - return hapd->driver->if_remove(hapd->drv_priv, type, ifname); -} - - -int hostapd_set_ieee8021x(struct hostapd_data *hapd, - struct wpa_bss_params *params) -{ - if (hapd->driver == NULL || hapd->driver->set_ieee8021x == NULL) - return 0; - return hapd->driver->set_ieee8021x(hapd->drv_priv, params); -} - - -int hostapd_get_seqnum(const char *ifname, struct hostapd_data *hapd, - const u8 *addr, int idx, u8 *seq) -{ - if (hapd->driver == NULL || hapd->driver->get_seqnum == NULL) - return 0; - return hapd->driver->get_seqnum(ifname, hapd->drv_priv, addr, idx, - seq); -} - - -int hostapd_flush(struct hostapd_data *hapd) -{ - if (hapd->driver == NULL || hapd->driver->flush == NULL) - return 0; - return hapd->driver->flush(hapd->drv_priv); -} - - -int hostapd_set_freq(struct hostapd_data *hapd, int mode, int freq, - int channel, int ht_enabled, int sec_channel_offset) -{ - struct hostapd_freq_params data; - if (hapd->driver == NULL) - return 0; - if (hapd->driver->set_freq == NULL) - return 0; - os_memset(&data, 0, sizeof(data)); - data.mode = mode; - data.freq = freq; - data.channel = channel; - data.ht_enabled = ht_enabled; - data.sec_channel_offset = sec_channel_offset; - return hapd->driver->set_freq(hapd->drv_priv, &data); -} - -int hostapd_set_rts(struct hostapd_data *hapd, int rts) -{ - if (hapd->driver == NULL || hapd->driver->set_rts == NULL) - return 0; - return hapd->driver->set_rts(hapd->drv_priv, rts); -} - - -int hostapd_set_frag(struct hostapd_data *hapd, int frag) -{ - if (hapd->driver == NULL || hapd->driver->set_frag == NULL) - return 0; - return hapd->driver->set_frag(hapd->drv_priv, frag); -} - - -int hostapd_sta_set_flags(struct hostapd_data *hapd, u8 *addr, - int total_flags, int flags_or, int flags_and) -{ - if (hapd->driver == NULL || hapd->driver->sta_set_flags == NULL) - return 0; - return hapd->driver->sta_set_flags(hapd->drv_priv, addr, total_flags, - flags_or, flags_and); -} - - -int hostapd_set_rate_sets(struct hostapd_data *hapd, int *supp_rates, - int *basic_rates, int mode) -{ - if (hapd->driver == NULL || hapd->driver->set_rate_sets == NULL) - return 0; - return hapd->driver->set_rate_sets(hapd->drv_priv, supp_rates, - basic_rates, mode); -} - - -int hostapd_set_country(struct hostapd_data *hapd, const char *country) -{ - if (hapd->driver == NULL || - hapd->driver->set_country == NULL) - return 0; - return hapd->driver->set_country(hapd->drv_priv, country); -} - - -int hostapd_set_cts_protect(struct hostapd_data *hapd, int value) -{ - if (hapd->driver == NULL || hapd->driver->set_cts_protect == NULL) - return 0; - return hapd->driver->set_cts_protect(hapd->drv_priv, value); -} - - -int hostapd_set_preamble(struct hostapd_data *hapd, int value) -{ - if (hapd->driver == NULL || hapd->driver->set_preamble == NULL) - return 0; - return hapd->driver->set_preamble(hapd->drv_priv, value); -} - - -int hostapd_set_short_slot_time(struct hostapd_data *hapd, int value) -{ - if (hapd->driver == NULL || hapd->driver->set_short_slot_time == NULL) - return 0; - return hapd->driver->set_short_slot_time(hapd->drv_priv, value); -} - - -int hostapd_set_tx_queue_params(struct hostapd_data *hapd, int queue, int aifs, - int cw_min, int cw_max, int burst_time) -{ - if (hapd->driver == NULL || hapd->driver->set_tx_queue_params == NULL) - return 0; - return hapd->driver->set_tx_queue_params(hapd->drv_priv, queue, aifs, - cw_min, cw_max, burst_time); -} - - -int hostapd_valid_bss_mask(struct hostapd_data *hapd, const u8 *addr, - const u8 *mask) -{ - if (hapd->driver == NULL || hapd->driver->valid_bss_mask == NULL) - return 1; - return hapd->driver->valid_bss_mask(hapd->drv_priv, addr, mask); -} - - -struct hostapd_hw_modes * -hostapd_get_hw_feature_data(struct hostapd_data *hapd, u16 *num_modes, - u16 *flags) -{ - if (hapd->driver == NULL || - hapd->driver->get_hw_feature_data == NULL) - return NULL; - return hapd->driver->get_hw_feature_data(hapd->drv_priv, num_modes, - flags); -} - - -int hostapd_driver_commit(struct hostapd_data *hapd) -{ - if (hapd->driver == NULL || hapd->driver->commit == NULL) - return 0; - return hapd->driver->commit(hapd->drv_priv); -} - - -int hostapd_set_ht_params(struct hostapd_data *hapd, - const u8 *ht_capab, size_t ht_capab_len, - const u8 *ht_oper, size_t ht_oper_len) -{ - if (hapd->driver == NULL || hapd->driver->set_ht_params == NULL || - ht_capab == NULL || ht_oper == NULL) - return 0; - return hapd->driver->set_ht_params(hapd->drv_priv, - ht_capab, ht_capab_len, - ht_oper, ht_oper_len); -} - - -int hostapd_drv_none(struct hostapd_data *hapd) -{ - return hapd->driver && os_strcmp(hapd->driver->name, "none") == 0; -} - - -int hostapd_driver_scan(struct hostapd_data *hapd, - struct wpa_driver_scan_params *params) -{ - if (hapd->driver && hapd->driver->scan2) - return hapd->driver->scan2(hapd->drv_priv, params); - return -1; -} - - -struct wpa_scan_results * hostapd_driver_get_scan_results( - struct hostapd_data *hapd) -{ - if (hapd->driver && hapd->driver->get_scan_results2) - return hapd->driver->get_scan_results2(hapd->drv_priv); - return NULL; -} - - -int hostapd_driver_set_noa(struct hostapd_data *hapd, u8 count, int start, - int duration) -{ - if (hapd->driver && hapd->driver->set_noa) - return hapd->driver->set_noa(hapd->drv_priv, count, start, - duration); - return -1; -} - - -int hostapd_drv_set_key(const char *ifname, struct hostapd_data *hapd, - enum wpa_alg alg, const u8 *addr, - int key_idx, int set_tx, - const u8 *seq, size_t seq_len, - const u8 *key, size_t key_len) -{ - if (hapd->driver == NULL || hapd->driver->set_key == NULL) - return 0; - return hapd->driver->set_key(ifname, hapd->drv_priv, alg, addr, - key_idx, set_tx, seq, seq_len, key, - key_len); -} - - -int hostapd_drv_send_mlme(struct hostapd_data *hapd, - const void *msg, size_t len) -{ - if (hapd->driver == NULL || hapd->driver->send_mlme == NULL) - return 0; - return hapd->driver->send_mlme(hapd->drv_priv, msg, len); -} - - -int hostapd_drv_sta_deauth(struct hostapd_data *hapd, - const u8 *addr, int reason) -{ - if (hapd->driver == NULL || hapd->driver->sta_deauth == NULL) - return 0; - return hapd->driver->sta_deauth(hapd->drv_priv, hapd->own_addr, addr, - reason); -} - - -int hostapd_drv_sta_disassoc(struct hostapd_data *hapd, - const u8 *addr, int reason) -{ - if (hapd->driver == NULL || hapd->driver->sta_disassoc == NULL) - return 0; - return hapd->driver->sta_disassoc(hapd->drv_priv, hapd->own_addr, addr, - reason); -} diff --git a/hostapd-0.8/src/ap/ap_drv_ops.h b/hostapd-0.8/src/ap/ap_drv_ops.h deleted file mode 100644 index 36bb826..0000000 --- a/hostapd-0.8/src/ap/ap_drv_ops.h +++ /dev/null @@ -1,197 +0,0 @@ -/* - * hostapd - Driver operations - * Copyright (c) 2009, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#ifndef AP_DRV_OPS -#define AP_DRV_OPS - -enum wpa_driver_if_type; -struct wpa_bss_params; -struct wpa_driver_scan_params; -struct ieee80211_ht_capabilities; - -u32 hostapd_sta_flags_to_drv(u32 flags); -int hostapd_set_ap_wps_ie(struct hostapd_data *hapd); -int hostapd_set_authorized(struct hostapd_data *hapd, - struct sta_info *sta, int authorized); -int hostapd_set_sta_flags(struct hostapd_data *hapd, struct sta_info *sta); -int hostapd_set_drv_ieee8021x(struct hostapd_data *hapd, const char *ifname, - int enabled); -int hostapd_set_bss_params(struct hostapd_data *hapd, int use_protection); -int hostapd_vlan_if_add(struct hostapd_data *hapd, const char *ifname); -int hostapd_vlan_if_remove(struct hostapd_data *hapd, const char *ifname); -int hostapd_set_wds_sta(struct hostapd_data *hapd, const u8 *addr, int aid, - int val); -int hostapd_sta_add(struct hostapd_data *hapd, - const u8 *addr, u16 aid, u16 capability, - const u8 *supp_rates, size_t supp_rates_len, - u16 listen_interval, - const struct ieee80211_ht_capabilities *ht_capab); -int hostapd_set_privacy(struct hostapd_data *hapd, int enabled); -int hostapd_set_generic_elem(struct hostapd_data *hapd, const u8 *elem, - size_t elem_len); -int hostapd_get_ssid(struct hostapd_data *hapd, u8 *buf, size_t len); -int hostapd_set_ssid(struct hostapd_data *hapd, const u8 *buf, size_t len); -int hostapd_if_add(struct hostapd_data *hapd, enum wpa_driver_if_type type, - const char *ifname, const u8 *addr, void *bss_ctx, - void **drv_priv, char *force_ifname, u8 *if_addr, - const char *bridge); -int hostapd_if_remove(struct hostapd_data *hapd, enum wpa_driver_if_type type, - const char *ifname); -int hostapd_set_ieee8021x(struct hostapd_data *hapd, - struct wpa_bss_params *params); -int hostapd_get_seqnum(const char *ifname, struct hostapd_data *hapd, - const u8 *addr, int idx, u8 *seq); -int hostapd_flush(struct hostapd_data *hapd); -int hostapd_set_freq(struct hostapd_data *hapd, int mode, int freq, - int channel, int ht_enabled, int sec_channel_offset); -int hostapd_set_rts(struct hostapd_data *hapd, int rts); -int hostapd_set_frag(struct hostapd_data *hapd, int frag); -int hostapd_sta_set_flags(struct hostapd_data *hapd, u8 *addr, - int total_flags, int flags_or, int flags_and); -int hostapd_set_rate_sets(struct hostapd_data *hapd, int *supp_rates, - int *basic_rates, int mode); -int hostapd_set_country(struct hostapd_data *hapd, const char *country); -int hostapd_set_cts_protect(struct hostapd_data *hapd, int value); -int hostapd_set_preamble(struct hostapd_data *hapd, int value); -int hostapd_set_short_slot_time(struct hostapd_data *hapd, int value); -int hostapd_set_tx_queue_params(struct hostapd_data *hapd, int queue, int aifs, - int cw_min, int cw_max, int burst_time); -int hostapd_valid_bss_mask(struct hostapd_data *hapd, const u8 *addr, - const u8 *mask); -struct hostapd_hw_modes * -hostapd_get_hw_feature_data(struct hostapd_data *hapd, u16 *num_modes, - u16 *flags); -int hostapd_driver_commit(struct hostapd_data *hapd); -int hostapd_set_ht_params(struct hostapd_data *hapd, - const u8 *ht_capab, size_t ht_capab_len, - const u8 *ht_oper, size_t ht_oper_len); -int hostapd_drv_none(struct hostapd_data *hapd); -int hostapd_driver_scan(struct hostapd_data *hapd, - struct wpa_driver_scan_params *params); -struct wpa_scan_results * hostapd_driver_get_scan_results( - struct hostapd_data *hapd); -int hostapd_driver_set_noa(struct hostapd_data *hapd, u8 count, int start, - int duration); -int hostapd_drv_set_key(const char *ifname, - struct hostapd_data *hapd, - enum wpa_alg alg, const u8 *addr, - int key_idx, int set_tx, - const u8 *seq, size_t seq_len, - const u8 *key, size_t key_len); -int hostapd_drv_send_mlme(struct hostapd_data *hapd, - const void *msg, size_t len); -int hostapd_drv_sta_deauth(struct hostapd_data *hapd, - const u8 *addr, int reason); -int hostapd_drv_sta_disassoc(struct hostapd_data *hapd, - const u8 *addr, int reason); - - -#include "drivers/driver.h" - -static inline int hostapd_drv_set_countermeasures(struct hostapd_data *hapd, - int enabled) -{ - if (hapd->driver == NULL || - hapd->driver->hapd_set_countermeasures == NULL) - return 0; - return hapd->driver->hapd_set_countermeasures(hapd->drv_priv, enabled); -} - -static inline int hostapd_drv_set_sta_vlan(const char *ifname, - struct hostapd_data *hapd, - const u8 *addr, int vlan_id) -{ - if (hapd->driver == NULL || hapd->driver->set_sta_vlan == NULL) - return 0; - return hapd->driver->set_sta_vlan(hapd->drv_priv, addr, ifname, - vlan_id); -} - -static inline int hostapd_drv_get_inact_sec(struct hostapd_data *hapd, - const u8 *addr) -{ - if (hapd->driver == NULL || hapd->driver->get_inact_sec == NULL) - return 0; - return hapd->driver->get_inact_sec(hapd->drv_priv, addr); -} - -static inline int hostapd_drv_sta_remove(struct hostapd_data *hapd, - const u8 *addr) -{ - if (hapd->driver == NULL || hapd->driver->sta_remove == NULL) - return 0; - return hapd->driver->sta_remove(hapd->drv_priv, addr); -} - -static inline int hostapd_drv_hapd_send_eapol(struct hostapd_data *hapd, - const u8 *addr, const u8 *data, - size_t data_len, int encrypt, - u32 flags) -{ - if (hapd->driver == NULL || hapd->driver->hapd_send_eapol == NULL) - return 0; - return hapd->driver->hapd_send_eapol(hapd->drv_priv, addr, data, - data_len, encrypt, - hapd->own_addr, flags); -} - -static inline int hostapd_drv_read_sta_data( - struct hostapd_data *hapd, struct hostap_sta_driver_data *data, - const u8 *addr) -{ - if (hapd->driver == NULL || hapd->driver->read_sta_data == NULL) - return -1; - return hapd->driver->read_sta_data(hapd->drv_priv, data, addr); -} - -static inline int hostapd_drv_sta_clear_stats(struct hostapd_data *hapd, - const u8 *addr) -{ - if (hapd->driver == NULL || hapd->driver->sta_clear_stats == NULL) - return 0; - return hapd->driver->sta_clear_stats(hapd->drv_priv, addr); -} - -static inline int hostapd_drv_set_beacon(struct hostapd_data *hapd, - const u8 *head, size_t head_len, - const u8 *tail, size_t tail_len, - int dtim_period, int beacon_int) -{ - if (hapd->driver == NULL || hapd->driver->set_beacon == NULL) - return 0; - return hapd->driver->set_beacon(hapd->drv_priv, - head, head_len, tail, tail_len, - dtim_period, beacon_int); -} - -static inline int hostapd_drv_set_radius_acl_auth(struct hostapd_data *hapd, - const u8 *mac, int accepted, - u32 session_timeout) -{ - if (hapd->driver == NULL || hapd->driver->set_radius_acl_auth == NULL) - return 0; - return hapd->driver->set_radius_acl_auth(hapd->drv_priv, mac, accepted, - session_timeout); -} - -static inline int hostapd_drv_set_radius_acl_expire(struct hostapd_data *hapd, - const u8 *mac) -{ - if (hapd->driver == NULL || - hapd->driver->set_radius_acl_expire == NULL) - return 0; - return hapd->driver->set_radius_acl_expire(hapd->drv_priv, mac); -} - -#endif /* AP_DRV_OPS */ diff --git a/hostapd-0.8/src/ap/ap_list.c b/hostapd-0.8/src/ap/ap_list.c deleted file mode 100644 index 9b9fc9e..0000000 --- a/hostapd-0.8/src/ap/ap_list.c +++ /dev/null @@ -1,399 +0,0 @@ -/* - * hostapd / AP table - * Copyright (c) 2002-2009, Jouni Malinen - * Copyright (c) 2003-2004, Instant802 Networks, Inc. - * Copyright (c) 2006, Devicescape Software, Inc. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#include "utils/includes.h" - -#include "utils/common.h" -#include "utils/eloop.h" -#include "common/ieee802_11_defs.h" -#include "common/ieee802_11_common.h" -#include "drivers/driver.h" -#include "hostapd.h" -#include "ap_config.h" -#include "ieee802_11.h" -#include "sta_info.h" -#include "beacon.h" -#include "ap_list.h" - - -/* AP list is a double linked list with head->prev pointing to the end of the - * list and tail->next = NULL. Entries are moved to the head of the list - * whenever a beacon has been received from the AP in question. The tail entry - * in this link will thus be the least recently used entry. */ - - -static int ap_list_beacon_olbc(struct hostapd_iface *iface, struct ap_info *ap) -{ - int i; - - if (iface->current_mode->mode != HOSTAPD_MODE_IEEE80211G || - iface->conf->channel != ap->channel) - return 0; - - if (ap->erp != -1 && (ap->erp & ERP_INFO_NON_ERP_PRESENT)) - return 1; - - for (i = 0; i < WLAN_SUPP_RATES_MAX; i++) { - int rate = (ap->supported_rates[i] & 0x7f) * 5; - if (rate == 60 || rate == 90 || rate > 110) - return 0; - } - - return 1; -} - - -struct ap_info * ap_get_ap(struct hostapd_iface *iface, const u8 *ap) -{ - struct ap_info *s; - - s = iface->ap_hash[STA_HASH(ap)]; - while (s != NULL && os_memcmp(s->addr, ap, ETH_ALEN) != 0) - s = s->hnext; - return s; -} - - -static void ap_ap_list_add(struct hostapd_iface *iface, struct ap_info *ap) -{ - if (iface->ap_list) { - ap->prev = iface->ap_list->prev; - iface->ap_list->prev = ap; - } else - ap->prev = ap; - ap->next = iface->ap_list; - iface->ap_list = ap; -} - - -static void ap_ap_list_del(struct hostapd_iface *iface, struct ap_info *ap) -{ - if (iface->ap_list == ap) - iface->ap_list = ap->next; - else - ap->prev->next = ap->next; - - if (ap->next) - ap->next->prev = ap->prev; - else if (iface->ap_list) - iface->ap_list->prev = ap->prev; -} - - -static void ap_ap_iter_list_add(struct hostapd_iface *iface, - struct ap_info *ap) -{ - if (iface->ap_iter_list) { - ap->iter_prev = iface->ap_iter_list->iter_prev; - iface->ap_iter_list->iter_prev = ap; - } else - ap->iter_prev = ap; - ap->iter_next = iface->ap_iter_list; - iface->ap_iter_list = ap; -} - - -static void ap_ap_iter_list_del(struct hostapd_iface *iface, - struct ap_info *ap) -{ - if (iface->ap_iter_list == ap) - iface->ap_iter_list = ap->iter_next; - else - ap->iter_prev->iter_next = ap->iter_next; - - if (ap->iter_next) - ap->iter_next->iter_prev = ap->iter_prev; - else if (iface->ap_iter_list) - iface->ap_iter_list->iter_prev = ap->iter_prev; -} - - -static void ap_ap_hash_add(struct hostapd_iface *iface, struct ap_info *ap) -{ - ap->hnext = iface->ap_hash[STA_HASH(ap->addr)]; - iface->ap_hash[STA_HASH(ap->addr)] = ap; -} - - -static void ap_ap_hash_del(struct hostapd_iface *iface, struct ap_info *ap) -{ - struct ap_info *s; - - s = iface->ap_hash[STA_HASH(ap->addr)]; - if (s == NULL) return; - if (os_memcmp(s->addr, ap->addr, ETH_ALEN) == 0) { - iface->ap_hash[STA_HASH(ap->addr)] = s->hnext; - return; - } - - while (s->hnext != NULL && - os_memcmp(s->hnext->addr, ap->addr, ETH_ALEN) != 0) - s = s->hnext; - if (s->hnext != NULL) - s->hnext = s->hnext->hnext; - else - printf("AP: could not remove AP " MACSTR " from hash table\n", - MAC2STR(ap->addr)); -} - - -static void ap_free_ap(struct hostapd_iface *iface, struct ap_info *ap) -{ - ap_ap_hash_del(iface, ap); - ap_ap_list_del(iface, ap); - ap_ap_iter_list_del(iface, ap); - - iface->num_ap--; - os_free(ap); -} - - -static void hostapd_free_aps(struct hostapd_iface *iface) -{ - struct ap_info *ap, *prev; - - ap = iface->ap_list; - - while (ap) { - prev = ap; - ap = ap->next; - ap_free_ap(iface, prev); - } - - iface->ap_list = NULL; -} - - -int ap_ap_for_each(struct hostapd_iface *iface, - int (*func)(struct ap_info *s, void *data), void *data) -{ - struct ap_info *s; - int ret = 0; - - s = iface->ap_list; - - while (s) { - ret = func(s, data); - if (ret) - break; - s = s->next; - } - - return ret; -} - - -static struct ap_info * ap_ap_add(struct hostapd_iface *iface, const u8 *addr) -{ - struct ap_info *ap; - - ap = os_zalloc(sizeof(struct ap_info)); - if (ap == NULL) - return NULL; - - /* initialize AP info data */ - os_memcpy(ap->addr, addr, ETH_ALEN); - ap_ap_list_add(iface, ap); - iface->num_ap++; - ap_ap_hash_add(iface, ap); - ap_ap_iter_list_add(iface, ap); - - if (iface->num_ap > iface->conf->ap_table_max_size && ap != ap->prev) { - wpa_printf(MSG_DEBUG, "Removing the least recently used AP " - MACSTR " from AP table", MAC2STR(ap->prev->addr)); - ap_free_ap(iface, ap->prev); - } - - return ap; -} - - -void ap_list_process_beacon(struct hostapd_iface *iface, - const struct ieee80211_mgmt *mgmt, - struct ieee802_11_elems *elems, - struct hostapd_frame_info *fi) -{ - struct ap_info *ap; - struct os_time now; - int new_ap = 0; - size_t len; - int set_beacon = 0; - - if (iface->conf->ap_table_max_size < 1) - return; - - ap = ap_get_ap(iface, mgmt->bssid); - if (!ap) { - ap = ap_ap_add(iface, mgmt->bssid); - if (!ap) { - printf("Failed to allocate AP information entry\n"); - return; - } - new_ap = 1; - } - - ap->beacon_int = le_to_host16(mgmt->u.beacon.beacon_int); - ap->capability = le_to_host16(mgmt->u.beacon.capab_info); - - if (elems->ssid) { - len = elems->ssid_len; - if (len >= sizeof(ap->ssid)) - len = sizeof(ap->ssid) - 1; - os_memcpy(ap->ssid, elems->ssid, len); - ap->ssid[len] = '\0'; - ap->ssid_len = len; - } - - os_memset(ap->supported_rates, 0, WLAN_SUPP_RATES_MAX); - len = 0; - if (elems->supp_rates) { - len = elems->supp_rates_len; - if (len > WLAN_SUPP_RATES_MAX) - len = WLAN_SUPP_RATES_MAX; - os_memcpy(ap->supported_rates, elems->supp_rates, len); - } - if (elems->ext_supp_rates) { - int len2; - if (len + elems->ext_supp_rates_len > WLAN_SUPP_RATES_MAX) - len2 = WLAN_SUPP_RATES_MAX - len; - else - len2 = elems->ext_supp_rates_len; - os_memcpy(ap->supported_rates + len, elems->ext_supp_rates, - len2); - } - - ap->wpa = elems->wpa_ie != NULL; - - if (elems->erp_info && elems->erp_info_len == 1) - ap->erp = elems->erp_info[0]; - else - ap->erp = -1; - - if (elems->ds_params && elems->ds_params_len == 1) - ap->channel = elems->ds_params[0]; - else if (fi) - ap->channel = fi->channel; - - if (elems->ht_capabilities) - ap->ht_support = 1; - else - ap->ht_support = 0; - - ap->num_beacons++; - os_get_time(&now); - ap->last_beacon = now.sec; - if (fi) { - ap->ssi_signal = fi->ssi_signal; - ap->datarate = fi->datarate; - } - - if (!new_ap && ap != iface->ap_list) { - /* move AP entry into the beginning of the list so that the - * oldest entry is always in the end of the list */ - ap_ap_list_del(iface, ap); - ap_ap_list_add(iface, ap); - } - - if (!iface->olbc && - ap_list_beacon_olbc(iface, ap)) { - iface->olbc = 1; - wpa_printf(MSG_DEBUG, "OLBC AP detected: " MACSTR " - enable " - "protection", MAC2STR(ap->addr)); - set_beacon++; - } - -#ifdef CONFIG_IEEE80211N - if (!iface->olbc_ht && !ap->ht_support) { - iface->olbc_ht = 1; - hostapd_ht_operation_update(iface); - wpa_printf(MSG_DEBUG, "OLBC HT AP detected: " MACSTR - " - enable protection", MAC2STR(ap->addr)); - set_beacon++; - } -#endif /* CONFIG_IEEE80211N */ - - if (set_beacon) - ieee802_11_set_beacons(iface); -} - - -static void ap_list_timer(void *eloop_ctx, void *timeout_ctx) -{ - struct hostapd_iface *iface = eloop_ctx; - struct os_time now; - struct ap_info *ap; - int set_beacon = 0; - - eloop_register_timeout(10, 0, ap_list_timer, iface, NULL); - - if (!iface->ap_list) - return; - - os_get_time(&now); - - while (iface->ap_list) { - ap = iface->ap_list->prev; - if (ap->last_beacon + iface->conf->ap_table_expiration_time >= - now.sec) - break; - - ap_free_ap(iface, ap); - } - - if (iface->olbc || iface->olbc_ht) { - int olbc = 0; - int olbc_ht = 0; - - ap = iface->ap_list; - while (ap && (olbc == 0 || olbc_ht == 0)) { - if (ap_list_beacon_olbc(iface, ap)) - olbc = 1; - if (!ap->ht_support) - olbc_ht = 1; - ap = ap->next; - } - if (!olbc && iface->olbc) { - wpa_printf(MSG_DEBUG, "OLBC not detected anymore"); - iface->olbc = 0; - set_beacon++; - } -#ifdef CONFIG_IEEE80211N - if (!olbc_ht && iface->olbc_ht) { - wpa_printf(MSG_DEBUG, "OLBC HT not detected anymore"); - iface->olbc_ht = 0; - hostapd_ht_operation_update(iface); - set_beacon++; - } -#endif /* CONFIG_IEEE80211N */ - } - - if (set_beacon) - ieee802_11_set_beacons(iface); -} - - -int ap_list_init(struct hostapd_iface *iface) -{ - eloop_register_timeout(10, 0, ap_list_timer, iface, NULL); - return 0; -} - - -void ap_list_deinit(struct hostapd_iface *iface) -{ - eloop_cancel_timeout(ap_list_timer, iface, NULL); - hostapd_free_aps(iface); -} diff --git a/hostapd-0.8/src/ap/ap_list.h b/hostapd-0.8/src/ap/ap_list.h deleted file mode 100644 index 6df8981..0000000 --- a/hostapd-0.8/src/ap/ap_list.h +++ /dev/null @@ -1,78 +0,0 @@ -/* - * hostapd / AP table - * Copyright (c) 2002-2003, Jouni Malinen - * Copyright (c) 2003-2004, Instant802 Networks, Inc. - * Copyright (c) 2006, Devicescape Software, Inc. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#ifndef AP_LIST_H -#define AP_LIST_H - -struct ap_info { - /* Note: next/prev pointers are updated whenever a new beacon is - * received because these are used to find the least recently used - * entries. iter_next/iter_prev are updated only when adding new BSSes - * and when removing old ones. These should be used when iterating - * through the table in a manner that allows beacons to be received - * during the iteration. */ - struct ap_info *next; /* next entry in AP list */ - struct ap_info *prev; /* previous entry in AP list */ - struct ap_info *hnext; /* next entry in hash table list */ - struct ap_info *iter_next; /* next entry in AP iteration list */ - struct ap_info *iter_prev; /* previous entry in AP iteration list */ - u8 addr[6]; - u16 beacon_int; - u16 capability; - u8 supported_rates[WLAN_SUPP_RATES_MAX]; - u8 ssid[33]; - size_t ssid_len; - int wpa; - int erp; /* ERP Info or -1 if ERP info element not present */ - - int channel; - int datarate; /* in 100 kbps */ - int ssi_signal; - - int ht_support; - - unsigned int num_beacons; /* number of beacon frames received */ - os_time_t last_beacon; - - int already_seen; /* whether API call AP-NEW has already fetched - * information about this AP */ -}; - -struct ieee802_11_elems; -struct hostapd_frame_info; - -struct ap_info * ap_get_ap(struct hostapd_iface *iface, const u8 *sta); -int ap_ap_for_each(struct hostapd_iface *iface, - int (*func)(struct ap_info *s, void *data), void *data); -void ap_list_process_beacon(struct hostapd_iface *iface, - const struct ieee80211_mgmt *mgmt, - struct ieee802_11_elems *elems, - struct hostapd_frame_info *fi); -#ifdef NEED_AP_MLME -int ap_list_init(struct hostapd_iface *iface); -void ap_list_deinit(struct hostapd_iface *iface); -#else /* NEED_AP_MLME */ -static inline int ap_list_init(struct hostapd_iface *iface) -{ - return 0; -} - -static inline void ap_list_deinit(struct hostapd_iface *iface) -{ -} -#endif /* NEED_AP_MLME */ - -#endif /* AP_LIST_H */ diff --git a/hostapd-0.8/src/ap/ap_mlme.c b/hostapd-0.8/src/ap/ap_mlme.c deleted file mode 100644 index 2b09b11..0000000 --- a/hostapd-0.8/src/ap/ap_mlme.c +++ /dev/null @@ -1,184 +0,0 @@ -/* - * hostapd / IEEE 802.11 MLME - * Copyright 2003-2006, Jouni Malinen - * Copyright 2003-2004, Instant802 Networks, Inc. - * Copyright 2005-2006, Devicescape Software, Inc. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#include "utils/includes.h" - -#include "utils/common.h" -#include "common/ieee802_11_defs.h" -#include "ieee802_11.h" -#include "wpa_auth.h" -#include "sta_info.h" -#include "ap_mlme.h" - - -#ifndef CONFIG_NO_HOSTAPD_LOGGER -static const char * mlme_auth_alg_str(int alg) -{ - switch (alg) { - case WLAN_AUTH_OPEN: - return "OPEN_SYSTEM"; - case WLAN_AUTH_SHARED_KEY: - return "SHARED_KEY"; - case WLAN_AUTH_FT: - return "FT"; - } - - return "unknown"; -} -#endif /* CONFIG_NO_HOSTAPD_LOGGER */ - - -/** - * mlme_authenticate_indication - Report the establishment of an authentication - * relationship with a specific peer MAC entity - * @hapd: BSS data - * @sta: peer STA data - * - * MLME calls this function as a result of the establishment of an - * authentication relationship with a specific peer MAC entity that - * resulted from an authentication procedure that was initiated by - * that specific peer MAC entity. - * - * PeerSTAAddress = sta->addr - * AuthenticationType = sta->auth_alg (WLAN_AUTH_OPEN / WLAN_AUTH_SHARED_KEY) - */ -void mlme_authenticate_indication(struct hostapd_data *hapd, - struct sta_info *sta) -{ - hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_MLME, - HOSTAPD_LEVEL_DEBUG, - "MLME-AUTHENTICATE.indication(" MACSTR ", %s)", - MAC2STR(sta->addr), mlme_auth_alg_str(sta->auth_alg)); - if (sta->auth_alg != WLAN_AUTH_FT && !(sta->flags & WLAN_STA_MFP)) - mlme_deletekeys_request(hapd, sta); -} - - -/** - * mlme_deauthenticate_indication - Report the invalidation of an - * authentication relationship with a specific peer MAC entity - * @hapd: BSS data - * @sta: Peer STA data - * @reason_code: ReasonCode from Deauthentication frame - * - * MLME calls this function as a result of the invalidation of an - * authentication relationship with a specific peer MAC entity. - * - * PeerSTAAddress = sta->addr - */ -void mlme_deauthenticate_indication(struct hostapd_data *hapd, - struct sta_info *sta, u16 reason_code) -{ - hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_MLME, - HOSTAPD_LEVEL_DEBUG, - "MLME-DEAUTHENTICATE.indication(" MACSTR ", %d)", - MAC2STR(sta->addr), reason_code); - mlme_deletekeys_request(hapd, sta); -} - - -/** - * mlme_associate_indication - Report the establishment of an association with - * a specific peer MAC entity - * @hapd: BSS data - * @sta: peer STA data - * - * MLME calls this function as a result of the establishment of an - * association with a specific peer MAC entity that resulted from an - * association procedure that was initiated by that specific peer MAC entity. - * - * PeerSTAAddress = sta->addr - */ -void mlme_associate_indication(struct hostapd_data *hapd, struct sta_info *sta) -{ - hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_MLME, - HOSTAPD_LEVEL_DEBUG, - "MLME-ASSOCIATE.indication(" MACSTR ")", - MAC2STR(sta->addr)); - if (sta->auth_alg != WLAN_AUTH_FT) - mlme_deletekeys_request(hapd, sta); -} - - -/** - * mlme_reassociate_indication - Report the establishment of an reassociation - * with a specific peer MAC entity - * @hapd: BSS data - * @sta: peer STA data - * - * MLME calls this function as a result of the establishment of an - * reassociation with a specific peer MAC entity that resulted from a - * reassociation procedure that was initiated by that specific peer MAC entity. - * - * PeerSTAAddress = sta->addr - * - * sta->previous_ap contains the "Current AP" information from ReassocReq. - */ -void mlme_reassociate_indication(struct hostapd_data *hapd, - struct sta_info *sta) -{ - hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_MLME, - HOSTAPD_LEVEL_DEBUG, - "MLME-REASSOCIATE.indication(" MACSTR ")", - MAC2STR(sta->addr)); - if (sta->auth_alg != WLAN_AUTH_FT) - mlme_deletekeys_request(hapd, sta); -} - - -/** - * mlme_disassociate_indication - Report disassociation with a specific peer - * MAC entity - * @hapd: BSS data - * @sta: Peer STA data - * @reason_code: ReasonCode from Disassociation frame - * - * MLME calls this function as a result of the invalidation of an association - * relationship with a specific peer MAC entity. - * - * PeerSTAAddress = sta->addr - */ -void mlme_disassociate_indication(struct hostapd_data *hapd, - struct sta_info *sta, u16 reason_code) -{ - hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_MLME, - HOSTAPD_LEVEL_DEBUG, - "MLME-DISASSOCIATE.indication(" MACSTR ", %d)", - MAC2STR(sta->addr), reason_code); - mlme_deletekeys_request(hapd, sta); -} - - -void mlme_michaelmicfailure_indication(struct hostapd_data *hapd, - const u8 *addr) -{ - hostapd_logger(hapd, addr, HOSTAPD_MODULE_MLME, - HOSTAPD_LEVEL_DEBUG, - "MLME-MichaelMICFailure.indication(" MACSTR ")", - MAC2STR(addr)); -} - - -void mlme_deletekeys_request(struct hostapd_data *hapd, struct sta_info *sta) -{ - hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_MLME, - HOSTAPD_LEVEL_DEBUG, - "MLME-DELETEKEYS.request(" MACSTR ")", - MAC2STR(sta->addr)); - - if (sta->wpa_sm) - wpa_remove_ptk(sta->wpa_sm); -} diff --git a/hostapd-0.8/src/ap/ap_mlme.h b/hostapd-0.8/src/ap/ap_mlme.h deleted file mode 100644 index c77a939..0000000 --- a/hostapd-0.8/src/ap/ap_mlme.h +++ /dev/null @@ -1,40 +0,0 @@ -/* - * hostapd / IEEE 802.11 MLME - * Copyright 2003, Jouni Malinen - * Copyright 2003-2004, Instant802 Networks, Inc. - * Copyright 2005-2006, Devicescape Software, Inc. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#ifndef MLME_H -#define MLME_H - -void mlme_authenticate_indication(struct hostapd_data *hapd, - struct sta_info *sta); - -void mlme_deauthenticate_indication(struct hostapd_data *hapd, - struct sta_info *sta, u16 reason_code); - -void mlme_associate_indication(struct hostapd_data *hapd, - struct sta_info *sta); - -void mlme_reassociate_indication(struct hostapd_data *hapd, - struct sta_info *sta); - -void mlme_disassociate_indication(struct hostapd_data *hapd, - struct sta_info *sta, u16 reason_code); - -void mlme_michaelmicfailure_indication(struct hostapd_data *hapd, - const u8 *addr); - -void mlme_deletekeys_request(struct hostapd_data *hapd, struct sta_info *sta); - -#endif /* MLME_H */ diff --git a/hostapd-0.8/src/ap/authsrv.c b/hostapd-0.8/src/ap/authsrv.c deleted file mode 100644 index 7c87fde..0000000 --- a/hostapd-0.8/src/ap/authsrv.c +++ /dev/null @@ -1,217 +0,0 @@ -/* - * Authentication server setup - * Copyright (c) 2002-2009, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#include "utils/includes.h" - -#include "utils/common.h" -#include "crypto/tls.h" -#include "eap_server/eap.h" -#include "eap_server/eap_sim_db.h" -#include "eapol_auth/eapol_auth_sm.h" -#include "radius/radius_server.h" -#include "hostapd.h" -#include "ap_config.h" -#include "sta_info.h" -#include "authsrv.h" - - -#if defined(EAP_SERVER_SIM) || defined(EAP_SERVER_AKA) -#define EAP_SIM_DB -#endif /* EAP_SERVER_SIM || EAP_SERVER_AKA */ - - -#ifdef EAP_SIM_DB -static int hostapd_sim_db_cb_sta(struct hostapd_data *hapd, - struct sta_info *sta, void *ctx) -{ - if (eapol_auth_eap_pending_cb(sta->eapol_sm, ctx) == 0) - return 1; - return 0; -} - - -static void hostapd_sim_db_cb(void *ctx, void *session_ctx) -{ - struct hostapd_data *hapd = ctx; - if (ap_for_each_sta(hapd, hostapd_sim_db_cb_sta, session_ctx) == 0) { -#ifdef RADIUS_SERVER - radius_server_eap_pending_cb(hapd->radius_srv, session_ctx); -#endif /* RADIUS_SERVER */ - } -} -#endif /* EAP_SIM_DB */ - - -#ifdef RADIUS_SERVER - -static int hostapd_radius_get_eap_user(void *ctx, const u8 *identity, - size_t identity_len, int phase2, - struct eap_user *user) -{ - const struct hostapd_eap_user *eap_user; - int i, count; - - eap_user = hostapd_get_eap_user(ctx, identity, identity_len, phase2); - if (eap_user == NULL) - return -1; - - if (user == NULL) - return 0; - - os_memset(user, 0, sizeof(*user)); - count = EAP_USER_MAX_METHODS; - if (count > EAP_MAX_METHODS) - count = EAP_MAX_METHODS; - for (i = 0; i < count; i++) { - user->methods[i].vendor = eap_user->methods[i].vendor; - user->methods[i].method = eap_user->methods[i].method; - } - - if (eap_user->password) { - user->password = os_malloc(eap_user->password_len); - if (user->password == NULL) - return -1; - os_memcpy(user->password, eap_user->password, - eap_user->password_len); - user->password_len = eap_user->password_len; - user->password_hash = eap_user->password_hash; - } - user->force_version = eap_user->force_version; - user->ttls_auth = eap_user->ttls_auth; - - return 0; -} - - -static int hostapd_setup_radius_srv(struct hostapd_data *hapd) -{ - struct radius_server_conf srv; - struct hostapd_bss_config *conf = hapd->conf; - os_memset(&srv, 0, sizeof(srv)); - srv.client_file = conf->radius_server_clients; - srv.auth_port = conf->radius_server_auth_port; - srv.conf_ctx = conf; - srv.eap_sim_db_priv = hapd->eap_sim_db_priv; - srv.ssl_ctx = hapd->ssl_ctx; - srv.msg_ctx = hapd->msg_ctx; - srv.pac_opaque_encr_key = conf->pac_opaque_encr_key; - srv.eap_fast_a_id = conf->eap_fast_a_id; - srv.eap_fast_a_id_len = conf->eap_fast_a_id_len; - srv.eap_fast_a_id_info = conf->eap_fast_a_id_info; - srv.eap_fast_prov = conf->eap_fast_prov; - srv.pac_key_lifetime = conf->pac_key_lifetime; - srv.pac_key_refresh_time = conf->pac_key_refresh_time; - srv.eap_sim_aka_result_ind = conf->eap_sim_aka_result_ind; - srv.tnc = conf->tnc; - srv.wps = hapd->wps; - srv.ipv6 = conf->radius_server_ipv6; - srv.get_eap_user = hostapd_radius_get_eap_user; - srv.eap_req_id_text = conf->eap_req_id_text; - srv.eap_req_id_text_len = conf->eap_req_id_text_len; - srv.pwd_group = conf->pwd_group; - - hapd->radius_srv = radius_server_init(&srv); - if (hapd->radius_srv == NULL) { - wpa_printf(MSG_ERROR, "RADIUS server initialization failed."); - return -1; - } - - return 0; -} - -#endif /* RADIUS_SERVER */ - - -int authsrv_init(struct hostapd_data *hapd) -{ -#ifdef EAP_TLS_FUNCS - if (hapd->conf->eap_server && - (hapd->conf->ca_cert || hapd->conf->server_cert || - hapd->conf->dh_file)) { - struct tls_connection_params params; - - hapd->ssl_ctx = tls_init(NULL); - if (hapd->ssl_ctx == NULL) { - wpa_printf(MSG_ERROR, "Failed to initialize TLS"); - authsrv_deinit(hapd); - return -1; - } - - os_memset(¶ms, 0, sizeof(params)); - params.ca_cert = hapd->conf->ca_cert; - params.client_cert = hapd->conf->server_cert; - params.private_key = hapd->conf->private_key; - params.private_key_passwd = hapd->conf->private_key_passwd; - params.dh_file = hapd->conf->dh_file; - - if (tls_global_set_params(hapd->ssl_ctx, ¶ms)) { - wpa_printf(MSG_ERROR, "Failed to set TLS parameters"); - authsrv_deinit(hapd); - return -1; - } - - if (tls_global_set_verify(hapd->ssl_ctx, - hapd->conf->check_crl)) { - wpa_printf(MSG_ERROR, "Failed to enable check_crl"); - authsrv_deinit(hapd); - return -1; - } - } -#endif /* EAP_TLS_FUNCS */ - -#ifdef EAP_SIM_DB - if (hapd->conf->eap_sim_db) { - hapd->eap_sim_db_priv = - eap_sim_db_init(hapd->conf->eap_sim_db, - hostapd_sim_db_cb, hapd); - if (hapd->eap_sim_db_priv == NULL) { - wpa_printf(MSG_ERROR, "Failed to initialize EAP-SIM " - "database interface"); - authsrv_deinit(hapd); - return -1; - } - } -#endif /* EAP_SIM_DB */ - -#ifdef RADIUS_SERVER - if (hapd->conf->radius_server_clients && - hostapd_setup_radius_srv(hapd)) - return -1; -#endif /* RADIUS_SERVER */ - - return 0; -} - - -void authsrv_deinit(struct hostapd_data *hapd) -{ -#ifdef RADIUS_SERVER - radius_server_deinit(hapd->radius_srv); - hapd->radius_srv = NULL; -#endif /* RADIUS_SERVER */ - -#ifdef EAP_TLS_FUNCS - if (hapd->ssl_ctx) { - tls_deinit(hapd->ssl_ctx); - hapd->ssl_ctx = NULL; - } -#endif /* EAP_TLS_FUNCS */ - -#ifdef EAP_SIM_DB - if (hapd->eap_sim_db_priv) { - eap_sim_db_deinit(hapd->eap_sim_db_priv); - hapd->eap_sim_db_priv = NULL; - } -#endif /* EAP_SIM_DB */ -} diff --git a/hostapd-0.8/src/ap/authsrv.h b/hostapd-0.8/src/ap/authsrv.h deleted file mode 100644 index be3051e..0000000 --- a/hostapd-0.8/src/ap/authsrv.h +++ /dev/null @@ -1,21 +0,0 @@ -/* - * Authentication server setup - * Copyright (c) 2002-2009, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#ifndef AUTHSRV_H -#define AUTHSRV_H - -int authsrv_init(struct hostapd_data *hapd); -void authsrv_deinit(struct hostapd_data *hapd); - -#endif /* AUTHSRV_H */ diff --git a/hostapd-0.8/src/ap/beacon.c b/hostapd-0.8/src/ap/beacon.c deleted file mode 100644 index 784f134..0000000 --- a/hostapd-0.8/src/ap/beacon.c +++ /dev/null @@ -1,540 +0,0 @@ -/* - * hostapd / IEEE 802.11 Management: Beacon and Probe Request/Response - * Copyright (c) 2002-2004, Instant802 Networks, Inc. - * Copyright (c) 2005-2006, Devicescape Software, Inc. - * Copyright (c) 2008-2009, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#include "utils/includes.h" - -#ifndef CONFIG_NATIVE_WINDOWS - -#include "utils/common.h" -#include "common/ieee802_11_defs.h" -#include "common/ieee802_11_common.h" -#include "drivers/driver.h" -#include "wps/wps_defs.h" -#include "p2p/p2p.h" -#include "hostapd.h" -#include "ieee802_11.h" -#include "wpa_auth.h" -#include "wmm.h" -#include "ap_config.h" -#include "sta_info.h" -#include "p2p_hostapd.h" -#include "ap_drv_ops.h" -#include "beacon.h" - - -static u8 ieee802_11_erp_info(struct hostapd_data *hapd) -{ - u8 erp = 0; - - if (hapd->iface->current_mode == NULL || - hapd->iface->current_mode->mode != HOSTAPD_MODE_IEEE80211G) - return 0; - - switch (hapd->iconf->cts_protection_type) { - case CTS_PROTECTION_FORCE_ENABLED: - erp |= ERP_INFO_NON_ERP_PRESENT | ERP_INFO_USE_PROTECTION; - break; - case CTS_PROTECTION_FORCE_DISABLED: - erp = 0; - break; - case CTS_PROTECTION_AUTOMATIC: - if (hapd->iface->olbc) - erp |= ERP_INFO_USE_PROTECTION; - /* continue */ - case CTS_PROTECTION_AUTOMATIC_NO_OLBC: - if (hapd->iface->num_sta_non_erp > 0) { - erp |= ERP_INFO_NON_ERP_PRESENT | - ERP_INFO_USE_PROTECTION; - } - break; - } - if (hapd->iface->num_sta_no_short_preamble > 0 || - hapd->iconf->preamble == LONG_PREAMBLE) - erp |= ERP_INFO_BARKER_PREAMBLE_MODE; - - return erp; -} - - -static u8 * hostapd_eid_ds_params(struct hostapd_data *hapd, u8 *eid) -{ - *eid++ = WLAN_EID_DS_PARAMS; - *eid++ = 1; - *eid++ = hapd->iconf->channel; - return eid; -} - - -static u8 * hostapd_eid_erp_info(struct hostapd_data *hapd, u8 *eid) -{ - if (hapd->iface->current_mode == NULL || - hapd->iface->current_mode->mode != HOSTAPD_MODE_IEEE80211G) - return eid; - - /* Set NonERP_present and use_protection bits if there - * are any associated NonERP stations. */ - /* TODO: use_protection bit can be set to zero even if - * there are NonERP stations present. This optimization - * might be useful if NonERP stations are "quiet". - * See 802.11g/D6 E-1 for recommended practice. - * In addition, Non ERP present might be set, if AP detects Non ERP - * operation on other APs. */ - - /* Add ERP Information element */ - *eid++ = WLAN_EID_ERP_INFO; - *eid++ = 1; - *eid++ = ieee802_11_erp_info(hapd); - - return eid; -} - - -static u8 * hostapd_eid_country_add(u8 *pos, u8 *end, int chan_spacing, - struct hostapd_channel_data *start, - struct hostapd_channel_data *prev) -{ - if (end - pos < 3) - return pos; - - /* first channel number */ - *pos++ = start->chan; - /* number of channels */ - *pos++ = (prev->chan - start->chan) / chan_spacing + 1; - /* maximum transmit power level */ - *pos++ = start->max_tx_power; - - return pos; -} - - -static u8 * hostapd_eid_country(struct hostapd_data *hapd, u8 *eid, - int max_len) -{ - u8 *pos = eid; - u8 *end = eid + max_len; - int i; - struct hostapd_hw_modes *mode; - struct hostapd_channel_data *start, *prev; - int chan_spacing = 1; - - if (!hapd->iconf->ieee80211d || max_len < 6 || - hapd->iface->current_mode == NULL) - return eid; - - *pos++ = WLAN_EID_COUNTRY; - pos++; /* length will be set later */ - os_memcpy(pos, hapd->iconf->country, 3); /* e.g., 'US ' */ - pos += 3; - - mode = hapd->iface->current_mode; - if (mode->mode == HOSTAPD_MODE_IEEE80211A) - chan_spacing = 4; - - start = prev = NULL; - for (i = 0; i < mode->num_channels; i++) { - struct hostapd_channel_data *chan = &mode->channels[i]; - if (chan->flag & HOSTAPD_CHAN_DISABLED) - continue; - if (start && prev && - prev->chan + chan_spacing == chan->chan && - start->max_tx_power == chan->max_tx_power) { - prev = chan; - continue; /* can use same entry */ - } - - if (start) { - pos = hostapd_eid_country_add(pos, end, chan_spacing, - start, prev); - start = NULL; - } - - /* Start new group */ - start = prev = chan; - } - - if (start) { - pos = hostapd_eid_country_add(pos, end, chan_spacing, - start, prev); - } - - if ((pos - eid) & 1) { - if (end - pos < 1) - return eid; - *pos++ = 0; /* pad for 16-bit alignment */ - } - - eid[1] = (pos - eid) - 2; - - return pos; -} - - -static u8 * hostapd_eid_wpa(struct hostapd_data *hapd, u8 *eid, size_t len, - struct sta_info *sta) -{ - const u8 *ie; - size_t ielen; - - ie = wpa_auth_get_wpa_ie(hapd->wpa_auth, &ielen); - if (ie == NULL || ielen > len) - return eid; - - os_memcpy(eid, ie, ielen); - return eid + ielen; -} - - -void handle_probe_req(struct hostapd_data *hapd, - const struct ieee80211_mgmt *mgmt, size_t len) -{ - struct ieee80211_mgmt *resp; - struct ieee802_11_elems elems; - char *ssid; - u8 *pos, *epos; - const u8 *ie; - size_t ssid_len, ie_len; - struct sta_info *sta = NULL; - size_t buflen; - size_t i; - - ie = mgmt->u.probe_req.variable; - if (len < IEEE80211_HDRLEN + sizeof(mgmt->u.probe_req)) - return; - ie_len = len - (IEEE80211_HDRLEN + sizeof(mgmt->u.probe_req)); - - for (i = 0; hapd->probereq_cb && i < hapd->num_probereq_cb; i++) - if (hapd->probereq_cb[i].cb(hapd->probereq_cb[i].ctx, - mgmt->sa, ie, ie_len) > 0) - return; - - if (!hapd->iconf->send_probe_response) - return; - - if (ieee802_11_parse_elems(ie, ie_len, &elems, 0) == ParseFailed) { - wpa_printf(MSG_DEBUG, "Could not parse ProbeReq from " MACSTR, - MAC2STR(mgmt->sa)); - return; - } - - ssid = NULL; - ssid_len = 0; - - if ((!elems.ssid || !elems.supp_rates)) { - wpa_printf(MSG_DEBUG, "STA " MACSTR " sent probe request " - "without SSID or supported rates element", - MAC2STR(mgmt->sa)); - return; - } - -#ifdef CONFIG_P2P - if (hapd->p2p && elems.wps_ie) { - struct wpabuf *wps; - wps = ieee802_11_vendor_ie_concat(ie, ie_len, WPS_DEV_OUI_WFA); - if (wps && !p2p_group_match_dev_type(hapd->p2p_group, wps)) { - wpa_printf(MSG_MSGDUMP, "P2P: Ignore Probe Request " - "due to mismatch with Requested Device " - "Type"); - wpabuf_free(wps); - return; - } - wpabuf_free(wps); - } -#endif /* CONFIG_P2P */ - - if (hapd->conf->ignore_broadcast_ssid && elems.ssid_len == 0) { - wpa_printf(MSG_MSGDUMP, "Probe Request from " MACSTR " for " - "broadcast SSID ignored", MAC2STR(mgmt->sa)); - return; - } - - sta = ap_get_sta(hapd, mgmt->sa); - -#ifdef CONFIG_P2P - if ((hapd->conf->p2p & P2P_GROUP_OWNER) && - elems.ssid_len == P2P_WILDCARD_SSID_LEN && - os_memcmp(elems.ssid, P2P_WILDCARD_SSID, - P2P_WILDCARD_SSID_LEN) == 0) { - /* Process P2P Wildcard SSID like Wildcard SSID */ - elems.ssid_len = 0; - } -#endif /* CONFIG_P2P */ - - if (elems.ssid_len == 0 || - (elems.ssid_len == hapd->conf->ssid.ssid_len && - os_memcmp(elems.ssid, hapd->conf->ssid.ssid, elems.ssid_len) == - 0)) { - ssid = hapd->conf->ssid.ssid; - ssid_len = hapd->conf->ssid.ssid_len; - if (sta) - sta->ssid_probe = &hapd->conf->ssid; - } - - if (!ssid) { - if (!(mgmt->da[0] & 0x01)) { - char ssid_txt[33]; - ieee802_11_print_ssid(ssid_txt, elems.ssid, - elems.ssid_len); - wpa_printf(MSG_MSGDUMP, "Probe Request from " MACSTR - " for foreign SSID '%s' (DA " MACSTR ")", - MAC2STR(mgmt->sa), ssid_txt, - MAC2STR(mgmt->da)); - } - return; - } - - /* TODO: verify that supp_rates contains at least one matching rate - * with AP configuration */ -#define MAX_PROBERESP_LEN 768 - buflen = MAX_PROBERESP_LEN; -#ifdef CONFIG_WPS - if (hapd->wps_probe_resp_ie) - buflen += wpabuf_len(hapd->wps_probe_resp_ie); -#endif /* CONFIG_WPS */ -#ifdef CONFIG_P2P - if (hapd->p2p_probe_resp_ie) - buflen += wpabuf_len(hapd->p2p_probe_resp_ie); -#endif /* CONFIG_P2P */ - resp = os_zalloc(buflen); - if (resp == NULL) - return; - epos = ((u8 *) resp) + MAX_PROBERESP_LEN; - - resp->frame_control = IEEE80211_FC(WLAN_FC_TYPE_MGMT, - WLAN_FC_STYPE_PROBE_RESP); - os_memcpy(resp->da, mgmt->sa, ETH_ALEN); - os_memcpy(resp->sa, hapd->own_addr, ETH_ALEN); - - os_memcpy(resp->bssid, hapd->own_addr, ETH_ALEN); - resp->u.probe_resp.beacon_int = - host_to_le16(hapd->iconf->beacon_int); - - /* hardware or low-level driver will setup seq_ctrl and timestamp */ - resp->u.probe_resp.capab_info = - host_to_le16(hostapd_own_capab_info(hapd, sta, 1)); - - pos = resp->u.probe_resp.variable; - *pos++ = WLAN_EID_SSID; - *pos++ = ssid_len; - os_memcpy(pos, ssid, ssid_len); - pos += ssid_len; - - /* Supported rates */ - pos = hostapd_eid_supp_rates(hapd, pos); - - /* DS Params */ - pos = hostapd_eid_ds_params(hapd, pos); - - pos = hostapd_eid_country(hapd, pos, epos - pos); - - /* ERP Information element */ - pos = hostapd_eid_erp_info(hapd, pos); - - /* Extended supported rates */ - pos = hostapd_eid_ext_supp_rates(hapd, pos); - - /* RSN, MDIE, WPA */ - pos = hostapd_eid_wpa(hapd, pos, epos - pos, sta); - -#ifdef CONFIG_IEEE80211N - pos = hostapd_eid_ht_capabilities(hapd, pos); - pos = hostapd_eid_ht_operation(hapd, pos); -#endif /* CONFIG_IEEE80211N */ - - pos = hostapd_eid_ext_capab(hapd, pos); - - /* Wi-Fi Alliance WMM */ - pos = hostapd_eid_wmm(hapd, pos); - -#ifdef CONFIG_WPS - if (hapd->conf->wps_state && hapd->wps_probe_resp_ie) { - os_memcpy(pos, wpabuf_head(hapd->wps_probe_resp_ie), - wpabuf_len(hapd->wps_probe_resp_ie)); - pos += wpabuf_len(hapd->wps_probe_resp_ie); - } -#endif /* CONFIG_WPS */ - -#ifdef CONFIG_P2P - if ((hapd->conf->p2p & P2P_ENABLED) && elems.p2p && - hapd->p2p_probe_resp_ie) { - os_memcpy(pos, wpabuf_head(hapd->p2p_probe_resp_ie), - wpabuf_len(hapd->p2p_probe_resp_ie)); - pos += wpabuf_len(hapd->p2p_probe_resp_ie); - } -#endif /* CONFIG_P2P */ -#ifdef CONFIG_P2P_MANAGER - if ((hapd->conf->p2p & (P2P_MANAGE | P2P_ENABLED | P2P_GROUP_OWNER)) == - P2P_MANAGE) - pos = hostapd_eid_p2p_manage(hapd, pos); -#endif /* CONFIG_P2P_MANAGER */ - - if (hostapd_drv_send_mlme(hapd, resp, pos - (u8 *) resp) < 0) - perror("handle_probe_req: send"); - - os_free(resp); - - wpa_printf(MSG_EXCESSIVE, "STA " MACSTR " sent probe request for %s " - "SSID", MAC2STR(mgmt->sa), - elems.ssid_len == 0 ? "broadcast" : "our"); -} - - -void ieee802_11_set_beacon(struct hostapd_data *hapd) -{ - struct ieee80211_mgmt *head; - u8 *pos, *tail, *tailpos; - u16 capab_info; - size_t head_len, tail_len; - -#ifdef CONFIG_P2P - if ((hapd->conf->p2p & (P2P_ENABLED | P2P_GROUP_OWNER)) == P2P_ENABLED) - goto no_beacon; -#endif /* CONFIG_P2P */ - -#define BEACON_HEAD_BUF_SIZE 256 -#define BEACON_TAIL_BUF_SIZE 512 - head = os_zalloc(BEACON_HEAD_BUF_SIZE); - tail_len = BEACON_TAIL_BUF_SIZE; -#ifdef CONFIG_WPS - if (hapd->conf->wps_state && hapd->wps_beacon_ie) - tail_len += wpabuf_len(hapd->wps_beacon_ie); -#endif /* CONFIG_WPS */ -#ifdef CONFIG_P2P - if (hapd->p2p_beacon_ie) - tail_len += wpabuf_len(hapd->p2p_beacon_ie); -#endif /* CONFIG_P2P */ - tailpos = tail = os_malloc(tail_len); - if (head == NULL || tail == NULL) { - wpa_printf(MSG_ERROR, "Failed to set beacon data"); - os_free(head); - os_free(tail); - return; - } - - head->frame_control = IEEE80211_FC(WLAN_FC_TYPE_MGMT, - WLAN_FC_STYPE_BEACON); - head->duration = host_to_le16(0); - os_memset(head->da, 0xff, ETH_ALEN); - - os_memcpy(head->sa, hapd->own_addr, ETH_ALEN); - os_memcpy(head->bssid, hapd->own_addr, ETH_ALEN); - head->u.beacon.beacon_int = - host_to_le16(hapd->iconf->beacon_int); - - /* hardware or low-level driver will setup seq_ctrl and timestamp */ - capab_info = hostapd_own_capab_info(hapd, NULL, 0); - head->u.beacon.capab_info = host_to_le16(capab_info); - pos = &head->u.beacon.variable[0]; - - /* SSID */ - *pos++ = WLAN_EID_SSID; - if (hapd->conf->ignore_broadcast_ssid == 2) { - /* clear the data, but keep the correct length of the SSID */ - *pos++ = hapd->conf->ssid.ssid_len; - os_memset(pos, 0, hapd->conf->ssid.ssid_len); - pos += hapd->conf->ssid.ssid_len; - } else if (hapd->conf->ignore_broadcast_ssid) { - *pos++ = 0; /* empty SSID */ - } else { - *pos++ = hapd->conf->ssid.ssid_len; - os_memcpy(pos, hapd->conf->ssid.ssid, - hapd->conf->ssid.ssid_len); - pos += hapd->conf->ssid.ssid_len; - } - - /* Supported rates */ - pos = hostapd_eid_supp_rates(hapd, pos); - - /* DS Params */ - pos = hostapd_eid_ds_params(hapd, pos); - - head_len = pos - (u8 *) head; - - tailpos = hostapd_eid_country(hapd, tailpos, - tail + BEACON_TAIL_BUF_SIZE - tailpos); - - /* ERP Information element */ - tailpos = hostapd_eid_erp_info(hapd, tailpos); - - /* Extended supported rates */ - tailpos = hostapd_eid_ext_supp_rates(hapd, tailpos); - - /* RSN, MDIE, WPA */ - tailpos = hostapd_eid_wpa(hapd, tailpos, tail + BEACON_TAIL_BUF_SIZE - - tailpos, NULL); - -#ifdef CONFIG_IEEE80211N - tailpos = hostapd_eid_ht_capabilities(hapd, tailpos); - tailpos = hostapd_eid_ht_operation(hapd, tailpos); - - //DRIVER_RTW ADD - if(hapd->iconf->ieee80211n) - hapd->conf->wmm_enabled = 1; - -#endif /* CONFIG_IEEE80211N */ - - tailpos = hostapd_eid_ext_capab(hapd, tailpos); - - /* Wi-Fi Alliance WMM */ - tailpos = hostapd_eid_wmm(hapd, tailpos); - -#ifdef CONFIG_WPS - if (hapd->conf->wps_state && hapd->wps_beacon_ie) { - os_memcpy(tailpos, wpabuf_head(hapd->wps_beacon_ie), - wpabuf_len(hapd->wps_beacon_ie)); - tailpos += wpabuf_len(hapd->wps_beacon_ie); - } -#endif /* CONFIG_WPS */ - -#ifdef CONFIG_P2P - if ((hapd->conf->p2p & P2P_ENABLED) && hapd->p2p_beacon_ie) { - os_memcpy(tailpos, wpabuf_head(hapd->p2p_beacon_ie), - wpabuf_len(hapd->p2p_beacon_ie)); - tailpos += wpabuf_len(hapd->p2p_beacon_ie); - } -#endif /* CONFIG_P2P */ -#ifdef CONFIG_P2P_MANAGER - if ((hapd->conf->p2p & (P2P_MANAGE | P2P_ENABLED | P2P_GROUP_OWNER)) == - P2P_MANAGE) - tailpos = hostapd_eid_p2p_manage(hapd, tailpos); -#endif /* CONFIG_P2P_MANAGER */ - - tail_len = tailpos > tail ? tailpos - tail : 0; - - if (hostapd_drv_set_beacon(hapd, (u8 *) head, head_len, - tail, tail_len, hapd->conf->dtim_period, - hapd->iconf->beacon_int)) - wpa_printf(MSG_ERROR, "Failed to set beacon head/tail or DTIM " - "period"); - - os_free(tail); - os_free(head); - -#ifdef CONFIG_P2P -no_beacon: -#endif /* CONFIG_P2P */ - hostapd_set_bss_params(hapd, !!(ieee802_11_erp_info(hapd) & - ERP_INFO_USE_PROTECTION)); -} - - -void ieee802_11_set_beacons(struct hostapd_iface *iface) -{ - size_t i; - for (i = 0; i < iface->num_bss; i++) - ieee802_11_set_beacon(iface->bss[i]); -} - -#endif /* CONFIG_NATIVE_WINDOWS */ diff --git a/hostapd-0.8/src/ap/beacon.h b/hostapd-0.8/src/ap/beacon.h deleted file mode 100644 index c1510e1..0000000 --- a/hostapd-0.8/src/ap/beacon.h +++ /dev/null @@ -1,36 +0,0 @@ -/* - * hostapd / IEEE 802.11 Management: Beacon and Probe Request/Response - * Copyright (c) 2002-2004, Instant802 Networks, Inc. - * Copyright (c) 2005-2006, Devicescape Software, Inc. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#ifndef BEACON_H -#define BEACON_H - -struct ieee80211_mgmt; - -void handle_probe_req(struct hostapd_data *hapd, - const struct ieee80211_mgmt *mgmt, size_t len); -#ifdef NEED_AP_MLME -void ieee802_11_set_beacon(struct hostapd_data *hapd); -void ieee802_11_set_beacons(struct hostapd_iface *iface); -#else /* NEED_AP_MLME */ -static inline void ieee802_11_set_beacon(struct hostapd_data *hapd) -{ -} - -static inline void ieee802_11_set_beacons(struct hostapd_iface *iface) -{ -} -#endif /* NEED_AP_MLME */ - -#endif /* BEACON_H */ diff --git a/hostapd-0.8/src/ap/ctrl_iface_ap.c b/hostapd-0.8/src/ap/ctrl_iface_ap.c deleted file mode 100644 index d348dc1..0000000 --- a/hostapd-0.8/src/ap/ctrl_iface_ap.c +++ /dev/null @@ -1,108 +0,0 @@ -/* - * Control interface for shared AP commands - * Copyright (c) 2004-2009, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#include "utils/includes.h" - -#include "utils/common.h" -#include "hostapd.h" -#include "ieee802_1x.h" -#include "wpa_auth.h" -#include "ieee802_11.h" -#include "sta_info.h" -#include "wps_hostapd.h" -#include "p2p_hostapd.h" -#include "ctrl_iface_ap.h" - - -static int hostapd_ctrl_iface_sta_mib(struct hostapd_data *hapd, - struct sta_info *sta, - char *buf, size_t buflen) -{ - int len, res, ret; - - if (sta == NULL) { - ret = os_snprintf(buf, buflen, "FAIL\n"); - if (ret < 0 || (size_t) ret >= buflen) - return 0; - return ret; - } - - len = 0; - ret = os_snprintf(buf + len, buflen - len, MACSTR "\n", - MAC2STR(sta->addr)); - if (ret < 0 || (size_t) ret >= buflen - len) - return len; - len += ret; - - res = ieee802_11_get_mib_sta(hapd, sta, buf + len, buflen - len); - if (res >= 0) - len += res; - res = wpa_get_mib_sta(sta->wpa_sm, buf + len, buflen - len); - if (res >= 0) - len += res; - res = ieee802_1x_get_mib_sta(hapd, sta, buf + len, buflen - len); - if (res >= 0) - len += res; - res = hostapd_wps_get_mib_sta(hapd, sta->addr, buf + len, - buflen - len); - if (res >= 0) - len += res; - res = hostapd_p2p_get_mib_sta(hapd, sta, buf + len, buflen - len); - if (res >= 0) - len += res; - - return len; -} - - -int hostapd_ctrl_iface_sta_first(struct hostapd_data *hapd, - char *buf, size_t buflen) -{ - return hostapd_ctrl_iface_sta_mib(hapd, hapd->sta_list, buf, buflen); -} - - -int hostapd_ctrl_iface_sta(struct hostapd_data *hapd, const char *txtaddr, - char *buf, size_t buflen) -{ - u8 addr[ETH_ALEN]; - int ret; - - if (hwaddr_aton(txtaddr, addr)) { - ret = os_snprintf(buf, buflen, "FAIL\n"); - if (ret < 0 || (size_t) ret >= buflen) - return 0; - return ret; - } - return hostapd_ctrl_iface_sta_mib(hapd, ap_get_sta(hapd, addr), - buf, buflen); -} - - -int hostapd_ctrl_iface_sta_next(struct hostapd_data *hapd, const char *txtaddr, - char *buf, size_t buflen) -{ - u8 addr[ETH_ALEN]; - struct sta_info *sta; - int ret; - - if (hwaddr_aton(txtaddr, addr) || - (sta = ap_get_sta(hapd, addr)) == NULL) { - ret = os_snprintf(buf, buflen, "FAIL\n"); - if (ret < 0 || (size_t) ret >= buflen) - return 0; - return ret; - } - return hostapd_ctrl_iface_sta_mib(hapd, sta->next, buf, buflen); -} diff --git a/hostapd-0.8/src/ap/ctrl_iface_ap.h b/hostapd-0.8/src/ap/ctrl_iface_ap.h deleted file mode 100644 index 8690bea..0000000 --- a/hostapd-0.8/src/ap/ctrl_iface_ap.h +++ /dev/null @@ -1,25 +0,0 @@ -/* - * Control interface for shared AP commands - * Copyright (c) 2004-2009, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#ifndef CTRL_IFACE_AP_H -#define CTRL_IFACE_AP_H - -int hostapd_ctrl_iface_sta_first(struct hostapd_data *hapd, - char *buf, size_t buflen); -int hostapd_ctrl_iface_sta(struct hostapd_data *hapd, const char *txtaddr, - char *buf, size_t buflen); -int hostapd_ctrl_iface_sta_next(struct hostapd_data *hapd, const char *txtaddr, - char *buf, size_t buflen); - -#endif /* CTRL_IFACE_AP_H */ diff --git a/hostapd-0.8/src/ap/drv_callbacks.c b/hostapd-0.8/src/ap/drv_callbacks.c deleted file mode 100644 index 02b7ecf..0000000 --- a/hostapd-0.8/src/ap/drv_callbacks.c +++ /dev/null @@ -1,539 +0,0 @@ -/* - * hostapd / Callback functions for driver wrappers - * Copyright (c) 2002-2009, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#include "utils/includes.h" - -#include "utils/common.h" -#include "radius/radius.h" -#include "drivers/driver.h" -#include "common/ieee802_11_defs.h" -#include "common/ieee802_11_common.h" -#include "common/wpa_ctrl.h" -#include "crypto/random.h" -#include "p2p/p2p.h" -#include "wps/wps.h" -#include "hostapd.h" -#include "ieee802_11.h" -#include "sta_info.h" -#include "accounting.h" -#include "tkip_countermeasures.h" -#include "iapp.h" -#include "ieee802_1x.h" -#include "wpa_auth.h" -#include "wmm.h" -#include "wps_hostapd.h" -#include "ap_drv_ops.h" -#include "ap_config.h" - - -int hostapd_notif_assoc(struct hostapd_data *hapd, const u8 *addr, - const u8 *ie, size_t ielen, int reassoc) -{ - struct sta_info *sta; - int new_assoc, res; - struct ieee802_11_elems elems; -#ifdef CONFIG_P2P - const u8 *all_ies = ie; - size_t all_ies_len = ielen; -#endif /* CONFIG_P2P */ - - if (addr == NULL) { - /* - * This could potentially happen with unexpected event from the - * driver wrapper. This was seen at least in one case where the - * driver ended up being set to station mode while hostapd was - * running, so better make sure we stop processing such an - * event here. - */ - wpa_printf(MSG_DEBUG, "hostapd_notif_assoc: Skip event with " - "no address"); - return -1; - } - random_add_randomness(addr, ETH_ALEN); - - hostapd_logger(hapd, addr, HOSTAPD_MODULE_IEEE80211, - HOSTAPD_LEVEL_INFO, "associated"); - - ieee802_11_parse_elems(ie, ielen, &elems, 0); - if (elems.wps_ie) { - ie = elems.wps_ie - 2; - ielen = elems.wps_ie_len + 2; - wpa_printf(MSG_DEBUG, "STA included WPS IE in (Re)AssocReq"); - } else if (elems.rsn_ie) { - ie = elems.rsn_ie - 2; - ielen = elems.rsn_ie_len + 2; - wpa_printf(MSG_DEBUG, "STA included RSN IE in (Re)AssocReq"); - } else if (elems.wpa_ie) { - ie = elems.wpa_ie - 2; - ielen = elems.wpa_ie_len + 2; - wpa_printf(MSG_DEBUG, "STA included WPA IE in (Re)AssocReq"); - } else { - ie = NULL; - ielen = 0; - wpa_printf(MSG_DEBUG, "STA did not include WPS/RSN/WPA IE in " - "(Re)AssocReq"); - } - - sta = ap_get_sta(hapd, addr); - if (sta) { - accounting_sta_stop(hapd, sta); - } else { - sta = ap_sta_add(hapd, addr); - if (sta == NULL) - return -1; - } - sta->flags &= ~(WLAN_STA_WPS | WLAN_STA_MAYBE_WPS); - -#ifdef CONFIG_P2P - if (elems.p2p) { - wpabuf_free(sta->p2p_ie); - sta->p2p_ie = ieee802_11_vendor_ie_concat(all_ies, all_ies_len, - P2P_IE_VENDOR_TYPE); - } -#endif /* CONFIG_P2P */ - - if (hapd->conf->wpa) { - if (ie == NULL || ielen == 0) { - if (hapd->conf->wps_state) { - wpa_printf(MSG_DEBUG, "STA did not include " - "WPA/RSN IE in (Re)Association " - "Request - possible WPS use"); - sta->flags |= WLAN_STA_MAYBE_WPS; - goto skip_wpa_check; - } - - wpa_printf(MSG_DEBUG, "No WPA/RSN IE from STA"); - return -1; - } - if (hapd->conf->wps_state && ie[0] == 0xdd && ie[1] >= 4 && - os_memcmp(ie + 2, "\x00\x50\xf2\x04", 4) == 0) { - sta->flags |= WLAN_STA_WPS; - goto skip_wpa_check; - } - - if (sta->wpa_sm == NULL) - sta->wpa_sm = wpa_auth_sta_init(hapd->wpa_auth, - sta->addr); - if (sta->wpa_sm == NULL) { - wpa_printf(MSG_ERROR, "Failed to initialize WPA state " - "machine"); - return -1; - } - res = wpa_validate_wpa_ie(hapd->wpa_auth, sta->wpa_sm, - ie, ielen, NULL, 0); - if (res != WPA_IE_OK) { - int resp; - wpa_printf(MSG_DEBUG, "WPA/RSN information element " - "rejected? (res %u)", res); - wpa_hexdump(MSG_DEBUG, "IE", ie, ielen); - if (res == WPA_INVALID_GROUP) - resp = WLAN_REASON_GROUP_CIPHER_NOT_VALID; - else if (res == WPA_INVALID_PAIRWISE) - resp = WLAN_REASON_PAIRWISE_CIPHER_NOT_VALID; - else if (res == WPA_INVALID_AKMP) - resp = WLAN_REASON_AKMP_NOT_VALID; -#ifdef CONFIG_IEEE80211W - else if (res == WPA_MGMT_FRAME_PROTECTION_VIOLATION) - resp = WLAN_REASON_INVALID_IE; - else if (res == WPA_INVALID_MGMT_GROUP_CIPHER) - resp = WLAN_REASON_GROUP_CIPHER_NOT_VALID; -#endif /* CONFIG_IEEE80211W */ - else - resp = WLAN_REASON_INVALID_IE; - hostapd_drv_sta_disassoc(hapd, sta->addr, resp); - ap_free_sta(hapd, sta); - return -1; - } - } else if (hapd->conf->wps_state) { -#ifdef CONFIG_WPS_STRICT - if (ie) { - struct wpabuf *wps; - wps = ieee802_11_vendor_ie_concat(ie, ielen, - WPS_IE_VENDOR_TYPE); - if (wps && wps_validate_assoc_req(wps) < 0) { - hostapd_drv_sta_disassoc( - hapd, sta->addr, - WLAN_REASON_INVALID_IE); - ap_free_sta(hapd, sta); - wpabuf_free(wps); - return -1; - } - wpabuf_free(wps); - } -#endif /* CONFIG_WPS_STRICT */ - if (ie && ielen > 4 && ie[0] == 0xdd && ie[1] >= 4 && - os_memcmp(ie + 2, "\x00\x50\xf2\x04", 4) == 0) { - sta->flags |= WLAN_STA_WPS; - } else - sta->flags |= WLAN_STA_MAYBE_WPS; - } -skip_wpa_check: - - new_assoc = (sta->flags & WLAN_STA_ASSOC) == 0; - sta->flags |= WLAN_STA_AUTH | WLAN_STA_ASSOC; - wpa_auth_sm_event(sta->wpa_sm, WPA_ASSOC); - - hostapd_new_assoc_sta(hapd, sta, !new_assoc); - - ieee802_1x_notify_port_enabled(sta->eapol_sm, 1); - -#ifdef CONFIG_P2P - p2p_group_notif_assoc(hapd->p2p_group, sta->addr, - all_ies, all_ies_len); -#endif /* CONFIG_P2P */ - - return 0; -} - - -void hostapd_notif_disassoc(struct hostapd_data *hapd, const u8 *addr) -{ - struct sta_info *sta; - - if (addr == NULL) { - /* - * This could potentially happen with unexpected event from the - * driver wrapper. This was seen at least in one case where the - * driver ended up reporting a station mode event while hostapd - * was running, so better make sure we stop processing such an - * event here. - */ - wpa_printf(MSG_DEBUG, "hostapd_notif_disassoc: Skip event " - "with no address"); - return; - } - - hostapd_logger(hapd, addr, HOSTAPD_MODULE_IEEE80211, - HOSTAPD_LEVEL_INFO, "disassociated"); - - sta = ap_get_sta(hapd, addr); - if (sta == NULL) { - wpa_printf(MSG_DEBUG, "Disassociation notification for " - "unknown STA " MACSTR, MAC2STR(addr)); - return; - } - - sta->flags &= ~(WLAN_STA_AUTH | WLAN_STA_ASSOC); - wpa_msg(hapd->msg_ctx, MSG_INFO, AP_STA_DISCONNECTED MACSTR, - MAC2STR(sta->addr)); - wpa_auth_sm_event(sta->wpa_sm, WPA_DISASSOC); - sta->acct_terminate_cause = RADIUS_ACCT_TERMINATE_CAUSE_USER_REQUEST; - ieee802_1x_notify_port_enabled(sta->eapol_sm, 0); - ap_free_sta(hapd, sta); -} - - -void hostapd_event_sta_low_ack(struct hostapd_data *hapd, const u8 *addr) -{ - struct sta_info *sta = ap_get_sta(hapd, addr); - - if (!sta || !hapd->conf->disassoc_low_ack) - return; - - hostapd_logger(hapd, addr, HOSTAPD_MODULE_IEEE80211, - HOSTAPD_LEVEL_INFO, "disconnected due to excessive " - "missing ACKs"); - hostapd_drv_sta_disassoc(hapd, addr, WLAN_REASON_DISASSOC_LOW_ACK); - if (sta) - ap_sta_disassociate(hapd, sta, WLAN_REASON_DISASSOC_LOW_ACK); -} - - -int hostapd_probe_req_rx(struct hostapd_data *hapd, const u8 *sa, - const u8 *ie, size_t ie_len) -{ - size_t i; - int ret = 0; - - if (sa == NULL || ie == NULL) - return -1; - - random_add_randomness(sa, ETH_ALEN); - for (i = 0; hapd->probereq_cb && i < hapd->num_probereq_cb; i++) { - if (hapd->probereq_cb[i].cb(hapd->probereq_cb[i].ctx, - sa, ie, ie_len) > 0) { - ret = 1; - break; - } - } - return ret; -} - - -#ifdef HOSTAPD - -#ifdef NEED_AP_MLME - -static const u8 * get_hdr_bssid(const struct ieee80211_hdr *hdr, size_t len) -{ - u16 fc, type, stype; - - /* - * PS-Poll frames are 16 bytes. All other frames are - * 24 bytes or longer. - */ - if (len < 16) - return NULL; - - fc = le_to_host16(hdr->frame_control); - type = WLAN_FC_GET_TYPE(fc); - stype = WLAN_FC_GET_STYPE(fc); - - switch (type) { - case WLAN_FC_TYPE_DATA: - if (len < 24) - return NULL; - switch (fc & (WLAN_FC_FROMDS | WLAN_FC_TODS)) { - case WLAN_FC_FROMDS | WLAN_FC_TODS: - case WLAN_FC_TODS: - return hdr->addr1; - case WLAN_FC_FROMDS: - return hdr->addr2; - default: - return NULL; - } - case WLAN_FC_TYPE_CTRL: - if (stype != WLAN_FC_STYPE_PSPOLL) - return NULL; - return hdr->addr1; - case WLAN_FC_TYPE_MGMT: - return hdr->addr3; - default: - return NULL; - } -} - - -#define HAPD_BROADCAST ((struct hostapd_data *) -1) - -static struct hostapd_data * get_hapd_bssid(struct hostapd_iface *iface, - const u8 *bssid) -{ - size_t i; - - if (bssid == NULL) - return NULL; - if (bssid[0] == 0xff && bssid[1] == 0xff && bssid[2] == 0xff && - bssid[3] == 0xff && bssid[4] == 0xff && bssid[5] == 0xff) - return HAPD_BROADCAST; - - for (i = 0; i < iface->num_bss; i++) { - if (os_memcmp(bssid, iface->bss[i]->own_addr, ETH_ALEN) == 0) - return iface->bss[i]; - } - - return NULL; -} - - -static void hostapd_rx_from_unknown_sta(struct hostapd_data *hapd, - const u8 *frame, size_t len) -{ - const struct ieee80211_hdr *hdr = (const struct ieee80211_hdr *) frame; - u16 fc = le_to_host16(hdr->frame_control); - hapd = get_hapd_bssid(hapd->iface, get_hdr_bssid(hdr, len)); - if (hapd == NULL || hapd == HAPD_BROADCAST) - return; - - ieee802_11_rx_from_unknown(hapd, hdr->addr2, - (fc & (WLAN_FC_TODS | WLAN_FC_FROMDS)) == - (WLAN_FC_TODS | WLAN_FC_FROMDS)); -} - - -static void hostapd_mgmt_rx(struct hostapd_data *hapd, struct rx_mgmt *rx_mgmt) -{ - struct hostapd_iface *iface = hapd->iface; - const struct ieee80211_hdr *hdr; - const u8 *bssid; - struct hostapd_frame_info fi; - - hdr = (const struct ieee80211_hdr *) rx_mgmt->frame; - bssid = get_hdr_bssid(hdr, rx_mgmt->frame_len); - if (bssid == NULL) - return; - - hapd = get_hapd_bssid(iface, bssid); - if (hapd == NULL) { - u16 fc; - fc = le_to_host16(hdr->frame_control); - - /* - * Drop frames to unknown BSSIDs except for Beacon frames which - * could be used to update neighbor information. - */ - if (WLAN_FC_GET_TYPE(fc) == WLAN_FC_TYPE_MGMT && - WLAN_FC_GET_STYPE(fc) == WLAN_FC_STYPE_BEACON) - hapd = iface->bss[0]; - else - return; - } - - os_memset(&fi, 0, sizeof(fi)); - fi.datarate = rx_mgmt->datarate; - fi.ssi_signal = rx_mgmt->ssi_signal; - - if (hapd == HAPD_BROADCAST) { - size_t i; - for (i = 0; i < iface->num_bss; i++) - ieee802_11_mgmt(iface->bss[i], rx_mgmt->frame, - rx_mgmt->frame_len, &fi); - } else - ieee802_11_mgmt(hapd, rx_mgmt->frame, rx_mgmt->frame_len, &fi); - - random_add_randomness(&fi, sizeof(fi)); -} - - -static void hostapd_mgmt_tx_cb(struct hostapd_data *hapd, const u8 *buf, - size_t len, u16 stype, int ok) -{ - struct ieee80211_hdr *hdr; - hdr = (struct ieee80211_hdr *) buf; - hapd = get_hapd_bssid(hapd->iface, get_hdr_bssid(hdr, len)); - if (hapd == NULL || hapd == HAPD_BROADCAST) - return; - ieee802_11_mgmt_cb(hapd, buf, len, stype, ok); -} - -#endif /* NEED_AP_MLME */ - - -static int hostapd_event_new_sta(struct hostapd_data *hapd, const u8 *addr) -{ - struct sta_info *sta = ap_get_sta(hapd, addr); - if (sta) - return 0; - - wpa_printf(MSG_DEBUG, "Data frame from unknown STA " MACSTR - " - adding a new STA", MAC2STR(addr)); - sta = ap_sta_add(hapd, addr); - if (sta) { - hostapd_new_assoc_sta(hapd, sta, 0); - } else { - wpa_printf(MSG_DEBUG, "Failed to add STA entry for " MACSTR, - MAC2STR(addr)); - return -1; - } - - return 0; -} - - -static void hostapd_event_eapol_rx(struct hostapd_data *hapd, const u8 *src, - const u8 *data, size_t data_len) -{ - struct hostapd_iface *iface = hapd->iface; - size_t j; - - for (j = 0; j < iface->num_bss; j++) { - if (ap_get_sta(iface->bss[j], src)) { - hapd = iface->bss[j]; - break; - } - } - - ieee802_1x_receive(hapd, src, data, data_len); -} - - -void wpa_supplicant_event(void *ctx, enum wpa_event_type event, - union wpa_event_data *data) -{ - struct hostapd_data *hapd = ctx; - - switch (event) { - case EVENT_MICHAEL_MIC_FAILURE: - michael_mic_failure(hapd, data->michael_mic_failure.src, 1); - break; - case EVENT_SCAN_RESULTS: - if (hapd->iface->scan_cb) - hapd->iface->scan_cb(hapd->iface); - break; -#ifdef CONFIG_IEEE80211R - case EVENT_FT_RRB_RX: - wpa_ft_rrb_rx(hapd->wpa_auth, data->ft_rrb_rx.src, - data->ft_rrb_rx.data, data->ft_rrb_rx.data_len); - break; -#endif /* CONFIG_IEEE80211R */ - case EVENT_WPS_BUTTON_PUSHED: - hostapd_wps_button_pushed(hapd, NULL); - break; -#ifdef NEED_AP_MLME - case EVENT_TX_STATUS: - switch (data->tx_status.type) { - case WLAN_FC_TYPE_MGMT: - hostapd_mgmt_tx_cb(hapd, data->tx_status.data, - data->tx_status.data_len, - data->tx_status.stype, - data->tx_status.ack); - break; - case WLAN_FC_TYPE_DATA: - hostapd_tx_status(hapd, data->tx_status.dst, - data->tx_status.data, - data->tx_status.data_len, - data->tx_status.ack); - break; - } - break; - case EVENT_RX_FROM_UNKNOWN: - hostapd_rx_from_unknown_sta(hapd, data->rx_from_unknown.frame, - data->rx_from_unknown.len); - break; - case EVENT_RX_MGMT: - hostapd_mgmt_rx(hapd, &data->rx_mgmt); - break; -#endif /* NEED_AP_MLME */ - case EVENT_RX_PROBE_REQ: - if (data->rx_probe_req.sa == NULL || - data->rx_probe_req.ie == NULL) - break; - hostapd_probe_req_rx(hapd, data->rx_probe_req.sa, - data->rx_probe_req.ie, - data->rx_probe_req.ie_len); - break; - case EVENT_NEW_STA: - hostapd_event_new_sta(hapd, data->new_sta.addr); - break; - case EVENT_EAPOL_RX: - hostapd_event_eapol_rx(hapd, data->eapol_rx.src, - data->eapol_rx.data, - data->eapol_rx.data_len); - break; - case EVENT_ASSOC: - hostapd_notif_assoc(hapd, data->assoc_info.addr, - data->assoc_info.req_ies, - data->assoc_info.req_ies_len, - data->assoc_info.reassoc); - break; - case EVENT_DISASSOC: - if (data) - hostapd_notif_disassoc(hapd, data->disassoc_info.addr); - break; - case EVENT_DEAUTH: - if (data) - hostapd_notif_disassoc(hapd, data->deauth_info.addr); - break; - case EVENT_STATION_LOW_ACK: - if (!data) - break; - hostapd_event_sta_low_ack(hapd, data->low_ack.addr); - break; - default: - wpa_printf(MSG_DEBUG, "Unknown event %d", event); - break; - } -} - -#endif /* HOSTAPD */ diff --git a/hostapd-0.8/src/ap/hostapd.c b/hostapd-0.8/src/ap/hostapd.c deleted file mode 100644 index 4e5eb01..0000000 --- a/hostapd-0.8/src/ap/hostapd.c +++ /dev/null @@ -1,929 +0,0 @@ -/* - * hostapd / Initialization and configuration - * Copyright (c) 2002-2009, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#include "utils/includes.h" - -#include "utils/common.h" -#include "utils/eloop.h" -#include "common/ieee802_11_defs.h" -#include "radius/radius_client.h" -#include "drivers/driver.h" -#include "hostapd.h" -#include "authsrv.h" -#include "sta_info.h" -#include "accounting.h" -#include "ap_list.h" -#include "beacon.h" -#include "iapp.h" -#include "ieee802_1x.h" -#include "ieee802_11_auth.h" -#include "vlan_init.h" -#include "wpa_auth.h" -#include "wps_hostapd.h" -#include "hw_features.h" -#include "wpa_auth_glue.h" -#include "ap_drv_ops.h" -#include "ap_config.h" -#include "p2p_hostapd.h" - - -static int hostapd_flush_old_stations(struct hostapd_data *hapd); -static int hostapd_setup_encryption(char *iface, struct hostapd_data *hapd); - -extern int wpa_debug_level; - - -static void hostapd_reload_bss(struct hostapd_data *hapd) -{ -#ifndef CONFIG_NO_RADIUS - radius_client_reconfig(hapd->radius, hapd->conf->radius); -#endif /* CONFIG_NO_RADIUS */ - - if (hostapd_setup_wpa_psk(hapd->conf)) { - wpa_printf(MSG_ERROR, "Failed to re-configure WPA PSK " - "after reloading configuration"); - } - - if (hapd->conf->ieee802_1x || hapd->conf->wpa) - hostapd_set_drv_ieee8021x(hapd, hapd->conf->iface, 1); - else - hostapd_set_drv_ieee8021x(hapd, hapd->conf->iface, 0); - - if (hapd->conf->wpa && hapd->wpa_auth == NULL) - hostapd_setup_wpa(hapd); - else if (hapd->conf->wpa) { - const u8 *wpa_ie; - size_t wpa_ie_len; - hostapd_reconfig_wpa(hapd); - wpa_ie = wpa_auth_get_wpa_ie(hapd->wpa_auth, &wpa_ie_len); - if (hostapd_set_generic_elem(hapd, wpa_ie, wpa_ie_len)) - wpa_printf(MSG_ERROR, "Failed to configure WPA IE for " - "the kernel driver."); - } else if (hapd->wpa_auth) { - wpa_deinit(hapd->wpa_auth); - hapd->wpa_auth = NULL; - hostapd_set_privacy(hapd, 0); - hostapd_setup_encryption(hapd->conf->iface, hapd); - hostapd_set_generic_elem(hapd, (u8 *) "", 0); - } - - ieee802_11_set_beacon(hapd); - hostapd_update_wps(hapd); - - if (hapd->conf->ssid.ssid_set && - hostapd_set_ssid(hapd, (u8 *) hapd->conf->ssid.ssid, - hapd->conf->ssid.ssid_len)) { - wpa_printf(MSG_ERROR, "Could not set SSID for kernel driver"); - /* try to continue */ - } - wpa_printf(MSG_DEBUG, "Reconfigured interface %s", hapd->conf->iface); -} - - -int hostapd_reload_config(struct hostapd_iface *iface) -{ - struct hostapd_data *hapd = iface->bss[0]; - struct hostapd_config *newconf, *oldconf; - size_t j; - - if (iface->config_read_cb == NULL) - return -1; - newconf = iface->config_read_cb(iface->config_fname); - if (newconf == NULL) - return -1; - - /* - * Deauthenticate all stations since the new configuration may not - * allow them to use the BSS anymore. - */ - for (j = 0; j < iface->num_bss; j++) { - hostapd_flush_old_stations(iface->bss[j]); - -#ifndef CONFIG_NO_RADIUS - /* TODO: update dynamic data based on changed configuration - * items (e.g., open/close sockets, etc.) */ - radius_client_flush(iface->bss[j]->radius, 0); -#endif /* CONFIG_NO_RADIUS */ - } - - oldconf = hapd->iconf; - iface->conf = newconf; - - for (j = 0; j < iface->num_bss; j++) { - hapd = iface->bss[j]; - hapd->iconf = newconf; - hapd->conf = &newconf->bss[j]; - hostapd_reload_bss(hapd); - } - - hostapd_config_free(oldconf); - - - return 0; -} - - -static void hostapd_broadcast_key_clear_iface(struct hostapd_data *hapd, - char *ifname) -{ - int i; - - for (i = 0; i < NUM_WEP_KEYS; i++) { - if (hostapd_drv_set_key(ifname, hapd, WPA_ALG_NONE, NULL, i, - 0, NULL, 0, NULL, 0)) { - wpa_printf(MSG_DEBUG, "Failed to clear default " - "encryption keys (ifname=%s keyidx=%d)", - ifname, i); - } - } -#ifdef CONFIG_IEEE80211W - if (hapd->conf->ieee80211w) { - for (i = NUM_WEP_KEYS; i < NUM_WEP_KEYS + 2; i++) { - if (hostapd_drv_set_key(ifname, hapd, WPA_ALG_NONE, - NULL, i, 0, NULL, - 0, NULL, 0)) { - wpa_printf(MSG_DEBUG, "Failed to clear " - "default mgmt encryption keys " - "(ifname=%s keyidx=%d)", ifname, i); - } - } - } -#endif /* CONFIG_IEEE80211W */ -} - - -static int hostapd_broadcast_wep_clear(struct hostapd_data *hapd) -{ - hostapd_broadcast_key_clear_iface(hapd, hapd->conf->iface); - return 0; -} - - -static int hostapd_broadcast_wep_set(struct hostapd_data *hapd) -{ - int errors = 0, idx; - struct hostapd_ssid *ssid = &hapd->conf->ssid; - - idx = ssid->wep.idx; - if (ssid->wep.default_len && - hostapd_drv_set_key(hapd->conf->iface, - hapd, WPA_ALG_WEP, broadcast_ether_addr, idx, - 1, NULL, 0, ssid->wep.key[idx], - ssid->wep.len[idx])) { - wpa_printf(MSG_WARNING, "Could not set WEP encryption."); - errors++; - } - - if (ssid->dyn_vlan_keys) { - size_t i; - for (i = 0; i <= ssid->max_dyn_vlan_keys; i++) { - const char *ifname; - struct hostapd_wep_keys *key = ssid->dyn_vlan_keys[i]; - if (key == NULL) - continue; - ifname = hostapd_get_vlan_id_ifname(hapd->conf->vlan, - i); - if (ifname == NULL) - continue; - - idx = key->idx; - if (hostapd_drv_set_key(ifname, hapd, WPA_ALG_WEP, - broadcast_ether_addr, idx, 1, - NULL, 0, key->key[idx], - key->len[idx])) { - wpa_printf(MSG_WARNING, "Could not set " - "dynamic VLAN WEP encryption."); - errors++; - } - } - } - - return errors; -} - -/** - * hostapd_cleanup - Per-BSS cleanup (deinitialization) - * @hapd: Pointer to BSS data - * - * This function is used to free all per-BSS data structures and resources. - * This gets called in a loop for each BSS between calls to - * hostapd_cleanup_iface_pre() and hostapd_cleanup_iface() when an interface - * is deinitialized. Most of the modules that are initialized in - * hostapd_setup_bss() are deinitialized here. - */ -static void hostapd_cleanup(struct hostapd_data *hapd) -{ - if (hapd->iface->ctrl_iface_deinit) - hapd->iface->ctrl_iface_deinit(hapd); - - iapp_deinit(hapd->iapp); - hapd->iapp = NULL; - accounting_deinit(hapd); - hostapd_deinit_wpa(hapd); - vlan_deinit(hapd); - hostapd_acl_deinit(hapd); -#ifndef CONFIG_NO_RADIUS - radius_client_deinit(hapd->radius); - hapd->radius = NULL; -#endif /* CONFIG_NO_RADIUS */ - - hostapd_deinit_wps(hapd); - - authsrv_deinit(hapd); - - if (hapd->interface_added && - hostapd_if_remove(hapd, WPA_IF_AP_BSS, hapd->conf->iface)) { - wpa_printf(MSG_WARNING, "Failed to remove BSS interface %s", - hapd->conf->iface); - } - - os_free(hapd->probereq_cb); - hapd->probereq_cb = NULL; - -#ifdef CONFIG_P2P - wpabuf_free(hapd->p2p_beacon_ie); - hapd->p2p_beacon_ie = NULL; - wpabuf_free(hapd->p2p_probe_resp_ie); - hapd->p2p_probe_resp_ie = NULL; -#endif /* CONFIG_P2P */ -} - - -/** - * hostapd_cleanup_iface_pre - Preliminary per-interface cleanup - * @iface: Pointer to interface data - * - * This function is called before per-BSS data structures are deinitialized - * with hostapd_cleanup(). - */ -static void hostapd_cleanup_iface_pre(struct hostapd_iface *iface) -{ -} - - -/** - * hostapd_cleanup_iface - Complete per-interface cleanup - * @iface: Pointer to interface data - * - * This function is called after per-BSS data structures are deinitialized - * with hostapd_cleanup(). - */ -static void hostapd_cleanup_iface(struct hostapd_iface *iface) -{ - hostapd_free_hw_features(iface->hw_features, iface->num_hw_features); - iface->hw_features = NULL; - os_free(iface->current_rates); - iface->current_rates = NULL; - ap_list_deinit(iface); - hostapd_config_free(iface->conf); - iface->conf = NULL; - - os_free(iface->config_fname); - os_free(iface->bss); - os_free(iface); -} - - -static int hostapd_setup_encryption(char *iface, struct hostapd_data *hapd) -{ - int i; - - hostapd_broadcast_wep_set(hapd); - - if (hapd->conf->ssid.wep.default_len) { - hostapd_set_privacy(hapd, 1); - return 0; - } - - for (i = 0; i < 4; i++) { - if (hapd->conf->ssid.wep.key[i] && - hostapd_drv_set_key(iface, hapd, WPA_ALG_WEP, NULL, i, - i == hapd->conf->ssid.wep.idx, NULL, 0, - hapd->conf->ssid.wep.key[i], - hapd->conf->ssid.wep.len[i])) { - wpa_printf(MSG_WARNING, "Could not set WEP " - "encryption."); - return -1; - } - if (hapd->conf->ssid.wep.key[i] && - i == hapd->conf->ssid.wep.idx) - hostapd_set_privacy(hapd, 1); - } - - return 0; -} - - -static int hostapd_flush_old_stations(struct hostapd_data *hapd) -{ - int ret = 0; - u8 addr[ETH_ALEN]; - - if (hostapd_drv_none(hapd) || hapd->drv_priv == NULL) - return 0; - - wpa_printf(MSG_DEBUG, "Flushing old station entries"); - if (hostapd_flush(hapd)) { - wpa_printf(MSG_WARNING, "Could not connect to kernel driver."); - ret = -1; - } - wpa_printf(MSG_DEBUG, "Deauthenticate all stations"); - os_memset(addr, 0xff, ETH_ALEN); - hostapd_drv_sta_deauth(hapd, addr, WLAN_REASON_PREV_AUTH_NOT_VALID); - hostapd_free_stas(hapd); - - return ret; -} - - -/** - * hostapd_validate_bssid_configuration - Validate BSSID configuration - * @iface: Pointer to interface data - * Returns: 0 on success, -1 on failure - * - * This function is used to validate that the configured BSSIDs are valid. - */ -static int hostapd_validate_bssid_configuration(struct hostapd_iface *iface) -{ - u8 mask[ETH_ALEN] = { 0 }; - struct hostapd_data *hapd = iface->bss[0]; - unsigned int i = iface->conf->num_bss, bits = 0, j; - int res; - int auto_addr = 0; - - if (hostapd_drv_none(hapd)) - return 0; - - /* Generate BSSID mask that is large enough to cover the BSSIDs. */ - - /* Determine the bits necessary to cover the number of BSSIDs. */ - for (i--; i; i >>= 1) - bits++; - - /* Determine the bits necessary to any configured BSSIDs, - if they are higher than the number of BSSIDs. */ - for (j = 0; j < iface->conf->num_bss; j++) { - if (hostapd_mac_comp_empty(iface->conf->bss[j].bssid) == 0) { - if (j) - auto_addr++; - continue; - } - - for (i = 0; i < ETH_ALEN; i++) { - mask[i] |= - iface->conf->bss[j].bssid[i] ^ - hapd->own_addr[i]; - } - } - - if (!auto_addr) - goto skip_mask_ext; - - for (i = 0; i < ETH_ALEN && mask[i] == 0; i++) - ; - j = 0; - if (i < ETH_ALEN) { - j = (5 - i) * 8; - - while (mask[i] != 0) { - mask[i] >>= 1; - j++; - } - } - - if (bits < j) - bits = j; - - if (bits > 40) { - wpa_printf(MSG_ERROR, "Too many bits in the BSSID mask (%u)", - bits); - return -1; - } - - os_memset(mask, 0xff, ETH_ALEN); - j = bits / 8; - for (i = 5; i > 5 - j; i--) - mask[i] = 0; - j = bits % 8; - while (j--) - mask[i] <<= 1; - -skip_mask_ext: - wpa_printf(MSG_DEBUG, "BSS count %lu, BSSID mask " MACSTR " (%d bits)", - (unsigned long) iface->conf->num_bss, MAC2STR(mask), bits); - - res = hostapd_valid_bss_mask(hapd, hapd->own_addr, mask); - if (res == 0) - return 0; - - if (res < 0) { - wpa_printf(MSG_ERROR, "Driver did not accept BSSID mask " - MACSTR " for start address " MACSTR ".", - MAC2STR(mask), MAC2STR(hapd->own_addr)); - return -1; - } - - if (!auto_addr) - return 0; - - for (i = 0; i < ETH_ALEN; i++) { - if ((hapd->own_addr[i] & mask[i]) != hapd->own_addr[i]) { - wpa_printf(MSG_ERROR, "Invalid BSSID mask " MACSTR - " for start address " MACSTR ".", - MAC2STR(mask), MAC2STR(hapd->own_addr)); - wpa_printf(MSG_ERROR, "Start address must be the " - "first address in the block (i.e., addr " - "AND mask == addr)."); - return -1; - } - } - - return 0; -} - - -static int mac_in_conf(struct hostapd_config *conf, const void *a) -{ - size_t i; - - for (i = 0; i < conf->num_bss; i++) { - if (hostapd_mac_comp(conf->bss[i].bssid, a) == 0) { - return 1; - } - } - - return 0; -} - - - - -/** - * hostapd_setup_bss - Per-BSS setup (initialization) - * @hapd: Pointer to BSS data - * @first: Whether this BSS is the first BSS of an interface - * - * This function is used to initialize all per-BSS data structures and - * resources. This gets called in a loop for each BSS when an interface is - * initialized. Most of the modules that are initialized here will be - * deinitialized in hostapd_cleanup(). - */ -static int hostapd_setup_bss(struct hostapd_data *hapd, int first) -{ - struct hostapd_bss_config *conf = hapd->conf; - u8 ssid[HOSTAPD_MAX_SSID_LEN + 1]; - int ssid_len, set_ssid; - char force_ifname[IFNAMSIZ]; - u8 if_addr[ETH_ALEN]; - - if (!first) { - if (hostapd_mac_comp_empty(hapd->conf->bssid) == 0) { - /* Allocate the next available BSSID. */ - do { - inc_byte_array(hapd->own_addr, ETH_ALEN); - } while (mac_in_conf(hapd->iconf, hapd->own_addr)); - } else { - /* Allocate the configured BSSID. */ - os_memcpy(hapd->own_addr, hapd->conf->bssid, ETH_ALEN); - - if (hostapd_mac_comp(hapd->own_addr, - hapd->iface->bss[0]->own_addr) == - 0) { - wpa_printf(MSG_ERROR, "BSS '%s' may not have " - "BSSID set to the MAC address of " - "the radio", hapd->conf->iface); - return -1; - } - } - - hapd->interface_added = 1; - if (hostapd_if_add(hapd->iface->bss[0], WPA_IF_AP_BSS, - hapd->conf->iface, hapd->own_addr, hapd, - &hapd->drv_priv, force_ifname, if_addr, - hapd->conf->bridge[0] ? hapd->conf->bridge : - NULL)) { - wpa_printf(MSG_ERROR, "Failed to add BSS (BSSID=" - MACSTR ")", MAC2STR(hapd->own_addr)); - return -1; - } - } - - if (conf->wmm_enabled < 0) - conf->wmm_enabled = hapd->iconf->ieee80211n; - - hostapd_flush_old_stations(hapd); - hostapd_set_privacy(hapd, 0); - - hostapd_broadcast_wep_clear(hapd); - if (hostapd_setup_encryption(hapd->conf->iface, hapd)) - return -1; - - /* - * Fetch the SSID from the system and use it or, - * if one was specified in the config file, verify they - * match. - */ - ssid_len = hostapd_get_ssid(hapd, ssid, sizeof(ssid)); - if (ssid_len < 0) { - wpa_printf(MSG_ERROR, "Could not read SSID from system"); - return -1; - } - if (conf->ssid.ssid_set) { - /* - * If SSID is specified in the config file and it differs - * from what is being used then force installation of the - * new SSID. - */ - set_ssid = (conf->ssid.ssid_len != (size_t) ssid_len || - os_memcmp(conf->ssid.ssid, ssid, ssid_len) != 0); - } else { - /* - * No SSID in the config file; just use the one we got - * from the system. - */ - set_ssid = 0; - conf->ssid.ssid_len = ssid_len; - os_memcpy(conf->ssid.ssid, ssid, conf->ssid.ssid_len); - conf->ssid.ssid[conf->ssid.ssid_len] = '\0'; - } - - if (!hostapd_drv_none(hapd)) { - wpa_printf(MSG_ERROR, "Using interface %s with hwaddr " MACSTR - " and ssid '%s'", - hapd->conf->iface, MAC2STR(hapd->own_addr), - hapd->conf->ssid.ssid); - } - - if (hostapd_setup_wpa_psk(conf)) { - wpa_printf(MSG_ERROR, "WPA-PSK setup failed."); - return -1; - } - - /* Set SSID for the kernel driver (to be used in beacon and probe - * response frames) */ - if (set_ssid && hostapd_set_ssid(hapd, (u8 *) conf->ssid.ssid, - conf->ssid.ssid_len)) { - wpa_printf(MSG_ERROR, "Could not set SSID for kernel driver"); - return -1; - } - - if (wpa_debug_level == MSG_MSGDUMP) - conf->radius->msg_dumps = 1; -#ifndef CONFIG_NO_RADIUS - hapd->radius = radius_client_init(hapd, conf->radius); - if (hapd->radius == NULL) { - wpa_printf(MSG_ERROR, "RADIUS client initialization failed."); - return -1; - } -#endif /* CONFIG_NO_RADIUS */ - - if (hostapd_acl_init(hapd)) { - wpa_printf(MSG_ERROR, "ACL initialization failed."); - return -1; - } - if (hostapd_init_wps(hapd, conf)) - return -1; - - if (authsrv_init(hapd) < 0) - return -1; - - if (ieee802_1x_init(hapd)) { - wpa_printf(MSG_ERROR, "IEEE 802.1X initialization failed."); - return -1; - } - - if (hapd->conf->wpa && hostapd_setup_wpa(hapd)) - return -1; - - if (accounting_init(hapd)) { - wpa_printf(MSG_ERROR, "Accounting initialization failed."); - return -1; - } - - if (hapd->conf->ieee802_11f && - (hapd->iapp = iapp_init(hapd, hapd->conf->iapp_iface)) == NULL) { - wpa_printf(MSG_ERROR, "IEEE 802.11F (IAPP) initialization " - "failed."); - return -1; - } - - if (hapd->iface->ctrl_iface_init && - hapd->iface->ctrl_iface_init(hapd)) { - wpa_printf(MSG_ERROR, "Failed to setup control interface"); - return -1; - } - - if (!hostapd_drv_none(hapd) && vlan_init(hapd)) { - wpa_printf(MSG_ERROR, "VLAN initialization failed."); - return -1; - } - - ieee802_11_set_beacon(hapd); - - if (hapd->driver && hapd->driver->set_operstate) - hapd->driver->set_operstate(hapd->drv_priv, 1); - - return 0; -} - - -static void hostapd_tx_queue_params(struct hostapd_iface *iface) -{ - struct hostapd_data *hapd = iface->bss[0]; - int i; - struct hostapd_tx_queue_params *p; - - for (i = 0; i < NUM_TX_QUEUES; i++) { - p = &iface->conf->tx_queue[i]; - - if (hostapd_set_tx_queue_params(hapd, i, p->aifs, p->cwmin, - p->cwmax, p->burst)) { - wpa_printf(MSG_DEBUG, "Failed to set TX queue " - "parameters for queue %d.", i); - /* Continue anyway */ - } - } -} - - -static int setup_interface(struct hostapd_iface *iface) -{ - struct hostapd_data *hapd = iface->bss[0]; - size_t i; - char country[4]; - - /* - * Make sure that all BSSes get configured with a pointer to the same - * driver interface. - */ - for (i = 1; i < iface->num_bss; i++) { - iface->bss[i]->driver = hapd->driver; - iface->bss[i]->drv_priv = hapd->drv_priv; - } - - if (hostapd_validate_bssid_configuration(iface)) - return -1; - - if (hapd->iconf->country[0] && hapd->iconf->country[1]) { - os_memcpy(country, hapd->iconf->country, 3); - country[3] = '\0'; - if (hostapd_set_country(hapd, country) < 0) { - wpa_printf(MSG_ERROR, "Failed to set country code"); - return -1; - } - } - - if (hostapd_get_hw_features(iface)) { - /* Not all drivers support this yet, so continue without hw - * feature data. */ - } else { - int ret = hostapd_select_hw_mode(iface); - if (ret < 0) { - wpa_printf(MSG_ERROR, "Could not select hw_mode and " - "channel. (%d)", ret); - return -1; - } - ret = hostapd_check_ht_capab(iface); - if (ret < 0) - return -1; - if (ret == 1) { - wpa_printf(MSG_DEBUG, "Interface initialization will " - "be completed in a callback"); - return 0; - } - } - return hostapd_setup_interface_complete(iface, 0); -} - - -int hostapd_setup_interface_complete(struct hostapd_iface *iface, int err) -{ - struct hostapd_data *hapd = iface->bss[0]; - size_t j; - u8 *prev_addr; - - if (err) { - wpa_printf(MSG_ERROR, "Interface initialization failed"); - eloop_terminate(); - return -1; - } - - wpa_printf(MSG_DEBUG, "Completing interface initialization"); - if (hapd->iconf->channel) { - iface->freq = hostapd_hw_get_freq(hapd, hapd->iconf->channel); - wpa_printf(MSG_DEBUG, "Mode: %s Channel: %d " - "Frequency: %d MHz", - hostapd_hw_mode_txt(hapd->iconf->hw_mode), - hapd->iconf->channel, iface->freq); - - if (hostapd_set_freq(hapd, hapd->iconf->hw_mode, iface->freq, - hapd->iconf->channel, - hapd->iconf->ieee80211n, - hapd->iconf->secondary_channel)) { - wpa_printf(MSG_ERROR, "Could not set channel for " - "kernel driver"); - return -1; - } - } - - if (iface->current_mode) { - if (hostapd_prepare_rates(hapd, iface->current_mode)) { - wpa_printf(MSG_ERROR, "Failed to prepare rates " - "table."); - hostapd_logger(hapd, NULL, HOSTAPD_MODULE_IEEE80211, - HOSTAPD_LEVEL_WARNING, - "Failed to prepare rates table."); - return -1; - } - } - - if (hapd->iconf->rts_threshold > -1 && - hostapd_set_rts(hapd, hapd->iconf->rts_threshold)) { - wpa_printf(MSG_ERROR, "Could not set RTS threshold for " - "kernel driver"); - return -1; - } - - if (hapd->iconf->fragm_threshold > -1 && - hostapd_set_frag(hapd, hapd->iconf->fragm_threshold)) { - wpa_printf(MSG_ERROR, "Could not set fragmentation threshold " - "for kernel driver"); - return -1; - } - - prev_addr = hapd->own_addr; - - for (j = 0; j < iface->num_bss; j++) { - hapd = iface->bss[j]; - if (j) - os_memcpy(hapd->own_addr, prev_addr, ETH_ALEN); - if (hostapd_setup_bss(hapd, j == 0)) - return -1; - if (hostapd_mac_comp_empty(hapd->conf->bssid) == 0) - prev_addr = hapd->own_addr; - } - - hostapd_tx_queue_params(iface); - - ap_list_init(iface); - - if (hostapd_driver_commit(hapd) < 0) { - wpa_printf(MSG_ERROR, "%s: Failed to commit driver " - "configuration", __func__); - return -1; - } - - if (hapd->setup_complete_cb) - hapd->setup_complete_cb(hapd->setup_complete_cb_ctx); - - wpa_printf(MSG_DEBUG, "%s: Setup of interface done.", - iface->bss[0]->conf->iface); - - return 0; -} - - -/** - * hostapd_setup_interface - Setup of an interface - * @iface: Pointer to interface data. - * Returns: 0 on success, -1 on failure - * - * Initializes the driver interface, validates the configuration, - * and sets driver parameters based on the configuration. - * Flushes old stations, sets the channel, encryption, - * beacons, and WDS links based on the configuration. - */ -int hostapd_setup_interface(struct hostapd_iface *iface) -{ - int ret; - - ret = setup_interface(iface); - if (ret) { - wpa_printf(MSG_ERROR, "%s: Unable to setup interface.", - iface->bss[0]->conf->iface); - return -1; - } - - return 0; -} - - -/** - * hostapd_alloc_bss_data - Allocate and initialize per-BSS data - * @hapd_iface: Pointer to interface data - * @conf: Pointer to per-interface configuration - * @bss: Pointer to per-BSS configuration for this BSS - * Returns: Pointer to allocated BSS data - * - * This function is used to allocate per-BSS data structure. This data will be - * freed after hostapd_cleanup() is called for it during interface - * deinitialization. - */ -struct hostapd_data * -hostapd_alloc_bss_data(struct hostapd_iface *hapd_iface, - struct hostapd_config *conf, - struct hostapd_bss_config *bss) -{ - struct hostapd_data *hapd; - - hapd = os_zalloc(sizeof(*hapd)); - if (hapd == NULL) - return NULL; - - hapd->new_assoc_sta_cb = hostapd_new_assoc_sta; - hapd->iconf = conf; - hapd->conf = bss; - hapd->iface = hapd_iface; - hapd->driver = hapd->iconf->driver; - - return hapd; -} - - -void hostapd_interface_deinit(struct hostapd_iface *iface) -{ - size_t j; - - if (iface == NULL) - return; - - hostapd_cleanup_iface_pre(iface); - for (j = 0; j < iface->num_bss; j++) { - struct hostapd_data *hapd = iface->bss[j]; - hostapd_free_stas(hapd); - hostapd_flush_old_stations(hapd); - hostapd_cleanup(hapd); - } -} - - -void hostapd_interface_free(struct hostapd_iface *iface) -{ - size_t j; - for (j = 0; j < iface->num_bss; j++) - os_free(iface->bss[j]); - hostapd_cleanup_iface(iface); -} - - -/** - * hostapd_new_assoc_sta - Notify that a new station associated with the AP - * @hapd: Pointer to BSS data - * @sta: Pointer to the associated STA data - * @reassoc: 1 to indicate this was a re-association; 0 = first association - * - * This function will be called whenever a station associates with the AP. It - * can be called from ieee802_11.c for drivers that export MLME to hostapd and - * from drv_callbacks.c based on driver events for drivers that take care of - * management frames (IEEE 802.11 authentication and association) internally. - */ -void hostapd_new_assoc_sta(struct hostapd_data *hapd, struct sta_info *sta, - int reassoc) -{ - if (hapd->tkip_countermeasures) { - hostapd_drv_sta_deauth(hapd, sta->addr, - WLAN_REASON_MICHAEL_MIC_FAILURE); - return; - } - - hostapd_prune_associations(hapd, sta->addr); - - /* IEEE 802.11F (IAPP) */ - if (hapd->conf->ieee802_11f) - iapp_new_station(hapd->iapp, sta); - -#ifdef CONFIG_P2P - if (sta->p2p_ie == NULL && !sta->no_p2p_set) { - sta->no_p2p_set = 1; - hapd->num_sta_no_p2p++; - if (hapd->num_sta_no_p2p == 1) - hostapd_p2p_non_p2p_sta_connected(hapd); - } -#endif /* CONFIG_P2P */ - - /* Start accounting here, if IEEE 802.1X and WPA are not used. - * IEEE 802.1X/WPA code will start accounting after the station has - * been authorized. */ - if (!hapd->conf->ieee802_1x && !hapd->conf->wpa) - accounting_sta_start(hapd, sta); - - /* Start IEEE 802.1X authentication process for new stations */ - ieee802_1x_new_station(hapd, sta); - if (reassoc) { - if (sta->auth_alg != WLAN_AUTH_FT && - !(sta->flags & (WLAN_STA_WPS | WLAN_STA_MAYBE_WPS))) - wpa_auth_sm_event(sta->wpa_sm, WPA_REAUTH); - } else - wpa_auth_sta_associated(hapd->wpa_auth, sta->wpa_sm); -} diff --git a/hostapd-0.8/src/ap/hostapd.h b/hostapd-0.8/src/ap/hostapd.h deleted file mode 100644 index d4501a1..0000000 --- a/hostapd-0.8/src/ap/hostapd.h +++ /dev/null @@ -1,262 +0,0 @@ -/* - * hostapd / Initialization and configuration - * Copyright (c) 2002-2009, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#ifndef HOSTAPD_H -#define HOSTAPD_H - -#include "common/defs.h" - -struct wpa_driver_ops; -struct wpa_ctrl_dst; -struct radius_server_data; -struct upnp_wps_device_sm; -struct hapd_interfaces; -struct hostapd_data; -struct sta_info; -struct hostap_sta_driver_data; -struct ieee80211_ht_capabilities; -struct full_dynamic_vlan; -enum wps_event; -union wps_event_data; - -struct hostapd_probereq_cb { - int (*cb)(void *ctx, const u8 *sa, const u8 *ie, size_t ie_len); - void *ctx; -}; - -#define HOSTAPD_RATE_BASIC 0x00000001 - -struct hostapd_rate_data { - int rate; /* rate in 100 kbps */ - int flags; /* HOSTAPD_RATE_ flags */ -}; - -struct hostapd_frame_info { - u32 channel; - u32 datarate; - u32 ssi_signal; -}; - - -/** - * struct hostapd_data - hostapd per-BSS data structure - */ -struct hostapd_data { - struct hostapd_iface *iface; - struct hostapd_config *iconf; - struct hostapd_bss_config *conf; - int interface_added; /* virtual interface added for this BSS */ - - u8 own_addr[ETH_ALEN]; - - int num_sta; /* number of entries in sta_list */ - struct sta_info *sta_list; /* STA info list head */ -#define STA_HASH_SIZE 256 -#define STA_HASH(sta) (sta[5]) - struct sta_info *sta_hash[STA_HASH_SIZE]; - - /* - * Bitfield for indicating which AIDs are allocated. Only AID values - * 1-2007 are used and as such, the bit at index 0 corresponds to AID - * 1. - */ -#define AID_WORDS ((2008 + 31) / 32) - u32 sta_aid[AID_WORDS]; - - const struct wpa_driver_ops *driver; - void *drv_priv; - - void (*new_assoc_sta_cb)(struct hostapd_data *hapd, - struct sta_info *sta, int reassoc); - - void *msg_ctx; /* ctx for wpa_msg() calls */ - - struct radius_client_data *radius; - u32 acct_session_id_hi, acct_session_id_lo; - - struct iapp_data *iapp; - - struct hostapd_cached_radius_acl *acl_cache; - struct hostapd_acl_query_data *acl_queries; - - struct wpa_authenticator *wpa_auth; - struct eapol_authenticator *eapol_auth; - - struct rsn_preauth_interface *preauth_iface; - time_t michael_mic_failure; - int michael_mic_failures; - int tkip_countermeasures; - - int ctrl_sock; - struct wpa_ctrl_dst *ctrl_dst; - - void *ssl_ctx; - void *eap_sim_db_priv; - struct radius_server_data *radius_srv; - - int parameter_set_count; - -#ifdef CONFIG_FULL_DYNAMIC_VLAN - struct full_dynamic_vlan *full_dynamic_vlan; -#endif /* CONFIG_FULL_DYNAMIC_VLAN */ - - struct l2_packet_data *l2; - struct wps_context *wps; - - struct wpabuf *wps_beacon_ie; - struct wpabuf *wps_probe_resp_ie; -#ifdef CONFIG_WPS - unsigned int ap_pin_failures; - struct upnp_wps_device_sm *wps_upnp; - unsigned int ap_pin_lockout_time; -#endif /* CONFIG_WPS */ - - struct hostapd_probereq_cb *probereq_cb; - size_t num_probereq_cb; - - void (*public_action_cb)(void *ctx, const u8 *buf, size_t len, - int freq); - void *public_action_cb_ctx; - - int (*vendor_action_cb)(void *ctx, const u8 *buf, size_t len, - int freq); - void *vendor_action_cb_ctx; - - void (*wps_reg_success_cb)(void *ctx, const u8 *mac_addr, - const u8 *uuid_e); - void *wps_reg_success_cb_ctx; - - void (*wps_event_cb)(void *ctx, enum wps_event event, - union wps_event_data *data); - void *wps_event_cb_ctx; - - void (*sta_authorized_cb)(void *ctx, const u8 *mac_addr, - int authorized); - void *sta_authorized_cb_ctx; - - void (*setup_complete_cb)(void *ctx); - void *setup_complete_cb_ctx; - -#ifdef CONFIG_P2P - struct p2p_data *p2p; - struct p2p_group *p2p_group; - struct wpabuf *p2p_beacon_ie; - struct wpabuf *p2p_probe_resp_ie; - - /* Number of non-P2P association stations */ - int num_sta_no_p2p; - - /* Periodic NoA (used only when no non-P2P clients in the group) */ - int noa_enabled; - int noa_start; - int noa_duration; -#endif /* CONFIG_P2P */ -}; - - -/** - * struct hostapd_iface - hostapd per-interface data structure - */ -struct hostapd_iface { - struct hapd_interfaces *interfaces; - void *owner; - int (*reload_config)(struct hostapd_iface *iface); - struct hostapd_config * (*config_read_cb)(const char *config_fname); - char *config_fname; - struct hostapd_config *conf; - - size_t num_bss; - struct hostapd_data **bss; - - int num_ap; /* number of entries in ap_list */ - struct ap_info *ap_list; /* AP info list head */ - struct ap_info *ap_hash[STA_HASH_SIZE]; - struct ap_info *ap_iter_list; - - unsigned int drv_flags; - struct hostapd_hw_modes *hw_features; - int num_hw_features; - struct hostapd_hw_modes *current_mode; - /* Rates that are currently used (i.e., filtered copy of - * current_mode->channels */ - int num_rates; - struct hostapd_rate_data *current_rates; - int freq; - - u16 hw_flags; - - /* Number of associated Non-ERP stations (i.e., stations using 802.11b - * in 802.11g BSS) */ - int num_sta_non_erp; - - /* Number of associated stations that do not support Short Slot Time */ - int num_sta_no_short_slot_time; - - /* Number of associated stations that do not support Short Preamble */ - int num_sta_no_short_preamble; - - int olbc; /* Overlapping Legacy BSS Condition */ - - /* Number of HT associated stations that do not support greenfield */ - int num_sta_ht_no_gf; - - /* Number of associated non-HT stations */ - int num_sta_no_ht; - - /* Number of HT associated stations 20 MHz */ - int num_sta_ht_20mhz; - - /* Overlapping BSS information */ - int olbc_ht; - - u16 ht_op_mode; - void (*scan_cb)(struct hostapd_iface *iface); - - int (*ctrl_iface_init)(struct hostapd_data *hapd); - void (*ctrl_iface_deinit)(struct hostapd_data *hapd); - - int (*for_each_interface)(struct hapd_interfaces *interfaces, - int (*cb)(struct hostapd_iface *iface, - void *ctx), void *ctx); -}; - -/* hostapd.c */ -int hostapd_reload_config(struct hostapd_iface *iface); -struct hostapd_data * -hostapd_alloc_bss_data(struct hostapd_iface *hapd_iface, - struct hostapd_config *conf, - struct hostapd_bss_config *bss); -int hostapd_setup_interface(struct hostapd_iface *iface); -int hostapd_setup_interface_complete(struct hostapd_iface *iface, int err); -void hostapd_interface_deinit(struct hostapd_iface *iface); -void hostapd_interface_free(struct hostapd_iface *iface); -void hostapd_new_assoc_sta(struct hostapd_data *hapd, struct sta_info *sta, - int reassoc); - -/* utils.c */ -int hostapd_register_probereq_cb(struct hostapd_data *hapd, - int (*cb)(void *ctx, const u8 *sa, - const u8 *ie, size_t ie_len), - void *ctx); -void hostapd_prune_associations(struct hostapd_data *hapd, const u8 *addr); - -/* drv_callbacks.c (TODO: move to somewhere else?) */ -int hostapd_notif_assoc(struct hostapd_data *hapd, const u8 *addr, - const u8 *ie, size_t ielen, int reassoc); -void hostapd_notif_disassoc(struct hostapd_data *hapd, const u8 *addr); -void hostapd_event_sta_low_ack(struct hostapd_data *hapd, const u8 *addr); -int hostapd_probe_req_rx(struct hostapd_data *hapd, const u8 *sa, - const u8 *ie, size_t ie_len); - -#endif /* HOSTAPD_H */ diff --git a/hostapd-0.8/src/ap/hw_features.c b/hostapd-0.8/src/ap/hw_features.c deleted file mode 100644 index 30af9d2..0000000 --- a/hostapd-0.8/src/ap/hw_features.c +++ /dev/null @@ -1,754 +0,0 @@ -/* - * hostapd / Hardware feature query and different modes - * Copyright 2002-2003, Instant802 Networks, Inc. - * Copyright 2005-2006, Devicescape Software, Inc. - * Copyright (c) 2008-2009, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#include "utils/includes.h" - -#include "utils/common.h" -#include "utils/eloop.h" -#include "common/ieee802_11_defs.h" -#include "common/ieee802_11_common.h" -#include "drivers/driver.h" -#include "hostapd.h" -#include "ap_config.h" -#include "ap_drv_ops.h" -#include "hw_features.h" - - -void hostapd_free_hw_features(struct hostapd_hw_modes *hw_features, - size_t num_hw_features) -{ - size_t i; - - if (hw_features == NULL) - return; - - for (i = 0; i < num_hw_features; i++) { - os_free(hw_features[i].channels); - os_free(hw_features[i].rates); - } - - os_free(hw_features); -} - - -int hostapd_get_hw_features(struct hostapd_iface *iface) -{ - struct hostapd_data *hapd = iface->bss[0]; - int ret = 0, i, j; - u16 num_modes, flags; - struct hostapd_hw_modes *modes; - - if (hostapd_drv_none(hapd)) - return -1; - modes = hostapd_get_hw_feature_data(hapd, &num_modes, &flags); - if (modes == NULL) { - hostapd_logger(hapd, NULL, HOSTAPD_MODULE_IEEE80211, - HOSTAPD_LEVEL_DEBUG, - "Fetching hardware channel/rate support not " - "supported."); - return -1; - } - - iface->hw_flags = flags; - - hostapd_free_hw_features(iface->hw_features, iface->num_hw_features); - iface->hw_features = modes; - iface->num_hw_features = num_modes; - - for (i = 0; i < num_modes; i++) { - struct hostapd_hw_modes *feature = &modes[i]; - /* set flag for channels we can use in current regulatory - * domain */ - for (j = 0; j < feature->num_channels; j++) { - /* - * Disable all channels that are marked not to allow - * IBSS operation or active scanning. In addition, - * disable all channels that require radar detection, - * since that (in addition to full DFS) is not yet - * supported. - */ - if (feature->channels[j].flag & - (HOSTAPD_CHAN_NO_IBSS | - HOSTAPD_CHAN_PASSIVE_SCAN | - HOSTAPD_CHAN_RADAR)) - feature->channels[j].flag |= - HOSTAPD_CHAN_DISABLED; - if (feature->channels[j].flag & HOSTAPD_CHAN_DISABLED) - continue; - wpa_printf(MSG_MSGDUMP, "Allowed channel: mode=%d " - "chan=%d freq=%d MHz max_tx_power=%d dBm", - feature->mode, - feature->channels[j].chan, - feature->channels[j].freq, - feature->channels[j].max_tx_power); - } - } - - return ret; -} - - -int hostapd_prepare_rates(struct hostapd_data *hapd, - struct hostapd_hw_modes *mode) -{ - int i, num_basic_rates = 0; - int basic_rates_a[] = { 60, 120, 240, -1 }; - int basic_rates_b[] = { 10, 20, -1 }; - int basic_rates_g[] = { 10, 20, 55, 110, -1 }; - int *basic_rates; - - if (hapd->iconf->basic_rates) - basic_rates = hapd->iconf->basic_rates; - else switch (mode->mode) { - case HOSTAPD_MODE_IEEE80211A: - basic_rates = basic_rates_a; - break; - case HOSTAPD_MODE_IEEE80211B: - basic_rates = basic_rates_b; - break; - case HOSTAPD_MODE_IEEE80211G: - basic_rates = basic_rates_g; - break; - default: - return -1; - } - - if (hostapd_set_rate_sets(hapd, hapd->iconf->supported_rates, - basic_rates, mode->mode)) { - wpa_printf(MSG_ERROR, "Failed to update rate sets in kernel " - "module"); - } - - os_free(hapd->iface->current_rates); - hapd->iface->num_rates = 0; - - hapd->iface->current_rates = - os_zalloc(mode->num_rates * sizeof(struct hostapd_rate_data)); - if (!hapd->iface->current_rates) { - wpa_printf(MSG_ERROR, "Failed to allocate memory for rate " - "table."); - return -1; - } - - for (i = 0; i < mode->num_rates; i++) { - struct hostapd_rate_data *rate; - - if (hapd->iconf->supported_rates && - !hostapd_rate_found(hapd->iconf->supported_rates, - mode->rates[i])) - continue; - - rate = &hapd->iface->current_rates[hapd->iface->num_rates]; - rate->rate = mode->rates[i]; - if (hostapd_rate_found(basic_rates, rate->rate)) { - rate->flags |= HOSTAPD_RATE_BASIC; - num_basic_rates++; - } - wpa_printf(MSG_DEBUG, "RATE[%d] rate=%d flags=0x%x", - hapd->iface->num_rates, rate->rate, rate->flags); - hapd->iface->num_rates++; - } - - if ((hapd->iface->num_rates == 0 || num_basic_rates == 0) && - (!hapd->iconf->ieee80211n || !hapd->iconf->require_ht)) { - wpa_printf(MSG_ERROR, "No rates remaining in supported/basic " - "rate sets (%d,%d).", - hapd->iface->num_rates, num_basic_rates); - return -1; - } - - return 0; -} - - -#ifdef CONFIG_IEEE80211N -static int ieee80211n_allowed_ht40_channel_pair(struct hostapd_iface *iface) -{ - int sec_chan, ok, j, first; - int allowed[] = { 36, 44, 52, 60, 100, 108, 116, 124, 132, 149, 157, - 184, 192 }; - size_t k; - - if (!iface->conf->secondary_channel) - return 1; /* HT40 not used */ - - sec_chan = iface->conf->channel + iface->conf->secondary_channel * 4; - wpa_printf(MSG_DEBUG, "HT40: control channel: %d " - "secondary channel: %d", - iface->conf->channel, sec_chan); - - /* Verify that HT40 secondary channel is an allowed 20 MHz - * channel */ - ok = 0; - for (j = 0; j < iface->current_mode->num_channels; j++) { - struct hostapd_channel_data *chan = - &iface->current_mode->channels[j]; - if (!(chan->flag & HOSTAPD_CHAN_DISABLED) && - chan->chan == sec_chan) { - ok = 1; - break; - } - } - if (!ok) { - wpa_printf(MSG_ERROR, "HT40 secondary channel %d not allowed", - sec_chan); - return 0; - } - - /* - * Verify that HT40 primary,secondary channel pair is allowed per - * IEEE 802.11n Annex J. This is only needed for 5 GHz band since - * 2.4 GHz rules allow all cases where the secondary channel fits into - * the list of allowed channels (already checked above). - */ - if (iface->current_mode->mode != HOSTAPD_MODE_IEEE80211A) - return 1; - - if (iface->conf->secondary_channel > 0) - first = iface->conf->channel; - else - first = sec_chan; - - ok = 0; - for (k = 0; k < sizeof(allowed) / sizeof(allowed[0]); k++) { - if (first == allowed[k]) { - ok = 1; - break; - } - } - if (!ok) { - wpa_printf(MSG_ERROR, "HT40 channel pair (%d, %d) not allowed", - iface->conf->channel, - iface->conf->secondary_channel); - return 0; - } - - return 1; -} - - -static void ieee80211n_switch_pri_sec(struct hostapd_iface *iface) -{ - if (iface->conf->secondary_channel > 0) { - iface->conf->channel += 4; - iface->conf->secondary_channel = -1; - } else { - iface->conf->channel -= 4; - iface->conf->secondary_channel = 1; - } -} - - -static void ieee80211n_get_pri_sec_chan(struct wpa_scan_res *bss, - int *pri_chan, int *sec_chan) -{ - struct ieee80211_ht_operation *oper; - struct ieee802_11_elems elems; - - *pri_chan = *sec_chan = 0; - - ieee802_11_parse_elems((u8 *) (bss + 1), bss->ie_len, &elems, 0); - if (elems.ht_operation && - elems.ht_operation_len >= sizeof(*oper)) { - oper = (struct ieee80211_ht_operation *) elems.ht_operation; - *pri_chan = oper->control_chan; - if (oper->ht_param & HT_INFO_HT_PARAM_REC_TRANS_CHNL_WIDTH) { - int sec = oper->ht_param & - HT_INFO_HT_PARAM_SECONDARY_CHNL_OFF_MASK; - if (sec == HT_INFO_HT_PARAM_SECONDARY_CHNL_ABOVE) - *sec_chan = *pri_chan + 4; - else if (sec == HT_INFO_HT_PARAM_SECONDARY_CHNL_BELOW) - *sec_chan = *pri_chan - 4; - } - } -} - - -static int ieee80211n_check_40mhz_5g(struct hostapd_iface *iface, - struct wpa_scan_results *scan_res) -{ - int pri_chan, sec_chan, pri_freq, sec_freq, pri_bss, sec_bss; - int bss_pri_chan, bss_sec_chan; - size_t i; - int match; - - pri_chan = iface->conf->channel; - sec_chan = iface->conf->secondary_channel * 4; - pri_freq = hostapd_hw_get_freq(iface->bss[0], pri_chan); - if (iface->conf->secondary_channel > 0) - sec_freq = pri_freq + 20; - else - sec_freq = pri_freq - 20; - - /* - * Switch PRI/SEC channels if Beacons were detected on selected SEC - * channel, but not on selected PRI channel. - */ - pri_bss = sec_bss = 0; - for (i = 0; i < scan_res->num; i++) { - struct wpa_scan_res *bss = scan_res->res[i]; - if (bss->freq == pri_freq) - pri_bss++; - else if (bss->freq == sec_freq) - sec_bss++; - } - if (sec_bss && !pri_bss) { - wpa_printf(MSG_INFO, "Switch own primary and secondary " - "channel to get secondary channel with no Beacons " - "from other BSSes"); - ieee80211n_switch_pri_sec(iface); - } - - /* - * Match PRI/SEC channel with any existing HT40 BSS on the same - * channels that we are about to use (if already mixed order in - * existing BSSes, use own preference). - */ - match = 0; - for (i = 0; i < scan_res->num; i++) { - struct wpa_scan_res *bss = scan_res->res[i]; - ieee80211n_get_pri_sec_chan(bss, &bss_pri_chan, &bss_sec_chan); - if (pri_chan == bss_pri_chan && - sec_chan == bss_sec_chan) { - match = 1; - break; - } - } - if (!match) { - for (i = 0; i < scan_res->num; i++) { - struct wpa_scan_res *bss = scan_res->res[i]; - ieee80211n_get_pri_sec_chan(bss, &bss_pri_chan, - &bss_sec_chan); - if (pri_chan == bss_sec_chan && - sec_chan == bss_pri_chan) { - wpa_printf(MSG_INFO, "Switch own primary and " - "secondary channel due to BSS " - "overlap with " MACSTR, - MAC2STR(bss->bssid)); - ieee80211n_switch_pri_sec(iface); - break; - } - } - } - - return 1; -} - - -static int ieee80211n_check_40mhz_2g4(struct hostapd_iface *iface, - struct wpa_scan_results *scan_res) -{ - int pri_freq, sec_freq; - int affected_start, affected_end; - size_t i; - - pri_freq = hostapd_hw_get_freq(iface->bss[0], iface->conf->channel); - if (iface->conf->secondary_channel > 0) - sec_freq = pri_freq + 20; - else - sec_freq = pri_freq - 20; - affected_start = (pri_freq + sec_freq) / 2 - 25; - affected_end = (pri_freq + sec_freq) / 2 + 25; - wpa_printf(MSG_DEBUG, "40 MHz affected channel range: [%d,%d] MHz", - affected_start, affected_end); - for (i = 0; i < scan_res->num; i++) { - struct wpa_scan_res *bss = scan_res->res[i]; - int pri = bss->freq; - int sec = pri; - int sec_chan, pri_chan; - - ieee80211n_get_pri_sec_chan(bss, &pri_chan, &sec_chan); - - if (sec_chan) { - if (sec_chan < pri_chan) - sec = pri - 20; - else - sec = pri + 20; - } - - if ((pri < affected_start || pri > affected_end) && - (sec < affected_start || sec > affected_end)) - continue; /* not within affected channel range */ - - wpa_printf(MSG_DEBUG, "Neighboring BSS: " MACSTR - " freq=%d pri=%d sec=%d", - MAC2STR(bss->bssid), bss->freq, pri_chan, sec_chan); - - if (sec_chan) { - if (pri_freq != pri || sec_freq != sec) { - wpa_printf(MSG_DEBUG, "40 MHz pri/sec " - "mismatch with BSS " MACSTR - " <%d,%d> (chan=%d%c) vs. <%d,%d>", - MAC2STR(bss->bssid), - pri, sec, pri_chan, - sec > pri ? '+' : '-', - pri_freq, sec_freq); - return 0; - } - } - - /* TODO: 40 MHz intolerant */ - } - - return 1; -} - - -static void wpa_scan_results_free(struct wpa_scan_results *res) -{ - size_t i; - - if (res == NULL) - return; - - for (i = 0; i < res->num; i++) - os_free(res->res[i]); - os_free(res->res); - os_free(res); -} - - -static void ieee80211n_check_scan(struct hostapd_iface *iface) -{ - struct wpa_scan_results *scan_res; - int oper40; - int res; - - /* Check list of neighboring BSSes (from scan) to see whether 40 MHz is - * allowed per IEEE 802.11n/D7.0, 11.14.3.2 */ - - iface->scan_cb = NULL; - - scan_res = hostapd_driver_get_scan_results(iface->bss[0]); - if (scan_res == NULL) { - hostapd_setup_interface_complete(iface, 1); - return; - } - - if (iface->current_mode->mode == HOSTAPD_MODE_IEEE80211A) - oper40 = ieee80211n_check_40mhz_5g(iface, scan_res); - else - oper40 = ieee80211n_check_40mhz_2g4(iface, scan_res); - wpa_scan_results_free(scan_res); - - if (!oper40) { - wpa_printf(MSG_INFO, "20/40 MHz operation not permitted on " - "channel pri=%d sec=%d based on overlapping BSSes", - iface->conf->channel, - iface->conf->channel + - iface->conf->secondary_channel * 4); - iface->conf->secondary_channel = 0; - iface->conf->ht_capab &= ~HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET; - } - - res = ieee80211n_allowed_ht40_channel_pair(iface); - hostapd_setup_interface_complete(iface, !res); -} - - -static int ieee80211n_check_40mhz(struct hostapd_iface *iface) -{ - struct wpa_driver_scan_params params; - - if (!iface->conf->secondary_channel) - return 0; /* HT40 not used */ - - wpa_printf(MSG_DEBUG, "Scan for neighboring BSSes prior to enabling " - "40 MHz channel"); - os_memset(¶ms, 0, sizeof(params)); - /* TODO: scan only the needed frequency */ - if (hostapd_driver_scan(iface->bss[0], ¶ms) < 0) { - wpa_printf(MSG_ERROR, "Failed to request a scan of " - "neighboring BSSes"); - - //DRIVER_RTW Modify - //return -1; - return 0;//ignore this error - } - - iface->scan_cb = ieee80211n_check_scan; - return 1; -} - - -static int ieee80211n_supported_ht_capab(struct hostapd_iface *iface) -{ - u16 hw = iface->current_mode->ht_capab; - u16 conf = iface->conf->ht_capab; - - if ((conf & HT_CAP_INFO_LDPC_CODING_CAP) && - !(hw & HT_CAP_INFO_LDPC_CODING_CAP)) { - wpa_printf(MSG_ERROR, "Driver does not support configured " - "HT capability [LDPC]"); - return 0; - } - - if ((conf & HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET) && - !(hw & HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET)) { - wpa_printf(MSG_ERROR, "Driver does not support configured " - "HT capability [HT40*]"); - return 0; - } - - if ((conf & HT_CAP_INFO_SMPS_MASK) != (hw & HT_CAP_INFO_SMPS_MASK) && - (conf & HT_CAP_INFO_SMPS_MASK) != HT_CAP_INFO_SMPS_DISABLED) { - wpa_printf(MSG_ERROR, "Driver does not support configured " - "HT capability [SMPS-*]"); - return 0; - } - - if ((conf & HT_CAP_INFO_GREEN_FIELD) && - !(hw & HT_CAP_INFO_GREEN_FIELD)) { - wpa_printf(MSG_ERROR, "Driver does not support configured " - "HT capability [GF]"); - return 0; - } - - if ((conf & HT_CAP_INFO_SHORT_GI20MHZ) && - !(hw & HT_CAP_INFO_SHORT_GI20MHZ)) { - wpa_printf(MSG_ERROR, "Driver does not support configured " - "HT capability [SHORT-GI-20]"); - return 0; - } - - if ((conf & HT_CAP_INFO_SHORT_GI40MHZ) && - !(hw & HT_CAP_INFO_SHORT_GI40MHZ)) { - wpa_printf(MSG_ERROR, "Driver does not support configured " - "HT capability [SHORT-GI-40]"); - return 0; - } - - if ((conf & HT_CAP_INFO_TX_STBC) && !(hw & HT_CAP_INFO_TX_STBC)) { - wpa_printf(MSG_ERROR, "Driver does not support configured " - "HT capability [TX-STBC]"); - return 0; - } - - if ((conf & HT_CAP_INFO_RX_STBC_MASK) > - (hw & HT_CAP_INFO_RX_STBC_MASK)) { - wpa_printf(MSG_ERROR, "Driver does not support configured " - "HT capability [RX-STBC*]"); - return 0; - } - - if ((conf & HT_CAP_INFO_DELAYED_BA) && - !(hw & HT_CAP_INFO_DELAYED_BA)) { - wpa_printf(MSG_ERROR, "Driver does not support configured " - "HT capability [DELAYED-BA]"); - return 0; - } - - if ((conf & HT_CAP_INFO_MAX_AMSDU_SIZE) && - !(hw & HT_CAP_INFO_MAX_AMSDU_SIZE)) { - wpa_printf(MSG_ERROR, "Driver does not support configured " - "HT capability [MAX-AMSDU-7935]"); - return 0; - } - - if ((conf & HT_CAP_INFO_DSSS_CCK40MHZ) && - !(hw & HT_CAP_INFO_DSSS_CCK40MHZ)) { - wpa_printf(MSG_ERROR, "Driver does not support configured " - "HT capability [DSSS_CCK-40]"); - return 0; - } - - if ((conf & HT_CAP_INFO_PSMP_SUPP) && !(hw & HT_CAP_INFO_PSMP_SUPP)) { - wpa_printf(MSG_ERROR, "Driver does not support configured " - "HT capability [PSMP]"); - return 0; - } - - if ((conf & HT_CAP_INFO_LSIG_TXOP_PROTECT_SUPPORT) && - !(hw & HT_CAP_INFO_LSIG_TXOP_PROTECT_SUPPORT)) { - wpa_printf(MSG_ERROR, "Driver does not support configured " - "HT capability [LSIG-TXOP-PROT]"); - return 0; - } - - return 1; -} - -#endif /* CONFIG_IEEE80211N */ - - -int hostapd_check_ht_capab(struct hostapd_iface *iface) -{ -#ifdef CONFIG_IEEE80211N - int ret; - if (!iface->conf->ieee80211n) - return 0; - if (!ieee80211n_supported_ht_capab(iface)) - return -1; - ret = ieee80211n_check_40mhz(iface); - if (ret) - return ret; - if (!ieee80211n_allowed_ht40_channel_pair(iface)) - return -1; -#endif /* CONFIG_IEEE80211N */ - - return 0; -} - - -/** - * hostapd_select_hw_mode - Select the hardware mode - * @iface: Pointer to interface data. - * Returns: 0 on success, -1 on failure - * - * Sets up the hardware mode, channel, rates, and passive scanning - * based on the configuration. - */ -int hostapd_select_hw_mode(struct hostapd_iface *iface) -{ - int i, j, ok; - - if (iface->num_hw_features < 1) - return -1; - - iface->current_mode = NULL; - for (i = 0; i < iface->num_hw_features; i++) { - struct hostapd_hw_modes *mode = &iface->hw_features[i]; - if (mode->mode == iface->conf->hw_mode) { - iface->current_mode = mode; - break; - } - } - - if (iface->current_mode == NULL) { - wpa_printf(MSG_ERROR, "Hardware does not support configured " - "mode"); - hostapd_logger(iface->bss[0], NULL, HOSTAPD_MODULE_IEEE80211, - HOSTAPD_LEVEL_WARNING, - "Hardware does not support configured mode " - "(%d)", (int) iface->conf->hw_mode); - return -1; - } - - ok = 0; - for (j = 0; j < iface->current_mode->num_channels; j++) { - struct hostapd_channel_data *chan = - &iface->current_mode->channels[j]; - if (!(chan->flag & HOSTAPD_CHAN_DISABLED) && - (chan->chan == iface->conf->channel)) { - ok = 1; - break; - } - } - if (ok && iface->conf->secondary_channel) { - int sec_ok = 0; - int sec_chan = iface->conf->channel + - iface->conf->secondary_channel * 4; - for (j = 0; j < iface->current_mode->num_channels; j++) { - struct hostapd_channel_data *chan = - &iface->current_mode->channels[j]; - if (!(chan->flag & HOSTAPD_CHAN_DISABLED) && - (chan->chan == sec_chan)) { - sec_ok = 1; - break; - } - } - if (!sec_ok) { - hostapd_logger(iface->bss[0], NULL, - HOSTAPD_MODULE_IEEE80211, - HOSTAPD_LEVEL_WARNING, - "Configured HT40 secondary channel " - "(%d) not found from the channel list " - "of current mode (%d) %s", - sec_chan, iface->current_mode->mode, - hostapd_hw_mode_txt( - iface->current_mode->mode)); - ok = 0; - } - } - if (iface->conf->channel == 0) { - /* TODO: could request a scan of neighboring BSSes and select - * the channel automatically */ - wpa_printf(MSG_ERROR, "Channel not configured " - "(hw_mode/channel in hostapd.conf)"); - return -1; - } - if (ok == 0 && iface->conf->channel != 0) { - hostapd_logger(iface->bss[0], NULL, - HOSTAPD_MODULE_IEEE80211, - HOSTAPD_LEVEL_WARNING, - "Configured channel (%d) not found from the " - "channel list of current mode (%d) %s", - iface->conf->channel, - iface->current_mode->mode, - hostapd_hw_mode_txt(iface->current_mode->mode)); - iface->current_mode = NULL; - } - - if (iface->current_mode == NULL) { - hostapd_logger(iface->bss[0], NULL, HOSTAPD_MODULE_IEEE80211, - HOSTAPD_LEVEL_WARNING, - "Hardware does not support configured channel"); - return -1; - } - - return 0; -} - - -const char * hostapd_hw_mode_txt(int mode) -{ - switch (mode) { - case HOSTAPD_MODE_IEEE80211A: - return "IEEE 802.11a"; - case HOSTAPD_MODE_IEEE80211B: - return "IEEE 802.11b"; - case HOSTAPD_MODE_IEEE80211G: - return "IEEE 802.11g"; - default: - return "UNKNOWN"; - } -} - - -int hostapd_hw_get_freq(struct hostapd_data *hapd, int chan) -{ - int i; - - if (!hapd->iface->current_mode) - return 0; - - for (i = 0; i < hapd->iface->current_mode->num_channels; i++) { - struct hostapd_channel_data *ch = - &hapd->iface->current_mode->channels[i]; - if (ch->chan == chan) - return ch->freq; - } - - return 0; -} - - -int hostapd_hw_get_channel(struct hostapd_data *hapd, int freq) -{ - int i; - - if (!hapd->iface->current_mode) - return 0; - - for (i = 0; i < hapd->iface->current_mode->num_channels; i++) { - struct hostapd_channel_data *ch = - &hapd->iface->current_mode->channels[i]; - if (ch->freq == freq) - return ch->chan; - } - - return 0; -} diff --git a/hostapd-0.8/src/ap/hw_features.h b/hostapd-0.8/src/ap/hw_features.h deleted file mode 100644 index 88c2322..0000000 --- a/hostapd-0.8/src/ap/hw_features.h +++ /dev/null @@ -1,70 +0,0 @@ -/* - * hostapd / Hardware feature query and different modes - * Copyright 2002-2003, Instant802 Networks, Inc. - * Copyright 2005-2006, Devicescape Software, Inc. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#ifndef HW_FEATURES_H -#define HW_FEATURES_H - -#ifdef NEED_AP_MLME -void hostapd_free_hw_features(struct hostapd_hw_modes *hw_features, - size_t num_hw_features); -int hostapd_get_hw_features(struct hostapd_iface *iface); -int hostapd_select_hw_mode(struct hostapd_iface *iface); -const char * hostapd_hw_mode_txt(int mode); -int hostapd_hw_get_freq(struct hostapd_data *hapd, int chan); -int hostapd_hw_get_channel(struct hostapd_data *hapd, int freq); -int hostapd_check_ht_capab(struct hostapd_iface *iface); -int hostapd_prepare_rates(struct hostapd_data *hapd, - struct hostapd_hw_modes *mode); -#else /* NEED_AP_MLME */ -static inline void -hostapd_free_hw_features(struct hostapd_hw_modes *hw_features, - size_t num_hw_features) -{ -} - -static inline int hostapd_get_hw_features(struct hostapd_iface *iface) -{ - return -1; -} - -static inline int hostapd_select_hw_mode(struct hostapd_iface *iface) -{ - return -1; -} - -static inline const char * hostapd_hw_mode_txt(int mode) -{ - return NULL; -} - -static inline int hostapd_hw_get_freq(struct hostapd_data *hapd, int chan) -{ - return -1; -} - -static inline int hostapd_check_ht_capab(struct hostapd_iface *iface) -{ - return 0; -} - -static inline int hostapd_prepare_rates(struct hostapd_data *hapd, - struct hostapd_hw_modes *mode) -{ - return 0; -} - -#endif /* NEED_AP_MLME */ - -#endif /* HW_FEATURES_H */ diff --git a/hostapd-0.8/src/ap/iapp.c b/hostapd-0.8/src/ap/iapp.c deleted file mode 100644 index 115d91e..0000000 --- a/hostapd-0.8/src/ap/iapp.c +++ /dev/null @@ -1,535 +0,0 @@ -/* - * hostapd / IEEE 802.11F-2003 Inter-Access Point Protocol (IAPP) - * Copyright (c) 2002-2007, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - * - * Note: IEEE 802.11F-2003 was a experimental use specification. It has expired - * and IEEE has withdrawn it. In other words, it is likely better to look at - * using some other mechanism for AP-to-AP communication than extending the - * implementation here. - */ - -/* TODO: - * Level 1: no administrative or security support - * (e.g., static BSSID to IP address mapping in each AP) - * Level 2: support for dynamic mapping of BSSID to IP address - * Level 3: support for encryption and authentication of IAPP messages - * - add support for MOVE-notify and MOVE-response (this requires support for - * finding out IP address for previous AP using RADIUS) - * - add support for Send- and ACK-Security-Block to speedup IEEE 802.1X during - * reassociation to another AP - * - implement counters etc. for IAPP MIB - * - verify endianness of fields in IAPP messages; are they big-endian as - * used here? - * - RADIUS connection for AP registration and BSSID to IP address mapping - * - TCP connection for IAPP MOVE, CACHE - * - broadcast ESP for IAPP ADD-notify - * - ESP for IAPP MOVE messages - * - security block sending/processing - * - IEEE 802.11 context transfer - */ - -#include "utils/includes.h" -#include -#include -#ifdef USE_KERNEL_HEADERS -#include -#else /* USE_KERNEL_HEADERS */ -#include -#endif /* USE_KERNEL_HEADERS */ - -#include "utils/common.h" -#include "utils/eloop.h" -#include "common/ieee802_11_defs.h" -#include "hostapd.h" -#include "ap_config.h" -#include "ieee802_11.h" -#include "sta_info.h" -#include "iapp.h" - - -#define IAPP_MULTICAST "224.0.1.178" -#define IAPP_UDP_PORT 3517 -#define IAPP_TCP_PORT 3517 - -struct iapp_hdr { - u8 version; - u8 command; - be16 identifier; - be16 length; - /* followed by length-6 octets of data */ -} __attribute__ ((packed)); - -#define IAPP_VERSION 0 - -enum IAPP_COMMAND { - IAPP_CMD_ADD_notify = 0, - IAPP_CMD_MOVE_notify = 1, - IAPP_CMD_MOVE_response = 2, - IAPP_CMD_Send_Security_Block = 3, - IAPP_CMD_ACK_Security_Block = 4, - IAPP_CMD_CACHE_notify = 5, - IAPP_CMD_CACHE_response = 6, -}; - - -/* ADD-notify - multicast UDP on the local LAN */ -struct iapp_add_notify { - u8 addr_len; /* ETH_ALEN */ - u8 reserved; - u8 mac_addr[ETH_ALEN]; - be16 seq_num; -} __attribute__ ((packed)); - - -/* Layer 2 Update frame (802.2 Type 1 LLC XID Update response) */ -struct iapp_layer2_update { - u8 da[ETH_ALEN]; /* broadcast */ - u8 sa[ETH_ALEN]; /* STA addr */ - be16 len; /* 6 */ - u8 dsap; /* null DSAP address */ - u8 ssap; /* null SSAP address, CR=Response */ - u8 control; - u8 xid_info[3]; -} __attribute__ ((packed)); - - -/* MOVE-notify - unicast TCP */ -struct iapp_move_notify { - u8 addr_len; /* ETH_ALEN */ - u8 reserved; - u8 mac_addr[ETH_ALEN]; - u16 seq_num; - u16 ctx_block_len; - /* followed by ctx_block_len bytes */ -} __attribute__ ((packed)); - - -/* MOVE-response - unicast TCP */ -struct iapp_move_response { - u8 addr_len; /* ETH_ALEN */ - u8 status; - u8 mac_addr[ETH_ALEN]; - u16 seq_num; - u16 ctx_block_len; - /* followed by ctx_block_len bytes */ -} __attribute__ ((packed)); - -enum { - IAPP_MOVE_SUCCESSFUL = 0, - IAPP_MOVE_DENIED = 1, - IAPP_MOVE_STALE_MOVE = 2, -}; - - -/* CACHE-notify */ -struct iapp_cache_notify { - u8 addr_len; /* ETH_ALEN */ - u8 reserved; - u8 mac_addr[ETH_ALEN]; - u16 seq_num; - u8 current_ap[ETH_ALEN]; - u16 ctx_block_len; - /* ctx_block_len bytes of context block followed by 16-bit context - * timeout */ -} __attribute__ ((packed)); - - -/* CACHE-response - unicast TCP */ -struct iapp_cache_response { - u8 addr_len; /* ETH_ALEN */ - u8 status; - u8 mac_addr[ETH_ALEN]; - u16 seq_num; -} __attribute__ ((packed)); - -enum { - IAPP_CACHE_SUCCESSFUL = 0, - IAPP_CACHE_STALE_CACHE = 1, -}; - - -/* Send-Security-Block - unicast TCP */ -struct iapp_send_security_block { - u8 iv[8]; - u16 sec_block_len; - /* followed by sec_block_len bytes of security block */ -} __attribute__ ((packed)); - - -/* ACK-Security-Block - unicast TCP */ -struct iapp_ack_security_block { - u8 iv[8]; - u8 new_ap_ack_authenticator[48]; -} __attribute__ ((packed)); - - -struct iapp_data { - struct hostapd_data *hapd; - u16 identifier; /* next IAPP identifier */ - struct in_addr own, multicast; - int udp_sock; - int packet_sock; -}; - - -static void iapp_send_add(struct iapp_data *iapp, u8 *mac_addr, u16 seq_num) -{ - char buf[128]; - struct iapp_hdr *hdr; - struct iapp_add_notify *add; - struct sockaddr_in addr; - - /* Send IAPP ADD-notify to remove possible association from other APs - */ - - hdr = (struct iapp_hdr *) buf; - hdr->version = IAPP_VERSION; - hdr->command = IAPP_CMD_ADD_notify; - hdr->identifier = host_to_be16(iapp->identifier++); - hdr->length = host_to_be16(sizeof(*hdr) + sizeof(*add)); - - add = (struct iapp_add_notify *) (hdr + 1); - add->addr_len = ETH_ALEN; - add->reserved = 0; - os_memcpy(add->mac_addr, mac_addr, ETH_ALEN); - - add->seq_num = host_to_be16(seq_num); - - os_memset(&addr, 0, sizeof(addr)); - addr.sin_family = AF_INET; - addr.sin_addr.s_addr = iapp->multicast.s_addr; - addr.sin_port = htons(IAPP_UDP_PORT); - if (sendto(iapp->udp_sock, buf, (char *) (add + 1) - buf, 0, - (struct sockaddr *) &addr, sizeof(addr)) < 0) - perror("sendto[IAPP-ADD]"); -} - - -static void iapp_send_layer2_update(struct iapp_data *iapp, u8 *addr) -{ - struct iapp_layer2_update msg; - - /* Send Level 2 Update Frame to update forwarding tables in layer 2 - * bridge devices */ - - /* 802.2 Type 1 Logical Link Control (LLC) Exchange Identifier (XID) - * Update response frame; IEEE Std 802.2-1998, 5.4.1.2.1 */ - - os_memset(msg.da, 0xff, ETH_ALEN); - os_memcpy(msg.sa, addr, ETH_ALEN); - msg.len = host_to_be16(6); - msg.dsap = 0; /* NULL DSAP address */ - msg.ssap = 0x01; /* NULL SSAP address, CR Bit: Response */ - msg.control = 0xaf; /* XID response lsb.1111F101. - * F=0 (no poll command; unsolicited frame) */ - msg.xid_info[0] = 0x81; /* XID format identifier */ - msg.xid_info[1] = 1; /* LLC types/classes: Type 1 LLC */ - msg.xid_info[2] = 1 << 1; /* XID sender's receive window size (RW) - * FIX: what is correct RW with 802.11? */ - - if (send(iapp->packet_sock, &msg, sizeof(msg), 0) < 0) - perror("send[L2 Update]"); -} - - -/** - * iapp_new_station - IAPP processing for a new STA - * @iapp: IAPP data - * @sta: The associated station - */ -void iapp_new_station(struct iapp_data *iapp, struct sta_info *sta) -{ - struct ieee80211_mgmt *assoc; - u16 seq; - - if (iapp == NULL) - return; - - assoc = sta->last_assoc_req; - seq = assoc ? WLAN_GET_SEQ_SEQ(le_to_host16(assoc->seq_ctrl)) : 0; - - /* IAPP-ADD.request(MAC Address, Sequence Number, Timeout) */ - hostapd_logger(iapp->hapd, sta->addr, HOSTAPD_MODULE_IAPP, - HOSTAPD_LEVEL_DEBUG, "IAPP-ADD.request(seq=%d)", seq); - iapp_send_layer2_update(iapp, sta->addr); - iapp_send_add(iapp, sta->addr, seq); - - if (assoc && WLAN_FC_GET_STYPE(le_to_host16(assoc->frame_control)) == - WLAN_FC_STYPE_REASSOC_REQ) { - /* IAPP-MOVE.request(MAC Address, Sequence Number, Old AP, - * Context Block, Timeout) - */ - /* TODO: Send IAPP-MOVE to the old AP; Map Old AP BSSID to - * IP address */ - } -} - - -static void iapp_process_add_notify(struct iapp_data *iapp, - struct sockaddr_in *from, - struct iapp_hdr *hdr, int len) -{ - struct iapp_add_notify *add = (struct iapp_add_notify *) (hdr + 1); - struct sta_info *sta; - - if (len != sizeof(*add)) { - printf("Invalid IAPP-ADD packet length %d (expected %lu)\n", - len, (unsigned long) sizeof(*add)); - return; - } - - sta = ap_get_sta(iapp->hapd, add->mac_addr); - - /* IAPP-ADD.indication(MAC Address, Sequence Number) */ - hostapd_logger(iapp->hapd, add->mac_addr, HOSTAPD_MODULE_IAPP, - HOSTAPD_LEVEL_INFO, - "Received IAPP ADD-notify (seq# %d) from %s:%d%s", - be_to_host16(add->seq_num), - inet_ntoa(from->sin_addr), ntohs(from->sin_port), - sta ? "" : " (STA not found)"); - - if (!sta) - return; - - /* TODO: could use seq_num to try to determine whether last association - * to this AP is newer than the one advertised in IAPP-ADD. Although, - * this is not really a reliable verification. */ - - hostapd_logger(iapp->hapd, add->mac_addr, HOSTAPD_MODULE_IAPP, - HOSTAPD_LEVEL_DEBUG, - "Removing STA due to IAPP ADD-notify"); - ap_sta_disconnect(iapp->hapd, sta, NULL, 0); -} - - -/** - * iapp_receive_udp - Process IAPP UDP frames - * @sock: File descriptor for the socket - * @eloop_ctx: IAPP data (struct iapp_data *) - * @sock_ctx: Not used - */ -static void iapp_receive_udp(int sock, void *eloop_ctx, void *sock_ctx) -{ - struct iapp_data *iapp = eloop_ctx; - int len, hlen; - unsigned char buf[128]; - struct sockaddr_in from; - socklen_t fromlen; - struct iapp_hdr *hdr; - - /* Handle incoming IAPP frames (over UDP/IP) */ - - fromlen = sizeof(from); - len = recvfrom(iapp->udp_sock, buf, sizeof(buf), 0, - (struct sockaddr *) &from, &fromlen); - if (len < 0) { - perror("recvfrom"); - return; - } - - if (from.sin_addr.s_addr == iapp->own.s_addr) - return; /* ignore own IAPP messages */ - - hostapd_logger(iapp->hapd, NULL, HOSTAPD_MODULE_IAPP, - HOSTAPD_LEVEL_DEBUG, - "Received %d byte IAPP frame from %s%s\n", - len, inet_ntoa(from.sin_addr), - len < (int) sizeof(*hdr) ? " (too short)" : ""); - - if (len < (int) sizeof(*hdr)) - return; - - hdr = (struct iapp_hdr *) buf; - hlen = be_to_host16(hdr->length); - hostapd_logger(iapp->hapd, NULL, HOSTAPD_MODULE_IAPP, - HOSTAPD_LEVEL_DEBUG, - "RX: version=%d command=%d id=%d len=%d\n", - hdr->version, hdr->command, - be_to_host16(hdr->identifier), hlen); - if (hdr->version != IAPP_VERSION) { - printf("Dropping IAPP frame with unknown version %d\n", - hdr->version); - return; - } - if (hlen > len) { - printf("Underflow IAPP frame (hlen=%d len=%d)\n", hlen, len); - return; - } - if (hlen < len) { - printf("Ignoring %d extra bytes from IAPP frame\n", - len - hlen); - len = hlen; - } - - switch (hdr->command) { - case IAPP_CMD_ADD_notify: - iapp_process_add_notify(iapp, &from, hdr, hlen - sizeof(*hdr)); - break; - case IAPP_CMD_MOVE_notify: - /* TODO: MOVE is using TCP; so move this to TCP handler once it - * is implemented.. */ - /* IAPP-MOVE.indication(MAC Address, New BSSID, - * Sequence Number, AP Address, Context Block) */ - /* TODO: process */ - break; - default: - printf("Unknown IAPP command %d\n", hdr->command); - break; - } -} - - -struct iapp_data * iapp_init(struct hostapd_data *hapd, const char *iface) -{ - struct ifreq ifr; - struct sockaddr_ll addr; - int ifindex; - struct sockaddr_in *paddr, uaddr; - struct iapp_data *iapp; - struct ip_mreqn mreq; - - iapp = os_zalloc(sizeof(*iapp)); - if (iapp == NULL) - return NULL; - iapp->hapd = hapd; - iapp->udp_sock = iapp->packet_sock = -1; - - /* TODO: - * open socket for sending and receiving IAPP frames over TCP - */ - - iapp->udp_sock = socket(PF_INET, SOCK_DGRAM, 0); - if (iapp->udp_sock < 0) { - perror("socket[PF_INET,SOCK_DGRAM]"); - iapp_deinit(iapp); - return NULL; - } - - os_memset(&ifr, 0, sizeof(ifr)); - os_strlcpy(ifr.ifr_name, iface, sizeof(ifr.ifr_name)); - if (ioctl(iapp->udp_sock, SIOCGIFINDEX, &ifr) != 0) { - perror("ioctl(SIOCGIFINDEX)"); - iapp_deinit(iapp); - return NULL; - } - ifindex = ifr.ifr_ifindex; - - if (ioctl(iapp->udp_sock, SIOCGIFADDR, &ifr) != 0) { - perror("ioctl(SIOCGIFADDR)"); - iapp_deinit(iapp); - return NULL; - } - paddr = (struct sockaddr_in *) &ifr.ifr_addr; - if (paddr->sin_family != AF_INET) { - printf("Invalid address family %i (SIOCGIFADDR)\n", - paddr->sin_family); - iapp_deinit(iapp); - return NULL; - } - iapp->own.s_addr = paddr->sin_addr.s_addr; - - if (ioctl(iapp->udp_sock, SIOCGIFBRDADDR, &ifr) != 0) { - perror("ioctl(SIOCGIFBRDADDR)"); - iapp_deinit(iapp); - return NULL; - } - paddr = (struct sockaddr_in *) &ifr.ifr_addr; - if (paddr->sin_family != AF_INET) { - printf("Invalid address family %i (SIOCGIFBRDADDR)\n", - paddr->sin_family); - iapp_deinit(iapp); - return NULL; - } - inet_aton(IAPP_MULTICAST, &iapp->multicast); - - os_memset(&uaddr, 0, sizeof(uaddr)); - uaddr.sin_family = AF_INET; - uaddr.sin_port = htons(IAPP_UDP_PORT); - if (bind(iapp->udp_sock, (struct sockaddr *) &uaddr, - sizeof(uaddr)) < 0) { - perror("bind[UDP]"); - iapp_deinit(iapp); - return NULL; - } - - os_memset(&mreq, 0, sizeof(mreq)); - mreq.imr_multiaddr = iapp->multicast; - mreq.imr_address.s_addr = INADDR_ANY; - mreq.imr_ifindex = 0; - if (setsockopt(iapp->udp_sock, SOL_IP, IP_ADD_MEMBERSHIP, &mreq, - sizeof(mreq)) < 0) { - perror("setsockopt[UDP,IP_ADD_MEMBERSHIP]"); - iapp_deinit(iapp); - return NULL; - } - - iapp->packet_sock = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL)); - if (iapp->packet_sock < 0) { - perror("socket[PF_PACKET,SOCK_RAW]"); - iapp_deinit(iapp); - return NULL; - } - - os_memset(&addr, 0, sizeof(addr)); - addr.sll_family = AF_PACKET; - addr.sll_ifindex = ifindex; - if (bind(iapp->packet_sock, (struct sockaddr *) &addr, - sizeof(addr)) < 0) { - perror("bind[PACKET]"); - iapp_deinit(iapp); - return NULL; - } - - if (eloop_register_read_sock(iapp->udp_sock, iapp_receive_udp, - iapp, NULL)) { - printf("Could not register read socket for IAPP.\n"); - iapp_deinit(iapp); - return NULL; - } - - printf("IEEE 802.11F (IAPP) using interface %s\n", iface); - - /* TODO: For levels 2 and 3: send RADIUS Initiate-Request, receive - * RADIUS Initiate-Accept or Initiate-Reject. IAPP port should actually - * be openned only after receiving Initiate-Accept. If Initiate-Reject - * is received, IAPP is not started. */ - - return iapp; -} - - -void iapp_deinit(struct iapp_data *iapp) -{ - struct ip_mreqn mreq; - - if (iapp == NULL) - return; - - if (iapp->udp_sock >= 0) { - os_memset(&mreq, 0, sizeof(mreq)); - mreq.imr_multiaddr = iapp->multicast; - mreq.imr_address.s_addr = INADDR_ANY; - mreq.imr_ifindex = 0; - if (setsockopt(iapp->udp_sock, SOL_IP, IP_DROP_MEMBERSHIP, - &mreq, sizeof(mreq)) < 0) { - perror("setsockopt[UDP,IP_DEL_MEMBERSHIP]"); - } - - eloop_unregister_read_sock(iapp->udp_sock); - close(iapp->udp_sock); - } - if (iapp->packet_sock >= 0) { - eloop_unregister_read_sock(iapp->packet_sock); - close(iapp->packet_sock); - } - os_free(iapp); -} diff --git a/hostapd-0.8/src/ap/iapp.h b/hostapd-0.8/src/ap/iapp.h deleted file mode 100644 index 5fc01cb..0000000 --- a/hostapd-0.8/src/ap/iapp.h +++ /dev/null @@ -1,45 +0,0 @@ -/* - * hostapd / IEEE 802.11F-2003 Inter-Access Point Protocol (IAPP) - * Copyright (c) 2002-2005, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#ifndef IAPP_H -#define IAPP_H - -struct iapp_data; - -#ifdef CONFIG_IAPP - -void iapp_new_station(struct iapp_data *iapp, struct sta_info *sta); -struct iapp_data * iapp_init(struct hostapd_data *hapd, const char *iface); -void iapp_deinit(struct iapp_data *iapp); - -#else /* CONFIG_IAPP */ - -static inline void iapp_new_station(struct iapp_data *iapp, - struct sta_info *sta) -{ -} - -static inline struct iapp_data * iapp_init(struct hostapd_data *hapd, - const char *iface) -{ - return NULL; -} - -static inline void iapp_deinit(struct iapp_data *iapp) -{ -} - -#endif /* CONFIG_IAPP */ - -#endif /* IAPP_H */ diff --git a/hostapd-0.8/src/ap/ieee802_11.c b/hostapd-0.8/src/ap/ieee802_11.c deleted file mode 100644 index 1fd4dab..0000000 --- a/hostapd-0.8/src/ap/ieee802_11.c +++ /dev/null @@ -1,1884 +0,0 @@ -/* - * hostapd / IEEE 802.11 Management - * Copyright (c) 2002-2010, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#include "utils/includes.h" - -#ifndef CONFIG_NATIVE_WINDOWS - -#include "utils/common.h" -#include "utils/eloop.h" -#include "crypto/crypto.h" -#include "drivers/driver.h" -#include "common/ieee802_11_defs.h" -#include "common/ieee802_11_common.h" -#include "common/wpa_ctrl.h" -#include "radius/radius.h" -#include "radius/radius_client.h" -#include "p2p/p2p.h" -#include "wps/wps.h" -#include "hostapd.h" -#include "beacon.h" -#include "ieee802_11_auth.h" -#include "sta_info.h" -#include "ieee802_1x.h" -#include "wpa_auth.h" -#include "wmm.h" -#include "ap_list.h" -#include "accounting.h" -#include "ap_config.h" -#include "ap_mlme.h" -#include "p2p_hostapd.h" -#include "ap_drv_ops.h" -#include "ieee802_11.h" - - -u8 * hostapd_eid_supp_rates(struct hostapd_data *hapd, u8 *eid) -{ - u8 *pos = eid; - int i, num, count; - - if (hapd->iface->current_rates == NULL) - return eid; - - *pos++ = WLAN_EID_SUPP_RATES; - num = hapd->iface->num_rates; - if (hapd->iconf->ieee80211n && hapd->iconf->require_ht) - num++; - if (num > 8) { - /* rest of the rates are encoded in Extended supported - * rates element */ - num = 8; - } - - *pos++ = num; - count = 0; - for (i = 0, count = 0; i < hapd->iface->num_rates && count < num; - i++) { - count++; - *pos = hapd->iface->current_rates[i].rate / 5; - if (hapd->iface->current_rates[i].flags & HOSTAPD_RATE_BASIC) - *pos |= 0x80; - pos++; - } - - if (hapd->iconf->ieee80211n && hapd->iconf->require_ht && - hapd->iface->num_rates < 8) - *pos++ = 0x80 | BSS_MEMBERSHIP_SELECTOR_HT_PHY; - - return pos; -} - - -u8 * hostapd_eid_ext_supp_rates(struct hostapd_data *hapd, u8 *eid) -{ - u8 *pos = eid; - int i, num, count; - - if (hapd->iface->current_rates == NULL) - return eid; - - num = hapd->iface->num_rates; - if (hapd->iconf->ieee80211n && hapd->iconf->require_ht) - num++; - if (num <= 8) - return eid; - num -= 8; - - *pos++ = WLAN_EID_EXT_SUPP_RATES; - *pos++ = num; - count = 0; - for (i = 0, count = 0; i < hapd->iface->num_rates && count < num + 8; - i++) { - count++; - if (count <= 8) - continue; /* already in SuppRates IE */ - *pos = hapd->iface->current_rates[i].rate / 5; - if (hapd->iface->current_rates[i].flags & HOSTAPD_RATE_BASIC) - *pos |= 0x80; - pos++; - } - - if (hapd->iconf->ieee80211n && hapd->iconf->require_ht && - hapd->iface->num_rates >= 8) - *pos++ = 0x80 | BSS_MEMBERSHIP_SELECTOR_HT_PHY; - - return pos; -} - - -u16 hostapd_own_capab_info(struct hostapd_data *hapd, struct sta_info *sta, - int probe) -{ - int capab = WLAN_CAPABILITY_ESS; - int privacy; - - if (hapd->iface->num_sta_no_short_preamble == 0 && - hapd->iconf->preamble == SHORT_PREAMBLE) - capab |= WLAN_CAPABILITY_SHORT_PREAMBLE; - - privacy = hapd->conf->ssid.wep.keys_set; - - if (hapd->conf->ieee802_1x && - (hapd->conf->default_wep_key_len || - hapd->conf->individual_wep_key_len)) - privacy = 1; - - if (hapd->conf->wpa) - privacy = 1; - - if (sta) { - int policy, def_klen; - if (probe && sta->ssid_probe) { - policy = sta->ssid_probe->security_policy; - def_klen = sta->ssid_probe->wep.default_len; - } else { - policy = sta->ssid->security_policy; - def_klen = sta->ssid->wep.default_len; - } - privacy = policy != SECURITY_PLAINTEXT; - if (policy == SECURITY_IEEE_802_1X && def_klen == 0) - privacy = 0; - } - - if (privacy) - capab |= WLAN_CAPABILITY_PRIVACY; - - if (hapd->iface->current_mode && - hapd->iface->current_mode->mode == HOSTAPD_MODE_IEEE80211G && - hapd->iface->num_sta_no_short_slot_time == 0) - capab |= WLAN_CAPABILITY_SHORT_SLOT_TIME; - - return capab; -} - - -u8 * hostapd_eid_ext_capab(struct hostapd_data *hapd, u8 *eid) -{ - u8 *pos = eid; - - if ((hapd->conf->tdls & (TDLS_PROHIBIT | TDLS_PROHIBIT_CHAN_SWITCH)) == - 0) - return eid; - - *pos++ = WLAN_EID_EXT_CAPAB; - *pos++ = 5; - *pos++ = 0x00; - *pos++ = 0x00; - *pos++ = 0x00; - *pos++ = 0x00; - *pos = 0x00; - if (hapd->conf->tdls & TDLS_PROHIBIT) - *pos |= 0x40; /* Bit 38 - TDLS Prohibited */ - if (hapd->conf->tdls & TDLS_PROHIBIT_CHAN_SWITCH) - *pos |= 0x80; /* Bit 39 - TDLS Channel Switching Prohibited */ - pos++; - - return pos; -} - - -#ifdef CONFIG_IEEE80211W -static u8 * hostapd_eid_assoc_comeback_time(struct hostapd_data *hapd, - struct sta_info *sta, u8 *eid) -{ - u8 *pos = eid; - u32 timeout, tu; - struct os_time now, passed; - - *pos++ = WLAN_EID_TIMEOUT_INTERVAL; - *pos++ = 5; - *pos++ = WLAN_TIMEOUT_ASSOC_COMEBACK; - os_get_time(&now); - os_time_sub(&now, &sta->sa_query_start, &passed); - tu = (passed.sec * 1000000 + passed.usec) / 1024; - if (hapd->conf->assoc_sa_query_max_timeout > tu) - timeout = hapd->conf->assoc_sa_query_max_timeout - tu; - else - timeout = 0; - if (timeout < hapd->conf->assoc_sa_query_max_timeout) - timeout++; /* add some extra time for local timers */ - WPA_PUT_LE32(pos, timeout); - pos += 4; - - return pos; -} -#endif /* CONFIG_IEEE80211W */ - - -void ieee802_11_print_ssid(char *buf, const u8 *ssid, u8 len) -{ - int i; - if (len > HOSTAPD_MAX_SSID_LEN) - len = HOSTAPD_MAX_SSID_LEN; - for (i = 0; i < len; i++) { - if (ssid[i] >= 32 && ssid[i] < 127) - buf[i] = ssid[i]; - else - buf[i] = '.'; - } - buf[len] = '\0'; -} - - -static u16 auth_shared_key(struct hostapd_data *hapd, struct sta_info *sta, - u16 auth_transaction, const u8 *challenge, - int iswep) -{ - hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211, - HOSTAPD_LEVEL_DEBUG, - "authentication (shared key, transaction %d)", - auth_transaction); - - if (auth_transaction == 1) { - if (!sta->challenge) { - /* Generate a pseudo-random challenge */ - u8 key[8]; - struct os_time now; - int r; - sta->challenge = os_zalloc(WLAN_AUTH_CHALLENGE_LEN); - if (sta->challenge == NULL) - return WLAN_STATUS_UNSPECIFIED_FAILURE; - - os_get_time(&now); - r = os_random(); - os_memcpy(key, &now.sec, 4); - os_memcpy(key + 4, &r, 4); - rc4_skip(key, sizeof(key), 0, - sta->challenge, WLAN_AUTH_CHALLENGE_LEN); - } - return 0; - } - - if (auth_transaction != 3) - return WLAN_STATUS_UNSPECIFIED_FAILURE; - - /* Transaction 3 */ - if (!iswep || !sta->challenge || !challenge || - os_memcmp(sta->challenge, challenge, WLAN_AUTH_CHALLENGE_LEN)) { - hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211, - HOSTAPD_LEVEL_INFO, - "shared key authentication - invalid " - "challenge-response"); - return WLAN_STATUS_CHALLENGE_FAIL; - } - - hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211, - HOSTAPD_LEVEL_DEBUG, - "authentication OK (shared key)"); -#ifdef IEEE80211_REQUIRE_AUTH_ACK - /* Station will be marked authenticated if it ACKs the - * authentication reply. */ -#else - sta->flags |= WLAN_STA_AUTH; - wpa_auth_sm_event(sta->wpa_sm, WPA_AUTH); -#endif - os_free(sta->challenge); - sta->challenge = NULL; - - return 0; -} - - -static void send_auth_reply(struct hostapd_data *hapd, - const u8 *dst, const u8 *bssid, - u16 auth_alg, u16 auth_transaction, u16 resp, - const u8 *ies, size_t ies_len) -{ - struct ieee80211_mgmt *reply; - u8 *buf; - size_t rlen; - - rlen = IEEE80211_HDRLEN + sizeof(reply->u.auth) + ies_len; - buf = os_zalloc(rlen); - if (buf == NULL) - return; - - reply = (struct ieee80211_mgmt *) buf; - reply->frame_control = IEEE80211_FC(WLAN_FC_TYPE_MGMT, - WLAN_FC_STYPE_AUTH); - os_memcpy(reply->da, dst, ETH_ALEN); - os_memcpy(reply->sa, hapd->own_addr, ETH_ALEN); - os_memcpy(reply->bssid, bssid, ETH_ALEN); - - reply->u.auth.auth_alg = host_to_le16(auth_alg); - reply->u.auth.auth_transaction = host_to_le16(auth_transaction); - reply->u.auth.status_code = host_to_le16(resp); - - if (ies && ies_len) - os_memcpy(reply->u.auth.variable, ies, ies_len); - - wpa_printf(MSG_DEBUG, "authentication reply: STA=" MACSTR - " auth_alg=%d auth_transaction=%d resp=%d (IE len=%lu)", - MAC2STR(dst), auth_alg, auth_transaction, - resp, (unsigned long) ies_len); - if (hostapd_drv_send_mlme(hapd, reply, rlen) < 0) - perror("send_auth_reply: send"); - - os_free(buf); -} - - -#ifdef CONFIG_IEEE80211R -static void handle_auth_ft_finish(void *ctx, const u8 *dst, const u8 *bssid, - u16 auth_transaction, u16 status, - const u8 *ies, size_t ies_len) -{ - struct hostapd_data *hapd = ctx; - struct sta_info *sta; - - send_auth_reply(hapd, dst, bssid, WLAN_AUTH_FT, auth_transaction, - status, ies, ies_len); - - if (status != WLAN_STATUS_SUCCESS) - return; - - sta = ap_get_sta(hapd, dst); - if (sta == NULL) - return; - - hostapd_logger(hapd, dst, HOSTAPD_MODULE_IEEE80211, - HOSTAPD_LEVEL_DEBUG, "authentication OK (FT)"); - sta->flags |= WLAN_STA_AUTH; - mlme_authenticate_indication(hapd, sta); -} -#endif /* CONFIG_IEEE80211R */ - - -static void handle_auth(struct hostapd_data *hapd, - const struct ieee80211_mgmt *mgmt, size_t len) -{ - u16 auth_alg, auth_transaction, status_code; - u16 resp = WLAN_STATUS_SUCCESS; - struct sta_info *sta = NULL; - int res; - u16 fc; - const u8 *challenge = NULL; - u32 session_timeout, acct_interim_interval; - int vlan_id = 0; - u8 resp_ies[2 + WLAN_AUTH_CHALLENGE_LEN]; - size_t resp_ies_len = 0; - - if (len < IEEE80211_HDRLEN + sizeof(mgmt->u.auth)) { - printf("handle_auth - too short payload (len=%lu)\n", - (unsigned long) len); - return; - } - - auth_alg = le_to_host16(mgmt->u.auth.auth_alg); - auth_transaction = le_to_host16(mgmt->u.auth.auth_transaction); - status_code = le_to_host16(mgmt->u.auth.status_code); - fc = le_to_host16(mgmt->frame_control); - - if (len >= IEEE80211_HDRLEN + sizeof(mgmt->u.auth) + - 2 + WLAN_AUTH_CHALLENGE_LEN && - mgmt->u.auth.variable[0] == WLAN_EID_CHALLENGE && - mgmt->u.auth.variable[1] == WLAN_AUTH_CHALLENGE_LEN) - challenge = &mgmt->u.auth.variable[2]; - - wpa_printf(MSG_DEBUG, "authentication: STA=" MACSTR " auth_alg=%d " - "auth_transaction=%d status_code=%d wep=%d%s", - MAC2STR(mgmt->sa), auth_alg, auth_transaction, - status_code, !!(fc & WLAN_FC_ISWEP), - challenge ? " challenge" : ""); - - if (hapd->tkip_countermeasures) { - resp = WLAN_REASON_MICHAEL_MIC_FAILURE; - goto fail; - } - - if (!(((hapd->conf->auth_algs & WPA_AUTH_ALG_OPEN) && - auth_alg == WLAN_AUTH_OPEN) || -#ifdef CONFIG_IEEE80211R - (hapd->conf->wpa && - (hapd->conf->wpa_key_mgmt & - (WPA_KEY_MGMT_FT_IEEE8021X | WPA_KEY_MGMT_FT_PSK)) && - auth_alg == WLAN_AUTH_FT) || -#endif /* CONFIG_IEEE80211R */ - ((hapd->conf->auth_algs & WPA_AUTH_ALG_SHARED) && - auth_alg == WLAN_AUTH_SHARED_KEY))) { - printf("Unsupported authentication algorithm (%d)\n", - auth_alg); - resp = WLAN_STATUS_NOT_SUPPORTED_AUTH_ALG; - goto fail; - } - - if (!(auth_transaction == 1 || - (auth_alg == WLAN_AUTH_SHARED_KEY && auth_transaction == 3))) { - printf("Unknown authentication transaction number (%d)\n", - auth_transaction); - resp = WLAN_STATUS_UNKNOWN_AUTH_TRANSACTION; - goto fail; - } - - if (os_memcmp(mgmt->sa, hapd->own_addr, ETH_ALEN) == 0) { - printf("Station " MACSTR " not allowed to authenticate.\n", - MAC2STR(mgmt->sa)); - resp = WLAN_STATUS_UNSPECIFIED_FAILURE; - goto fail; - } - - res = hostapd_allowed_address(hapd, mgmt->sa, (u8 *) mgmt, len, - &session_timeout, - &acct_interim_interval, &vlan_id); - if (res == HOSTAPD_ACL_REJECT) { - printf("Station " MACSTR " not allowed to authenticate.\n", - MAC2STR(mgmt->sa)); - resp = WLAN_STATUS_UNSPECIFIED_FAILURE; - goto fail; - } - if (res == HOSTAPD_ACL_PENDING) { - wpa_printf(MSG_DEBUG, "Authentication frame from " MACSTR - " waiting for an external authentication", - MAC2STR(mgmt->sa)); - /* Authentication code will re-send the authentication frame - * after it has received (and cached) information from the - * external source. */ - return; - } - - sta = ap_sta_add(hapd, mgmt->sa); - if (!sta) { - resp = WLAN_STATUS_UNSPECIFIED_FAILURE; - goto fail; - } - - if (vlan_id > 0) { - if (hostapd_get_vlan_id_ifname(hapd->conf->vlan, - vlan_id) == NULL) { - hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_RADIUS, - HOSTAPD_LEVEL_INFO, "Invalid VLAN ID " - "%d received from RADIUS server", - vlan_id); - resp = WLAN_STATUS_UNSPECIFIED_FAILURE; - goto fail; - } - sta->vlan_id = vlan_id; - hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_RADIUS, - HOSTAPD_LEVEL_INFO, "VLAN ID %d", sta->vlan_id); - } - - sta->flags &= ~WLAN_STA_PREAUTH; - ieee802_1x_notify_pre_auth(sta->eapol_sm, 0); - - if (hapd->conf->acct_interim_interval == 0 && acct_interim_interval) - sta->acct_interim_interval = acct_interim_interval; - if (res == HOSTAPD_ACL_ACCEPT_TIMEOUT) - ap_sta_session_timeout(hapd, sta, session_timeout); - else - ap_sta_no_session_timeout(hapd, sta); - - switch (auth_alg) { - case WLAN_AUTH_OPEN: - hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211, - HOSTAPD_LEVEL_DEBUG, - "authentication OK (open system)"); -#ifdef IEEE80211_REQUIRE_AUTH_ACK - /* Station will be marked authenticated if it ACKs the - * authentication reply. */ -#else - sta->flags |= WLAN_STA_AUTH; - wpa_auth_sm_event(sta->wpa_sm, WPA_AUTH); - sta->auth_alg = WLAN_AUTH_OPEN; - mlme_authenticate_indication(hapd, sta); -#endif - break; - case WLAN_AUTH_SHARED_KEY: - resp = auth_shared_key(hapd, sta, auth_transaction, challenge, - fc & WLAN_FC_ISWEP); - sta->auth_alg = WLAN_AUTH_SHARED_KEY; - mlme_authenticate_indication(hapd, sta); - if (sta->challenge && auth_transaction == 1) { - resp_ies[0] = WLAN_EID_CHALLENGE; - resp_ies[1] = WLAN_AUTH_CHALLENGE_LEN; - os_memcpy(resp_ies + 2, sta->challenge, - WLAN_AUTH_CHALLENGE_LEN); - resp_ies_len = 2 + WLAN_AUTH_CHALLENGE_LEN; - } - break; -#ifdef CONFIG_IEEE80211R - case WLAN_AUTH_FT: - sta->auth_alg = WLAN_AUTH_FT; - if (sta->wpa_sm == NULL) - sta->wpa_sm = wpa_auth_sta_init(hapd->wpa_auth, - sta->addr); - if (sta->wpa_sm == NULL) { - wpa_printf(MSG_DEBUG, "FT: Failed to initialize WPA " - "state machine"); - resp = WLAN_STATUS_UNSPECIFIED_FAILURE; - goto fail; - } - wpa_ft_process_auth(sta->wpa_sm, mgmt->bssid, - auth_transaction, mgmt->u.auth.variable, - len - IEEE80211_HDRLEN - - sizeof(mgmt->u.auth), - handle_auth_ft_finish, hapd); - /* handle_auth_ft_finish() callback will complete auth. */ - return; -#endif /* CONFIG_IEEE80211R */ - } - - fail: - send_auth_reply(hapd, mgmt->sa, mgmt->bssid, auth_alg, - auth_transaction + 1, resp, resp_ies, resp_ies_len); -} - - -static int hostapd_get_aid(struct hostapd_data *hapd, struct sta_info *sta) -{ - int i, j = 32, aid; - - /* get a unique AID */ - if (sta->aid > 0) { - wpa_printf(MSG_DEBUG, " old AID %d", sta->aid); - return 0; - } - - for (i = 0; i < AID_WORDS; i++) { - if (hapd->sta_aid[i] == (u32) -1) - continue; - for (j = 0; j < 32; j++) { - if (!(hapd->sta_aid[i] & BIT(j))) - break; - } - if (j < 32) - break; - } - if (j == 32) - return -1; - aid = i * 32 + j + 1; - if (aid > 2007) - return -1; - - sta->aid = aid; - hapd->sta_aid[i] |= BIT(j); - wpa_printf(MSG_DEBUG, " new AID %d", sta->aid); - return 0; -} - - -static u16 check_ssid(struct hostapd_data *hapd, struct sta_info *sta, - const u8 *ssid_ie, size_t ssid_ie_len) -{ - if (ssid_ie == NULL) - return WLAN_STATUS_UNSPECIFIED_FAILURE; - - if (ssid_ie_len != hapd->conf->ssid.ssid_len || - os_memcmp(ssid_ie, hapd->conf->ssid.ssid, ssid_ie_len) != 0) { - char ssid_txt[33]; - ieee802_11_print_ssid(ssid_txt, ssid_ie, ssid_ie_len); - hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211, - HOSTAPD_LEVEL_INFO, - "Station tried to associate with unknown SSID " - "'%s'", ssid_txt); - return WLAN_STATUS_UNSPECIFIED_FAILURE; - } - - return WLAN_STATUS_SUCCESS; -} - - -static u16 check_wmm(struct hostapd_data *hapd, struct sta_info *sta, - const u8 *wmm_ie, size_t wmm_ie_len) -{ - sta->flags &= ~WLAN_STA_WMM; - if (wmm_ie && hapd->conf->wmm_enabled) { - if (hostapd_eid_wmm_valid(hapd, wmm_ie, wmm_ie_len)) - hostapd_logger(hapd, sta->addr, - HOSTAPD_MODULE_WPA, - HOSTAPD_LEVEL_DEBUG, - "invalid WMM element in association " - "request"); - else - sta->flags |= WLAN_STA_WMM; - } - return WLAN_STATUS_SUCCESS; -} - - -static u16 copy_supp_rates(struct hostapd_data *hapd, struct sta_info *sta, - struct ieee802_11_elems *elems) -{ - if (!elems->supp_rates) { - hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211, - HOSTAPD_LEVEL_DEBUG, - "No supported rates element in AssocReq"); - return WLAN_STATUS_UNSPECIFIED_FAILURE; - } - - if (elems->supp_rates_len > sizeof(sta->supported_rates)) { - hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211, - HOSTAPD_LEVEL_DEBUG, - "Invalid supported rates element length %d", - elems->supp_rates_len); - return WLAN_STATUS_UNSPECIFIED_FAILURE; - } - - os_memset(sta->supported_rates, 0, sizeof(sta->supported_rates)); - os_memcpy(sta->supported_rates, elems->supp_rates, - elems->supp_rates_len); - sta->supported_rates_len = elems->supp_rates_len; - - if (elems->ext_supp_rates) { - if (elems->supp_rates_len + elems->ext_supp_rates_len > - sizeof(sta->supported_rates)) { - hostapd_logger(hapd, sta->addr, - HOSTAPD_MODULE_IEEE80211, - HOSTAPD_LEVEL_DEBUG, - "Invalid supported rates element length" - " %d+%d", elems->supp_rates_len, - elems->ext_supp_rates_len); - return WLAN_STATUS_UNSPECIFIED_FAILURE; - } - - os_memcpy(sta->supported_rates + elems->supp_rates_len, - elems->ext_supp_rates, elems->ext_supp_rates_len); - sta->supported_rates_len += elems->ext_supp_rates_len; - } - - return WLAN_STATUS_SUCCESS; -} - - -static u16 check_assoc_ies(struct hostapd_data *hapd, struct sta_info *sta, - const u8 *ies, size_t ies_len, int reassoc) -{ - struct ieee802_11_elems elems; - u16 resp; - const u8 *wpa_ie; - size_t wpa_ie_len; - - if (ieee802_11_parse_elems(ies, ies_len, &elems, 1) == ParseFailed) { - hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211, - HOSTAPD_LEVEL_INFO, "Station sent an invalid " - "association request"); - return WLAN_STATUS_UNSPECIFIED_FAILURE; - } - - resp = check_ssid(hapd, sta, elems.ssid, elems.ssid_len); - if (resp != WLAN_STATUS_SUCCESS) - return resp; - resp = check_wmm(hapd, sta, elems.wmm, elems.wmm_len); - if (resp != WLAN_STATUS_SUCCESS) - return resp; - resp = copy_supp_rates(hapd, sta, &elems); - if (resp != WLAN_STATUS_SUCCESS) - return resp; -#ifdef CONFIG_IEEE80211N - resp = copy_sta_ht_capab(hapd, sta, elems.ht_capabilities, - elems.ht_capabilities_len); - if (resp != WLAN_STATUS_SUCCESS) - return resp; - if (hapd->iconf->ieee80211n && hapd->iconf->require_ht && - !(sta->flags & WLAN_STA_HT)) { - hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211, - HOSTAPD_LEVEL_INFO, "Station does not support " - "mandatory HT PHY - reject association"); - return WLAN_STATUS_ASSOC_DENIED_NO_HT; - } -#endif /* CONFIG_IEEE80211N */ - - if ((hapd->conf->wpa & WPA_PROTO_RSN) && elems.rsn_ie) { - wpa_ie = elems.rsn_ie; - wpa_ie_len = elems.rsn_ie_len; - } else if ((hapd->conf->wpa & WPA_PROTO_WPA) && - elems.wpa_ie) { - wpa_ie = elems.wpa_ie; - wpa_ie_len = elems.wpa_ie_len; - } else { - wpa_ie = NULL; - wpa_ie_len = 0; - } - -#ifdef CONFIG_WPS - sta->flags &= ~(WLAN_STA_WPS | WLAN_STA_MAYBE_WPS); - if (hapd->conf->wps_state && elems.wps_ie) { - wpa_printf(MSG_DEBUG, "STA included WPS IE in (Re)Association " - "Request - assume WPS is used"); - sta->flags |= WLAN_STA_WPS; - wpabuf_free(sta->wps_ie); - sta->wps_ie = ieee802_11_vendor_ie_concat(ies, ies_len, - WPS_IE_VENDOR_TYPE); - wpa_ie = NULL; - wpa_ie_len = 0; - if (sta->wps_ie && wps_validate_assoc_req(sta->wps_ie) < 0) { - wpa_printf(MSG_DEBUG, "WPS: Invalid WPS IE in " - "(Re)Association Request - reject"); - return WLAN_STATUS_INVALID_IE; - } - } else if (hapd->conf->wps_state && wpa_ie == NULL) { - wpa_printf(MSG_DEBUG, "STA did not include WPA/RSN IE in " - "(Re)Association Request - possible WPS use"); - sta->flags |= WLAN_STA_MAYBE_WPS; - } else -#endif /* CONFIG_WPS */ - if (hapd->conf->wpa && wpa_ie == NULL) { - hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211, - HOSTAPD_LEVEL_INFO, - "No WPA/RSN IE in association request"); - return WLAN_STATUS_INVALID_IE; - } - - if (hapd->conf->wpa && wpa_ie) { - int res; - wpa_ie -= 2; - wpa_ie_len += 2; - if (sta->wpa_sm == NULL) - sta->wpa_sm = wpa_auth_sta_init(hapd->wpa_auth, - sta->addr); - if (sta->wpa_sm == NULL) { - wpa_printf(MSG_WARNING, "Failed to initialize WPA " - "state machine"); - return WLAN_STATUS_UNSPECIFIED_FAILURE; - } - res = wpa_validate_wpa_ie(hapd->wpa_auth, sta->wpa_sm, - wpa_ie, wpa_ie_len, - elems.mdie, elems.mdie_len); - if (res == WPA_INVALID_GROUP) - resp = WLAN_STATUS_GROUP_CIPHER_NOT_VALID; - else if (res == WPA_INVALID_PAIRWISE) - resp = WLAN_STATUS_PAIRWISE_CIPHER_NOT_VALID; - else if (res == WPA_INVALID_AKMP) - resp = WLAN_STATUS_AKMP_NOT_VALID; - else if (res == WPA_ALLOC_FAIL) - resp = WLAN_STATUS_UNSPECIFIED_FAILURE; -#ifdef CONFIG_IEEE80211W - else if (res == WPA_MGMT_FRAME_PROTECTION_VIOLATION) - resp = WLAN_STATUS_ROBUST_MGMT_FRAME_POLICY_VIOLATION; - else if (res == WPA_INVALID_MGMT_GROUP_CIPHER) - resp = WLAN_STATUS_ROBUST_MGMT_FRAME_POLICY_VIOLATION; -#endif /* CONFIG_IEEE80211W */ - else if (res == WPA_INVALID_MDIE) - resp = WLAN_STATUS_INVALID_MDIE; - else if (res != WPA_IE_OK) - resp = WLAN_STATUS_INVALID_IE; - if (resp != WLAN_STATUS_SUCCESS) - return resp; -#ifdef CONFIG_IEEE80211W - if ((sta->flags & WLAN_STA_MFP) && !sta->sa_query_timed_out && - sta->sa_query_count > 0) - ap_check_sa_query_timeout(hapd, sta); - if ((sta->flags & WLAN_STA_MFP) && !sta->sa_query_timed_out && - (!reassoc || sta->auth_alg != WLAN_AUTH_FT)) { - /* - * STA has already been associated with MFP and SA - * Query timeout has not been reached. Reject the - * association attempt temporarily and start SA Query, - * if one is not pending. - */ - - if (sta->sa_query_count == 0) - ap_sta_start_sa_query(hapd, sta); - - return WLAN_STATUS_ASSOC_REJECTED_TEMPORARILY; - } - - if (wpa_auth_uses_mfp(sta->wpa_sm)) - sta->flags |= WLAN_STA_MFP; - else - sta->flags &= ~WLAN_STA_MFP; -#endif /* CONFIG_IEEE80211W */ - -#ifdef CONFIG_IEEE80211R - if (sta->auth_alg == WLAN_AUTH_FT) { - if (!reassoc) { - wpa_printf(MSG_DEBUG, "FT: " MACSTR " tried " - "to use association (not " - "re-association) with FT auth_alg", - MAC2STR(sta->addr)); - return WLAN_STATUS_UNSPECIFIED_FAILURE; - } - - resp = wpa_ft_validate_reassoc(sta->wpa_sm, ies, - ies_len); - if (resp != WLAN_STATUS_SUCCESS) - return resp; - } -#endif /* CONFIG_IEEE80211R */ - -#ifdef CONFIG_IEEE80211N - if ((sta->flags & WLAN_STA_HT) && - wpa_auth_get_pairwise(sta->wpa_sm) == WPA_CIPHER_TKIP) { - hostapd_logger(hapd, sta->addr, - HOSTAPD_MODULE_IEEE80211, - HOSTAPD_LEVEL_INFO, - "Station tried to use TKIP with HT " - "association"); - return WLAN_STATUS_CIPHER_REJECTED_PER_POLICY; - } -#endif /* CONFIG_IEEE80211N */ - } else - wpa_auth_sta_no_wpa(sta->wpa_sm); - -#ifdef CONFIG_P2P - if (elems.p2p) { - wpabuf_free(sta->p2p_ie); - sta->p2p_ie = ieee802_11_vendor_ie_concat(ies, ies_len, - P2P_IE_VENDOR_TYPE); - - } else { - wpabuf_free(sta->p2p_ie); - sta->p2p_ie = NULL; - } - - p2p_group_notif_assoc(hapd->p2p_group, sta->addr, ies, ies_len); -#endif /* CONFIG_P2P */ - - return WLAN_STATUS_SUCCESS; -} - - -static void send_deauth(struct hostapd_data *hapd, const u8 *addr, - u16 reason_code) -{ - int send_len; - struct ieee80211_mgmt reply; - - os_memset(&reply, 0, sizeof(reply)); - reply.frame_control = - IEEE80211_FC(WLAN_FC_TYPE_MGMT, WLAN_FC_STYPE_DEAUTH); - os_memcpy(reply.da, addr, ETH_ALEN); - os_memcpy(reply.sa, hapd->own_addr, ETH_ALEN); - os_memcpy(reply.bssid, hapd->own_addr, ETH_ALEN); - - send_len = IEEE80211_HDRLEN + sizeof(reply.u.deauth); - reply.u.deauth.reason_code = host_to_le16(reason_code); - - if (hostapd_drv_send_mlme(hapd, &reply, send_len) < 0) - wpa_printf(MSG_INFO, "Failed to send deauth: %s", - strerror(errno)); -} - - -static void send_assoc_resp(struct hostapd_data *hapd, struct sta_info *sta, - u16 status_code, int reassoc, const u8 *ies, - size_t ies_len) -{ - int send_len; - u8 buf[sizeof(struct ieee80211_mgmt) + 1024]; - struct ieee80211_mgmt *reply; - u8 *p; - - os_memset(buf, 0, sizeof(buf)); - reply = (struct ieee80211_mgmt *) buf; - reply->frame_control = - IEEE80211_FC(WLAN_FC_TYPE_MGMT, - (reassoc ? WLAN_FC_STYPE_REASSOC_RESP : - WLAN_FC_STYPE_ASSOC_RESP)); - os_memcpy(reply->da, sta->addr, ETH_ALEN); - os_memcpy(reply->sa, hapd->own_addr, ETH_ALEN); - os_memcpy(reply->bssid, hapd->own_addr, ETH_ALEN); - - send_len = IEEE80211_HDRLEN; - send_len += sizeof(reply->u.assoc_resp); - reply->u.assoc_resp.capab_info = - host_to_le16(hostapd_own_capab_info(hapd, sta, 0)); - reply->u.assoc_resp.status_code = host_to_le16(status_code); - reply->u.assoc_resp.aid = host_to_le16((sta ? sta->aid : 0) - | BIT(14) | BIT(15)); - /* Supported rates */ - p = hostapd_eid_supp_rates(hapd, reply->u.assoc_resp.variable); - /* Extended supported rates */ - p = hostapd_eid_ext_supp_rates(hapd, p); - -#ifdef CONFIG_IEEE80211R - if (status_code == WLAN_STATUS_SUCCESS) { - /* IEEE 802.11r: Mobility Domain Information, Fast BSS - * Transition Information, RSN, [RIC Response] */ - p = wpa_sm_write_assoc_resp_ies(sta->wpa_sm, p, - buf + sizeof(buf) - p, - sta->auth_alg, ies, ies_len); - } -#endif /* CONFIG_IEEE80211R */ - -#ifdef CONFIG_IEEE80211W - if (status_code == WLAN_STATUS_ASSOC_REJECTED_TEMPORARILY) - p = hostapd_eid_assoc_comeback_time(hapd, sta, p); -#endif /* CONFIG_IEEE80211W */ - -#ifdef CONFIG_IEEE80211N - p = hostapd_eid_ht_capabilities(hapd, p); - p = hostapd_eid_ht_operation(hapd, p); -#endif /* CONFIG_IEEE80211N */ - - p = hostapd_eid_ext_capab(hapd, p); - - if (sta->flags & WLAN_STA_WMM) - p = hostapd_eid_wmm(hapd, p); - -#ifdef CONFIG_WPS - if (sta->flags & WLAN_STA_WPS) { - struct wpabuf *wps = wps_build_assoc_resp_ie(); - if (wps) { - os_memcpy(p, wpabuf_head(wps), wpabuf_len(wps)); - p += wpabuf_len(wps); - wpabuf_free(wps); - } - } -#endif /* CONFIG_WPS */ - -#ifdef CONFIG_P2P - if (sta->p2p_ie) { - struct wpabuf *p2p_resp_ie; - enum p2p_status_code status; - switch (status_code) { - case WLAN_STATUS_SUCCESS: - status = P2P_SC_SUCCESS; - break; - case WLAN_STATUS_AP_UNABLE_TO_HANDLE_NEW_STA: - status = P2P_SC_FAIL_LIMIT_REACHED; - break; - default: - status = P2P_SC_FAIL_INVALID_PARAMS; - break; - } - p2p_resp_ie = p2p_group_assoc_resp_ie(hapd->p2p_group, status); - if (p2p_resp_ie) { - os_memcpy(p, wpabuf_head(p2p_resp_ie), - wpabuf_len(p2p_resp_ie)); - p += wpabuf_len(p2p_resp_ie); - wpabuf_free(p2p_resp_ie); - } - } -#endif /* CONFIG_P2P */ - -#ifdef CONFIG_P2P_MANAGER - if (hapd->conf->p2p & P2P_MANAGE) - p = hostapd_eid_p2p_manage(hapd, p); -#endif /* CONFIG_P2P_MANAGER */ - - send_len += p - reply->u.assoc_resp.variable; - - if (hostapd_drv_send_mlme(hapd, reply, send_len) < 0) - wpa_printf(MSG_INFO, "Failed to send assoc resp: %s", - strerror(errno)); -} - - -static void handle_assoc(struct hostapd_data *hapd, - const struct ieee80211_mgmt *mgmt, size_t len, - int reassoc) -{ - u16 capab_info, listen_interval; - u16 resp = WLAN_STATUS_SUCCESS; - const u8 *pos; - int left, i; - struct sta_info *sta; - - if (len < IEEE80211_HDRLEN + (reassoc ? sizeof(mgmt->u.reassoc_req) : - sizeof(mgmt->u.assoc_req))) { - printf("handle_assoc(reassoc=%d) - too short payload (len=%lu)" - "\n", reassoc, (unsigned long) len); - return; - } - - if (reassoc) { - capab_info = le_to_host16(mgmt->u.reassoc_req.capab_info); - listen_interval = le_to_host16( - mgmt->u.reassoc_req.listen_interval); - wpa_printf(MSG_DEBUG, "reassociation request: STA=" MACSTR - " capab_info=0x%02x listen_interval=%d current_ap=" - MACSTR, - MAC2STR(mgmt->sa), capab_info, listen_interval, - MAC2STR(mgmt->u.reassoc_req.current_ap)); - left = len - (IEEE80211_HDRLEN + sizeof(mgmt->u.reassoc_req)); - pos = mgmt->u.reassoc_req.variable; - } else { - capab_info = le_to_host16(mgmt->u.assoc_req.capab_info); - listen_interval = le_to_host16( - mgmt->u.assoc_req.listen_interval); - wpa_printf(MSG_DEBUG, "association request: STA=" MACSTR - " capab_info=0x%02x listen_interval=%d", - MAC2STR(mgmt->sa), capab_info, listen_interval); - left = len - (IEEE80211_HDRLEN + sizeof(mgmt->u.assoc_req)); - pos = mgmt->u.assoc_req.variable; - } - - sta = ap_get_sta(hapd, mgmt->sa); -#ifdef CONFIG_IEEE80211R - if (sta && sta->auth_alg == WLAN_AUTH_FT && - (sta->flags & WLAN_STA_AUTH) == 0) { - wpa_printf(MSG_DEBUG, "FT: Allow STA " MACSTR " to associate " - "prior to authentication since it is using " - "over-the-DS FT", MAC2STR(mgmt->sa)); - } else -#endif /* CONFIG_IEEE80211R */ - if (sta == NULL || (sta->flags & WLAN_STA_AUTH) == 0) { - hostapd_logger(hapd, mgmt->sa, HOSTAPD_MODULE_IEEE80211, - HOSTAPD_LEVEL_INFO, "Station tried to " - "associate before authentication " - "(aid=%d flags=0x%x)", - sta ? sta->aid : -1, - sta ? sta->flags : 0); - send_deauth(hapd, mgmt->sa, - WLAN_REASON_CLASS2_FRAME_FROM_NONAUTH_STA); - return; - } - - if (hapd->tkip_countermeasures) { - resp = WLAN_REASON_MICHAEL_MIC_FAILURE; - goto fail; - } - - if (listen_interval > hapd->conf->max_listen_interval) { - hostapd_logger(hapd, mgmt->sa, HOSTAPD_MODULE_IEEE80211, - HOSTAPD_LEVEL_DEBUG, - "Too large Listen Interval (%d)", - listen_interval); - resp = WLAN_STATUS_ASSOC_DENIED_LISTEN_INT_TOO_LARGE; - goto fail; - } - - /* followed by SSID and Supported rates; and HT capabilities if 802.11n - * is used */ - resp = check_assoc_ies(hapd, sta, pos, left, reassoc); - if (resp != WLAN_STATUS_SUCCESS) - goto fail; - - if (hostapd_get_aid(hapd, sta) < 0) { - hostapd_logger(hapd, mgmt->sa, HOSTAPD_MODULE_IEEE80211, - HOSTAPD_LEVEL_INFO, "No room for more AIDs"); - resp = WLAN_STATUS_AP_UNABLE_TO_HANDLE_NEW_STA; - goto fail; - } - - sta->capability = capab_info; - sta->listen_interval = listen_interval; - - if (hapd->iface->current_mode->mode == HOSTAPD_MODE_IEEE80211G) - sta->flags |= WLAN_STA_NONERP; - for (i = 0; i < sta->supported_rates_len; i++) { - if ((sta->supported_rates[i] & 0x7f) > 22) { - sta->flags &= ~WLAN_STA_NONERP; - break; - } - } - if (sta->flags & WLAN_STA_NONERP && !sta->nonerp_set) { - sta->nonerp_set = 1; - hapd->iface->num_sta_non_erp++; - if (hapd->iface->num_sta_non_erp == 1) - ieee802_11_set_beacons(hapd->iface); - } - - if (!(sta->capability & WLAN_CAPABILITY_SHORT_SLOT_TIME) && - !sta->no_short_slot_time_set) { - sta->no_short_slot_time_set = 1; - hapd->iface->num_sta_no_short_slot_time++; - if (hapd->iface->current_mode->mode == - HOSTAPD_MODE_IEEE80211G && - hapd->iface->num_sta_no_short_slot_time == 1) - ieee802_11_set_beacons(hapd->iface); - } - - if (sta->capability & WLAN_CAPABILITY_SHORT_PREAMBLE) - sta->flags |= WLAN_STA_SHORT_PREAMBLE; - else - sta->flags &= ~WLAN_STA_SHORT_PREAMBLE; - - if (!(sta->capability & WLAN_CAPABILITY_SHORT_PREAMBLE) && - !sta->no_short_preamble_set) { - sta->no_short_preamble_set = 1; - hapd->iface->num_sta_no_short_preamble++; - if (hapd->iface->current_mode->mode == HOSTAPD_MODE_IEEE80211G - && hapd->iface->num_sta_no_short_preamble == 1) - ieee802_11_set_beacons(hapd->iface); - } - -#ifdef CONFIG_IEEE80211N - update_ht_state(hapd, sta); -#endif /* CONFIG_IEEE80211N */ - - hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211, - HOSTAPD_LEVEL_DEBUG, - "association OK (aid %d)", sta->aid); - /* Station will be marked associated, after it acknowledges AssocResp - */ - sta->flags |= WLAN_STA_ASSOC_REQ_OK; - -#ifdef CONFIG_IEEE80211W - if ((sta->flags & WLAN_STA_MFP) && sta->sa_query_timed_out) { - wpa_printf(MSG_DEBUG, "Allowing %sassociation after timed out " - "SA Query procedure", reassoc ? "re" : ""); - /* TODO: Send a protected Disassociate frame to the STA using - * the old key and Reason Code "Previous Authentication no - * longer valid". Make sure this is only sent protected since - * unprotected frame would be received by the STA that is now - * trying to associate. - */ - } -#endif /* CONFIG_IEEE80211W */ - - if (reassoc) { - os_memcpy(sta->previous_ap, mgmt->u.reassoc_req.current_ap, - ETH_ALEN); - } - - if (sta->last_assoc_req) - os_free(sta->last_assoc_req); - sta->last_assoc_req = os_malloc(len); - if (sta->last_assoc_req) - os_memcpy(sta->last_assoc_req, mgmt, len); - - /* Make sure that the previously registered inactivity timer will not - * remove the STA immediately. */ - sta->timeout_next = STA_NULLFUNC; - - fail: - send_assoc_resp(hapd, sta, resp, reassoc, pos, left); -} - - -static void handle_disassoc(struct hostapd_data *hapd, - const struct ieee80211_mgmt *mgmt, size_t len) -{ - struct sta_info *sta; - - if (len < IEEE80211_HDRLEN + sizeof(mgmt->u.disassoc)) { - printf("handle_disassoc - too short payload (len=%lu)\n", - (unsigned long) len); - return; - } - - wpa_printf(MSG_DEBUG, "disassocation: STA=" MACSTR " reason_code=%d", - MAC2STR(mgmt->sa), - le_to_host16(mgmt->u.disassoc.reason_code)); - - sta = ap_get_sta(hapd, mgmt->sa); - if (sta == NULL) { - printf("Station " MACSTR " trying to disassociate, but it " - "is not associated.\n", MAC2STR(mgmt->sa)); - return; - } - - sta->flags &= ~(WLAN_STA_ASSOC | WLAN_STA_ASSOC_REQ_OK); - wpa_msg(hapd->msg_ctx, MSG_INFO, AP_STA_DISCONNECTED MACSTR, - MAC2STR(sta->addr)); - wpa_auth_sm_event(sta->wpa_sm, WPA_DISASSOC); - hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211, - HOSTAPD_LEVEL_INFO, "disassociated"); - sta->acct_terminate_cause = RADIUS_ACCT_TERMINATE_CAUSE_USER_REQUEST; - ieee802_1x_notify_port_enabled(sta->eapol_sm, 0); - /* Stop Accounting and IEEE 802.1X sessions, but leave the STA - * authenticated. */ - accounting_sta_stop(hapd, sta); - ieee802_1x_free_station(sta); - hostapd_drv_sta_remove(hapd, sta->addr); - - if (sta->timeout_next == STA_NULLFUNC || - sta->timeout_next == STA_DISASSOC) { - sta->timeout_next = STA_DEAUTH; - eloop_cancel_timeout(ap_handle_timer, hapd, sta); - eloop_register_timeout(AP_DEAUTH_DELAY, 0, ap_handle_timer, - hapd, sta); - } - - mlme_disassociate_indication( - hapd, sta, le_to_host16(mgmt->u.disassoc.reason_code)); -} - - -static void handle_deauth(struct hostapd_data *hapd, - const struct ieee80211_mgmt *mgmt, size_t len) -{ - struct sta_info *sta; - - if (len < IEEE80211_HDRLEN + sizeof(mgmt->u.deauth)) { - wpa_msg(hapd, MSG_DEBUG, "handle_deauth - too short payload " - "(len=%lu)", (unsigned long) len); - return; - } - - wpa_msg(hapd, MSG_DEBUG, "deauthentication: STA=" MACSTR - " reason_code=%d", - MAC2STR(mgmt->sa), le_to_host16(mgmt->u.deauth.reason_code)); - - sta = ap_get_sta(hapd, mgmt->sa); - if (sta == NULL) { - wpa_msg(hapd, MSG_DEBUG, "Station " MACSTR " trying to " - "deauthenticate, but it is not authenticated", - MAC2STR(mgmt->sa)); - return; - } - - sta->flags &= ~(WLAN_STA_AUTH | WLAN_STA_ASSOC | - WLAN_STA_ASSOC_REQ_OK); - wpa_msg(hapd->msg_ctx, MSG_INFO, AP_STA_DISCONNECTED MACSTR, - MAC2STR(sta->addr)); - wpa_auth_sm_event(sta->wpa_sm, WPA_DEAUTH); - hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211, - HOSTAPD_LEVEL_DEBUG, "deauthenticated"); - mlme_deauthenticate_indication( - hapd, sta, le_to_host16(mgmt->u.deauth.reason_code)); - sta->acct_terminate_cause = RADIUS_ACCT_TERMINATE_CAUSE_USER_REQUEST; - ieee802_1x_notify_port_enabled(sta->eapol_sm, 0); - ap_free_sta(hapd, sta); -} - - -static void handle_beacon(struct hostapd_data *hapd, - const struct ieee80211_mgmt *mgmt, size_t len, - struct hostapd_frame_info *fi) -{ - struct ieee802_11_elems elems; - - if (len < IEEE80211_HDRLEN + sizeof(mgmt->u.beacon)) { - printf("handle_beacon - too short payload (len=%lu)\n", - (unsigned long) len); - return; - } - - (void) ieee802_11_parse_elems(mgmt->u.beacon.variable, - len - (IEEE80211_HDRLEN + - sizeof(mgmt->u.beacon)), &elems, - 0); - - ap_list_process_beacon(hapd->iface, mgmt, &elems, fi); -} - - -#ifdef CONFIG_IEEE80211W - -/* MLME-SAQuery.request */ -void ieee802_11_send_sa_query_req(struct hostapd_data *hapd, - const u8 *addr, const u8 *trans_id) -{ - struct ieee80211_mgmt mgmt; - u8 *end; - - wpa_printf(MSG_DEBUG, "IEEE 802.11: Sending SA Query Request to " - MACSTR, MAC2STR(addr)); - wpa_hexdump(MSG_DEBUG, "IEEE 802.11: SA Query Transaction ID", - trans_id, WLAN_SA_QUERY_TR_ID_LEN); - - os_memset(&mgmt, 0, sizeof(mgmt)); - mgmt.frame_control = IEEE80211_FC(WLAN_FC_TYPE_MGMT, - WLAN_FC_STYPE_ACTION); - os_memcpy(mgmt.da, addr, ETH_ALEN); - os_memcpy(mgmt.sa, hapd->own_addr, ETH_ALEN); - os_memcpy(mgmt.bssid, hapd->own_addr, ETH_ALEN); - mgmt.u.action.category = WLAN_ACTION_SA_QUERY; - mgmt.u.action.u.sa_query_req.action = WLAN_SA_QUERY_REQUEST; - os_memcpy(mgmt.u.action.u.sa_query_req.trans_id, trans_id, - WLAN_SA_QUERY_TR_ID_LEN); - end = mgmt.u.action.u.sa_query_req.trans_id + WLAN_SA_QUERY_TR_ID_LEN; - if (hostapd_drv_send_mlme(hapd, &mgmt, end - (u8 *) &mgmt) < 0) - perror("ieee802_11_send_sa_query_req: send"); -} - - -static void hostapd_sa_query_request(struct hostapd_data *hapd, - const struct ieee80211_mgmt *mgmt) -{ - struct sta_info *sta; - struct ieee80211_mgmt resp; - u8 *end; - - wpa_printf(MSG_DEBUG, "IEEE 802.11: Received SA Query Request from " - MACSTR, MAC2STR(mgmt->sa)); - wpa_hexdump(MSG_DEBUG, "IEEE 802.11: SA Query Transaction ID", - mgmt->u.action.u.sa_query_resp.trans_id, - WLAN_SA_QUERY_TR_ID_LEN); - - sta = ap_get_sta(hapd, mgmt->sa); - if (sta == NULL || !(sta->flags & WLAN_STA_ASSOC)) { - wpa_printf(MSG_DEBUG, "IEEE 802.11: Ignore SA Query Request " - "from unassociated STA " MACSTR, MAC2STR(mgmt->sa)); - return; - } - - wpa_printf(MSG_DEBUG, "IEEE 802.11: Sending SA Query Response to " - MACSTR, MAC2STR(mgmt->sa)); - - os_memset(&resp, 0, sizeof(resp)); - resp.frame_control = IEEE80211_FC(WLAN_FC_TYPE_MGMT, - WLAN_FC_STYPE_ACTION); - os_memcpy(resp.da, mgmt->sa, ETH_ALEN); - os_memcpy(resp.sa, hapd->own_addr, ETH_ALEN); - os_memcpy(resp.bssid, hapd->own_addr, ETH_ALEN); - resp.u.action.category = WLAN_ACTION_SA_QUERY; - resp.u.action.u.sa_query_req.action = WLAN_SA_QUERY_RESPONSE; - os_memcpy(resp.u.action.u.sa_query_req.trans_id, - mgmt->u.action.u.sa_query_req.trans_id, - WLAN_SA_QUERY_TR_ID_LEN); - end = resp.u.action.u.sa_query_req.trans_id + WLAN_SA_QUERY_TR_ID_LEN; - if (hostapd_drv_send_mlme(hapd, &resp, end - (u8 *) &resp) < 0) - perror("hostapd_sa_query_request: send"); -} - - -static void hostapd_sa_query_action(struct hostapd_data *hapd, - const struct ieee80211_mgmt *mgmt, - size_t len) -{ - struct sta_info *sta; - const u8 *end; - int i; - - end = mgmt->u.action.u.sa_query_resp.trans_id + - WLAN_SA_QUERY_TR_ID_LEN; - if (((u8 *) mgmt) + len < end) { - wpa_printf(MSG_DEBUG, "IEEE 802.11: Too short SA Query Action " - "frame (len=%lu)", (unsigned long) len); - return; - } - - if (mgmt->u.action.u.sa_query_resp.action == WLAN_SA_QUERY_REQUEST) { - hostapd_sa_query_request(hapd, mgmt); - return; - } - - if (mgmt->u.action.u.sa_query_resp.action != WLAN_SA_QUERY_RESPONSE) { - wpa_printf(MSG_DEBUG, "IEEE 802.11: Unexpected SA Query " - "Action %d", mgmt->u.action.u.sa_query_resp.action); - return; - } - - wpa_printf(MSG_DEBUG, "IEEE 802.11: Received SA Query Response from " - MACSTR, MAC2STR(mgmt->sa)); - wpa_hexdump(MSG_DEBUG, "IEEE 802.11: SA Query Transaction ID", - mgmt->u.action.u.sa_query_resp.trans_id, - WLAN_SA_QUERY_TR_ID_LEN); - - /* MLME-SAQuery.confirm */ - - sta = ap_get_sta(hapd, mgmt->sa); - if (sta == NULL || sta->sa_query_trans_id == NULL) { - wpa_printf(MSG_DEBUG, "IEEE 802.11: No matching STA with " - "pending SA Query request found"); - return; - } - - for (i = 0; i < sta->sa_query_count; i++) { - if (os_memcmp(sta->sa_query_trans_id + - i * WLAN_SA_QUERY_TR_ID_LEN, - mgmt->u.action.u.sa_query_resp.trans_id, - WLAN_SA_QUERY_TR_ID_LEN) == 0) - break; - } - - if (i >= sta->sa_query_count) { - wpa_printf(MSG_DEBUG, "IEEE 802.11: No matching SA Query " - "transaction identifier found"); - return; - } - - hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211, - HOSTAPD_LEVEL_DEBUG, - "Reply to pending SA Query received"); - ap_sta_stop_sa_query(hapd, sta); -} - - -static int robust_action_frame(u8 category) -{ - return category != WLAN_ACTION_PUBLIC && - category != WLAN_ACTION_HT; -} -#endif /* CONFIG_IEEE80211W */ - - -static void handle_action(struct hostapd_data *hapd, - const struct ieee80211_mgmt *mgmt, size_t len) -{ -#ifdef CONFIG_IEEE80211W - struct sta_info *sta; -#endif - - if (len < IEEE80211_HDRLEN + 1) { - hostapd_logger(hapd, mgmt->sa, HOSTAPD_MODULE_IEEE80211, - HOSTAPD_LEVEL_DEBUG, - "handle_action - too short payload (len=%lu)", - (unsigned long) len); - return; - } - -#ifdef CONFIG_IEEE80211W - sta = ap_get_sta(hapd, mgmt->sa); - if (sta && (sta->flags & WLAN_STA_MFP) && - !(mgmt->frame_control & host_to_le16(WLAN_FC_ISWEP) && - robust_action_frame(mgmt->u.action.category))) { - hostapd_logger(hapd, mgmt->sa, HOSTAPD_MODULE_IEEE80211, - HOSTAPD_LEVEL_DEBUG, - "Dropped unprotected Robust Action frame from " - "an MFP STA"); - return; - } -#endif /* CONFIG_IEEE80211W */ - - switch (mgmt->u.action.category) { -#ifdef CONFIG_IEEE80211R - case WLAN_ACTION_FT: - { - if (sta == NULL || !(sta->flags & WLAN_STA_ASSOC)) { - wpa_printf(MSG_DEBUG, "IEEE 802.11: Ignored FT Action " - "frame from unassociated STA " MACSTR, - MAC2STR(mgmt->sa)); - return; - } - - if (wpa_ft_action_rx(sta->wpa_sm, (u8 *) &mgmt->u.action, - len - IEEE80211_HDRLEN)) - break; - - return; - } -#endif /* CONFIG_IEEE80211R */ - case WLAN_ACTION_WMM: - hostapd_wmm_action(hapd, mgmt, len); - return; -#ifdef CONFIG_IEEE80211W - case WLAN_ACTION_SA_QUERY: - hostapd_sa_query_action(hapd, mgmt, len); - return; -#endif /* CONFIG_IEEE80211W */ - case WLAN_ACTION_PUBLIC: - if (hapd->public_action_cb) { - hapd->public_action_cb(hapd->public_action_cb_ctx, - (u8 *) mgmt, len, - hapd->iface->freq); - return; - } - break; - case WLAN_ACTION_VENDOR_SPECIFIC: - if (hapd->vendor_action_cb) { - if (hapd->vendor_action_cb(hapd->vendor_action_cb_ctx, - (u8 *) mgmt, len, - hapd->iface->freq) == 0) - return; - } - break; - } - - hostapd_logger(hapd, mgmt->sa, HOSTAPD_MODULE_IEEE80211, - HOSTAPD_LEVEL_DEBUG, - "handle_action - unknown action category %d or invalid " - "frame", - mgmt->u.action.category); - if (!(mgmt->da[0] & 0x01) && !(mgmt->u.action.category & 0x80) && - !(mgmt->sa[0] & 0x01)) { - struct ieee80211_mgmt *resp; - - /* - * IEEE 802.11-REVma/D9.0 - 7.3.1.11 - * Return the Action frame to the source without change - * except that MSB of the Category set to 1. - */ - wpa_printf(MSG_DEBUG, "IEEE 802.11: Return unknown Action " - "frame back to sender"); - resp = os_malloc(len); - if (resp == NULL) - return; - os_memcpy(resp, mgmt, len); - os_memcpy(resp->da, resp->sa, ETH_ALEN); - os_memcpy(resp->sa, hapd->own_addr, ETH_ALEN); - os_memcpy(resp->bssid, hapd->own_addr, ETH_ALEN); - resp->u.action.category |= 0x80; - - hostapd_drv_send_mlme(hapd, resp, len); - os_free(resp); - } -} - - -/** - * ieee802_11_mgmt - process incoming IEEE 802.11 management frames - * @hapd: hostapd BSS data structure (the BSS to which the management frame was - * sent to) - * @buf: management frame data (starting from IEEE 802.11 header) - * @len: length of frame data in octets - * @fi: meta data about received frame (signal level, etc.) - * - * Process all incoming IEEE 802.11 management frames. This will be called for - * each frame received from the kernel driver through wlan#ap interface. In - * addition, it can be called to re-inserted pending frames (e.g., when using - * external RADIUS server as an MAC ACL). - */ -void ieee802_11_mgmt(struct hostapd_data *hapd, const u8 *buf, size_t len, - struct hostapd_frame_info *fi) -{ - struct ieee80211_mgmt *mgmt; - int broadcast; - u16 fc, stype; - - if (len < 24) - return; - - mgmt = (struct ieee80211_mgmt *) buf; - fc = le_to_host16(mgmt->frame_control); - stype = WLAN_FC_GET_STYPE(fc); - - if (stype == WLAN_FC_STYPE_BEACON) { - handle_beacon(hapd, mgmt, len, fi); - return; - } - - broadcast = mgmt->bssid[0] == 0xff && mgmt->bssid[1] == 0xff && - mgmt->bssid[2] == 0xff && mgmt->bssid[3] == 0xff && - mgmt->bssid[4] == 0xff && mgmt->bssid[5] == 0xff; - - if (!broadcast && - os_memcmp(mgmt->bssid, hapd->own_addr, ETH_ALEN) != 0) { - printf("MGMT: BSSID=" MACSTR " not our address\n", - MAC2STR(mgmt->bssid)); - return; - } - - - if (stype == WLAN_FC_STYPE_PROBE_REQ) { - handle_probe_req(hapd, mgmt, len); - return; - } - - if (os_memcmp(mgmt->da, hapd->own_addr, ETH_ALEN) != 0) { - hostapd_logger(hapd, mgmt->sa, HOSTAPD_MODULE_IEEE80211, - HOSTAPD_LEVEL_DEBUG, - "MGMT: DA=" MACSTR " not our address", - MAC2STR(mgmt->da)); - return; - } - - switch (stype) { - case WLAN_FC_STYPE_AUTH: - wpa_printf(MSG_DEBUG, "mgmt::auth"); - handle_auth(hapd, mgmt, len); - break; - case WLAN_FC_STYPE_ASSOC_REQ: - wpa_printf(MSG_DEBUG, "mgmt::assoc_req"); - handle_assoc(hapd, mgmt, len, 0); - break; - case WLAN_FC_STYPE_REASSOC_REQ: - wpa_printf(MSG_DEBUG, "mgmt::reassoc_req"); - handle_assoc(hapd, mgmt, len, 1); - break; - case WLAN_FC_STYPE_DISASSOC: - wpa_printf(MSG_DEBUG, "mgmt::disassoc"); - handle_disassoc(hapd, mgmt, len); - break; - case WLAN_FC_STYPE_DEAUTH: - wpa_msg(hapd, MSG_DEBUG, "mgmt::deauth"); - handle_deauth(hapd, mgmt, len); - break; - case WLAN_FC_STYPE_ACTION: - wpa_printf(MSG_DEBUG, "mgmt::action"); - handle_action(hapd, mgmt, len); - break; - default: - hostapd_logger(hapd, mgmt->sa, HOSTAPD_MODULE_IEEE80211, - HOSTAPD_LEVEL_DEBUG, - "unknown mgmt frame subtype %d", stype); - break; - } -} - - -static void handle_auth_cb(struct hostapd_data *hapd, - const struct ieee80211_mgmt *mgmt, - size_t len, int ok) -{ - u16 auth_alg, auth_transaction, status_code; - struct sta_info *sta; - - if (!ok) { - hostapd_logger(hapd, mgmt->da, HOSTAPD_MODULE_IEEE80211, - HOSTAPD_LEVEL_NOTICE, - "did not acknowledge authentication response"); - return; - } - - if (len < IEEE80211_HDRLEN + sizeof(mgmt->u.auth)) { - printf("handle_auth_cb - too short payload (len=%lu)\n", - (unsigned long) len); - return; - } - - auth_alg = le_to_host16(mgmt->u.auth.auth_alg); - auth_transaction = le_to_host16(mgmt->u.auth.auth_transaction); - status_code = le_to_host16(mgmt->u.auth.status_code); - - sta = ap_get_sta(hapd, mgmt->da); - if (!sta) { - printf("handle_auth_cb: STA " MACSTR " not found\n", - MAC2STR(mgmt->da)); - return; - } - - if (status_code == WLAN_STATUS_SUCCESS && - ((auth_alg == WLAN_AUTH_OPEN && auth_transaction == 2) || - (auth_alg == WLAN_AUTH_SHARED_KEY && auth_transaction == 4))) { - hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211, - HOSTAPD_LEVEL_INFO, "authenticated"); - sta->flags |= WLAN_STA_AUTH; - } -} - - -static void handle_assoc_cb(struct hostapd_data *hapd, - const struct ieee80211_mgmt *mgmt, - size_t len, int reassoc, int ok) -{ - u16 status; - struct sta_info *sta; - int new_assoc = 1; - struct ieee80211_ht_capabilities ht_cap; - - if (!ok) { - hostapd_logger(hapd, mgmt->da, HOSTAPD_MODULE_IEEE80211, - HOSTAPD_LEVEL_DEBUG, - "did not acknowledge association response"); - return; - } - - if (len < IEEE80211_HDRLEN + (reassoc ? sizeof(mgmt->u.reassoc_resp) : - sizeof(mgmt->u.assoc_resp))) { - printf("handle_assoc_cb(reassoc=%d) - too short payload " - "(len=%lu)\n", reassoc, (unsigned long) len); - return; - } - - if (reassoc) - status = le_to_host16(mgmt->u.reassoc_resp.status_code); - else - status = le_to_host16(mgmt->u.assoc_resp.status_code); - - sta = ap_get_sta(hapd, mgmt->da); - if (!sta) { - printf("handle_assoc_cb: STA " MACSTR " not found\n", - MAC2STR(mgmt->da)); - return; - } - - if (status != WLAN_STATUS_SUCCESS) - goto fail; - - /* Stop previous accounting session, if one is started, and allocate - * new session id for the new session. */ - accounting_sta_stop(hapd, sta); - - hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211, - HOSTAPD_LEVEL_INFO, - "associated (aid %d)", - sta->aid); - - if (sta->flags & WLAN_STA_ASSOC) - new_assoc = 0; - sta->flags |= WLAN_STA_ASSOC; - if ((!hapd->conf->ieee802_1x && !hapd->conf->wpa) || - sta->auth_alg == WLAN_AUTH_FT) { - /* - * Open, static WEP, or FT protocol; no separate authorization - * step. - */ - ap_sta_set_authorized(hapd, sta, 1); - wpa_msg(hapd->msg_ctx, MSG_INFO, - AP_STA_CONNECTED MACSTR, MAC2STR(sta->addr)); - } - - if (reassoc) - mlme_reassociate_indication(hapd, sta); - else - mlme_associate_indication(hapd, sta); - -#ifdef CONFIG_IEEE80211W - sta->sa_query_timed_out = 0; -#endif /* CONFIG_IEEE80211W */ - - /* - * Remove the STA entry in order to make sure the STA PS state gets - * cleared and configuration gets updated in case of reassociation back - * to the same AP. - */ - hostapd_drv_sta_remove(hapd, sta->addr); - -#ifdef CONFIG_IEEE80211N - if (sta->flags & WLAN_STA_HT) - hostapd_get_ht_capab(hapd, sta->ht_capabilities, &ht_cap); -#endif /* CONFIG_IEEE80211N */ - - if (hostapd_sta_add(hapd, sta->addr, sta->aid, sta->capability, - sta->supported_rates, sta->supported_rates_len, - sta->listen_interval, - sta->flags & WLAN_STA_HT ? &ht_cap : NULL)) { - hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211, - HOSTAPD_LEVEL_NOTICE, - "Could not add STA to kernel driver"); - } - - if (sta->flags & WLAN_STA_WDS) - hostapd_set_wds_sta(hapd, sta->addr, sta->aid, 1); - - if (sta->eapol_sm == NULL) { - /* - * This STA does not use RADIUS server for EAP authentication, - * so bind it to the selected VLAN interface now, since the - * interface selection is not going to change anymore. - */ - if (ap_sta_bind_vlan(hapd, sta, 0) < 0) - goto fail; - } else if (sta->vlan_id) { - /* VLAN ID already set (e.g., by PMKSA caching), so bind STA */ - if (ap_sta_bind_vlan(hapd, sta, 0) < 0) - goto fail; - } - - hostapd_set_sta_flags(hapd, sta); - - if (sta->auth_alg == WLAN_AUTH_FT) - wpa_auth_sm_event(sta->wpa_sm, WPA_ASSOC_FT); - else - wpa_auth_sm_event(sta->wpa_sm, WPA_ASSOC); - hapd->new_assoc_sta_cb(hapd, sta, !new_assoc); - - ieee802_1x_notify_port_enabled(sta->eapol_sm, 1); - - fail: - /* Copy of the association request is not needed anymore */ - if (sta->last_assoc_req) { - os_free(sta->last_assoc_req); - sta->last_assoc_req = NULL; - } -} - - -/** - * ieee802_11_mgmt_cb - Process management frame TX status callback - * @hapd: hostapd BSS data structure (the BSS from which the management frame - * was sent from) - * @buf: management frame data (starting from IEEE 802.11 header) - * @len: length of frame data in octets - * @stype: management frame subtype from frame control field - * @ok: Whether the frame was ACK'ed - */ -void ieee802_11_mgmt_cb(struct hostapd_data *hapd, const u8 *buf, size_t len, - u16 stype, int ok) -{ - const struct ieee80211_mgmt *mgmt; - mgmt = (const struct ieee80211_mgmt *) buf; - - switch (stype) { - case WLAN_FC_STYPE_AUTH: - wpa_printf(MSG_DEBUG, "mgmt::auth cb"); - handle_auth_cb(hapd, mgmt, len, ok); - break; - case WLAN_FC_STYPE_ASSOC_RESP: - wpa_printf(MSG_DEBUG, "mgmt::assoc_resp cb"); - handle_assoc_cb(hapd, mgmt, len, 0, ok); - break; - case WLAN_FC_STYPE_REASSOC_RESP: - wpa_printf(MSG_DEBUG, "mgmt::reassoc_resp cb"); - handle_assoc_cb(hapd, mgmt, len, 1, ok); - break; - case WLAN_FC_STYPE_PROBE_RESP: - wpa_printf(MSG_EXCESSIVE, "mgmt::proberesp cb"); - break; - case WLAN_FC_STYPE_DEAUTH: - /* ignore */ - break; - case WLAN_FC_STYPE_ACTION: - wpa_printf(MSG_DEBUG, "mgmt::action cb"); - break; - default: - printf("unknown mgmt cb frame subtype %d\n", stype); - break; - } -} - - -int ieee802_11_get_mib(struct hostapd_data *hapd, char *buf, size_t buflen) -{ - /* TODO */ - return 0; -} - - -int ieee802_11_get_mib_sta(struct hostapd_data *hapd, struct sta_info *sta, - char *buf, size_t buflen) -{ - /* TODO */ - return 0; -} - - -void hostapd_tx_status(struct hostapd_data *hapd, const u8 *addr, - const u8 *buf, size_t len, int ack) -{ - struct sta_info *sta; - struct hostapd_iface *iface = hapd->iface; - - sta = ap_get_sta(hapd, addr); - if (sta == NULL && iface->num_bss > 1) { - size_t j; - for (j = 0; j < iface->num_bss; j++) { - hapd = iface->bss[j]; - sta = ap_get_sta(hapd, addr); - if (sta) - break; - } - } - if (sta == NULL) - return; - if (sta->flags & WLAN_STA_PENDING_POLL) { - wpa_printf(MSG_DEBUG, "STA " MACSTR " %s pending " - "activity poll", MAC2STR(sta->addr), - ack ? "ACKed" : "did not ACK"); - if (ack) - sta->flags &= ~WLAN_STA_PENDING_POLL; - } - - ieee802_1x_tx_status(hapd, sta, buf, len, ack); -} - - -void ieee802_11_rx_from_unknown(struct hostapd_data *hapd, const u8 *src, - int wds) -{ - struct sta_info *sta; - - sta = ap_get_sta(hapd, src); - if (sta && (sta->flags & WLAN_STA_ASSOC)) { - if (wds && !(sta->flags & WLAN_STA_WDS)) { - wpa_printf(MSG_DEBUG, "Enable 4-address WDS mode for " - "STA " MACSTR " (aid %u)", - MAC2STR(sta->addr), sta->aid); - sta->flags |= WLAN_STA_WDS; - hostapd_set_wds_sta(hapd, sta->addr, sta->aid, 1); - } - return; - } - - wpa_printf(MSG_DEBUG, "Data/PS-poll frame from not associated STA " - MACSTR, MAC2STR(src)); - if (src[0] & 0x01) { - /* Broadcast bit set in SA?! Ignore the frame silently. */ - return; - } - - if (sta && (sta->flags & WLAN_STA_ASSOC_REQ_OK)) { - wpa_printf(MSG_DEBUG, "Association Response to the STA has " - "already been sent, but no TX status yet known - " - "ignore Class 3 frame issue with " MACSTR, - MAC2STR(src)); - return; - } - - if (sta && (sta->flags & WLAN_STA_AUTH)) - hostapd_drv_sta_disassoc( - hapd, src, - WLAN_REASON_CLASS3_FRAME_FROM_NONASSOC_STA); - else - hostapd_drv_sta_deauth( - hapd, src, - WLAN_REASON_CLASS3_FRAME_FROM_NONASSOC_STA); -} - - -#endif /* CONFIG_NATIVE_WINDOWS */ diff --git a/hostapd-0.8/src/ap/ieee802_11.h b/hostapd-0.8/src/ap/ieee802_11.h deleted file mode 100644 index 157198c..0000000 --- a/hostapd-0.8/src/ap/ieee802_11.h +++ /dev/null @@ -1,68 +0,0 @@ -/* - * hostapd / IEEE 802.11 Management - * Copyright (c) 2002-2009, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#ifndef IEEE802_11_H -#define IEEE802_11_H - -struct hostapd_iface; -struct hostapd_data; -struct sta_info; -struct hostapd_frame_info; -struct ieee80211_ht_capabilities; - -void ieee802_11_mgmt(struct hostapd_data *hapd, const u8 *buf, size_t len, - struct hostapd_frame_info *fi); -void ieee802_11_mgmt_cb(struct hostapd_data *hapd, const u8 *buf, size_t len, - u16 stype, int ok); -void ieee802_11_print_ssid(char *buf, const u8 *ssid, u8 len); -#ifdef NEED_AP_MLME -int ieee802_11_get_mib(struct hostapd_data *hapd, char *buf, size_t buflen); -int ieee802_11_get_mib_sta(struct hostapd_data *hapd, struct sta_info *sta, - char *buf, size_t buflen); -#else /* NEED_AP_MLME */ -static inline int ieee802_11_get_mib(struct hostapd_data *hapd, char *buf, - size_t buflen) -{ - return 0; -} - -static inline int ieee802_11_get_mib_sta(struct hostapd_data *hapd, - struct sta_info *sta, - char *buf, size_t buflen) -{ - return 0; -} -#endif /* NEED_AP_MLME */ -u16 hostapd_own_capab_info(struct hostapd_data *hapd, struct sta_info *sta, - int probe); -u8 * hostapd_eid_ext_capab(struct hostapd_data *hapd, u8 *eid); -u8 * hostapd_eid_supp_rates(struct hostapd_data *hapd, u8 *eid); -u8 * hostapd_eid_ext_supp_rates(struct hostapd_data *hapd, u8 *eid); -u8 * hostapd_eid_ht_capabilities(struct hostapd_data *hapd, u8 *eid); -u8 * hostapd_eid_ht_operation(struct hostapd_data *hapd, u8 *eid); -int hostapd_ht_operation_update(struct hostapd_iface *iface); -void ieee802_11_send_sa_query_req(struct hostapd_data *hapd, - const u8 *addr, const u8 *trans_id); -void hostapd_get_ht_capab(struct hostapd_data *hapd, - struct ieee80211_ht_capabilities *ht_cap, - struct ieee80211_ht_capabilities *neg_ht_cap); -u16 copy_sta_ht_capab(struct hostapd_data *hapd, struct sta_info *sta, - const u8 *ht_capab, size_t ht_capab_len); -void update_ht_state(struct hostapd_data *hapd, struct sta_info *sta); -void hostapd_tx_status(struct hostapd_data *hapd, const u8 *addr, - const u8 *buf, size_t len, int ack); -void ieee802_11_rx_from_unknown(struct hostapd_data *hapd, const u8 *src, - int wds); - -#endif /* IEEE802_11_H */ diff --git a/hostapd-0.8/src/ap/ieee802_11_auth.c b/hostapd-0.8/src/ap/ieee802_11_auth.c deleted file mode 100644 index b933263..0000000 --- a/hostapd-0.8/src/ap/ieee802_11_auth.c +++ /dev/null @@ -1,524 +0,0 @@ -/* - * hostapd / IEEE 802.11 authentication (ACL) - * Copyright (c) 2003-2009, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - * - * Access control list for IEEE 802.11 authentication can uses statically - * configured ACL from configuration files or an external RADIUS server. - * Results from external RADIUS queries are cached to allow faster - * authentication frame processing. - */ - -#include "utils/includes.h" - -#include "utils/common.h" -#include "utils/eloop.h" -#include "radius/radius.h" -#include "radius/radius_client.h" -#include "hostapd.h" -#include "ap_config.h" -#include "ap_drv_ops.h" -#include "ieee802_11.h" -#include "ieee802_11_auth.h" - -#define RADIUS_ACL_TIMEOUT 30 - - -struct hostapd_cached_radius_acl { - os_time_t timestamp; - macaddr addr; - int accepted; /* HOSTAPD_ACL_* */ - struct hostapd_cached_radius_acl *next; - u32 session_timeout; - u32 acct_interim_interval; - int vlan_id; -}; - - -struct hostapd_acl_query_data { - os_time_t timestamp; - u8 radius_id; - macaddr addr; - u8 *auth_msg; /* IEEE 802.11 authentication frame from station */ - size_t auth_msg_len; - struct hostapd_acl_query_data *next; -}; - - -#ifndef CONFIG_NO_RADIUS -static void hostapd_acl_cache_free(struct hostapd_cached_radius_acl *acl_cache) -{ - struct hostapd_cached_radius_acl *prev; - - while (acl_cache) { - prev = acl_cache; - acl_cache = acl_cache->next; - os_free(prev); - } -} - - -static int hostapd_acl_cache_get(struct hostapd_data *hapd, const u8 *addr, - u32 *session_timeout, - u32 *acct_interim_interval, int *vlan_id) -{ - struct hostapd_cached_radius_acl *entry; - struct os_time now; - - os_get_time(&now); - entry = hapd->acl_cache; - - while (entry) { - if (os_memcmp(entry->addr, addr, ETH_ALEN) == 0) { - if (now.sec - entry->timestamp > RADIUS_ACL_TIMEOUT) - return -1; /* entry has expired */ - if (entry->accepted == HOSTAPD_ACL_ACCEPT_TIMEOUT) - if (session_timeout) - *session_timeout = - entry->session_timeout; - if (acct_interim_interval) - *acct_interim_interval = - entry->acct_interim_interval; - if (vlan_id) - *vlan_id = entry->vlan_id; - return entry->accepted; - } - - entry = entry->next; - } - - return -1; -} -#endif /* CONFIG_NO_RADIUS */ - - -static void hostapd_acl_query_free(struct hostapd_acl_query_data *query) -{ - if (query == NULL) - return; - os_free(query->auth_msg); - os_free(query); -} - - -#ifndef CONFIG_NO_RADIUS -static int hostapd_radius_acl_query(struct hostapd_data *hapd, const u8 *addr, - struct hostapd_acl_query_data *query) -{ - struct radius_msg *msg; - char buf[128]; - - query->radius_id = radius_client_get_id(hapd->radius); - msg = radius_msg_new(RADIUS_CODE_ACCESS_REQUEST, query->radius_id); - if (msg == NULL) - return -1; - - radius_msg_make_authenticator(msg, addr, ETH_ALEN); - - os_snprintf(buf, sizeof(buf), RADIUS_ADDR_FORMAT, MAC2STR(addr)); - if (!radius_msg_add_attr(msg, RADIUS_ATTR_USER_NAME, (u8 *) buf, - os_strlen(buf))) { - wpa_printf(MSG_DEBUG, "Could not add User-Name"); - goto fail; - } - - if (!radius_msg_add_attr_user_password( - msg, (u8 *) buf, os_strlen(buf), - hapd->conf->radius->auth_server->shared_secret, - hapd->conf->radius->auth_server->shared_secret_len)) { - wpa_printf(MSG_DEBUG, "Could not add User-Password"); - goto fail; - } - - if (hapd->conf->own_ip_addr.af == AF_INET && - !radius_msg_add_attr(msg, RADIUS_ATTR_NAS_IP_ADDRESS, - (u8 *) &hapd->conf->own_ip_addr.u.v4, 4)) { - wpa_printf(MSG_DEBUG, "Could not add NAS-IP-Address"); - goto fail; - } - -#ifdef CONFIG_IPV6 - if (hapd->conf->own_ip_addr.af == AF_INET6 && - !radius_msg_add_attr(msg, RADIUS_ATTR_NAS_IPV6_ADDRESS, - (u8 *) &hapd->conf->own_ip_addr.u.v6, 16)) { - wpa_printf(MSG_DEBUG, "Could not add NAS-IPv6-Address"); - goto fail; - } -#endif /* CONFIG_IPV6 */ - - if (hapd->conf->nas_identifier && - !radius_msg_add_attr(msg, RADIUS_ATTR_NAS_IDENTIFIER, - (u8 *) hapd->conf->nas_identifier, - os_strlen(hapd->conf->nas_identifier))) { - wpa_printf(MSG_DEBUG, "Could not add NAS-Identifier"); - goto fail; - } - - os_snprintf(buf, sizeof(buf), RADIUS_802_1X_ADDR_FORMAT ":%s", - MAC2STR(hapd->own_addr), hapd->conf->ssid.ssid); - if (!radius_msg_add_attr(msg, RADIUS_ATTR_CALLED_STATION_ID, - (u8 *) buf, os_strlen(buf))) { - wpa_printf(MSG_DEBUG, "Could not add Called-Station-Id"); - goto fail; - } - - os_snprintf(buf, sizeof(buf), RADIUS_802_1X_ADDR_FORMAT, - MAC2STR(addr)); - if (!radius_msg_add_attr(msg, RADIUS_ATTR_CALLING_STATION_ID, - (u8 *) buf, os_strlen(buf))) { - wpa_printf(MSG_DEBUG, "Could not add Calling-Station-Id"); - goto fail; - } - - if (!radius_msg_add_attr_int32(msg, RADIUS_ATTR_NAS_PORT_TYPE, - RADIUS_NAS_PORT_TYPE_IEEE_802_11)) { - wpa_printf(MSG_DEBUG, "Could not add NAS-Port-Type"); - goto fail; - } - - os_snprintf(buf, sizeof(buf), "CONNECT 11Mbps 802.11b"); - if (!radius_msg_add_attr(msg, RADIUS_ATTR_CONNECT_INFO, - (u8 *) buf, os_strlen(buf))) { - wpa_printf(MSG_DEBUG, "Could not add Connect-Info"); - goto fail; - } - - radius_client_send(hapd->radius, msg, RADIUS_AUTH, addr); - return 0; - - fail: - radius_msg_free(msg); - return -1; -} -#endif /* CONFIG_NO_RADIUS */ - - -/** - * hostapd_allowed_address - Check whether a specified STA can be authenticated - * @hapd: hostapd BSS data - * @addr: MAC address of the STA - * @msg: Authentication message - * @len: Length of msg in octets - * @session_timeout: Buffer for returning session timeout (from RADIUS) - * @acct_interim_interval: Buffer for returning account interval (from RADIUS) - * @vlan_id: Buffer for returning VLAN ID - * Returns: HOSTAPD_ACL_ACCEPT, HOSTAPD_ACL_REJECT, or HOSTAPD_ACL_PENDING - */ -int hostapd_allowed_address(struct hostapd_data *hapd, const u8 *addr, - const u8 *msg, size_t len, u32 *session_timeout, - u32 *acct_interim_interval, int *vlan_id) -{ - if (session_timeout) - *session_timeout = 0; - if (acct_interim_interval) - *acct_interim_interval = 0; - if (vlan_id) - *vlan_id = 0; - - if (hostapd_maclist_found(hapd->conf->accept_mac, - hapd->conf->num_accept_mac, addr, vlan_id)) - return HOSTAPD_ACL_ACCEPT; - - if (hostapd_maclist_found(hapd->conf->deny_mac, - hapd->conf->num_deny_mac, addr, vlan_id)) - return HOSTAPD_ACL_REJECT; - - if (hapd->conf->macaddr_acl == ACCEPT_UNLESS_DENIED) - return HOSTAPD_ACL_ACCEPT; - if (hapd->conf->macaddr_acl == DENY_UNLESS_ACCEPTED) - return HOSTAPD_ACL_REJECT; - - if (hapd->conf->macaddr_acl == USE_EXTERNAL_RADIUS_AUTH) { -#ifdef CONFIG_NO_RADIUS - return HOSTAPD_ACL_REJECT; -#else /* CONFIG_NO_RADIUS */ - struct hostapd_acl_query_data *query; - - /* Check whether ACL cache has an entry for this station */ - int res = hostapd_acl_cache_get(hapd, addr, session_timeout, - acct_interim_interval, - vlan_id); - if (res == HOSTAPD_ACL_ACCEPT || - res == HOSTAPD_ACL_ACCEPT_TIMEOUT) - return res; - if (res == HOSTAPD_ACL_REJECT) - return HOSTAPD_ACL_REJECT; - - query = hapd->acl_queries; - while (query) { - if (os_memcmp(query->addr, addr, ETH_ALEN) == 0) { - /* pending query in RADIUS retransmit queue; - * do not generate a new one */ - return HOSTAPD_ACL_PENDING; - } - query = query->next; - } - - if (!hapd->conf->radius->auth_server) - return HOSTAPD_ACL_REJECT; - - /* No entry in the cache - query external RADIUS server */ - query = os_zalloc(sizeof(*query)); - if (query == NULL) { - wpa_printf(MSG_ERROR, "malloc for query data failed"); - return HOSTAPD_ACL_REJECT; - } - time(&query->timestamp); - os_memcpy(query->addr, addr, ETH_ALEN); - if (hostapd_radius_acl_query(hapd, addr, query)) { - wpa_printf(MSG_DEBUG, "Failed to send Access-Request " - "for ACL query."); - hostapd_acl_query_free(query); - return HOSTAPD_ACL_REJECT; - } - - query->auth_msg = os_malloc(len); - if (query->auth_msg == NULL) { - wpa_printf(MSG_ERROR, "Failed to allocate memory for " - "auth frame."); - hostapd_acl_query_free(query); - return HOSTAPD_ACL_REJECT; - } - os_memcpy(query->auth_msg, msg, len); - query->auth_msg_len = len; - query->next = hapd->acl_queries; - hapd->acl_queries = query; - - /* Queued data will be processed in hostapd_acl_recv_radius() - * when RADIUS server replies to the sent Access-Request. */ - return HOSTAPD_ACL_PENDING; -#endif /* CONFIG_NO_RADIUS */ - } - - return HOSTAPD_ACL_REJECT; -} - - -#ifndef CONFIG_NO_RADIUS -static void hostapd_acl_expire_cache(struct hostapd_data *hapd, os_time_t now) -{ - struct hostapd_cached_radius_acl *prev, *entry, *tmp; - - prev = NULL; - entry = hapd->acl_cache; - - while (entry) { - if (now - entry->timestamp > RADIUS_ACL_TIMEOUT) { - wpa_printf(MSG_DEBUG, "Cached ACL entry for " MACSTR - " has expired.", MAC2STR(entry->addr)); - if (prev) - prev->next = entry->next; - else - hapd->acl_cache = entry->next; - hostapd_drv_set_radius_acl_expire(hapd, entry->addr); - tmp = entry; - entry = entry->next; - os_free(tmp); - continue; - } - - prev = entry; - entry = entry->next; - } -} - - -static void hostapd_acl_expire_queries(struct hostapd_data *hapd, - os_time_t now) -{ - struct hostapd_acl_query_data *prev, *entry, *tmp; - - prev = NULL; - entry = hapd->acl_queries; - - while (entry) { - if (now - entry->timestamp > RADIUS_ACL_TIMEOUT) { - wpa_printf(MSG_DEBUG, "ACL query for " MACSTR - " has expired.", MAC2STR(entry->addr)); - if (prev) - prev->next = entry->next; - else - hapd->acl_queries = entry->next; - - tmp = entry; - entry = entry->next; - hostapd_acl_query_free(tmp); - continue; - } - - prev = entry; - entry = entry->next; - } -} - - -/** - * hostapd_acl_expire - ACL cache expiration callback - * @eloop_ctx: struct hostapd_data * - * @timeout_ctx: Not used - */ -static void hostapd_acl_expire(void *eloop_ctx, void *timeout_ctx) -{ - struct hostapd_data *hapd = eloop_ctx; - struct os_time now; - - os_get_time(&now); - hostapd_acl_expire_cache(hapd, now.sec); - hostapd_acl_expire_queries(hapd, now.sec); - - eloop_register_timeout(10, 0, hostapd_acl_expire, hapd, NULL); -} - - -/** - * hostapd_acl_recv_radius - Process incoming RADIUS Authentication messages - * @msg: RADIUS response message - * @req: RADIUS request message - * @shared_secret: RADIUS shared secret - * @shared_secret_len: Length of shared_secret in octets - * @data: Context data (struct hostapd_data *) - * Returns: RADIUS_RX_PROCESSED if RADIUS message was a reply to ACL query (and - * was processed here) or RADIUS_RX_UNKNOWN if not. - */ -static RadiusRxResult -hostapd_acl_recv_radius(struct radius_msg *msg, struct radius_msg *req, - const u8 *shared_secret, size_t shared_secret_len, - void *data) -{ - struct hostapd_data *hapd = data; - struct hostapd_acl_query_data *query, *prev; - struct hostapd_cached_radius_acl *cache; - struct radius_hdr *hdr = radius_msg_get_hdr(msg); - - query = hapd->acl_queries; - prev = NULL; - while (query) { - if (query->radius_id == hdr->identifier) - break; - prev = query; - query = query->next; - } - if (query == NULL) - return RADIUS_RX_UNKNOWN; - - wpa_printf(MSG_DEBUG, "Found matching Access-Request for RADIUS " - "message (id=%d)", query->radius_id); - - if (radius_msg_verify(msg, shared_secret, shared_secret_len, req, 0)) { - wpa_printf(MSG_INFO, "Incoming RADIUS packet did not have " - "correct authenticator - dropped\n"); - return RADIUS_RX_INVALID_AUTHENTICATOR; - } - - if (hdr->code != RADIUS_CODE_ACCESS_ACCEPT && - hdr->code != RADIUS_CODE_ACCESS_REJECT) { - wpa_printf(MSG_DEBUG, "Unknown RADIUS message code %d to ACL " - "query", hdr->code); - return RADIUS_RX_UNKNOWN; - } - - /* Insert Accept/Reject info into ACL cache */ - cache = os_zalloc(sizeof(*cache)); - if (cache == NULL) { - wpa_printf(MSG_DEBUG, "Failed to add ACL cache entry"); - goto done; - } - time(&cache->timestamp); - os_memcpy(cache->addr, query->addr, sizeof(cache->addr)); - if (hdr->code == RADIUS_CODE_ACCESS_ACCEPT) { - if (radius_msg_get_attr_int32(msg, RADIUS_ATTR_SESSION_TIMEOUT, - &cache->session_timeout) == 0) - cache->accepted = HOSTAPD_ACL_ACCEPT_TIMEOUT; - else - cache->accepted = HOSTAPD_ACL_ACCEPT; - - if (radius_msg_get_attr_int32( - msg, RADIUS_ATTR_ACCT_INTERIM_INTERVAL, - &cache->acct_interim_interval) == 0 && - cache->acct_interim_interval < 60) { - wpa_printf(MSG_DEBUG, "Ignored too small " - "Acct-Interim-Interval %d for STA " MACSTR, - cache->acct_interim_interval, - MAC2STR(query->addr)); - cache->acct_interim_interval = 0; - } - - cache->vlan_id = radius_msg_get_vlanid(msg); - } else - cache->accepted = HOSTAPD_ACL_REJECT; - cache->next = hapd->acl_cache; - hapd->acl_cache = cache; - -#ifdef CONFIG_DRIVER_RADIUS_ACL - hostapd_drv_set_radius_acl_auth(hapd, query->addr, cache->accepted, - cache->session_timeout); -#else /* CONFIG_DRIVER_RADIUS_ACL */ -#ifdef NEED_AP_MLME - /* Re-send original authentication frame for 802.11 processing */ - wpa_printf(MSG_DEBUG, "Re-sending authentication frame after " - "successful RADIUS ACL query"); - ieee802_11_mgmt(hapd, query->auth_msg, query->auth_msg_len, NULL); -#endif /* NEED_AP_MLME */ -#endif /* CONFIG_DRIVER_RADIUS_ACL */ - - done: - if (prev == NULL) - hapd->acl_queries = query->next; - else - prev->next = query->next; - - hostapd_acl_query_free(query); - - return RADIUS_RX_PROCESSED; -} -#endif /* CONFIG_NO_RADIUS */ - - -/** - * hostapd_acl_init: Initialize IEEE 802.11 ACL - * @hapd: hostapd BSS data - * Returns: 0 on success, -1 on failure - */ -int hostapd_acl_init(struct hostapd_data *hapd) -{ -#ifndef CONFIG_NO_RADIUS - if (radius_client_register(hapd->radius, RADIUS_AUTH, - hostapd_acl_recv_radius, hapd)) - return -1; - - eloop_register_timeout(10, 0, hostapd_acl_expire, hapd, NULL); -#endif /* CONFIG_NO_RADIUS */ - - return 0; -} - - -/** - * hostapd_acl_deinit - Deinitialize IEEE 802.11 ACL - * @hapd: hostapd BSS data - */ -void hostapd_acl_deinit(struct hostapd_data *hapd) -{ - struct hostapd_acl_query_data *query, *prev; - -#ifndef CONFIG_NO_RADIUS - eloop_cancel_timeout(hostapd_acl_expire, hapd, NULL); - - hostapd_acl_cache_free(hapd->acl_cache); -#endif /* CONFIG_NO_RADIUS */ - - query = hapd->acl_queries; - while (query) { - prev = query; - query = query->next; - hostapd_acl_query_free(prev); - } -} diff --git a/hostapd-0.8/src/ap/ieee802_11_auth.h b/hostapd-0.8/src/ap/ieee802_11_auth.h deleted file mode 100644 index b2971e5..0000000 --- a/hostapd-0.8/src/ap/ieee802_11_auth.h +++ /dev/null @@ -1,31 +0,0 @@ -/* - * hostapd / IEEE 802.11 authentication (ACL) - * Copyright (c) 2003-2005, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#ifndef IEEE802_11_AUTH_H -#define IEEE802_11_AUTH_H - -enum { - HOSTAPD_ACL_REJECT = 0, - HOSTAPD_ACL_ACCEPT = 1, - HOSTAPD_ACL_PENDING = 2, - HOSTAPD_ACL_ACCEPT_TIMEOUT = 3 -}; - -int hostapd_allowed_address(struct hostapd_data *hapd, const u8 *addr, - const u8 *msg, size_t len, u32 *session_timeout, - u32 *acct_interim_interval, int *vlan_id); -int hostapd_acl_init(struct hostapd_data *hapd); -void hostapd_acl_deinit(struct hostapd_data *hapd); - -#endif /* IEEE802_11_AUTH_H */ diff --git a/hostapd-0.8/src/ap/ieee802_11_ht.c b/hostapd-0.8/src/ap/ieee802_11_ht.c deleted file mode 100644 index 3dce5cb..0000000 --- a/hostapd-0.8/src/ap/ieee802_11_ht.c +++ /dev/null @@ -1,267 +0,0 @@ -/* - * hostapd / IEEE 802.11n HT - * Copyright (c) 2002-2009, Jouni Malinen - * Copyright (c) 2007-2008, Intel Corporation - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#include "utils/includes.h" - -#include "utils/common.h" -#include "common/ieee802_11_defs.h" -#include "drivers/driver.h" -#include "hostapd.h" -#include "ap_config.h" -#include "sta_info.h" -#include "beacon.h" -#include "ieee802_11.h" - - -u8 * hostapd_eid_ht_capabilities(struct hostapd_data *hapd, u8 *eid) -{ - struct ieee80211_ht_capabilities *cap; - u8 *pos = eid; - - if (!hapd->iconf->ieee80211n || !hapd->iface->current_mode || - hapd->conf->disable_11n) - return eid; - - *pos++ = WLAN_EID_HT_CAP; - *pos++ = sizeof(*cap); - - cap = (struct ieee80211_ht_capabilities *) pos; - os_memset(cap, 0, sizeof(*cap)); - cap->ht_capabilities_info = host_to_le16(hapd->iconf->ht_capab); - cap->a_mpdu_params = hapd->iface->current_mode->a_mpdu_params; - os_memcpy(cap->supported_mcs_set, hapd->iface->current_mode->mcs_set, - 16); - - /* TODO: ht_extended_capabilities (now fully disabled) */ - /* TODO: tx_bf_capability_info (now fully disabled) */ - /* TODO: asel_capabilities (now fully disabled) */ - - pos += sizeof(*cap); - - return pos; -} - - -u8 * hostapd_eid_ht_operation(struct hostapd_data *hapd, u8 *eid) -{ - struct ieee80211_ht_operation *oper; - u8 *pos = eid; - - if (!hapd->iconf->ieee80211n || hapd->conf->disable_11n) - return eid; - - *pos++ = WLAN_EID_HT_OPERATION; - *pos++ = sizeof(*oper); - - oper = (struct ieee80211_ht_operation *) pos; - os_memset(oper, 0, sizeof(*oper)); - - oper->control_chan = hapd->iconf->channel; - oper->operation_mode = host_to_le16(hapd->iface->ht_op_mode); - if (hapd->iconf->secondary_channel == 1) - oper->ht_param |= HT_INFO_HT_PARAM_SECONDARY_CHNL_ABOVE | - HT_INFO_HT_PARAM_REC_TRANS_CHNL_WIDTH; - if (hapd->iconf->secondary_channel == -1) - oper->ht_param |= HT_INFO_HT_PARAM_SECONDARY_CHNL_BELOW | - HT_INFO_HT_PARAM_REC_TRANS_CHNL_WIDTH; - - pos += sizeof(*oper); - - return pos; -} - - -/* -op_mode -Set to 0 (HT pure) under the followign conditions - - all STAs in the BSS are 20/40 MHz HT in 20/40 MHz BSS or - - all STAs in the BSS are 20 MHz HT in 20 MHz BSS -Set to 1 (HT non-member protection) if there may be non-HT STAs - in both the primary and the secondary channel -Set to 2 if only HT STAs are associated in BSS, - however and at least one 20 MHz HT STA is associated -Set to 3 (HT mixed mode) when one or more non-HT STAs are associated -*/ -int hostapd_ht_operation_update(struct hostapd_iface *iface) -{ - u16 cur_op_mode, new_op_mode; - int op_mode_changes = 0; - - if (!iface->conf->ieee80211n || iface->conf->ht_op_mode_fixed) - return 0; - - wpa_printf(MSG_DEBUG, "%s current operation mode=0x%X", - __func__, iface->ht_op_mode); - - if (!(iface->ht_op_mode & HT_INFO_OPERATION_MODE_NON_GF_DEVS_PRESENT) - && iface->num_sta_ht_no_gf) { - iface->ht_op_mode |= - HT_INFO_OPERATION_MODE_NON_GF_DEVS_PRESENT; - op_mode_changes++; - } else if ((iface->ht_op_mode & - HT_INFO_OPERATION_MODE_NON_GF_DEVS_PRESENT) && - iface->num_sta_ht_no_gf == 0) { - iface->ht_op_mode &= - ~HT_INFO_OPERATION_MODE_NON_GF_DEVS_PRESENT; - op_mode_changes++; - } - - if (!(iface->ht_op_mode & HT_INFO_OPERATION_MODE_NON_HT_STA_PRESENT) && - (iface->num_sta_no_ht || iface->olbc_ht)) { - iface->ht_op_mode |= HT_INFO_OPERATION_MODE_NON_HT_STA_PRESENT; - op_mode_changes++; - } else if ((iface->ht_op_mode & - HT_INFO_OPERATION_MODE_NON_HT_STA_PRESENT) && - (iface->num_sta_no_ht == 0 && !iface->olbc_ht)) { - iface->ht_op_mode &= - ~HT_INFO_OPERATION_MODE_NON_HT_STA_PRESENT; - op_mode_changes++; - } - - new_op_mode = 0; - if (iface->num_sta_no_ht) - new_op_mode = OP_MODE_MIXED; - else if ((iface->conf->ht_capab & HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET) - && iface->num_sta_ht_20mhz) - new_op_mode = OP_MODE_20MHZ_HT_STA_ASSOCED; - else if (iface->olbc_ht) - new_op_mode = OP_MODE_MAY_BE_LEGACY_STAS; - else - new_op_mode = OP_MODE_PURE; - - cur_op_mode = iface->ht_op_mode & HT_INFO_OPERATION_MODE_OP_MODE_MASK; - if (cur_op_mode != new_op_mode) { - iface->ht_op_mode &= ~HT_INFO_OPERATION_MODE_OP_MODE_MASK; - iface->ht_op_mode |= new_op_mode; - op_mode_changes++; - } - - wpa_printf(MSG_DEBUG, "%s new operation mode=0x%X changes=%d", - __func__, iface->ht_op_mode, op_mode_changes); - - return op_mode_changes; -} - - -u16 copy_sta_ht_capab(struct hostapd_data *hapd, struct sta_info *sta, - const u8 *ht_capab, size_t ht_capab_len) -{ - /* Disable HT caps for STAs associated to no-HT BSSes. */ - if (!ht_capab || - ht_capab_len < sizeof(struct ieee80211_ht_capabilities) || - hapd->conf->disable_11n) { - sta->flags &= ~WLAN_STA_HT; - os_free(sta->ht_capabilities); - sta->ht_capabilities = NULL; - return WLAN_STATUS_SUCCESS; - } - - if (sta->ht_capabilities == NULL) { - sta->ht_capabilities = - os_zalloc(sizeof(struct ieee80211_ht_capabilities)); - if (sta->ht_capabilities == NULL) - return WLAN_STATUS_UNSPECIFIED_FAILURE; - } - - sta->flags |= WLAN_STA_HT; - os_memcpy(sta->ht_capabilities, ht_capab, - sizeof(struct ieee80211_ht_capabilities)); - - return WLAN_STATUS_SUCCESS; -} - - -static void update_sta_ht(struct hostapd_data *hapd, struct sta_info *sta) -{ - u16 ht_capab; - - ht_capab = le_to_host16(sta->ht_capabilities->ht_capabilities_info); - wpa_printf(MSG_DEBUG, "HT: STA " MACSTR " HT Capabilities Info: " - "0x%04x", MAC2STR(sta->addr), ht_capab); - if ((ht_capab & HT_CAP_INFO_GREEN_FIELD) == 0) { - if (!sta->no_ht_gf_set) { - sta->no_ht_gf_set = 1; - hapd->iface->num_sta_ht_no_gf++; - } - wpa_printf(MSG_DEBUG, "%s STA " MACSTR " - no greenfield, num " - "of non-gf stations %d", - __func__, MAC2STR(sta->addr), - hapd->iface->num_sta_ht_no_gf); - } - if ((ht_capab & HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET) == 0) { - if (!sta->ht_20mhz_set) { - sta->ht_20mhz_set = 1; - hapd->iface->num_sta_ht_20mhz++; - } - wpa_printf(MSG_DEBUG, "%s STA " MACSTR " - 20 MHz HT, num of " - "20MHz HT STAs %d", - __func__, MAC2STR(sta->addr), - hapd->iface->num_sta_ht_20mhz); - } -} - - -static void update_sta_no_ht(struct hostapd_data *hapd, struct sta_info *sta) -{ - if (!sta->no_ht_set) { - sta->no_ht_set = 1; - hapd->iface->num_sta_no_ht++; - } - if (hapd->iconf->ieee80211n) { - wpa_printf(MSG_DEBUG, "%s STA " MACSTR " - no HT, num of " - "non-HT stations %d", - __func__, MAC2STR(sta->addr), - hapd->iface->num_sta_no_ht); - } -} - - -void update_ht_state(struct hostapd_data *hapd, struct sta_info *sta) -{ - if ((sta->flags & WLAN_STA_HT) && sta->ht_capabilities) - update_sta_ht(hapd, sta); - else - update_sta_no_ht(hapd, sta); - - if (hostapd_ht_operation_update(hapd->iface) > 0) - ieee802_11_set_beacons(hapd->iface); -} - - -void hostapd_get_ht_capab(struct hostapd_data *hapd, - struct ieee80211_ht_capabilities *ht_cap, - struct ieee80211_ht_capabilities *neg_ht_cap) -{ - u16 cap; - - if (ht_cap == NULL) - return; - os_memcpy(neg_ht_cap, ht_cap, sizeof(*neg_ht_cap)); - cap = le_to_host16(neg_ht_cap->ht_capabilities_info); - cap &= hapd->iconf->ht_capab; - cap |= (hapd->iconf->ht_capab & HT_CAP_INFO_SMPS_DISABLED); - - /* - * STBC needs to be handled specially - * if we don't support RX STBC, mask out TX STBC in the STA's HT caps - * if we don't support TX STBC, mask out RX STBC in the STA's HT caps - */ - if (!(hapd->iconf->ht_capab & HT_CAP_INFO_RX_STBC_MASK)) - cap &= ~HT_CAP_INFO_TX_STBC; - if (!(hapd->iconf->ht_capab & HT_CAP_INFO_TX_STBC)) - cap &= ~HT_CAP_INFO_RX_STBC_MASK; - - neg_ht_cap->ht_capabilities_info = host_to_le16(cap); -} diff --git a/hostapd-0.8/src/ap/ieee802_1x.c b/hostapd-0.8/src/ap/ieee802_1x.c deleted file mode 100644 index ac0c127..0000000 --- a/hostapd-0.8/src/ap/ieee802_1x.c +++ /dev/null @@ -1,2085 +0,0 @@ -/* - * hostapd / IEEE 802.1X-2004 Authenticator - * Copyright (c) 2002-2011, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#include "utils/includes.h" - -#include "utils/common.h" -#include "utils/eloop.h" -#include "crypto/md5.h" -#include "crypto/crypto.h" -#include "crypto/random.h" -#include "common/ieee802_11_defs.h" -#include "common/wpa_ctrl.h" -#include "radius/radius.h" -#include "radius/radius_client.h" -#include "eap_server/eap.h" -#include "eap_common/eap_wsc_common.h" -#include "eapol_auth/eapol_auth_sm.h" -#include "eapol_auth/eapol_auth_sm_i.h" -#include "hostapd.h" -#include "accounting.h" -#include "sta_info.h" -#include "wpa_auth.h" -#include "preauth_auth.h" -#include "pmksa_cache_auth.h" -#include "ap_config.h" -#include "ap_drv_ops.h" -#include "ieee802_1x.h" - - -static void ieee802_1x_finished(struct hostapd_data *hapd, - struct sta_info *sta, int success); - - -static void ieee802_1x_send(struct hostapd_data *hapd, struct sta_info *sta, - u8 type, const u8 *data, size_t datalen) -{ - u8 *buf; - struct ieee802_1x_hdr *xhdr; - size_t len; - int encrypt = 0; - - len = sizeof(*xhdr) + datalen; - buf = os_zalloc(len); - if (buf == NULL) { - wpa_printf(MSG_ERROR, "malloc() failed for " - "ieee802_1x_send(len=%lu)", - (unsigned long) len); - return; - } - - xhdr = (struct ieee802_1x_hdr *) buf; - xhdr->version = hapd->conf->eapol_version; - xhdr->type = type; - xhdr->length = host_to_be16(datalen); - - if (datalen > 0 && data != NULL) - os_memcpy(xhdr + 1, data, datalen); - - if (wpa_auth_pairwise_set(sta->wpa_sm)) - encrypt = 1; - if (sta->flags & WLAN_STA_PREAUTH) { - rsn_preauth_send(hapd, sta, buf, len); - } else { - hostapd_drv_hapd_send_eapol(hapd, sta->addr, buf, len, - encrypt, sta->flags); - } - - os_free(buf); -} - - -void ieee802_1x_set_sta_authorized(struct hostapd_data *hapd, - struct sta_info *sta, int authorized) -{ - int res; - - if (sta->flags & WLAN_STA_PREAUTH) - return; - - if (authorized) { - if (!ap_sta_is_authorized(sta)) - wpa_msg(hapd->msg_ctx, MSG_INFO, - AP_STA_CONNECTED MACSTR, MAC2STR(sta->addr)); - ap_sta_set_authorized(hapd, sta, 1); - res = hostapd_set_authorized(hapd, sta, 1); - hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE8021X, - HOSTAPD_LEVEL_DEBUG, "authorizing port"); - } else { - if (ap_sta_is_authorized(sta) && (sta->flags & WLAN_STA_ASSOC)) - wpa_msg(hapd->msg_ctx, MSG_INFO, - AP_STA_DISCONNECTED MACSTR, - MAC2STR(sta->addr)); - ap_sta_set_authorized(hapd, sta, 0); - res = hostapd_set_authorized(hapd, sta, 0); - hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE8021X, - HOSTAPD_LEVEL_DEBUG, "unauthorizing port"); - } - - if (res && errno != ENOENT) { - printf("Could not set station " MACSTR " flags for kernel " - "driver (errno=%d).\n", MAC2STR(sta->addr), errno); - } - - if (authorized) - accounting_sta_start(hapd, sta); -} - - -static void ieee802_1x_tx_key_one(struct hostapd_data *hapd, - struct sta_info *sta, - int idx, int broadcast, - u8 *key_data, size_t key_len) -{ - u8 *buf, *ekey; - struct ieee802_1x_hdr *hdr; - struct ieee802_1x_eapol_key *key; - size_t len, ekey_len; - struct eapol_state_machine *sm = sta->eapol_sm; - - if (sm == NULL) - return; - - len = sizeof(*key) + key_len; - buf = os_zalloc(sizeof(*hdr) + len); - if (buf == NULL) - return; - - hdr = (struct ieee802_1x_hdr *) buf; - key = (struct ieee802_1x_eapol_key *) (hdr + 1); - key->type = EAPOL_KEY_TYPE_RC4; - key->key_length = htons(key_len); - wpa_get_ntp_timestamp(key->replay_counter); - - if (random_get_bytes(key->key_iv, sizeof(key->key_iv))) { - wpa_printf(MSG_ERROR, "Could not get random numbers"); - os_free(buf); - return; - } - - key->key_index = idx | (broadcast ? 0 : BIT(7)); - if (hapd->conf->eapol_key_index_workaround) { - /* According to some information, WinXP Supplicant seems to - * interpret bit7 as an indication whether the key is to be - * activated, so make it possible to enable workaround that - * sets this bit for all keys. */ - key->key_index |= BIT(7); - } - - /* Key is encrypted using "Key-IV + MSK[0..31]" as the RC4-key and - * MSK[32..63] is used to sign the message. */ - if (sm->eap_if->eapKeyData == NULL || sm->eap_if->eapKeyDataLen < 64) { - wpa_printf(MSG_ERROR, "No eapKeyData available for encrypting " - "and signing EAPOL-Key"); - os_free(buf); - return; - } - os_memcpy((u8 *) (key + 1), key_data, key_len); - ekey_len = sizeof(key->key_iv) + 32; - ekey = os_malloc(ekey_len); - if (ekey == NULL) { - wpa_printf(MSG_ERROR, "Could not encrypt key"); - os_free(buf); - return; - } - os_memcpy(ekey, key->key_iv, sizeof(key->key_iv)); - os_memcpy(ekey + sizeof(key->key_iv), sm->eap_if->eapKeyData, 32); - rc4_skip(ekey, ekey_len, 0, (u8 *) (key + 1), key_len); - os_free(ekey); - - /* This header is needed here for HMAC-MD5, but it will be regenerated - * in ieee802_1x_send() */ - hdr->version = hapd->conf->eapol_version; - hdr->type = IEEE802_1X_TYPE_EAPOL_KEY; - hdr->length = host_to_be16(len); - hmac_md5(sm->eap_if->eapKeyData + 32, 32, buf, sizeof(*hdr) + len, - key->key_signature); - - wpa_printf(MSG_DEBUG, "IEEE 802.1X: Sending EAPOL-Key to " MACSTR - " (%s index=%d)", MAC2STR(sm->addr), - broadcast ? "broadcast" : "unicast", idx); - ieee802_1x_send(hapd, sta, IEEE802_1X_TYPE_EAPOL_KEY, (u8 *) key, len); - if (sta->eapol_sm) - sta->eapol_sm->dot1xAuthEapolFramesTx++; - os_free(buf); -} - - -#ifndef CONFIG_NO_VLAN -static struct hostapd_wep_keys * -ieee802_1x_group_alloc(struct hostapd_data *hapd, const char *ifname) -{ - struct hostapd_wep_keys *key; - - key = os_zalloc(sizeof(*key)); - if (key == NULL) - return NULL; - - key->default_len = hapd->conf->default_wep_key_len; - - if (key->idx >= hapd->conf->broadcast_key_idx_max || - key->idx < hapd->conf->broadcast_key_idx_min) - key->idx = hapd->conf->broadcast_key_idx_min; - else - key->idx++; - - if (!key->key[key->idx]) - key->key[key->idx] = os_malloc(key->default_len); - if (key->key[key->idx] == NULL || - random_get_bytes(key->key[key->idx], key->default_len)) { - printf("Could not generate random WEP key (dynamic VLAN).\n"); - os_free(key->key[key->idx]); - key->key[key->idx] = NULL; - os_free(key); - return NULL; - } - key->len[key->idx] = key->default_len; - - wpa_printf(MSG_DEBUG, "%s: Default WEP idx %d for dynamic VLAN\n", - ifname, key->idx); - wpa_hexdump_key(MSG_DEBUG, "Default WEP key (dynamic VLAN)", - key->key[key->idx], key->len[key->idx]); - - if (hostapd_drv_set_key(ifname, hapd, WPA_ALG_WEP, - broadcast_ether_addr, key->idx, 1, - NULL, 0, key->key[key->idx], - key->len[key->idx])) - printf("Could not set dynamic VLAN WEP encryption key.\n"); - - hostapd_set_drv_ieee8021x(hapd, ifname, 1); - - return key; -} - - -static struct hostapd_wep_keys * -ieee802_1x_get_group(struct hostapd_data *hapd, struct hostapd_ssid *ssid, - size_t vlan_id) -{ - const char *ifname; - - if (vlan_id == 0) - return &ssid->wep; - - if (vlan_id <= ssid->max_dyn_vlan_keys && ssid->dyn_vlan_keys && - ssid->dyn_vlan_keys[vlan_id]) - return ssid->dyn_vlan_keys[vlan_id]; - - wpa_printf(MSG_DEBUG, "IEEE 802.1X: Creating new group " - "state machine for VLAN ID %lu", - (unsigned long) vlan_id); - - ifname = hostapd_get_vlan_id_ifname(hapd->conf->vlan, vlan_id); - if (ifname == NULL) { - wpa_printf(MSG_DEBUG, "IEEE 802.1X: Unknown VLAN ID %lu - " - "cannot create group key state machine", - (unsigned long) vlan_id); - return NULL; - } - - if (ssid->dyn_vlan_keys == NULL) { - int size = (vlan_id + 1) * sizeof(ssid->dyn_vlan_keys[0]); - ssid->dyn_vlan_keys = os_zalloc(size); - if (ssid->dyn_vlan_keys == NULL) - return NULL; - ssid->max_dyn_vlan_keys = vlan_id; - } - - if (ssid->max_dyn_vlan_keys < vlan_id) { - struct hostapd_wep_keys **na; - int size = (vlan_id + 1) * sizeof(ssid->dyn_vlan_keys[0]); - na = os_realloc(ssid->dyn_vlan_keys, size); - if (na == NULL) - return NULL; - ssid->dyn_vlan_keys = na; - os_memset(&ssid->dyn_vlan_keys[ssid->max_dyn_vlan_keys + 1], 0, - (vlan_id - ssid->max_dyn_vlan_keys) * - sizeof(ssid->dyn_vlan_keys[0])); - ssid->max_dyn_vlan_keys = vlan_id; - } - - ssid->dyn_vlan_keys[vlan_id] = ieee802_1x_group_alloc(hapd, ifname); - - return ssid->dyn_vlan_keys[vlan_id]; -} -#endif /* CONFIG_NO_VLAN */ - - -void ieee802_1x_tx_key(struct hostapd_data *hapd, struct sta_info *sta) -{ - struct eapol_authenticator *eapol = hapd->eapol_auth; - struct eapol_state_machine *sm = sta->eapol_sm; -#ifndef CONFIG_NO_VLAN - struct hostapd_wep_keys *key = NULL; - int vlan_id; -#endif /* CONFIG_NO_VLAN */ - - if (sm == NULL || !sm->eap_if->eapKeyData) - return; - - wpa_printf(MSG_DEBUG, "IEEE 802.1X: Sending EAPOL-Key(s) to " MACSTR, - MAC2STR(sta->addr)); - -#ifndef CONFIG_NO_VLAN - vlan_id = sta->vlan_id; - if (vlan_id < 0 || vlan_id > MAX_VLAN_ID) - vlan_id = 0; - - if (vlan_id) { - key = ieee802_1x_get_group(hapd, sta->ssid, vlan_id); - if (key && key->key[key->idx]) - ieee802_1x_tx_key_one(hapd, sta, key->idx, 1, - key->key[key->idx], - key->len[key->idx]); - } else -#endif /* CONFIG_NO_VLAN */ - if (eapol->default_wep_key) { - ieee802_1x_tx_key_one(hapd, sta, eapol->default_wep_key_idx, 1, - eapol->default_wep_key, - hapd->conf->default_wep_key_len); - } - - if (hapd->conf->individual_wep_key_len > 0) { - u8 *ikey; - ikey = os_malloc(hapd->conf->individual_wep_key_len); - if (ikey == NULL || - random_get_bytes(ikey, hapd->conf->individual_wep_key_len)) - { - wpa_printf(MSG_ERROR, "Could not generate random " - "individual WEP key."); - os_free(ikey); - return; - } - - wpa_hexdump_key(MSG_DEBUG, "Individual WEP key", - ikey, hapd->conf->individual_wep_key_len); - - ieee802_1x_tx_key_one(hapd, sta, 0, 0, ikey, - hapd->conf->individual_wep_key_len); - - /* TODO: set encryption in TX callback, i.e., only after STA - * has ACKed EAPOL-Key frame */ - if (hostapd_drv_set_key(hapd->conf->iface, hapd, WPA_ALG_WEP, - sta->addr, 0, 1, NULL, 0, ikey, - hapd->conf->individual_wep_key_len)) { - wpa_printf(MSG_ERROR, "Could not set individual WEP " - "encryption."); - } - - os_free(ikey); - } -} - - -const char *radius_mode_txt(struct hostapd_data *hapd) -{ - switch (hapd->iface->conf->hw_mode) { - case HOSTAPD_MODE_IEEE80211A: - return "802.11a"; - case HOSTAPD_MODE_IEEE80211G: - return "802.11g"; - case HOSTAPD_MODE_IEEE80211B: - default: - return "802.11b"; - } -} - - -int radius_sta_rate(struct hostapd_data *hapd, struct sta_info *sta) -{ - int i; - u8 rate = 0; - - for (i = 0; i < sta->supported_rates_len; i++) - if ((sta->supported_rates[i] & 0x7f) > rate) - rate = sta->supported_rates[i] & 0x7f; - - return rate; -} - - -#ifndef CONFIG_NO_RADIUS -static void ieee802_1x_learn_identity(struct hostapd_data *hapd, - struct eapol_state_machine *sm, - const u8 *eap, size_t len) -{ - const u8 *identity; - size_t identity_len; - - if (len <= sizeof(struct eap_hdr) || - eap[sizeof(struct eap_hdr)] != EAP_TYPE_IDENTITY) - return; - - identity = eap_get_identity(sm->eap, &identity_len); - if (identity == NULL) - return; - - /* Save station identity for future RADIUS packets */ - os_free(sm->identity); - sm->identity = os_malloc(identity_len + 1); - if (sm->identity == NULL) { - sm->identity_len = 0; - return; - } - - os_memcpy(sm->identity, identity, identity_len); - sm->identity_len = identity_len; - sm->identity[identity_len] = '\0'; - hostapd_logger(hapd, sm->addr, HOSTAPD_MODULE_IEEE8021X, - HOSTAPD_LEVEL_DEBUG, "STA identity '%s'", sm->identity); - sm->dot1xAuthEapolRespIdFramesRx++; -} - - -static void ieee802_1x_encapsulate_radius(struct hostapd_data *hapd, - struct sta_info *sta, - const u8 *eap, size_t len) -{ - struct radius_msg *msg; - char buf[128]; - struct eapol_state_machine *sm = sta->eapol_sm; - - if (sm == NULL) - return; - - ieee802_1x_learn_identity(hapd, sm, eap, len); - - wpa_printf(MSG_DEBUG, "Encapsulating EAP message into a RADIUS " - "packet"); - - sm->radius_identifier = radius_client_get_id(hapd->radius); - msg = radius_msg_new(RADIUS_CODE_ACCESS_REQUEST, - sm->radius_identifier); - if (msg == NULL) { - printf("Could not create net RADIUS packet\n"); - return; - } - - radius_msg_make_authenticator(msg, (u8 *) sta, sizeof(*sta)); - - if (sm->identity && - !radius_msg_add_attr(msg, RADIUS_ATTR_USER_NAME, - sm->identity, sm->identity_len)) { - printf("Could not add User-Name\n"); - goto fail; - } - - if (hapd->conf->own_ip_addr.af == AF_INET && - !radius_msg_add_attr(msg, RADIUS_ATTR_NAS_IP_ADDRESS, - (u8 *) &hapd->conf->own_ip_addr.u.v4, 4)) { - printf("Could not add NAS-IP-Address\n"); - goto fail; - } - -#ifdef CONFIG_IPV6 - if (hapd->conf->own_ip_addr.af == AF_INET6 && - !radius_msg_add_attr(msg, RADIUS_ATTR_NAS_IPV6_ADDRESS, - (u8 *) &hapd->conf->own_ip_addr.u.v6, 16)) { - printf("Could not add NAS-IPv6-Address\n"); - goto fail; - } -#endif /* CONFIG_IPV6 */ - - if (hapd->conf->nas_identifier && - !radius_msg_add_attr(msg, RADIUS_ATTR_NAS_IDENTIFIER, - (u8 *) hapd->conf->nas_identifier, - os_strlen(hapd->conf->nas_identifier))) { - printf("Could not add NAS-Identifier\n"); - goto fail; - } - - if (!radius_msg_add_attr_int32(msg, RADIUS_ATTR_NAS_PORT, sta->aid)) { - printf("Could not add NAS-Port\n"); - goto fail; - } - - os_snprintf(buf, sizeof(buf), RADIUS_802_1X_ADDR_FORMAT ":%s", - MAC2STR(hapd->own_addr), hapd->conf->ssid.ssid); - buf[sizeof(buf) - 1] = '\0'; - if (!radius_msg_add_attr(msg, RADIUS_ATTR_CALLED_STATION_ID, - (u8 *) buf, os_strlen(buf))) { - printf("Could not add Called-Station-Id\n"); - goto fail; - } - - os_snprintf(buf, sizeof(buf), RADIUS_802_1X_ADDR_FORMAT, - MAC2STR(sta->addr)); - buf[sizeof(buf) - 1] = '\0'; - if (!radius_msg_add_attr(msg, RADIUS_ATTR_CALLING_STATION_ID, - (u8 *) buf, os_strlen(buf))) { - printf("Could not add Calling-Station-Id\n"); - goto fail; - } - - /* TODO: should probably check MTU from driver config; 2304 is max for - * IEEE 802.11, but use 1400 to avoid problems with too large packets - */ - if (!radius_msg_add_attr_int32(msg, RADIUS_ATTR_FRAMED_MTU, 1400)) { - printf("Could not add Framed-MTU\n"); - goto fail; - } - - if (!radius_msg_add_attr_int32(msg, RADIUS_ATTR_NAS_PORT_TYPE, - RADIUS_NAS_PORT_TYPE_IEEE_802_11)) { - printf("Could not add NAS-Port-Type\n"); - goto fail; - } - - if (sta->flags & WLAN_STA_PREAUTH) { - os_strlcpy(buf, "IEEE 802.11i Pre-Authentication", - sizeof(buf)); - } else { - os_snprintf(buf, sizeof(buf), "CONNECT %d%sMbps %s", - radius_sta_rate(hapd, sta) / 2, - (radius_sta_rate(hapd, sta) & 1) ? ".5" : "", - radius_mode_txt(hapd)); - buf[sizeof(buf) - 1] = '\0'; - } - if (!radius_msg_add_attr(msg, RADIUS_ATTR_CONNECT_INFO, - (u8 *) buf, os_strlen(buf))) { - printf("Could not add Connect-Info\n"); - goto fail; - } - - if (eap && !radius_msg_add_eap(msg, eap, len)) { - printf("Could not add EAP-Message\n"); - goto fail; - } - - /* State attribute must be copied if and only if this packet is - * Access-Request reply to the previous Access-Challenge */ - if (sm->last_recv_radius && - radius_msg_get_hdr(sm->last_recv_radius)->code == - RADIUS_CODE_ACCESS_CHALLENGE) { - int res = radius_msg_copy_attr(msg, sm->last_recv_radius, - RADIUS_ATTR_STATE); - if (res < 0) { - printf("Could not copy State attribute from previous " - "Access-Challenge\n"); - goto fail; - } - if (res > 0) { - wpa_printf(MSG_DEBUG, "Copied RADIUS State Attribute"); - } - } - - if (radius_client_send(hapd->radius, msg, RADIUS_AUTH, sta->addr) < 0) - goto fail; - - return; - - fail: - radius_msg_free(msg); -} -#endif /* CONFIG_NO_RADIUS */ - - -static void handle_eap_response(struct hostapd_data *hapd, - struct sta_info *sta, struct eap_hdr *eap, - size_t len) -{ - u8 type, *data; - struct eapol_state_machine *sm = sta->eapol_sm; - if (sm == NULL) - return; - - data = (u8 *) (eap + 1); - - if (len < sizeof(*eap) + 1) { - printf("handle_eap_response: too short response data\n"); - return; - } - - sm->eap_type_supp = type = data[0]; - - hostapd_logger(hapd, sm->addr, HOSTAPD_MODULE_IEEE8021X, - HOSTAPD_LEVEL_DEBUG, "received EAP packet (code=%d " - "id=%d len=%d) from STA: EAP Response-%s (%d)", - eap->code, eap->identifier, be_to_host16(eap->length), - eap_server_get_name(0, type), type); - - sm->dot1xAuthEapolRespFramesRx++; - - wpabuf_free(sm->eap_if->eapRespData); - sm->eap_if->eapRespData = wpabuf_alloc_copy(eap, len); - sm->eapolEap = TRUE; -} - - -/* Process incoming EAP packet from Supplicant */ -static void handle_eap(struct hostapd_data *hapd, struct sta_info *sta, - u8 *buf, size_t len) -{ - struct eap_hdr *eap; - u16 eap_len; - - if (len < sizeof(*eap)) { - printf(" too short EAP packet\n"); - return; - } - - eap = (struct eap_hdr *) buf; - - eap_len = be_to_host16(eap->length); - wpa_printf(MSG_DEBUG, "EAP: code=%d identifier=%d length=%d", - eap->code, eap->identifier, eap_len); - if (eap_len < sizeof(*eap)) { - wpa_printf(MSG_DEBUG, " Invalid EAP length"); - return; - } else if (eap_len > len) { - wpa_printf(MSG_DEBUG, " Too short frame to contain this EAP " - "packet"); - return; - } else if (eap_len < len) { - wpa_printf(MSG_DEBUG, " Ignoring %lu extra bytes after EAP " - "packet", (unsigned long) len - eap_len); - } - - switch (eap->code) { - case EAP_CODE_REQUEST: - wpa_printf(MSG_DEBUG, " (request)"); - return; - case EAP_CODE_RESPONSE: - wpa_printf(MSG_DEBUG, " (response)"); - handle_eap_response(hapd, sta, eap, eap_len); - break; - case EAP_CODE_SUCCESS: - wpa_printf(MSG_DEBUG, " (success)"); - return; - case EAP_CODE_FAILURE: - wpa_printf(MSG_DEBUG, " (failure)"); - return; - default: - wpa_printf(MSG_DEBUG, " (unknown code)"); - return; - } -} - - -static struct eapol_state_machine * -ieee802_1x_alloc_eapol_sm(struct hostapd_data *hapd, struct sta_info *sta) -{ - int flags = 0; - if (sta->flags & WLAN_STA_PREAUTH) - flags |= EAPOL_SM_PREAUTH; - if (sta->wpa_sm) { - flags |= EAPOL_SM_USES_WPA; - if (wpa_auth_sta_get_pmksa(sta->wpa_sm)) - flags |= EAPOL_SM_FROM_PMKSA_CACHE; - } - return eapol_auth_alloc(hapd->eapol_auth, sta->addr, flags, - sta->wps_ie, sta->p2p_ie, sta); -} - - -/** - * ieee802_1x_receive - Process the EAPOL frames from the Supplicant - * @hapd: hostapd BSS data - * @sa: Source address (sender of the EAPOL frame) - * @buf: EAPOL frame - * @len: Length of buf in octets - * - * This function is called for each incoming EAPOL frame from the interface - */ -void ieee802_1x_receive(struct hostapd_data *hapd, const u8 *sa, const u8 *buf, - size_t len) -{ - struct sta_info *sta; - struct ieee802_1x_hdr *hdr; - struct ieee802_1x_eapol_key *key; - u16 datalen; - struct rsn_pmksa_cache_entry *pmksa; - int key_mgmt; - - if (!hapd->conf->ieee802_1x && !hapd->conf->wpa && - !hapd->conf->wps_state) - return; - - wpa_printf(MSG_DEBUG, "IEEE 802.1X: %lu bytes from " MACSTR, - (unsigned long) len, MAC2STR(sa)); - sta = ap_get_sta(hapd, sa); - if (!sta || !(sta->flags & (WLAN_STA_ASSOC | WLAN_STA_PREAUTH))) { - wpa_printf(MSG_DEBUG, "IEEE 802.1X data frame from not " - "associated/Pre-authenticating STA"); - return; - } - - if (len < sizeof(*hdr)) { - printf(" too short IEEE 802.1X packet\n"); - return; - } - - hdr = (struct ieee802_1x_hdr *) buf; - datalen = be_to_host16(hdr->length); - wpa_printf(MSG_DEBUG, " IEEE 802.1X: version=%d type=%d length=%d", - hdr->version, hdr->type, datalen); - - if (len - sizeof(*hdr) < datalen) { - printf(" frame too short for this IEEE 802.1X packet\n"); - if (sta->eapol_sm) - sta->eapol_sm->dot1xAuthEapLengthErrorFramesRx++; - return; - } - if (len - sizeof(*hdr) > datalen) { - wpa_printf(MSG_DEBUG, " ignoring %lu extra octets after " - "IEEE 802.1X packet", - (unsigned long) len - sizeof(*hdr) - datalen); - } - - if (sta->eapol_sm) { - sta->eapol_sm->dot1xAuthLastEapolFrameVersion = hdr->version; - sta->eapol_sm->dot1xAuthEapolFramesRx++; - } - - key = (struct ieee802_1x_eapol_key *) (hdr + 1); - if (datalen >= sizeof(struct ieee802_1x_eapol_key) && - hdr->type == IEEE802_1X_TYPE_EAPOL_KEY && - (key->type == EAPOL_KEY_TYPE_WPA || - key->type == EAPOL_KEY_TYPE_RSN)) { - wpa_receive(hapd->wpa_auth, sta->wpa_sm, (u8 *) hdr, - sizeof(*hdr) + datalen); - return; - } - - if (!hapd->conf->ieee802_1x && - !(sta->flags & (WLAN_STA_WPS | WLAN_STA_MAYBE_WPS))) { - wpa_printf(MSG_DEBUG, "IEEE 802.1X: Ignore EAPOL message - " - "802.1X not enabled and WPS not used"); - return; - } - - key_mgmt = wpa_auth_sta_key_mgmt(sta->wpa_sm); - if (key_mgmt != -1 && wpa_key_mgmt_wpa_psk(key_mgmt)) { - wpa_printf(MSG_DEBUG, "IEEE 802.1X: Ignore EAPOL message - " - "STA is using PSK"); - return; - } - - if (!sta->eapol_sm) { - sta->eapol_sm = ieee802_1x_alloc_eapol_sm(hapd, sta); - if (!sta->eapol_sm) - return; - -#ifdef CONFIG_WPS - if (!hapd->conf->ieee802_1x && - ((sta->flags & (WLAN_STA_WPS | WLAN_STA_MAYBE_WPS)) == - WLAN_STA_MAYBE_WPS)) { - /* - * Delay EAPOL frame transmission until a possible WPS - * STA initiates the handshake with EAPOL-Start. - */ - sta->eapol_sm->flags |= EAPOL_SM_WAIT_START; - } -#endif /* CONFIG_WPS */ - - sta->eapol_sm->eap_if->portEnabled = TRUE; - } - - /* since we support version 1, we can ignore version field and proceed - * as specified in version 1 standard [IEEE Std 802.1X-2001, 7.5.5] */ - /* TODO: actually, we are not version 1 anymore.. However, Version 2 - * does not change frame contents, so should be ok to process frames - * more or less identically. Some changes might be needed for - * verification of fields. */ - - switch (hdr->type) { - case IEEE802_1X_TYPE_EAP_PACKET: - handle_eap(hapd, sta, (u8 *) (hdr + 1), datalen); - break; - - case IEEE802_1X_TYPE_EAPOL_START: - hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE8021X, - HOSTAPD_LEVEL_DEBUG, "received EAPOL-Start " - "from STA"); - sta->eapol_sm->flags &= ~EAPOL_SM_WAIT_START; - pmksa = wpa_auth_sta_get_pmksa(sta->wpa_sm); - if (pmksa) { - hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_WPA, - HOSTAPD_LEVEL_DEBUG, "cached PMKSA " - "available - ignore it since " - "STA sent EAPOL-Start"); - wpa_auth_sta_clear_pmksa(sta->wpa_sm, pmksa); - } - sta->eapol_sm->eapolStart = TRUE; - sta->eapol_sm->dot1xAuthEapolStartFramesRx++; - eap_server_clear_identity(sta->eapol_sm->eap); - wpa_auth_sm_event(sta->wpa_sm, WPA_REAUTH_EAPOL); - break; - - case IEEE802_1X_TYPE_EAPOL_LOGOFF: - hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE8021X, - HOSTAPD_LEVEL_DEBUG, "received EAPOL-Logoff " - "from STA"); - sta->acct_terminate_cause = - RADIUS_ACCT_TERMINATE_CAUSE_USER_REQUEST; - accounting_sta_stop(hapd, sta); - sta->eapol_sm->eapolLogoff = TRUE; - sta->eapol_sm->dot1xAuthEapolLogoffFramesRx++; - eap_server_clear_identity(sta->eapol_sm->eap); - break; - - case IEEE802_1X_TYPE_EAPOL_KEY: - wpa_printf(MSG_DEBUG, " EAPOL-Key"); - if (!ap_sta_is_authorized(sta)) { - wpa_printf(MSG_DEBUG, " Dropped key data from " - "unauthorized Supplicant"); - break; - } - break; - - case IEEE802_1X_TYPE_EAPOL_ENCAPSULATED_ASF_ALERT: - wpa_printf(MSG_DEBUG, " EAPOL-Encapsulated-ASF-Alert"); - /* TODO: implement support for this; show data */ - break; - - default: - wpa_printf(MSG_DEBUG, " unknown IEEE 802.1X packet type"); - sta->eapol_sm->dot1xAuthInvalidEapolFramesRx++; - break; - } - - eapol_auth_step(sta->eapol_sm); -} - - -/** - * ieee802_1x_new_station - Start IEEE 802.1X authentication - * @hapd: hostapd BSS data - * @sta: The station - * - * This function is called to start IEEE 802.1X authentication when a new - * station completes IEEE 802.11 association. - */ -void ieee802_1x_new_station(struct hostapd_data *hapd, struct sta_info *sta) -{ - struct rsn_pmksa_cache_entry *pmksa; - int reassoc = 1; - int force_1x = 0; - int key_mgmt; - -#ifdef CONFIG_WPS - if (hapd->conf->wps_state && hapd->conf->wpa && - (sta->flags & (WLAN_STA_WPS | WLAN_STA_MAYBE_WPS))) { - /* - * Need to enable IEEE 802.1X/EAPOL state machines for possible - * WPS handshake even if IEEE 802.1X/EAPOL is not used for - * authentication in this BSS. - */ - force_1x = 1; - } -#endif /* CONFIG_WPS */ - - if (!force_1x && !hapd->conf->ieee802_1x) { - wpa_printf(MSG_DEBUG, "IEEE 802.1X: Ignore STA - " - "802.1X not enabled or forced for WPS"); - return; - } - - key_mgmt = wpa_auth_sta_key_mgmt(sta->wpa_sm); - if (key_mgmt != -1 && wpa_key_mgmt_wpa_psk(key_mgmt)) { - wpa_printf(MSG_DEBUG, "IEEE 802.1X: Ignore STA - using PSK"); - return; - } - - if (sta->eapol_sm == NULL) { - hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE8021X, - HOSTAPD_LEVEL_DEBUG, "start authentication"); - sta->eapol_sm = ieee802_1x_alloc_eapol_sm(hapd, sta); - if (sta->eapol_sm == NULL) { - hostapd_logger(hapd, sta->addr, - HOSTAPD_MODULE_IEEE8021X, - HOSTAPD_LEVEL_INFO, - "failed to allocate state machine"); - return; - } - reassoc = 0; - } - -#ifdef CONFIG_WPS - sta->eapol_sm->flags &= ~EAPOL_SM_WAIT_START; - if (!hapd->conf->ieee802_1x && !(sta->flags & WLAN_STA_WPS)) { - /* - * Delay EAPOL frame transmission until a possible WPS - * initiates the handshake with EAPOL-Start. - */ - sta->eapol_sm->flags |= EAPOL_SM_WAIT_START; - } -#endif /* CONFIG_WPS */ - - sta->eapol_sm->eap_if->portEnabled = TRUE; - -#ifdef CONFIG_IEEE80211R - if (sta->auth_alg == WLAN_AUTH_FT) { - hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE8021X, - HOSTAPD_LEVEL_DEBUG, - "PMK from FT - skip IEEE 802.1X/EAP"); - /* Setup EAPOL state machines to already authenticated state - * because of existing FT information from R0KH. */ - sta->eapol_sm->keyRun = TRUE; - sta->eapol_sm->eap_if->eapKeyAvailable = TRUE; - sta->eapol_sm->auth_pae_state = AUTH_PAE_AUTHENTICATING; - sta->eapol_sm->be_auth_state = BE_AUTH_SUCCESS; - sta->eapol_sm->authSuccess = TRUE; - if (sta->eapol_sm->eap) - eap_sm_notify_cached(sta->eapol_sm->eap); - /* TODO: get vlan_id from R0KH using RRB message */ - return; - } -#endif /* CONFIG_IEEE80211R */ - - pmksa = wpa_auth_sta_get_pmksa(sta->wpa_sm); - if (pmksa) { - int old_vlanid; - - hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE8021X, - HOSTAPD_LEVEL_DEBUG, - "PMK from PMKSA cache - skip IEEE 802.1X/EAP"); - /* Setup EAPOL state machines to already authenticated state - * because of existing PMKSA information in the cache. */ - sta->eapol_sm->keyRun = TRUE; - sta->eapol_sm->eap_if->eapKeyAvailable = TRUE; - sta->eapol_sm->auth_pae_state = AUTH_PAE_AUTHENTICATING; - sta->eapol_sm->be_auth_state = BE_AUTH_SUCCESS; - sta->eapol_sm->authSuccess = TRUE; - if (sta->eapol_sm->eap) - eap_sm_notify_cached(sta->eapol_sm->eap); - old_vlanid = sta->vlan_id; - pmksa_cache_to_eapol_data(pmksa, sta->eapol_sm); - if (sta->ssid->dynamic_vlan == DYNAMIC_VLAN_DISABLED) - sta->vlan_id = 0; - ap_sta_bind_vlan(hapd, sta, old_vlanid); - } else { - if (reassoc) { - /* - * Force EAPOL state machines to start - * re-authentication without having to wait for the - * Supplicant to send EAPOL-Start. - */ - sta->eapol_sm->reAuthenticate = TRUE; - } - eapol_auth_step(sta->eapol_sm); - } -} - - -void ieee802_1x_free_station(struct sta_info *sta) -{ - struct eapol_state_machine *sm = sta->eapol_sm; - - if (sm == NULL) - return; - - sta->eapol_sm = NULL; - -#ifndef CONFIG_NO_RADIUS - radius_msg_free(sm->last_recv_radius); - radius_free_class(&sm->radius_class); -#endif /* CONFIG_NO_RADIUS */ - - os_free(sm->identity); - eapol_auth_free(sm); -} - - -#ifndef CONFIG_NO_RADIUS -static void ieee802_1x_decapsulate_radius(struct hostapd_data *hapd, - struct sta_info *sta) -{ - u8 *eap; - size_t len; - struct eap_hdr *hdr; - int eap_type = -1; - char buf[64]; - struct radius_msg *msg; - struct eapol_state_machine *sm = sta->eapol_sm; - - if (sm == NULL || sm->last_recv_radius == NULL) { - if (sm) - sm->eap_if->aaaEapNoReq = TRUE; - return; - } - - msg = sm->last_recv_radius; - - eap = radius_msg_get_eap(msg, &len); - if (eap == NULL) { - /* RFC 3579, Chap. 2.6.3: - * RADIUS server SHOULD NOT send Access-Reject/no EAP-Message - * attribute */ - hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE8021X, - HOSTAPD_LEVEL_WARNING, "could not extract " - "EAP-Message from RADIUS message"); - sm->eap_if->aaaEapNoReq = TRUE; - return; - } - - if (len < sizeof(*hdr)) { - hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE8021X, - HOSTAPD_LEVEL_WARNING, "too short EAP packet " - "received from authentication server"); - os_free(eap); - sm->eap_if->aaaEapNoReq = TRUE; - return; - } - - if (len > sizeof(*hdr)) - eap_type = eap[sizeof(*hdr)]; - - hdr = (struct eap_hdr *) eap; - switch (hdr->code) { - case EAP_CODE_REQUEST: - if (eap_type >= 0) - sm->eap_type_authsrv = eap_type; - os_snprintf(buf, sizeof(buf), "EAP-Request-%s (%d)", - eap_type >= 0 ? eap_server_get_name(0, eap_type) : - "??", - eap_type); - break; - case EAP_CODE_RESPONSE: - os_snprintf(buf, sizeof(buf), "EAP Response-%s (%d)", - eap_type >= 0 ? eap_server_get_name(0, eap_type) : - "??", - eap_type); - break; - case EAP_CODE_SUCCESS: - os_strlcpy(buf, "EAP Success", sizeof(buf)); - break; - case EAP_CODE_FAILURE: - os_strlcpy(buf, "EAP Failure", sizeof(buf)); - break; - default: - os_strlcpy(buf, "unknown EAP code", sizeof(buf)); - break; - } - buf[sizeof(buf) - 1] = '\0'; - hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE8021X, - HOSTAPD_LEVEL_DEBUG, "decapsulated EAP packet (code=%d " - "id=%d len=%d) from RADIUS server: %s", - hdr->code, hdr->identifier, be_to_host16(hdr->length), - buf); - sm->eap_if->aaaEapReq = TRUE; - - wpabuf_free(sm->eap_if->aaaEapReqData); - sm->eap_if->aaaEapReqData = wpabuf_alloc_ext_data(eap, len); -} - - -static void ieee802_1x_get_keys(struct hostapd_data *hapd, - struct sta_info *sta, struct radius_msg *msg, - struct radius_msg *req, - const u8 *shared_secret, - size_t shared_secret_len) -{ - struct radius_ms_mppe_keys *keys; - struct eapol_state_machine *sm = sta->eapol_sm; - if (sm == NULL) - return; - - keys = radius_msg_get_ms_keys(msg, req, shared_secret, - shared_secret_len); - - if (keys && keys->send && keys->recv) { - size_t len = keys->send_len + keys->recv_len; - wpa_hexdump_key(MSG_DEBUG, "MS-MPPE-Send-Key", - keys->send, keys->send_len); - wpa_hexdump_key(MSG_DEBUG, "MS-MPPE-Recv-Key", - keys->recv, keys->recv_len); - - os_free(sm->eap_if->aaaEapKeyData); - sm->eap_if->aaaEapKeyData = os_malloc(len); - if (sm->eap_if->aaaEapKeyData) { - os_memcpy(sm->eap_if->aaaEapKeyData, keys->recv, - keys->recv_len); - os_memcpy(sm->eap_if->aaaEapKeyData + keys->recv_len, - keys->send, keys->send_len); - sm->eap_if->aaaEapKeyDataLen = len; - sm->eap_if->aaaEapKeyAvailable = TRUE; - } - } - - if (keys) { - os_free(keys->send); - os_free(keys->recv); - os_free(keys); - } -} - - -static void ieee802_1x_store_radius_class(struct hostapd_data *hapd, - struct sta_info *sta, - struct radius_msg *msg) -{ - u8 *class; - size_t class_len; - struct eapol_state_machine *sm = sta->eapol_sm; - int count, i; - struct radius_attr_data *nclass; - size_t nclass_count; - - if (!hapd->conf->radius->acct_server || hapd->radius == NULL || - sm == NULL) - return; - - radius_free_class(&sm->radius_class); - count = radius_msg_count_attr(msg, RADIUS_ATTR_CLASS, 1); - if (count <= 0) - return; - - nclass = os_zalloc(count * sizeof(struct radius_attr_data)); - if (nclass == NULL) - return; - - nclass_count = 0; - - class = NULL; - for (i = 0; i < count; i++) { - do { - if (radius_msg_get_attr_ptr(msg, RADIUS_ATTR_CLASS, - &class, &class_len, - class) < 0) { - i = count; - break; - } - } while (class_len < 1); - - nclass[nclass_count].data = os_malloc(class_len); - if (nclass[nclass_count].data == NULL) - break; - - os_memcpy(nclass[nclass_count].data, class, class_len); - nclass[nclass_count].len = class_len; - nclass_count++; - } - - sm->radius_class.attr = nclass; - sm->radius_class.count = nclass_count; - wpa_printf(MSG_DEBUG, "IEEE 802.1X: Stored %lu RADIUS Class " - "attributes for " MACSTR, - (unsigned long) sm->radius_class.count, - MAC2STR(sta->addr)); -} - - -/* Update sta->identity based on User-Name attribute in Access-Accept */ -static void ieee802_1x_update_sta_identity(struct hostapd_data *hapd, - struct sta_info *sta, - struct radius_msg *msg) -{ - u8 *buf, *identity; - size_t len; - struct eapol_state_machine *sm = sta->eapol_sm; - - if (sm == NULL) - return; - - if (radius_msg_get_attr_ptr(msg, RADIUS_ATTR_USER_NAME, &buf, &len, - NULL) < 0) - return; - - identity = os_malloc(len + 1); - if (identity == NULL) - return; - - os_memcpy(identity, buf, len); - identity[len] = '\0'; - - hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE8021X, - HOSTAPD_LEVEL_DEBUG, "old identity '%s' updated with " - "User-Name from Access-Accept '%s'", - sm->identity ? (char *) sm->identity : "N/A", - (char *) identity); - - os_free(sm->identity); - sm->identity = identity; - sm->identity_len = len; -} - - -struct sta_id_search { - u8 identifier; - struct eapol_state_machine *sm; -}; - - -static int ieee802_1x_select_radius_identifier(struct hostapd_data *hapd, - struct sta_info *sta, - void *ctx) -{ - struct sta_id_search *id_search = ctx; - struct eapol_state_machine *sm = sta->eapol_sm; - - if (sm && sm->radius_identifier >= 0 && - sm->radius_identifier == id_search->identifier) { - id_search->sm = sm; - return 1; - } - return 0; -} - - -static struct eapol_state_machine * -ieee802_1x_search_radius_identifier(struct hostapd_data *hapd, u8 identifier) -{ - struct sta_id_search id_search; - id_search.identifier = identifier; - id_search.sm = NULL; - ap_for_each_sta(hapd, ieee802_1x_select_radius_identifier, &id_search); - return id_search.sm; -} - - -/** - * ieee802_1x_receive_auth - Process RADIUS frames from Authentication Server - * @msg: RADIUS response message - * @req: RADIUS request message - * @shared_secret: RADIUS shared secret - * @shared_secret_len: Length of shared_secret in octets - * @data: Context data (struct hostapd_data *) - * Returns: Processing status - */ -static RadiusRxResult -ieee802_1x_receive_auth(struct radius_msg *msg, struct radius_msg *req, - const u8 *shared_secret, size_t shared_secret_len, - void *data) -{ - struct hostapd_data *hapd = data; - struct sta_info *sta; - u32 session_timeout = 0, termination_action, acct_interim_interval; - int session_timeout_set, old_vlanid = 0; - struct eapol_state_machine *sm; - int override_eapReq = 0; - struct radius_hdr *hdr = radius_msg_get_hdr(msg); - - sm = ieee802_1x_search_radius_identifier(hapd, hdr->identifier); - if (sm == NULL) { - wpa_printf(MSG_DEBUG, "IEEE 802.1X: Could not find matching " - "station for this RADIUS message"); - return RADIUS_RX_UNKNOWN; - } - sta = sm->sta; - - /* RFC 2869, Ch. 5.13: valid Message-Authenticator attribute MUST be - * present when packet contains an EAP-Message attribute */ - if (hdr->code == RADIUS_CODE_ACCESS_REJECT && - radius_msg_get_attr(msg, RADIUS_ATTR_MESSAGE_AUTHENTICATOR, NULL, - 0) < 0 && - radius_msg_get_attr(msg, RADIUS_ATTR_EAP_MESSAGE, NULL, 0) < 0) { - wpa_printf(MSG_DEBUG, "Allowing RADIUS Access-Reject without " - "Message-Authenticator since it does not include " - "EAP-Message"); - } else if (radius_msg_verify(msg, shared_secret, shared_secret_len, - req, 1)) { - printf("Incoming RADIUS packet did not have correct " - "Message-Authenticator - dropped\n"); - return RADIUS_RX_INVALID_AUTHENTICATOR; - } - - if (hdr->code != RADIUS_CODE_ACCESS_ACCEPT && - hdr->code != RADIUS_CODE_ACCESS_REJECT && - hdr->code != RADIUS_CODE_ACCESS_CHALLENGE) { - printf("Unknown RADIUS message code\n"); - return RADIUS_RX_UNKNOWN; - } - - sm->radius_identifier = -1; - wpa_printf(MSG_DEBUG, "RADIUS packet matching with station " MACSTR, - MAC2STR(sta->addr)); - - radius_msg_free(sm->last_recv_radius); - sm->last_recv_radius = msg; - - session_timeout_set = - !radius_msg_get_attr_int32(msg, RADIUS_ATTR_SESSION_TIMEOUT, - &session_timeout); - if (radius_msg_get_attr_int32(msg, RADIUS_ATTR_TERMINATION_ACTION, - &termination_action)) - termination_action = RADIUS_TERMINATION_ACTION_DEFAULT; - - if (hapd->conf->acct_interim_interval == 0 && - hdr->code == RADIUS_CODE_ACCESS_ACCEPT && - radius_msg_get_attr_int32(msg, RADIUS_ATTR_ACCT_INTERIM_INTERVAL, - &acct_interim_interval) == 0) { - if (acct_interim_interval < 60) { - hostapd_logger(hapd, sta->addr, - HOSTAPD_MODULE_IEEE8021X, - HOSTAPD_LEVEL_INFO, - "ignored too small " - "Acct-Interim-Interval %d", - acct_interim_interval); - } else - sta->acct_interim_interval = acct_interim_interval; - } - - - switch (hdr->code) { - case RADIUS_CODE_ACCESS_ACCEPT: - if (sta->ssid->dynamic_vlan == DYNAMIC_VLAN_DISABLED) - sta->vlan_id = 0; -#ifndef CONFIG_NO_VLAN - else { - old_vlanid = sta->vlan_id; - sta->vlan_id = radius_msg_get_vlanid(msg); - } - if (sta->vlan_id > 0 && - hostapd_get_vlan_id_ifname(hapd->conf->vlan, - sta->vlan_id)) { - hostapd_logger(hapd, sta->addr, - HOSTAPD_MODULE_RADIUS, - HOSTAPD_LEVEL_INFO, - "VLAN ID %d", sta->vlan_id); - } else if (sta->ssid->dynamic_vlan == DYNAMIC_VLAN_REQUIRED) { - sta->eapol_sm->authFail = TRUE; - hostapd_logger(hapd, sta->addr, - HOSTAPD_MODULE_IEEE8021X, - HOSTAPD_LEVEL_INFO, "authentication " - "server did not include required VLAN " - "ID in Access-Accept"); - break; - } -#endif /* CONFIG_NO_VLAN */ - - if (ap_sta_bind_vlan(hapd, sta, old_vlanid) < 0) - break; - - /* RFC 3580, Ch. 3.17 */ - if (session_timeout_set && termination_action == - RADIUS_TERMINATION_ACTION_RADIUS_REQUEST) { - sm->reAuthPeriod = session_timeout; - } else if (session_timeout_set) - ap_sta_session_timeout(hapd, sta, session_timeout); - - sm->eap_if->aaaSuccess = TRUE; - override_eapReq = 1; - ieee802_1x_get_keys(hapd, sta, msg, req, shared_secret, - shared_secret_len); - ieee802_1x_store_radius_class(hapd, sta, msg); - ieee802_1x_update_sta_identity(hapd, sta, msg); - if (sm->eap_if->eapKeyAvailable && - wpa_auth_pmksa_add(sta->wpa_sm, sm->eapol_key_crypt, - session_timeout_set ? - (int) session_timeout : -1, sm) == 0) { - hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_WPA, - HOSTAPD_LEVEL_DEBUG, - "Added PMKSA cache entry"); - } - break; - case RADIUS_CODE_ACCESS_REJECT: - sm->eap_if->aaaFail = TRUE; - override_eapReq = 1; - break; - case RADIUS_CODE_ACCESS_CHALLENGE: - sm->eap_if->aaaEapReq = TRUE; - if (session_timeout_set) { - /* RFC 2869, Ch. 2.3.2; RFC 3580, Ch. 3.17 */ - sm->eap_if->aaaMethodTimeout = session_timeout; - hostapd_logger(hapd, sm->addr, - HOSTAPD_MODULE_IEEE8021X, - HOSTAPD_LEVEL_DEBUG, - "using EAP timeout of %d seconds (from " - "RADIUS)", - sm->eap_if->aaaMethodTimeout); - } else { - /* - * Use dynamic retransmission behavior per EAP - * specification. - */ - sm->eap_if->aaaMethodTimeout = 0; - } - break; - } - - ieee802_1x_decapsulate_radius(hapd, sta); - if (override_eapReq) - sm->eap_if->aaaEapReq = FALSE; - - eapol_auth_step(sm); - - return RADIUS_RX_QUEUED; -} -#endif /* CONFIG_NO_RADIUS */ - - -void ieee802_1x_abort_auth(struct hostapd_data *hapd, struct sta_info *sta) -{ - struct eapol_state_machine *sm = sta->eapol_sm; - if (sm == NULL) - return; - - hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE8021X, - HOSTAPD_LEVEL_DEBUG, "aborting authentication"); - -#ifndef CONFIG_NO_RADIUS - radius_msg_free(sm->last_recv_radius); - sm->last_recv_radius = NULL; -#endif /* CONFIG_NO_RADIUS */ - - if (sm->eap_if->eapTimeout) { - /* - * Disconnect the STA since it did not reply to the last EAP - * request and we cannot continue EAP processing (EAP-Failure - * could only be sent if the EAP peer actually replied). - */ - sm->eap_if->portEnabled = FALSE; - ap_sta_disconnect(hapd, sta, sta->addr, - WLAN_REASON_PREV_AUTH_NOT_VALID); - } -} - - -static int ieee802_1x_rekey_broadcast(struct hostapd_data *hapd) -{ - struct eapol_authenticator *eapol = hapd->eapol_auth; - - if (hapd->conf->default_wep_key_len < 1) - return 0; - - os_free(eapol->default_wep_key); - eapol->default_wep_key = os_malloc(hapd->conf->default_wep_key_len); - if (eapol->default_wep_key == NULL || - random_get_bytes(eapol->default_wep_key, - hapd->conf->default_wep_key_len)) { - printf("Could not generate random WEP key.\n"); - os_free(eapol->default_wep_key); - eapol->default_wep_key = NULL; - return -1; - } - - wpa_hexdump_key(MSG_DEBUG, "IEEE 802.1X: New default WEP key", - eapol->default_wep_key, - hapd->conf->default_wep_key_len); - - return 0; -} - - -static int ieee802_1x_sta_key_available(struct hostapd_data *hapd, - struct sta_info *sta, void *ctx) -{ - if (sta->eapol_sm) { - sta->eapol_sm->eap_if->eapKeyAvailable = TRUE; - eapol_auth_step(sta->eapol_sm); - } - return 0; -} - - -static void ieee802_1x_rekey(void *eloop_ctx, void *timeout_ctx) -{ - struct hostapd_data *hapd = eloop_ctx; - struct eapol_authenticator *eapol = hapd->eapol_auth; - - if (eapol->default_wep_key_idx >= 3) - eapol->default_wep_key_idx = - hapd->conf->individual_wep_key_len > 0 ? 1 : 0; - else - eapol->default_wep_key_idx++; - - wpa_printf(MSG_DEBUG, "IEEE 802.1X: New default WEP key index %d", - eapol->default_wep_key_idx); - - if (ieee802_1x_rekey_broadcast(hapd)) { - hostapd_logger(hapd, NULL, HOSTAPD_MODULE_IEEE8021X, - HOSTAPD_LEVEL_WARNING, "failed to generate a " - "new broadcast key"); - os_free(eapol->default_wep_key); - eapol->default_wep_key = NULL; - return; - } - - /* TODO: Could setup key for RX here, but change default TX keyid only - * after new broadcast key has been sent to all stations. */ - if (hostapd_drv_set_key(hapd->conf->iface, hapd, WPA_ALG_WEP, - broadcast_ether_addr, - eapol->default_wep_key_idx, 1, NULL, 0, - eapol->default_wep_key, - hapd->conf->default_wep_key_len)) { - hostapd_logger(hapd, NULL, HOSTAPD_MODULE_IEEE8021X, - HOSTAPD_LEVEL_WARNING, "failed to configure a " - "new broadcast key"); - os_free(eapol->default_wep_key); - eapol->default_wep_key = NULL; - return; - } - - ap_for_each_sta(hapd, ieee802_1x_sta_key_available, NULL); - - if (hapd->conf->wep_rekeying_period > 0) { - eloop_register_timeout(hapd->conf->wep_rekeying_period, 0, - ieee802_1x_rekey, hapd, NULL); - } -} - - -static void ieee802_1x_eapol_send(void *ctx, void *sta_ctx, u8 type, - const u8 *data, size_t datalen) -{ -#ifdef CONFIG_WPS - struct sta_info *sta = sta_ctx; - - if ((sta->flags & (WLAN_STA_WPS | WLAN_STA_MAYBE_WPS)) == - WLAN_STA_MAYBE_WPS) { - const u8 *identity; - size_t identity_len; - struct eapol_state_machine *sm = sta->eapol_sm; - - identity = eap_get_identity(sm->eap, &identity_len); - if (identity && - ((identity_len == WSC_ID_ENROLLEE_LEN && - os_memcmp(identity, WSC_ID_ENROLLEE, - WSC_ID_ENROLLEE_LEN) == 0) || - (identity_len == WSC_ID_REGISTRAR_LEN && - os_memcmp(identity, WSC_ID_REGISTRAR, - WSC_ID_REGISTRAR_LEN) == 0))) { - wpa_printf(MSG_DEBUG, "WPS: WLAN_STA_MAYBE_WPS -> " - "WLAN_STA_WPS"); - sta->flags |= WLAN_STA_WPS; - } - } -#endif /* CONFIG_WPS */ - - ieee802_1x_send(ctx, sta_ctx, type, data, datalen); -} - - -static void ieee802_1x_aaa_send(void *ctx, void *sta_ctx, - const u8 *data, size_t datalen) -{ -#ifndef CONFIG_NO_RADIUS - struct hostapd_data *hapd = ctx; - struct sta_info *sta = sta_ctx; - - ieee802_1x_encapsulate_radius(hapd, sta, data, datalen); -#endif /* CONFIG_NO_RADIUS */ -} - - -static void _ieee802_1x_finished(void *ctx, void *sta_ctx, int success, - int preauth) -{ - struct hostapd_data *hapd = ctx; - struct sta_info *sta = sta_ctx; - if (preauth) - rsn_preauth_finished(hapd, sta, success); - else - ieee802_1x_finished(hapd, sta, success); -} - - -static int ieee802_1x_get_eap_user(void *ctx, const u8 *identity, - size_t identity_len, int phase2, - struct eap_user *user) -{ - struct hostapd_data *hapd = ctx; - const struct hostapd_eap_user *eap_user; - int i, count; - - eap_user = hostapd_get_eap_user(hapd->conf, identity, - identity_len, phase2); - if (eap_user == NULL) - return -1; - - os_memset(user, 0, sizeof(*user)); - user->phase2 = phase2; - count = EAP_USER_MAX_METHODS; - if (count > EAP_MAX_METHODS) - count = EAP_MAX_METHODS; - for (i = 0; i < count; i++) { - user->methods[i].vendor = eap_user->methods[i].vendor; - user->methods[i].method = eap_user->methods[i].method; - } - - if (eap_user->password) { - user->password = os_malloc(eap_user->password_len); - if (user->password == NULL) - return -1; - os_memcpy(user->password, eap_user->password, - eap_user->password_len); - user->password_len = eap_user->password_len; - } - user->force_version = eap_user->force_version; - user->ttls_auth = eap_user->ttls_auth; - - return 0; -} - - -static int ieee802_1x_sta_entry_alive(void *ctx, const u8 *addr) -{ - struct hostapd_data *hapd = ctx; - struct sta_info *sta; - sta = ap_get_sta(hapd, addr); - if (sta == NULL || sta->eapol_sm == NULL) - return 0; - return 1; -} - - -static void ieee802_1x_logger(void *ctx, const u8 *addr, - eapol_logger_level level, const char *txt) -{ -#ifndef CONFIG_NO_HOSTAPD_LOGGER - struct hostapd_data *hapd = ctx; - int hlevel; - - switch (level) { - case EAPOL_LOGGER_WARNING: - hlevel = HOSTAPD_LEVEL_WARNING; - break; - case EAPOL_LOGGER_INFO: - hlevel = HOSTAPD_LEVEL_INFO; - break; - case EAPOL_LOGGER_DEBUG: - default: - hlevel = HOSTAPD_LEVEL_DEBUG; - break; - } - - hostapd_logger(hapd, addr, HOSTAPD_MODULE_IEEE8021X, hlevel, "%s", - txt); -#endif /* CONFIG_NO_HOSTAPD_LOGGER */ -} - - -static void ieee802_1x_set_port_authorized(void *ctx, void *sta_ctx, - int authorized) -{ - struct hostapd_data *hapd = ctx; - struct sta_info *sta = sta_ctx; - ieee802_1x_set_sta_authorized(hapd, sta, authorized); -} - - -static void _ieee802_1x_abort_auth(void *ctx, void *sta_ctx) -{ - struct hostapd_data *hapd = ctx; - struct sta_info *sta = sta_ctx; - ieee802_1x_abort_auth(hapd, sta); -} - - -static void _ieee802_1x_tx_key(void *ctx, void *sta_ctx) -{ - struct hostapd_data *hapd = ctx; - struct sta_info *sta = sta_ctx; - ieee802_1x_tx_key(hapd, sta); -} - - -static void ieee802_1x_eapol_event(void *ctx, void *sta_ctx, - enum eapol_event type) -{ - /* struct hostapd_data *hapd = ctx; */ - struct sta_info *sta = sta_ctx; - switch (type) { - case EAPOL_AUTH_SM_CHANGE: - wpa_auth_sm_notify(sta->wpa_sm); - break; - case EAPOL_AUTH_REAUTHENTICATE: - wpa_auth_sm_event(sta->wpa_sm, WPA_REAUTH_EAPOL); - break; - } -} - - -int ieee802_1x_init(struct hostapd_data *hapd) -{ - int i; - struct eapol_auth_config conf; - struct eapol_auth_cb cb; - - os_memset(&conf, 0, sizeof(conf)); - conf.ctx = hapd; - conf.eap_reauth_period = hapd->conf->eap_reauth_period; - conf.wpa = hapd->conf->wpa; - conf.individual_wep_key_len = hapd->conf->individual_wep_key_len; - conf.eap_server = hapd->conf->eap_server; - conf.ssl_ctx = hapd->ssl_ctx; - conf.msg_ctx = hapd->msg_ctx; - conf.eap_sim_db_priv = hapd->eap_sim_db_priv; - conf.eap_req_id_text = hapd->conf->eap_req_id_text; - conf.eap_req_id_text_len = hapd->conf->eap_req_id_text_len; - conf.pac_opaque_encr_key = hapd->conf->pac_opaque_encr_key; - conf.eap_fast_a_id = hapd->conf->eap_fast_a_id; - conf.eap_fast_a_id_len = hapd->conf->eap_fast_a_id_len; - conf.eap_fast_a_id_info = hapd->conf->eap_fast_a_id_info; - conf.eap_fast_prov = hapd->conf->eap_fast_prov; - conf.pac_key_lifetime = hapd->conf->pac_key_lifetime; - conf.pac_key_refresh_time = hapd->conf->pac_key_refresh_time; - conf.eap_sim_aka_result_ind = hapd->conf->eap_sim_aka_result_ind; - conf.tnc = hapd->conf->tnc; - conf.wps = hapd->wps; - conf.fragment_size = hapd->conf->fragment_size; - conf.pwd_group = hapd->conf->pwd_group; - - os_memset(&cb, 0, sizeof(cb)); - cb.eapol_send = ieee802_1x_eapol_send; - cb.aaa_send = ieee802_1x_aaa_send; - cb.finished = _ieee802_1x_finished; - cb.get_eap_user = ieee802_1x_get_eap_user; - cb.sta_entry_alive = ieee802_1x_sta_entry_alive; - cb.logger = ieee802_1x_logger; - cb.set_port_authorized = ieee802_1x_set_port_authorized; - cb.abort_auth = _ieee802_1x_abort_auth; - cb.tx_key = _ieee802_1x_tx_key; - cb.eapol_event = ieee802_1x_eapol_event; - - hapd->eapol_auth = eapol_auth_init(&conf, &cb); - if (hapd->eapol_auth == NULL) - return -1; - - if ((hapd->conf->ieee802_1x || hapd->conf->wpa) && - hostapd_set_drv_ieee8021x(hapd, hapd->conf->iface, 1)) - return -1; - -#ifndef CONFIG_NO_RADIUS - if (radius_client_register(hapd->radius, RADIUS_AUTH, - ieee802_1x_receive_auth, hapd)) - return -1; -#endif /* CONFIG_NO_RADIUS */ - - if (hapd->conf->default_wep_key_len) { - for (i = 0; i < 4; i++) - hostapd_drv_set_key(hapd->conf->iface, hapd, - WPA_ALG_NONE, NULL, i, 0, NULL, 0, - NULL, 0); - - ieee802_1x_rekey(hapd, NULL); - - if (hapd->eapol_auth->default_wep_key == NULL) - return -1; - } - - return 0; -} - - -void ieee802_1x_deinit(struct hostapd_data *hapd) -{ - eloop_cancel_timeout(ieee802_1x_rekey, hapd, NULL); - - if (hapd->driver != NULL && - (hapd->conf->ieee802_1x || hapd->conf->wpa)) - hostapd_set_drv_ieee8021x(hapd, hapd->conf->iface, 0); - - eapol_auth_deinit(hapd->eapol_auth); - hapd->eapol_auth = NULL; -} - - -int ieee802_1x_tx_status(struct hostapd_data *hapd, struct sta_info *sta, - const u8 *buf, size_t len, int ack) -{ - struct ieee80211_hdr *hdr; - struct ieee802_1x_hdr *xhdr; - struct ieee802_1x_eapol_key *key; - u8 *pos; - const unsigned char rfc1042_hdr[ETH_ALEN] = - { 0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00 }; - - if (sta == NULL) - return -1; - if (len < sizeof(*hdr) + sizeof(rfc1042_hdr) + 2 + sizeof(*xhdr)) - return 0; - - hdr = (struct ieee80211_hdr *) buf; - pos = (u8 *) (hdr + 1); - if (os_memcmp(pos, rfc1042_hdr, sizeof(rfc1042_hdr)) != 0) - return 0; - pos += sizeof(rfc1042_hdr); - if (WPA_GET_BE16(pos) != ETH_P_PAE) - return 0; - pos += 2; - - xhdr = (struct ieee802_1x_hdr *) pos; - pos += sizeof(*xhdr); - - wpa_printf(MSG_DEBUG, "IEEE 802.1X: " MACSTR " TX status - version=%d " - "type=%d length=%d - ack=%d", - MAC2STR(sta->addr), xhdr->version, xhdr->type, - be_to_host16(xhdr->length), ack); - - if (xhdr->type == IEEE802_1X_TYPE_EAPOL_KEY && - pos + sizeof(struct wpa_eapol_key) <= buf + len) { - const struct wpa_eapol_key *wpa; - wpa = (const struct wpa_eapol_key *) pos; - if (wpa->type == EAPOL_KEY_TYPE_RSN || - wpa->type == EAPOL_KEY_TYPE_WPA) - wpa_auth_eapol_key_tx_status(hapd->wpa_auth, - sta->wpa_sm, ack); - } - - /* EAPOL EAP-Packet packets are eventually re-sent by either Supplicant - * or Authenticator state machines, but EAPOL-Key packets are not - * retransmitted in case of failure. Try to re-sent failed EAPOL-Key - * packets couple of times because otherwise STA keys become - * unsynchronized with AP. */ - if (xhdr->type == IEEE802_1X_TYPE_EAPOL_KEY && !ack && - pos + sizeof(*key) <= buf + len) { - key = (struct ieee802_1x_eapol_key *) pos; - hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE8021X, - HOSTAPD_LEVEL_DEBUG, "did not Ack EAPOL-Key " - "frame (%scast index=%d)", - key->key_index & BIT(7) ? "uni" : "broad", - key->key_index & ~BIT(7)); - /* TODO: re-send EAPOL-Key couple of times (with short delay - * between them?). If all attempt fail, report error and - * deauthenticate STA so that it will get new keys when - * authenticating again (e.g., after returning in range). - * Separate limit/transmit state needed both for unicast and - * broadcast keys(?) */ - } - /* TODO: could move unicast key configuration from ieee802_1x_tx_key() - * to here and change the key only if the EAPOL-Key packet was Acked. - */ - - return 1; -} - - -u8 * ieee802_1x_get_identity(struct eapol_state_machine *sm, size_t *len) -{ - if (sm == NULL || sm->identity == NULL) - return NULL; - - *len = sm->identity_len; - return sm->identity; -} - - -u8 * ieee802_1x_get_radius_class(struct eapol_state_machine *sm, size_t *len, - int idx) -{ - if (sm == NULL || sm->radius_class.attr == NULL || - idx >= (int) sm->radius_class.count) - return NULL; - - *len = sm->radius_class.attr[idx].len; - return sm->radius_class.attr[idx].data; -} - - -const u8 * ieee802_1x_get_key(struct eapol_state_machine *sm, size_t *len) -{ - if (sm == NULL) - return NULL; - - *len = sm->eap_if->eapKeyDataLen; - return sm->eap_if->eapKeyData; -} - - -void ieee802_1x_notify_port_enabled(struct eapol_state_machine *sm, - int enabled) -{ - if (sm == NULL) - return; - sm->eap_if->portEnabled = enabled ? TRUE : FALSE; - eapol_auth_step(sm); -} - - -void ieee802_1x_notify_port_valid(struct eapol_state_machine *sm, - int valid) -{ - if (sm == NULL) - return; - sm->portValid = valid ? TRUE : FALSE; - eapol_auth_step(sm); -} - - -void ieee802_1x_notify_pre_auth(struct eapol_state_machine *sm, int pre_auth) -{ - if (sm == NULL) - return; - if (pre_auth) - sm->flags |= EAPOL_SM_PREAUTH; - else - sm->flags &= ~EAPOL_SM_PREAUTH; -} - - -static const char * bool_txt(Boolean bool) -{ - return bool ? "TRUE" : "FALSE"; -} - - -int ieee802_1x_get_mib(struct hostapd_data *hapd, char *buf, size_t buflen) -{ - /* TODO */ - return 0; -} - - -int ieee802_1x_get_mib_sta(struct hostapd_data *hapd, struct sta_info *sta, - char *buf, size_t buflen) -{ - int len = 0, ret; - struct eapol_state_machine *sm = sta->eapol_sm; - - if (sm == NULL) - return 0; - - ret = os_snprintf(buf + len, buflen - len, - "dot1xPaePortNumber=%d\n" - "dot1xPaePortProtocolVersion=%d\n" - "dot1xPaePortCapabilities=1\n" - "dot1xPaePortInitialize=%d\n" - "dot1xPaePortReauthenticate=FALSE\n", - sta->aid, - EAPOL_VERSION, - sm->initialize); - if (ret < 0 || (size_t) ret >= buflen - len) - return len; - len += ret; - - /* dot1xAuthConfigTable */ - ret = os_snprintf(buf + len, buflen - len, - "dot1xAuthPaeState=%d\n" - "dot1xAuthBackendAuthState=%d\n" - "dot1xAuthAdminControlledDirections=%d\n" - "dot1xAuthOperControlledDirections=%d\n" - "dot1xAuthAuthControlledPortStatus=%d\n" - "dot1xAuthAuthControlledPortControl=%d\n" - "dot1xAuthQuietPeriod=%u\n" - "dot1xAuthServerTimeout=%u\n" - "dot1xAuthReAuthPeriod=%u\n" - "dot1xAuthReAuthEnabled=%s\n" - "dot1xAuthKeyTxEnabled=%s\n", - sm->auth_pae_state + 1, - sm->be_auth_state + 1, - sm->adminControlledDirections, - sm->operControlledDirections, - sm->authPortStatus, - sm->portControl, - sm->quietPeriod, - sm->serverTimeout, - sm->reAuthPeriod, - bool_txt(sm->reAuthEnabled), - bool_txt(sm->keyTxEnabled)); - if (ret < 0 || (size_t) ret >= buflen - len) - return len; - len += ret; - - /* dot1xAuthStatsTable */ - ret = os_snprintf(buf + len, buflen - len, - "dot1xAuthEapolFramesRx=%u\n" - "dot1xAuthEapolFramesTx=%u\n" - "dot1xAuthEapolStartFramesRx=%u\n" - "dot1xAuthEapolLogoffFramesRx=%u\n" - "dot1xAuthEapolRespIdFramesRx=%u\n" - "dot1xAuthEapolRespFramesRx=%u\n" - "dot1xAuthEapolReqIdFramesTx=%u\n" - "dot1xAuthEapolReqFramesTx=%u\n" - "dot1xAuthInvalidEapolFramesRx=%u\n" - "dot1xAuthEapLengthErrorFramesRx=%u\n" - "dot1xAuthLastEapolFrameVersion=%u\n" - "dot1xAuthLastEapolFrameSource=" MACSTR "\n", - sm->dot1xAuthEapolFramesRx, - sm->dot1xAuthEapolFramesTx, - sm->dot1xAuthEapolStartFramesRx, - sm->dot1xAuthEapolLogoffFramesRx, - sm->dot1xAuthEapolRespIdFramesRx, - sm->dot1xAuthEapolRespFramesRx, - sm->dot1xAuthEapolReqIdFramesTx, - sm->dot1xAuthEapolReqFramesTx, - sm->dot1xAuthInvalidEapolFramesRx, - sm->dot1xAuthEapLengthErrorFramesRx, - sm->dot1xAuthLastEapolFrameVersion, - MAC2STR(sm->addr)); - if (ret < 0 || (size_t) ret >= buflen - len) - return len; - len += ret; - - /* dot1xAuthDiagTable */ - ret = os_snprintf(buf + len, buflen - len, - "dot1xAuthEntersConnecting=%u\n" - "dot1xAuthEapLogoffsWhileConnecting=%u\n" - "dot1xAuthEntersAuthenticating=%u\n" - "dot1xAuthAuthSuccessesWhileAuthenticating=%u\n" - "dot1xAuthAuthTimeoutsWhileAuthenticating=%u\n" - "dot1xAuthAuthFailWhileAuthenticating=%u\n" - "dot1xAuthAuthEapStartsWhileAuthenticating=%u\n" - "dot1xAuthAuthEapLogoffWhileAuthenticating=%u\n" - "dot1xAuthAuthReauthsWhileAuthenticated=%u\n" - "dot1xAuthAuthEapStartsWhileAuthenticated=%u\n" - "dot1xAuthAuthEapLogoffWhileAuthenticated=%u\n" - "dot1xAuthBackendResponses=%u\n" - "dot1xAuthBackendAccessChallenges=%u\n" - "dot1xAuthBackendOtherRequestsToSupplicant=%u\n" - "dot1xAuthBackendAuthSuccesses=%u\n" - "dot1xAuthBackendAuthFails=%u\n", - sm->authEntersConnecting, - sm->authEapLogoffsWhileConnecting, - sm->authEntersAuthenticating, - sm->authAuthSuccessesWhileAuthenticating, - sm->authAuthTimeoutsWhileAuthenticating, - sm->authAuthFailWhileAuthenticating, - sm->authAuthEapStartsWhileAuthenticating, - sm->authAuthEapLogoffWhileAuthenticating, - sm->authAuthReauthsWhileAuthenticated, - sm->authAuthEapStartsWhileAuthenticated, - sm->authAuthEapLogoffWhileAuthenticated, - sm->backendResponses, - sm->backendAccessChallenges, - sm->backendOtherRequestsToSupplicant, - sm->backendAuthSuccesses, - sm->backendAuthFails); - if (ret < 0 || (size_t) ret >= buflen - len) - return len; - len += ret; - - /* dot1xAuthSessionStatsTable */ - ret = os_snprintf(buf + len, buflen - len, - /* TODO: dot1xAuthSessionOctetsRx */ - /* TODO: dot1xAuthSessionOctetsTx */ - /* TODO: dot1xAuthSessionFramesRx */ - /* TODO: dot1xAuthSessionFramesTx */ - "dot1xAuthSessionId=%08X-%08X\n" - "dot1xAuthSessionAuthenticMethod=%d\n" - "dot1xAuthSessionTime=%u\n" - "dot1xAuthSessionTerminateCause=999\n" - "dot1xAuthSessionUserName=%s\n", - sta->acct_session_id_hi, sta->acct_session_id_lo, - (wpa_key_mgmt_wpa_ieee8021x( - wpa_auth_sta_key_mgmt(sta->wpa_sm))) ? - 1 : 2, - (unsigned int) (time(NULL) - - sta->acct_session_start), - sm->identity); - if (ret < 0 || (size_t) ret >= buflen - len) - return len; - len += ret; - - return len; -} - - -static void ieee802_1x_finished(struct hostapd_data *hapd, - struct sta_info *sta, int success) -{ - const u8 *key; - size_t len; - /* TODO: get PMKLifetime from WPA parameters */ - static const int dot11RSNAConfigPMKLifetime = 43200; - - key = ieee802_1x_get_key(sta->eapol_sm, &len); - if (success && key && len >= PMK_LEN && - wpa_auth_pmksa_add(sta->wpa_sm, key, dot11RSNAConfigPMKLifetime, - sta->eapol_sm) == 0) { - hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_WPA, - HOSTAPD_LEVEL_DEBUG, - "Added PMKSA cache entry (IEEE 802.1X)"); - } - -#ifdef CONFIG_WPS - if (!success && (sta->flags & WLAN_STA_WPS)) { - /* - * Many devices require deauthentication after WPS provisioning - * and some may not be be able to do that themselves, so - * disconnect the client here. - */ - wpa_printf(MSG_DEBUG, "WPS: Force disconnection after " - "EAP-Failure"); - /* Add a small sleep to increase likelihood of previously - * requested EAP-Failure TX getting out before this should the - * driver reorder operations. - */ - os_sleep(0, 10000); - ap_sta_disconnect(hapd, sta, sta->addr, - WLAN_REASON_PREV_AUTH_NOT_VALID); - } -#endif /* CONFIG_WPS */ -} diff --git a/hostapd-0.8/src/ap/ieee802_1x.h b/hostapd-0.8/src/ap/ieee802_1x.h deleted file mode 100644 index 1a4d2eb..0000000 --- a/hostapd-0.8/src/ap/ieee802_1x.h +++ /dev/null @@ -1,89 +0,0 @@ -/* - * hostapd / IEEE 802.1X-2004 Authenticator - * Copyright (c) 2002-2007, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#ifndef IEEE802_1X_H -#define IEEE802_1X_H - -struct hostapd_data; -struct sta_info; -struct eapol_state_machine; -struct hostapd_config; -struct hostapd_bss_config; - -#ifdef _MSC_VER -#pragma pack(push, 1) -#endif /* _MSC_VER */ - -/* RFC 3580, 4. RC4 EAPOL-Key Frame */ - -struct ieee802_1x_eapol_key { - u8 type; - u16 key_length; - u8 replay_counter[8]; /* does not repeat within the life of the keying - * material used to encrypt the Key field; - * 64-bit NTP timestamp MAY be used here */ - u8 key_iv[16]; /* cryptographically random number */ - u8 key_index; /* key flag in the most significant bit: - * 0 = broadcast (default key), - * 1 = unicast (key mapping key); key index is in the - * 7 least significant bits */ - u8 key_signature[16]; /* HMAC-MD5 message integrity check computed with - * MS-MPPE-Send-Key as the key */ - - /* followed by key: if packet body length = 44 + key length, then the - * key field (of key_length bytes) contains the key in encrypted form; - * if packet body length = 44, key field is absent and key_length - * represents the number of least significant octets from - * MS-MPPE-Send-Key attribute to be used as the keying material; - * RC4 key used in encryption = Key-IV + MS-MPPE-Recv-Key */ -} STRUCT_PACKED; - -#ifdef _MSC_VER -#pragma pack(pop) -#endif /* _MSC_VER */ - - -void ieee802_1x_receive(struct hostapd_data *hapd, const u8 *sa, const u8 *buf, - size_t len); -void ieee802_1x_new_station(struct hostapd_data *hapd, struct sta_info *sta); -void ieee802_1x_free_station(struct sta_info *sta); - -void ieee802_1x_tx_key(struct hostapd_data *hapd, struct sta_info *sta); -void ieee802_1x_abort_auth(struct hostapd_data *hapd, struct sta_info *sta); -void ieee802_1x_set_sta_authorized(struct hostapd_data *hapd, - struct sta_info *sta, int authorized); -void ieee802_1x_dump_state(FILE *f, const char *prefix, struct sta_info *sta); -int ieee802_1x_init(struct hostapd_data *hapd); -void ieee802_1x_deinit(struct hostapd_data *hapd); -int ieee802_1x_tx_status(struct hostapd_data *hapd, struct sta_info *sta, - const u8 *buf, size_t len, int ack); -u8 * ieee802_1x_get_identity(struct eapol_state_machine *sm, size_t *len); -u8 * ieee802_1x_get_radius_class(struct eapol_state_machine *sm, size_t *len, - int idx); -const u8 * ieee802_1x_get_key(struct eapol_state_machine *sm, size_t *len); -void ieee802_1x_notify_port_enabled(struct eapol_state_machine *sm, - int enabled); -void ieee802_1x_notify_port_valid(struct eapol_state_machine *sm, - int valid); -void ieee802_1x_notify_pre_auth(struct eapol_state_machine *sm, int pre_auth); -int ieee802_1x_get_mib(struct hostapd_data *hapd, char *buf, size_t buflen); -int ieee802_1x_get_mib_sta(struct hostapd_data *hapd, struct sta_info *sta, - char *buf, size_t buflen); -void hostapd_get_ntp_timestamp(u8 *buf); -char *eap_type_text(u8 type); - -const char *radius_mode_txt(struct hostapd_data *hapd); -int radius_sta_rate(struct hostapd_data *hapd, struct sta_info *sta); - -#endif /* IEEE802_1X_H */ diff --git a/hostapd-0.8/src/ap/p2p_hostapd.c b/hostapd-0.8/src/ap/p2p_hostapd.c deleted file mode 100644 index 6f8b778..0000000 --- a/hostapd-0.8/src/ap/p2p_hostapd.c +++ /dev/null @@ -1,120 +0,0 @@ -/* - * hostapd / P2P integration - * Copyright (c) 2009-2010, Atheros Communications - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#include "utils/includes.h" - -#include "utils/common.h" -#include "common/ieee802_11_defs.h" -#include "p2p/p2p.h" -#include "hostapd.h" -#include "ap_config.h" -#include "ap_drv_ops.h" -#include "sta_info.h" -#include "p2p_hostapd.h" - - -#ifdef CONFIG_P2P - -int hostapd_p2p_get_mib_sta(struct hostapd_data *hapd, struct sta_info *sta, - char *buf, size_t buflen) -{ - if (sta->p2p_ie == NULL) - return 0; - - return p2p_ie_text(sta->p2p_ie, buf, buf + buflen); -} - - -int hostapd_p2p_set_noa(struct hostapd_data *hapd, u8 count, int start, - int duration) -{ - wpa_printf(MSG_DEBUG, "P2P: Set NoA parameters: count=%u start=%d " - "duration=%d", count, start, duration); - - if (count == 0) { - hapd->noa_enabled = 0; - hapd->noa_start = 0; - hapd->noa_duration = 0; - } - - if (count != 255) { - wpa_printf(MSG_DEBUG, "P2P: Non-periodic NoA - set " - "NoA parameters"); - return hostapd_driver_set_noa(hapd, count, start, duration); - } - - hapd->noa_enabled = 1; - hapd->noa_start = start; - hapd->noa_duration = duration; - - if (hapd->num_sta_no_p2p == 0) { - wpa_printf(MSG_DEBUG, "P2P: No legacy STAs connected - update " - "periodic NoA parameters"); - return hostapd_driver_set_noa(hapd, count, start, duration); - } - - wpa_printf(MSG_DEBUG, "P2P: Legacy STA(s) connected - do not enable " - "periodic NoA"); - - return 0; -} - - -void hostapd_p2p_non_p2p_sta_connected(struct hostapd_data *hapd) -{ - wpa_printf(MSG_DEBUG, "P2P: First non-P2P device connected"); - - if (hapd->noa_enabled) { - wpa_printf(MSG_DEBUG, "P2P: Disable periodic NoA"); - hostapd_driver_set_noa(hapd, 0, 0, 0); - } -} - - -void hostapd_p2p_non_p2p_sta_disconnected(struct hostapd_data *hapd) -{ - wpa_printf(MSG_DEBUG, "P2P: Last non-P2P device disconnected"); - - if (hapd->noa_enabled) { - wpa_printf(MSG_DEBUG, "P2P: Enable periodic NoA"); - hostapd_driver_set_noa(hapd, 255, hapd->noa_start, - hapd->noa_duration); - } -} - -#endif /* CONFIG_P2P */ - - -#ifdef CONFIG_P2P_MANAGER -u8 * hostapd_eid_p2p_manage(struct hostapd_data *hapd, u8 *eid) -{ - u8 bitmap; - *eid++ = WLAN_EID_VENDOR_SPECIFIC; - *eid++ = 4 + 3 + 1; - WPA_PUT_BE24(eid, OUI_WFA); - eid += 3; - *eid++ = P2P_OUI_TYPE; - - *eid++ = P2P_ATTR_MANAGEABILITY; - WPA_PUT_LE16(eid, 1); - eid += 2; - bitmap = P2P_MAN_DEVICE_MANAGEMENT; - if (hapd->conf->p2p & P2P_ALLOW_CROSS_CONNECTION) - bitmap |= P2P_MAN_CROSS_CONNECTION_PERMITTED; - bitmap |= P2P_MAN_COEXISTENCE_OPTIONAL; - *eid++ = bitmap; - - return eid; -} -#endif /* CONFIG_P2P_MANAGER */ diff --git a/hostapd-0.8/src/ap/p2p_hostapd.h b/hostapd-0.8/src/ap/p2p_hostapd.h deleted file mode 100644 index 95b31d9..0000000 --- a/hostapd-0.8/src/ap/p2p_hostapd.h +++ /dev/null @@ -1,41 +0,0 @@ -/* - * hostapd / P2P integration - * Copyright (c) 2009-2010, Atheros Communications - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#ifndef P2P_HOSTAPD_H -#define P2P_HOSTAPD_H - -#ifdef CONFIG_P2P - -int hostapd_p2p_get_mib_sta(struct hostapd_data *hapd, struct sta_info *sta, - char *buf, size_t buflen); -int hostapd_p2p_set_noa(struct hostapd_data *hapd, u8 count, int start, - int duration); -void hostapd_p2p_non_p2p_sta_connected(struct hostapd_data *hapd); -void hostapd_p2p_non_p2p_sta_disconnected(struct hostapd_data *hapd); - - -#else /* CONFIG_P2P */ - -static inline int hostapd_p2p_get_mib_sta(struct hostapd_data *hapd, - struct sta_info *sta, - char *buf, size_t buflen) -{ - return 0; -} - -#endif /* CONFIG_P2P */ - -u8 * hostapd_eid_p2p_manage(struct hostapd_data *hapd, u8 *eid); - -#endif /* P2P_HOSTAPD_H */ diff --git a/hostapd-0.8/src/ap/peerkey_auth.c b/hostapd-0.8/src/ap/peerkey_auth.c deleted file mode 100644 index b8fa5a9..0000000 --- a/hostapd-0.8/src/ap/peerkey_auth.c +++ /dev/null @@ -1,402 +0,0 @@ -/* - * hostapd - PeerKey for Direct Link Setup (DLS) - * Copyright (c) 2006-2009, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#include "utils/includes.h" - -#include "utils/common.h" -#include "utils/eloop.h" -#include "crypto/sha1.h" -#include "crypto/sha256.h" -#include "crypto/random.h" -#include "wpa_auth.h" -#include "wpa_auth_i.h" -#include "wpa_auth_ie.h" - -#ifdef CONFIG_PEERKEY - -static void wpa_stsl_step(void *eloop_ctx, void *timeout_ctx) -{ -#if 0 - struct wpa_authenticator *wpa_auth = eloop_ctx; - struct wpa_stsl_negotiation *neg = timeout_ctx; -#endif - - /* TODO: ? */ -} - - -struct wpa_stsl_search { - const u8 *addr; - struct wpa_state_machine *sm; -}; - - -static int wpa_stsl_select_sta(struct wpa_state_machine *sm, void *ctx) -{ - struct wpa_stsl_search *search = ctx; - if (os_memcmp(search->addr, sm->addr, ETH_ALEN) == 0) { - search->sm = sm; - return 1; - } - return 0; -} - - -static void wpa_smk_send_error(struct wpa_authenticator *wpa_auth, - struct wpa_state_machine *sm, const u8 *peer, - u16 mui, u16 error_type) -{ - u8 kde[2 + RSN_SELECTOR_LEN + ETH_ALEN + - 2 + RSN_SELECTOR_LEN + sizeof(struct rsn_error_kde)]; - u8 *pos; - struct rsn_error_kde error; - - wpa_auth_logger(wpa_auth, sm->addr, LOGGER_DEBUG, - "Sending SMK Error"); - - pos = kde; - - if (peer) { - pos = wpa_add_kde(pos, RSN_KEY_DATA_MAC_ADDR, peer, ETH_ALEN, - NULL, 0); - } - - error.mui = host_to_be16(mui); - error.error_type = host_to_be16(error_type); - pos = wpa_add_kde(pos, RSN_KEY_DATA_ERROR, - (u8 *) &error, sizeof(error), NULL, 0); - - __wpa_send_eapol(wpa_auth, sm, - WPA_KEY_INFO_SECURE | WPA_KEY_INFO_MIC | - WPA_KEY_INFO_SMK_MESSAGE | WPA_KEY_INFO_ERROR, - NULL, NULL, kde, pos - kde, 0, 0, 0); -} - - -void wpa_smk_m1(struct wpa_authenticator *wpa_auth, - struct wpa_state_machine *sm, struct wpa_eapol_key *key) -{ - struct wpa_eapol_ie_parse kde; - struct wpa_stsl_search search; - u8 *buf, *pos; - size_t buf_len; - - if (wpa_parse_kde_ies((const u8 *) (key + 1), - WPA_GET_BE16(key->key_data_length), &kde) < 0) { - wpa_printf(MSG_INFO, "RSN: Failed to parse KDEs in SMK M1"); - return; - } - - if (kde.rsn_ie == NULL || kde.mac_addr == NULL || - kde.mac_addr_len < ETH_ALEN) { - wpa_printf(MSG_INFO, "RSN: No RSN IE or MAC address KDE in " - "SMK M1"); - return; - } - - /* Initiator = sm->addr; Peer = kde.mac_addr */ - - search.addr = kde.mac_addr; - search.sm = NULL; - if (wpa_auth_for_each_sta(wpa_auth, wpa_stsl_select_sta, &search) == - 0 || search.sm == NULL) { - wpa_printf(MSG_DEBUG, "RSN: SMK handshake with " MACSTR - " aborted - STA not associated anymore", - MAC2STR(kde.mac_addr)); - wpa_smk_send_error(wpa_auth, sm, kde.mac_addr, STK_MUI_SMK, - STK_ERR_STA_NR); - /* FIX: wpa_stsl_remove(wpa_auth, neg); */ - return; - } - - buf_len = kde.rsn_ie_len + 2 + RSN_SELECTOR_LEN + ETH_ALEN; - buf = os_malloc(buf_len); - if (buf == NULL) - return; - /* Initiator RSN IE */ - os_memcpy(buf, kde.rsn_ie, kde.rsn_ie_len); - pos = buf + kde.rsn_ie_len; - /* Initiator MAC Address */ - pos = wpa_add_kde(pos, RSN_KEY_DATA_MAC_ADDR, sm->addr, ETH_ALEN, - NULL, 0); - - /* SMK M2: - * EAPOL-Key(S=1, M=1, A=1, I=0, K=0, SM=1, KeyRSC=0, Nonce=INonce, - * MIC=MIC, DataKDs=(RSNIE_I, MAC_I KDE) - */ - - wpa_auth_logger(wpa_auth, search.sm->addr, LOGGER_DEBUG, - "Sending SMK M2"); - - __wpa_send_eapol(wpa_auth, search.sm, - WPA_KEY_INFO_SECURE | WPA_KEY_INFO_MIC | - WPA_KEY_INFO_ACK | WPA_KEY_INFO_SMK_MESSAGE, - NULL, key->key_nonce, buf, pos - buf, 0, 0, 0); - - os_free(buf); -} - - -static void wpa_send_smk_m4(struct wpa_authenticator *wpa_auth, - struct wpa_state_machine *sm, - struct wpa_eapol_key *key, - struct wpa_eapol_ie_parse *kde, - const u8 *smk) -{ - u8 *buf, *pos; - size_t buf_len; - u32 lifetime; - - /* SMK M4: - * EAPOL-Key(S=1, M=1, A=0, I=1, K=0, SM=1, KeyRSC=0, Nonce=PNonce, - * MIC=MIC, DataKDs=(MAC_I KDE, INonce KDE, SMK KDE, - * Lifetime KDE) - */ - - buf_len = 2 + RSN_SELECTOR_LEN + ETH_ALEN + - 2 + RSN_SELECTOR_LEN + WPA_NONCE_LEN + - 2 + RSN_SELECTOR_LEN + PMK_LEN + WPA_NONCE_LEN + - 2 + RSN_SELECTOR_LEN + sizeof(lifetime); - pos = buf = os_malloc(buf_len); - if (buf == NULL) - return; - - /* Initiator MAC Address */ - pos = wpa_add_kde(pos, RSN_KEY_DATA_MAC_ADDR, kde->mac_addr, ETH_ALEN, - NULL, 0); - - /* Initiator Nonce */ - pos = wpa_add_kde(pos, RSN_KEY_DATA_NONCE, kde->nonce, WPA_NONCE_LEN, - NULL, 0); - - /* SMK with PNonce */ - pos = wpa_add_kde(pos, RSN_KEY_DATA_SMK, smk, PMK_LEN, - key->key_nonce, WPA_NONCE_LEN); - - /* Lifetime */ - lifetime = htonl(43200); /* dot11RSNAConfigSMKLifetime */ - pos = wpa_add_kde(pos, RSN_KEY_DATA_LIFETIME, - (u8 *) &lifetime, sizeof(lifetime), NULL, 0); - - wpa_auth_logger(sm->wpa_auth, sm->addr, LOGGER_DEBUG, - "Sending SMK M4"); - - __wpa_send_eapol(wpa_auth, sm, - WPA_KEY_INFO_SECURE | WPA_KEY_INFO_MIC | - WPA_KEY_INFO_INSTALL | WPA_KEY_INFO_SMK_MESSAGE, - NULL, key->key_nonce, buf, pos - buf, 0, 1, 0); - - os_free(buf); -} - - -static void wpa_send_smk_m5(struct wpa_authenticator *wpa_auth, - struct wpa_state_machine *sm, - struct wpa_eapol_key *key, - struct wpa_eapol_ie_parse *kde, - const u8 *smk, const u8 *peer) -{ - u8 *buf, *pos; - size_t buf_len; - u32 lifetime; - - /* SMK M5: - * EAPOL-Key(S=1, M=1, A=0, I=0, K=0, SM=1, KeyRSC=0, Nonce=INonce, - * MIC=MIC, DataKDs=(RSNIE_P, MAC_P KDE, PNonce, SMK KDE, - * Lifetime KDE)) - */ - - buf_len = kde->rsn_ie_len + - 2 + RSN_SELECTOR_LEN + ETH_ALEN + - 2 + RSN_SELECTOR_LEN + WPA_NONCE_LEN + - 2 + RSN_SELECTOR_LEN + PMK_LEN + WPA_NONCE_LEN + - 2 + RSN_SELECTOR_LEN + sizeof(lifetime); - pos = buf = os_malloc(buf_len); - if (buf == NULL) - return; - - /* Peer RSN IE */ - os_memcpy(buf, kde->rsn_ie, kde->rsn_ie_len); - pos = buf + kde->rsn_ie_len; - - /* Peer MAC Address */ - pos = wpa_add_kde(pos, RSN_KEY_DATA_MAC_ADDR, peer, ETH_ALEN, NULL, 0); - - /* PNonce */ - pos = wpa_add_kde(pos, RSN_KEY_DATA_NONCE, key->key_nonce, - WPA_NONCE_LEN, NULL, 0); - - /* SMK and INonce */ - pos = wpa_add_kde(pos, RSN_KEY_DATA_SMK, smk, PMK_LEN, - kde->nonce, WPA_NONCE_LEN); - - /* Lifetime */ - lifetime = htonl(43200); /* dot11RSNAConfigSMKLifetime */ - pos = wpa_add_kde(pos, RSN_KEY_DATA_LIFETIME, - (u8 *) &lifetime, sizeof(lifetime), NULL, 0); - - wpa_auth_logger(sm->wpa_auth, sm->addr, LOGGER_DEBUG, - "Sending SMK M5"); - - __wpa_send_eapol(wpa_auth, sm, - WPA_KEY_INFO_SECURE | WPA_KEY_INFO_MIC | - WPA_KEY_INFO_SMK_MESSAGE, - NULL, kde->nonce, buf, pos - buf, 0, 1, 0); - - os_free(buf); -} - - -void wpa_smk_m3(struct wpa_authenticator *wpa_auth, - struct wpa_state_machine *sm, struct wpa_eapol_key *key) -{ - struct wpa_eapol_ie_parse kde; - struct wpa_stsl_search search; - u8 smk[32], buf[ETH_ALEN + 8 + 2 * WPA_NONCE_LEN], *pos; - - if (wpa_parse_kde_ies((const u8 *) (key + 1), - WPA_GET_BE16(key->key_data_length), &kde) < 0) { - wpa_printf(MSG_INFO, "RSN: Failed to parse KDEs in SMK M3"); - return; - } - - if (kde.rsn_ie == NULL || - kde.mac_addr == NULL || kde.mac_addr_len < ETH_ALEN || - kde.nonce == NULL || kde.nonce_len < WPA_NONCE_LEN) { - wpa_printf(MSG_INFO, "RSN: No RSN IE, MAC address KDE, or " - "Nonce KDE in SMK M3"); - return; - } - - /* Peer = sm->addr; Initiator = kde.mac_addr; - * Peer Nonce = key->key_nonce; Initiator Nonce = kde.nonce */ - - search.addr = kde.mac_addr; - search.sm = NULL; - if (wpa_auth_for_each_sta(wpa_auth, wpa_stsl_select_sta, &search) == - 0 || search.sm == NULL) { - wpa_printf(MSG_DEBUG, "RSN: SMK handshake with " MACSTR - " aborted - STA not associated anymore", - MAC2STR(kde.mac_addr)); - wpa_smk_send_error(wpa_auth, sm, kde.mac_addr, STK_MUI_SMK, - STK_ERR_STA_NR); - /* FIX: wpa_stsl_remove(wpa_auth, neg); */ - return; - } - - if (random_get_bytes(smk, PMK_LEN)) { - wpa_printf(MSG_DEBUG, "RSN: Failed to generate SMK"); - return; - } - - /* SMK = PRF-256(Random number, "SMK Derivation", - * AA || Time || INonce || PNonce) - */ - os_memcpy(buf, wpa_auth->addr, ETH_ALEN); - pos = buf + ETH_ALEN; - wpa_get_ntp_timestamp(pos); - pos += 8; - os_memcpy(pos, kde.nonce, WPA_NONCE_LEN); - pos += WPA_NONCE_LEN; - os_memcpy(pos, key->key_nonce, WPA_NONCE_LEN); -#ifdef CONFIG_IEEE80211W - sha256_prf(smk, PMK_LEN, "SMK Derivation", buf, sizeof(buf), - smk, PMK_LEN); -#else /* CONFIG_IEEE80211W */ - sha1_prf(smk, PMK_LEN, "SMK Derivation", buf, sizeof(buf), - smk, PMK_LEN); -#endif /* CONFIG_IEEE80211W */ - - wpa_hexdump_key(MSG_DEBUG, "RSN: SMK", smk, PMK_LEN); - - wpa_send_smk_m4(wpa_auth, sm, key, &kde, smk); - wpa_send_smk_m5(wpa_auth, search.sm, key, &kde, smk, sm->addr); - - /* Authenticator does not need SMK anymore and it is required to forget - * it. */ - os_memset(smk, 0, sizeof(*smk)); -} - - -void wpa_smk_error(struct wpa_authenticator *wpa_auth, - struct wpa_state_machine *sm, struct wpa_eapol_key *key) -{ - struct wpa_eapol_ie_parse kde; - struct wpa_stsl_search search; - struct rsn_error_kde error; - u16 mui, error_type; - - if (wpa_parse_kde_ies((const u8 *) (key + 1), - WPA_GET_BE16(key->key_data_length), &kde) < 0) { - wpa_printf(MSG_INFO, "RSN: Failed to parse KDEs in SMK Error"); - return; - } - - if (kde.mac_addr == NULL || kde.mac_addr_len < ETH_ALEN || - kde.error == NULL || kde.error_len < sizeof(error)) { - wpa_printf(MSG_INFO, "RSN: No MAC address or Error KDE in " - "SMK Error"); - return; - } - - search.addr = kde.mac_addr; - search.sm = NULL; - if (wpa_auth_for_each_sta(wpa_auth, wpa_stsl_select_sta, &search) == - 0 || search.sm == NULL) { - wpa_printf(MSG_DEBUG, "RSN: Peer STA " MACSTR " not " - "associated for SMK Error message from " MACSTR, - MAC2STR(kde.mac_addr), MAC2STR(sm->addr)); - return; - } - - os_memcpy(&error, kde.error, sizeof(error)); - mui = be_to_host16(error.mui); - error_type = be_to_host16(error.error_type); - wpa_auth_vlogger(wpa_auth, sm->addr, LOGGER_INFO, - "STA reported SMK Error: Peer " MACSTR - " MUI %d Error Type %d", - MAC2STR(kde.mac_addr), mui, error_type); - - wpa_smk_send_error(wpa_auth, search.sm, sm->addr, mui, error_type); -} - - -int wpa_stsl_remove(struct wpa_authenticator *wpa_auth, - struct wpa_stsl_negotiation *neg) -{ - struct wpa_stsl_negotiation *pos, *prev; - - if (wpa_auth == NULL) - return -1; - pos = wpa_auth->stsl_negotiations; - prev = NULL; - while (pos) { - if (pos == neg) { - if (prev) - prev->next = pos->next; - else - wpa_auth->stsl_negotiations = pos->next; - - eloop_cancel_timeout(wpa_stsl_step, wpa_auth, pos); - os_free(pos); - return 0; - } - prev = pos; - pos = pos->next; - } - - return -1; -} - -#endif /* CONFIG_PEERKEY */ diff --git a/hostapd-0.8/src/ap/pmksa_cache_auth.c b/hostapd-0.8/src/ap/pmksa_cache_auth.c deleted file mode 100644 index 22f44b7..0000000 --- a/hostapd-0.8/src/ap/pmksa_cache_auth.c +++ /dev/null @@ -1,425 +0,0 @@ -/* - * hostapd - PMKSA cache for IEEE 802.11i RSN - * Copyright (c) 2004-2008, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#include "utils/includes.h" - -#include "utils/common.h" -#include "utils/eloop.h" -#include "eapol_auth/eapol_auth_sm.h" -#include "eapol_auth/eapol_auth_sm_i.h" -#include "sta_info.h" -#include "ap_config.h" -#include "pmksa_cache_auth.h" - - -static const int pmksa_cache_max_entries = 1024; -static const int dot11RSNAConfigPMKLifetime = 43200; - -struct rsn_pmksa_cache { -#define PMKID_HASH_SIZE 128 -#define PMKID_HASH(pmkid) (unsigned int) ((pmkid)[0] & 0x7f) - struct rsn_pmksa_cache_entry *pmkid[PMKID_HASH_SIZE]; - struct rsn_pmksa_cache_entry *pmksa; - int pmksa_count; - - void (*free_cb)(struct rsn_pmksa_cache_entry *entry, void *ctx); - void *ctx; -}; - - -static void pmksa_cache_set_expiration(struct rsn_pmksa_cache *pmksa); - - -static void _pmksa_cache_free_entry(struct rsn_pmksa_cache_entry *entry) -{ - if (entry == NULL) - return; - os_free(entry->identity); -#ifndef CONFIG_NO_RADIUS - radius_free_class(&entry->radius_class); -#endif /* CONFIG_NO_RADIUS */ - os_free(entry); -} - - -static void pmksa_cache_free_entry(struct rsn_pmksa_cache *pmksa, - struct rsn_pmksa_cache_entry *entry) -{ - struct rsn_pmksa_cache_entry *pos, *prev; - - pmksa->pmksa_count--; - pmksa->free_cb(entry, pmksa->ctx); - pos = pmksa->pmkid[PMKID_HASH(entry->pmkid)]; - prev = NULL; - while (pos) { - if (pos == entry) { - if (prev != NULL) { - prev->hnext = pos->hnext; - } else { - pmksa->pmkid[PMKID_HASH(entry->pmkid)] = - pos->hnext; - } - break; - } - prev = pos; - pos = pos->hnext; - } - - pos = pmksa->pmksa; - prev = NULL; - while (pos) { - if (pos == entry) { - if (prev != NULL) - prev->next = pos->next; - else - pmksa->pmksa = pos->next; - break; - } - prev = pos; - pos = pos->next; - } - _pmksa_cache_free_entry(entry); -} - - -static void pmksa_cache_expire(void *eloop_ctx, void *timeout_ctx) -{ - struct rsn_pmksa_cache *pmksa = eloop_ctx; - struct os_time now; - - os_get_time(&now); - while (pmksa->pmksa && pmksa->pmksa->expiration <= now.sec) { - struct rsn_pmksa_cache_entry *entry = pmksa->pmksa; - pmksa->pmksa = entry->next; - wpa_printf(MSG_DEBUG, "RSN: expired PMKSA cache entry for " - MACSTR, MAC2STR(entry->spa)); - pmksa_cache_free_entry(pmksa, entry); - } - - pmksa_cache_set_expiration(pmksa); -} - - -static void pmksa_cache_set_expiration(struct rsn_pmksa_cache *pmksa) -{ - int sec; - struct os_time now; - - eloop_cancel_timeout(pmksa_cache_expire, pmksa, NULL); - if (pmksa->pmksa == NULL) - return; - os_get_time(&now); - sec = pmksa->pmksa->expiration - now.sec; - if (sec < 0) - sec = 0; - eloop_register_timeout(sec + 1, 0, pmksa_cache_expire, pmksa, NULL); -} - - -static void pmksa_cache_from_eapol_data(struct rsn_pmksa_cache_entry *entry, - struct eapol_state_machine *eapol) -{ - if (eapol == NULL) - return; - - if (eapol->identity) { - entry->identity = os_malloc(eapol->identity_len); - if (entry->identity) { - entry->identity_len = eapol->identity_len; - os_memcpy(entry->identity, eapol->identity, - eapol->identity_len); - } - } - -#ifndef CONFIG_NO_RADIUS - radius_copy_class(&entry->radius_class, &eapol->radius_class); -#endif /* CONFIG_NO_RADIUS */ - - entry->eap_type_authsrv = eapol->eap_type_authsrv; - entry->vlan_id = ((struct sta_info *) eapol->sta)->vlan_id; -} - - -void pmksa_cache_to_eapol_data(struct rsn_pmksa_cache_entry *entry, - struct eapol_state_machine *eapol) -{ - if (entry == NULL || eapol == NULL) - return; - - if (entry->identity) { - os_free(eapol->identity); - eapol->identity = os_malloc(entry->identity_len); - if (eapol->identity) { - eapol->identity_len = entry->identity_len; - os_memcpy(eapol->identity, entry->identity, - entry->identity_len); - } - wpa_hexdump_ascii(MSG_DEBUG, "STA identity from PMKSA", - eapol->identity, eapol->identity_len); - } - -#ifndef CONFIG_NO_RADIUS - radius_free_class(&eapol->radius_class); - radius_copy_class(&eapol->radius_class, &entry->radius_class); -#endif /* CONFIG_NO_RADIUS */ - if (eapol->radius_class.attr) { - wpa_printf(MSG_DEBUG, "Copied %lu Class attribute(s) from " - "PMKSA", (unsigned long) eapol->radius_class.count); - } - - eapol->eap_type_authsrv = entry->eap_type_authsrv; - ((struct sta_info *) eapol->sta)->vlan_id = entry->vlan_id; -} - - -static void pmksa_cache_link_entry(struct rsn_pmksa_cache *pmksa, - struct rsn_pmksa_cache_entry *entry) -{ - struct rsn_pmksa_cache_entry *pos, *prev; - - /* Add the new entry; order by expiration time */ - pos = pmksa->pmksa; - prev = NULL; - while (pos) { - if (pos->expiration > entry->expiration) - break; - prev = pos; - pos = pos->next; - } - if (prev == NULL) { - entry->next = pmksa->pmksa; - pmksa->pmksa = entry; - } else { - entry->next = prev->next; - prev->next = entry; - } - entry->hnext = pmksa->pmkid[PMKID_HASH(entry->pmkid)]; - pmksa->pmkid[PMKID_HASH(entry->pmkid)] = entry; - - pmksa->pmksa_count++; - wpa_printf(MSG_DEBUG, "RSN: added PMKSA cache entry for " MACSTR, - MAC2STR(entry->spa)); - wpa_hexdump(MSG_DEBUG, "RSN: added PMKID", entry->pmkid, PMKID_LEN); -} - - -/** - * pmksa_cache_auth_add - Add a PMKSA cache entry - * @pmksa: Pointer to PMKSA cache data from pmksa_cache_auth_init() - * @pmk: The new pairwise master key - * @pmk_len: PMK length in bytes, usually PMK_LEN (32) - * @aa: Authenticator address - * @spa: Supplicant address - * @session_timeout: Session timeout - * @eapol: Pointer to EAPOL state machine data - * @akmp: WPA_KEY_MGMT_* used in key derivation - * Returns: Pointer to the added PMKSA cache entry or %NULL on error - * - * This function create a PMKSA entry for a new PMK and adds it to the PMKSA - * cache. If an old entry is already in the cache for the same Supplicant, - * this entry will be replaced with the new entry. PMKID will be calculated - * based on the PMK. - */ -struct rsn_pmksa_cache_entry * -pmksa_cache_auth_add(struct rsn_pmksa_cache *pmksa, - const u8 *pmk, size_t pmk_len, - const u8 *aa, const u8 *spa, int session_timeout, - struct eapol_state_machine *eapol, int akmp) -{ - struct rsn_pmksa_cache_entry *entry, *pos; - struct os_time now; - - if (pmk_len > PMK_LEN) - return NULL; - - entry = os_zalloc(sizeof(*entry)); - if (entry == NULL) - return NULL; - os_memcpy(entry->pmk, pmk, pmk_len); - entry->pmk_len = pmk_len; - rsn_pmkid(pmk, pmk_len, aa, spa, entry->pmkid, - wpa_key_mgmt_sha256(akmp)); - os_get_time(&now); - entry->expiration = now.sec; - if (session_timeout > 0) - entry->expiration += session_timeout; - else - entry->expiration += dot11RSNAConfigPMKLifetime; - entry->akmp = akmp; - os_memcpy(entry->spa, spa, ETH_ALEN); - pmksa_cache_from_eapol_data(entry, eapol); - - /* Replace an old entry for the same STA (if found) with the new entry - */ - pos = pmksa_cache_auth_get(pmksa, spa, NULL); - if (pos) - pmksa_cache_free_entry(pmksa, pos); - - if (pmksa->pmksa_count >= pmksa_cache_max_entries && pmksa->pmksa) { - /* Remove the oldest entry to make room for the new entry */ - wpa_printf(MSG_DEBUG, "RSN: removed the oldest PMKSA cache " - "entry (for " MACSTR ") to make room for new one", - MAC2STR(pmksa->pmksa->spa)); - pmksa_cache_free_entry(pmksa, pmksa->pmksa); - } - - pmksa_cache_link_entry(pmksa, entry); - - return entry; -} - - -struct rsn_pmksa_cache_entry * -pmksa_cache_add_okc(struct rsn_pmksa_cache *pmksa, - const struct rsn_pmksa_cache_entry *old_entry, - const u8 *aa, const u8 *pmkid) -{ - struct rsn_pmksa_cache_entry *entry; - - entry = os_zalloc(sizeof(*entry)); - if (entry == NULL) - return NULL; - os_memcpy(entry->pmkid, pmkid, PMKID_LEN); - os_memcpy(entry->pmk, old_entry->pmk, old_entry->pmk_len); - entry->pmk_len = old_entry->pmk_len; - entry->expiration = old_entry->expiration; - entry->akmp = old_entry->akmp; - os_memcpy(entry->spa, old_entry->spa, ETH_ALEN); - entry->opportunistic = 1; - if (old_entry->identity) { - entry->identity = os_malloc(old_entry->identity_len); - if (entry->identity) { - entry->identity_len = old_entry->identity_len; - os_memcpy(entry->identity, old_entry->identity, - old_entry->identity_len); - } - } -#ifndef CONFIG_NO_RADIUS - radius_copy_class(&entry->radius_class, &old_entry->radius_class); -#endif /* CONFIG_NO_RADIUS */ - entry->eap_type_authsrv = old_entry->eap_type_authsrv; - entry->vlan_id = old_entry->vlan_id; - entry->opportunistic = 1; - - pmksa_cache_link_entry(pmksa, entry); - - return entry; -} - - -/** - * pmksa_cache_auth_deinit - Free all entries in PMKSA cache - * @pmksa: Pointer to PMKSA cache data from pmksa_cache_auth_init() - */ -void pmksa_cache_auth_deinit(struct rsn_pmksa_cache *pmksa) -{ - struct rsn_pmksa_cache_entry *entry, *prev; - int i; - - if (pmksa == NULL) - return; - - entry = pmksa->pmksa; - while (entry) { - prev = entry; - entry = entry->next; - _pmksa_cache_free_entry(prev); - } - eloop_cancel_timeout(pmksa_cache_expire, pmksa, NULL); - for (i = 0; i < PMKID_HASH_SIZE; i++) - pmksa->pmkid[i] = NULL; - os_free(pmksa); -} - - -/** - * pmksa_cache_auth_get - Fetch a PMKSA cache entry - * @pmksa: Pointer to PMKSA cache data from pmksa_cache_auth_init() - * @spa: Supplicant address or %NULL to match any - * @pmkid: PMKID or %NULL to match any - * Returns: Pointer to PMKSA cache entry or %NULL if no match was found - */ -struct rsn_pmksa_cache_entry * -pmksa_cache_auth_get(struct rsn_pmksa_cache *pmksa, - const u8 *spa, const u8 *pmkid) -{ - struct rsn_pmksa_cache_entry *entry; - - if (pmkid) - entry = pmksa->pmkid[PMKID_HASH(pmkid)]; - else - entry = pmksa->pmksa; - while (entry) { - if ((spa == NULL || - os_memcmp(entry->spa, spa, ETH_ALEN) == 0) && - (pmkid == NULL || - os_memcmp(entry->pmkid, pmkid, PMKID_LEN) == 0)) - return entry; - entry = pmkid ? entry->hnext : entry->next; - } - return NULL; -} - - -/** - * pmksa_cache_get_okc - Fetch a PMKSA cache entry using OKC - * @pmksa: Pointer to PMKSA cache data from pmksa_cache_auth_init() - * @aa: Authenticator address - * @spa: Supplicant address - * @pmkid: PMKID - * Returns: Pointer to PMKSA cache entry or %NULL if no match was found - * - * Use opportunistic key caching (OKC) to find a PMK for a supplicant. - */ -struct rsn_pmksa_cache_entry * pmksa_cache_get_okc( - struct rsn_pmksa_cache *pmksa, const u8 *aa, const u8 *spa, - const u8 *pmkid) -{ - struct rsn_pmksa_cache_entry *entry; - u8 new_pmkid[PMKID_LEN]; - - entry = pmksa->pmksa; - while (entry) { - if (os_memcmp(entry->spa, spa, ETH_ALEN) != 0) - continue; - rsn_pmkid(entry->pmk, entry->pmk_len, aa, spa, new_pmkid, - wpa_key_mgmt_sha256(entry->akmp)); - if (os_memcmp(new_pmkid, pmkid, PMKID_LEN) == 0) - return entry; - entry = entry->next; - } - return NULL; -} - - -/** - * pmksa_cache_auth_init - Initialize PMKSA cache - * @free_cb: Callback function to be called when a PMKSA cache entry is freed - * @ctx: Context pointer for free_cb function - * Returns: Pointer to PMKSA cache data or %NULL on failure - */ -struct rsn_pmksa_cache * -pmksa_cache_auth_init(void (*free_cb)(struct rsn_pmksa_cache_entry *entry, - void *ctx), void *ctx) -{ - struct rsn_pmksa_cache *pmksa; - - pmksa = os_zalloc(sizeof(*pmksa)); - if (pmksa) { - pmksa->free_cb = free_cb; - pmksa->ctx = ctx; - } - - return pmksa; -} diff --git a/hostapd-0.8/src/ap/pmksa_cache_auth.h b/hostapd-0.8/src/ap/pmksa_cache_auth.h deleted file mode 100644 index 9628b13..0000000 --- a/hostapd-0.8/src/ap/pmksa_cache_auth.h +++ /dev/null @@ -1,64 +0,0 @@ -/* - * hostapd - PMKSA cache for IEEE 802.11i RSN - * Copyright (c) 2004-2008, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#ifndef PMKSA_CACHE_H -#define PMKSA_CACHE_H - -#include "radius/radius.h" - -/** - * struct rsn_pmksa_cache_entry - PMKSA cache entry - */ -struct rsn_pmksa_cache_entry { - struct rsn_pmksa_cache_entry *next, *hnext; - u8 pmkid[PMKID_LEN]; - u8 pmk[PMK_LEN]; - size_t pmk_len; - os_time_t expiration; - int akmp; /* WPA_KEY_MGMT_* */ - u8 spa[ETH_ALEN]; - - u8 *identity; - size_t identity_len; - struct radius_class_data radius_class; - u8 eap_type_authsrv; - int vlan_id; - int opportunistic; -}; - -struct rsn_pmksa_cache; - -struct rsn_pmksa_cache * -pmksa_cache_auth_init(void (*free_cb)(struct rsn_pmksa_cache_entry *entry, - void *ctx), void *ctx); -void pmksa_cache_auth_deinit(struct rsn_pmksa_cache *pmksa); -struct rsn_pmksa_cache_entry * -pmksa_cache_auth_get(struct rsn_pmksa_cache *pmksa, - const u8 *spa, const u8 *pmkid); -struct rsn_pmksa_cache_entry * pmksa_cache_get_okc( - struct rsn_pmksa_cache *pmksa, const u8 *spa, const u8 *aa, - const u8 *pmkid); -struct rsn_pmksa_cache_entry * -pmksa_cache_auth_add(struct rsn_pmksa_cache *pmksa, - const u8 *pmk, size_t pmk_len, - const u8 *aa, const u8 *spa, int session_timeout, - struct eapol_state_machine *eapol, int akmp); -struct rsn_pmksa_cache_entry * -pmksa_cache_add_okc(struct rsn_pmksa_cache *pmksa, - const struct rsn_pmksa_cache_entry *old_entry, - const u8 *aa, const u8 *pmkid); -void pmksa_cache_to_eapol_data(struct rsn_pmksa_cache_entry *entry, - struct eapol_state_machine *eapol); - -#endif /* PMKSA_CACHE_H */ diff --git a/hostapd-0.8/src/ap/preauth_auth.c b/hostapd-0.8/src/ap/preauth_auth.c deleted file mode 100644 index 8e13315..0000000 --- a/hostapd-0.8/src/ap/preauth_auth.c +++ /dev/null @@ -1,279 +0,0 @@ -/* - * hostapd - Authenticator for IEEE 802.11i RSN pre-authentication - * Copyright (c) 2004-2007, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#include "utils/includes.h" - -#ifdef CONFIG_RSN_PREAUTH - -#include "utils/common.h" -#include "utils/eloop.h" -#include "l2_packet/l2_packet.h" -#include "common/wpa_common.h" -#include "eapol_auth/eapol_auth_sm.h" -#include "eapol_auth/eapol_auth_sm_i.h" -#include "hostapd.h" -#include "ap_config.h" -#include "ieee802_1x.h" -#include "sta_info.h" -#include "wpa_auth.h" -#include "preauth_auth.h" - -#ifndef ETH_P_PREAUTH -#define ETH_P_PREAUTH 0x88C7 /* IEEE 802.11i pre-authentication */ -#endif /* ETH_P_PREAUTH */ - -static const int dot11RSNAConfigPMKLifetime = 43200; - -struct rsn_preauth_interface { - struct rsn_preauth_interface *next; - struct hostapd_data *hapd; - struct l2_packet_data *l2; - char *ifname; - int ifindex; -}; - - -static void rsn_preauth_receive(void *ctx, const u8 *src_addr, - const u8 *buf, size_t len) -{ - struct rsn_preauth_interface *piface = ctx; - struct hostapd_data *hapd = piface->hapd; - struct ieee802_1x_hdr *hdr; - struct sta_info *sta; - struct l2_ethhdr *ethhdr; - - wpa_printf(MSG_DEBUG, "RSN: receive pre-auth packet " - "from interface '%s'", piface->ifname); - if (len < sizeof(*ethhdr) + sizeof(*hdr)) { - wpa_printf(MSG_DEBUG, "RSN: too short pre-auth packet " - "(len=%lu)", (unsigned long) len); - return; - } - - ethhdr = (struct l2_ethhdr *) buf; - hdr = (struct ieee802_1x_hdr *) (ethhdr + 1); - - if (os_memcmp(ethhdr->h_dest, hapd->own_addr, ETH_ALEN) != 0) { - wpa_printf(MSG_DEBUG, "RSN: pre-auth for foreign address " - MACSTR, MAC2STR(ethhdr->h_dest)); - return; - } - - sta = ap_get_sta(hapd, ethhdr->h_source); - if (sta && (sta->flags & WLAN_STA_ASSOC)) { - wpa_printf(MSG_DEBUG, "RSN: pre-auth for already association " - "STA " MACSTR, MAC2STR(sta->addr)); - return; - } - if (!sta && hdr->type == IEEE802_1X_TYPE_EAPOL_START) { - sta = ap_sta_add(hapd, ethhdr->h_source); - if (sta == NULL) - return; - sta->flags = WLAN_STA_PREAUTH; - - ieee802_1x_new_station(hapd, sta); - if (sta->eapol_sm == NULL) { - ap_free_sta(hapd, sta); - sta = NULL; - } else { - sta->eapol_sm->radius_identifier = -1; - sta->eapol_sm->portValid = TRUE; - sta->eapol_sm->flags |= EAPOL_SM_PREAUTH; - } - } - if (sta == NULL) - return; - sta->preauth_iface = piface; - ieee802_1x_receive(hapd, ethhdr->h_source, (u8 *) (ethhdr + 1), - len - sizeof(*ethhdr)); -} - - -static int rsn_preauth_iface_add(struct hostapd_data *hapd, const char *ifname) -{ - struct rsn_preauth_interface *piface; - - wpa_printf(MSG_DEBUG, "RSN pre-auth interface '%s'", ifname); - - piface = os_zalloc(sizeof(*piface)); - if (piface == NULL) - return -1; - piface->hapd = hapd; - - piface->ifname = os_strdup(ifname); - if (piface->ifname == NULL) { - goto fail1; - } - - piface->l2 = l2_packet_init(piface->ifname, NULL, ETH_P_PREAUTH, - rsn_preauth_receive, piface, 1); - if (piface->l2 == NULL) { - wpa_printf(MSG_ERROR, "Failed to open register layer 2 access " - "to ETH_P_PREAUTH"); - goto fail2; - } - - piface->next = hapd->preauth_iface; - hapd->preauth_iface = piface; - return 0; - -fail2: - os_free(piface->ifname); -fail1: - os_free(piface); - return -1; -} - - -void rsn_preauth_iface_deinit(struct hostapd_data *hapd) -{ - struct rsn_preauth_interface *piface, *prev; - - piface = hapd->preauth_iface; - hapd->preauth_iface = NULL; - while (piface) { - prev = piface; - piface = piface->next; - l2_packet_deinit(prev->l2); - os_free(prev->ifname); - os_free(prev); - } -} - - -int rsn_preauth_iface_init(struct hostapd_data *hapd) -{ - char *tmp, *start, *end; - - if (hapd->conf->rsn_preauth_interfaces == NULL) - return 0; - - tmp = os_strdup(hapd->conf->rsn_preauth_interfaces); - if (tmp == NULL) - return -1; - start = tmp; - for (;;) { - while (*start == ' ') - start++; - if (*start == '\0') - break; - end = os_strchr(start, ' '); - if (end) - *end = '\0'; - - if (rsn_preauth_iface_add(hapd, start)) { - rsn_preauth_iface_deinit(hapd); - os_free(tmp); - return -1; - } - - if (end) - start = end + 1; - else - break; - } - os_free(tmp); - return 0; -} - - -static void rsn_preauth_finished_cb(void *eloop_ctx, void *timeout_ctx) -{ - struct hostapd_data *hapd = eloop_ctx; - struct sta_info *sta = timeout_ctx; - wpa_printf(MSG_DEBUG, "RSN: Removing pre-authentication STA entry for " - MACSTR, MAC2STR(sta->addr)); - ap_free_sta(hapd, sta); -} - - -void rsn_preauth_finished(struct hostapd_data *hapd, struct sta_info *sta, - int success) -{ - const u8 *key; - size_t len; - hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_WPA, - HOSTAPD_LEVEL_INFO, "pre-authentication %s", - success ? "succeeded" : "failed"); - - key = ieee802_1x_get_key(sta->eapol_sm, &len); - if (len > PMK_LEN) - len = PMK_LEN; - if (success && key) { - if (wpa_auth_pmksa_add_preauth(hapd->wpa_auth, key, len, - sta->addr, - dot11RSNAConfigPMKLifetime, - sta->eapol_sm) == 0) { - hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_WPA, - HOSTAPD_LEVEL_DEBUG, - "added PMKSA cache entry (pre-auth)"); - } else { - hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_WPA, - HOSTAPD_LEVEL_DEBUG, - "failed to add PMKSA cache entry " - "(pre-auth)"); - } - } - - /* - * Finish STA entry removal from timeout in order to avoid freeing - * STA data before the caller has finished processing. - */ - eloop_register_timeout(0, 0, rsn_preauth_finished_cb, hapd, sta); -} - - -void rsn_preauth_send(struct hostapd_data *hapd, struct sta_info *sta, - u8 *buf, size_t len) -{ - struct rsn_preauth_interface *piface; - struct l2_ethhdr *ethhdr; - - piface = hapd->preauth_iface; - while (piface) { - if (piface == sta->preauth_iface) - break; - piface = piface->next; - } - - if (piface == NULL) { - wpa_printf(MSG_DEBUG, "RSN: Could not find pre-authentication " - "interface for " MACSTR, MAC2STR(sta->addr)); - return; - } - - ethhdr = os_malloc(sizeof(*ethhdr) + len); - if (ethhdr == NULL) - return; - - os_memcpy(ethhdr->h_dest, sta->addr, ETH_ALEN); - os_memcpy(ethhdr->h_source, hapd->own_addr, ETH_ALEN); - ethhdr->h_proto = host_to_be16(ETH_P_PREAUTH); - os_memcpy(ethhdr + 1, buf, len); - - if (l2_packet_send(piface->l2, sta->addr, ETH_P_PREAUTH, (u8 *) ethhdr, - sizeof(*ethhdr) + len) < 0) { - wpa_printf(MSG_ERROR, "Failed to send preauth packet using " - "l2_packet_send\n"); - } - os_free(ethhdr); -} - - -void rsn_preauth_free_station(struct hostapd_data *hapd, struct sta_info *sta) -{ - eloop_cancel_timeout(rsn_preauth_finished_cb, hapd, sta); -} - -#endif /* CONFIG_RSN_PREAUTH */ diff --git a/hostapd-0.8/src/ap/preauth_auth.h b/hostapd-0.8/src/ap/preauth_auth.h deleted file mode 100644 index 5348bee..0000000 --- a/hostapd-0.8/src/ap/preauth_auth.h +++ /dev/null @@ -1,58 +0,0 @@ -/* - * hostapd - Authenticator for IEEE 802.11i RSN pre-authentication - * Copyright (c) 2004-2005, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#ifndef PREAUTH_H -#define PREAUTH_H - -#ifdef CONFIG_RSN_PREAUTH - -int rsn_preauth_iface_init(struct hostapd_data *hapd); -void rsn_preauth_iface_deinit(struct hostapd_data *hapd); -void rsn_preauth_finished(struct hostapd_data *hapd, struct sta_info *sta, - int success); -void rsn_preauth_send(struct hostapd_data *hapd, struct sta_info *sta, - u8 *buf, size_t len); -void rsn_preauth_free_station(struct hostapd_data *hapd, struct sta_info *sta); - -#else /* CONFIG_RSN_PREAUTH */ - -static inline int rsn_preauth_iface_init(struct hostapd_data *hapd) -{ - return 0; -} - -static inline void rsn_preauth_iface_deinit(struct hostapd_data *hapd) -{ -} - -static inline void rsn_preauth_finished(struct hostapd_data *hapd, - struct sta_info *sta, - int success) -{ -} - -static inline void rsn_preauth_send(struct hostapd_data *hapd, - struct sta_info *sta, - u8 *buf, size_t len) -{ -} - -static inline void rsn_preauth_free_station(struct hostapd_data *hapd, - struct sta_info *sta) -{ -} - -#endif /* CONFIG_RSN_PREAUTH */ - -#endif /* PREAUTH_H */ diff --git a/hostapd-0.8/src/ap/sta_info.c b/hostapd-0.8/src/ap/sta_info.c deleted file mode 100644 index e829447..0000000 --- a/hostapd-0.8/src/ap/sta_info.c +++ /dev/null @@ -1,796 +0,0 @@ -/* - * hostapd / Station table - * Copyright (c) 2002-2009, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#include "utils/includes.h" - -#include "utils/common.h" -#include "utils/eloop.h" -#include "common/ieee802_11_defs.h" -#include "radius/radius.h" -#include "radius/radius_client.h" -#include "drivers/driver.h" -#include "p2p/p2p.h" -#include "hostapd.h" -#include "accounting.h" -#include "ieee802_1x.h" -#include "ieee802_11.h" -#include "wpa_auth.h" -#include "preauth_auth.h" -#include "ap_config.h" -#include "beacon.h" -#include "ap_mlme.h" -#include "vlan_init.h" -#include "p2p_hostapd.h" -#include "ap_drv_ops.h" -#include "sta_info.h" - -static void ap_sta_remove_in_other_bss(struct hostapd_data *hapd, - struct sta_info *sta); -static void ap_handle_session_timer(void *eloop_ctx, void *timeout_ctx); -#ifdef CONFIG_IEEE80211W -static void ap_sa_query_timer(void *eloop_ctx, void *timeout_ctx); -#endif /* CONFIG_IEEE80211W */ - -int ap_for_each_sta(struct hostapd_data *hapd, - int (*cb)(struct hostapd_data *hapd, struct sta_info *sta, - void *ctx), - void *ctx) -{ - struct sta_info *sta; - - for (sta = hapd->sta_list; sta; sta = sta->next) { - if (cb(hapd, sta, ctx)) - return 1; - } - - return 0; -} - - -struct sta_info * ap_get_sta(struct hostapd_data *hapd, const u8 *sta) -{ - struct sta_info *s; - - s = hapd->sta_hash[STA_HASH(sta)]; - while (s != NULL && os_memcmp(s->addr, sta, 6) != 0) - s = s->hnext; - return s; -} - - -static void ap_sta_list_del(struct hostapd_data *hapd, struct sta_info *sta) -{ - struct sta_info *tmp; - - if (hapd->sta_list == sta) { - hapd->sta_list = sta->next; - return; - } - - tmp = hapd->sta_list; - while (tmp != NULL && tmp->next != sta) - tmp = tmp->next; - if (tmp == NULL) { - wpa_printf(MSG_DEBUG, "Could not remove STA " MACSTR " from " - "list.", MAC2STR(sta->addr)); - } else - tmp->next = sta->next; -} - - -void ap_sta_hash_add(struct hostapd_data *hapd, struct sta_info *sta) -{ - sta->hnext = hapd->sta_hash[STA_HASH(sta->addr)]; - hapd->sta_hash[STA_HASH(sta->addr)] = sta; -} - - -static void ap_sta_hash_del(struct hostapd_data *hapd, struct sta_info *sta) -{ - struct sta_info *s; - - s = hapd->sta_hash[STA_HASH(sta->addr)]; - if (s == NULL) return; - if (os_memcmp(s->addr, sta->addr, 6) == 0) { - hapd->sta_hash[STA_HASH(sta->addr)] = s->hnext; - return; - } - - while (s->hnext != NULL && - os_memcmp(s->hnext->addr, sta->addr, ETH_ALEN) != 0) - s = s->hnext; - if (s->hnext != NULL) - s->hnext = s->hnext->hnext; - else - wpa_printf(MSG_DEBUG, "AP: could not remove STA " MACSTR - " from hash table", MAC2STR(sta->addr)); -} - - -void ap_free_sta(struct hostapd_data *hapd, struct sta_info *sta) -{ - int set_beacon = 0; - - accounting_sta_stop(hapd, sta); - - /* just in case */ - ap_sta_set_authorized(hapd, sta, 0); - - if (sta->flags & WLAN_STA_WDS) - hostapd_set_wds_sta(hapd, sta->addr, sta->aid, 0); - - if (!(sta->flags & WLAN_STA_PREAUTH)) - hostapd_drv_sta_remove(hapd, sta->addr); - - ap_sta_hash_del(hapd, sta); - ap_sta_list_del(hapd, sta); - - if (sta->aid > 0) - hapd->sta_aid[(sta->aid - 1) / 32] &= - ~BIT((sta->aid - 1) % 32); - - hapd->num_sta--; - if (sta->nonerp_set) { - sta->nonerp_set = 0; - hapd->iface->num_sta_non_erp--; - if (hapd->iface->num_sta_non_erp == 0) - set_beacon++; - } - - if (sta->no_short_slot_time_set) { - sta->no_short_slot_time_set = 0; - hapd->iface->num_sta_no_short_slot_time--; - if (hapd->iface->current_mode->mode == HOSTAPD_MODE_IEEE80211G - && hapd->iface->num_sta_no_short_slot_time == 0) - set_beacon++; - } - - if (sta->no_short_preamble_set) { - sta->no_short_preamble_set = 0; - hapd->iface->num_sta_no_short_preamble--; - if (hapd->iface->current_mode->mode == HOSTAPD_MODE_IEEE80211G - && hapd->iface->num_sta_no_short_preamble == 0) - set_beacon++; - } - - if (sta->no_ht_gf_set) { - sta->no_ht_gf_set = 0; - hapd->iface->num_sta_ht_no_gf--; - } - - if (sta->no_ht_set) { - sta->no_ht_set = 0; - hapd->iface->num_sta_no_ht--; - } - - if (sta->ht_20mhz_set) { - sta->ht_20mhz_set = 0; - hapd->iface->num_sta_ht_20mhz--; - } - -#ifdef CONFIG_P2P - if (sta->no_p2p_set) { - sta->no_p2p_set = 0; - hapd->num_sta_no_p2p--; - if (hapd->num_sta_no_p2p == 0) - hostapd_p2p_non_p2p_sta_disconnected(hapd); - } -#endif /* CONFIG_P2P */ - -#if defined(NEED_AP_MLME) && defined(CONFIG_IEEE80211N) - if (hostapd_ht_operation_update(hapd->iface) > 0) - set_beacon++; -#endif /* NEED_AP_MLME && CONFIG_IEEE80211N */ - - if (set_beacon) - ieee802_11_set_beacons(hapd->iface); - - eloop_cancel_timeout(ap_handle_timer, hapd, sta); - eloop_cancel_timeout(ap_handle_session_timer, hapd, sta); - - ieee802_1x_free_station(sta); - wpa_auth_sta_deinit(sta->wpa_sm); - rsn_preauth_free_station(hapd, sta); -#ifndef CONFIG_NO_RADIUS - radius_client_flush_auth(hapd->radius, sta->addr); -#endif /* CONFIG_NO_RADIUS */ - - os_free(sta->last_assoc_req); - os_free(sta->challenge); - -#ifdef CONFIG_IEEE80211W - os_free(sta->sa_query_trans_id); - eloop_cancel_timeout(ap_sa_query_timer, hapd, sta); -#endif /* CONFIG_IEEE80211W */ - -#ifdef CONFIG_P2P - p2p_group_notif_disassoc(hapd->p2p_group, sta->addr); -#endif /* CONFIG_P2P */ - - wpabuf_free(sta->wps_ie); - wpabuf_free(sta->p2p_ie); - - os_free(sta->ht_capabilities); - - os_free(sta); -} - - -void hostapd_free_stas(struct hostapd_data *hapd) -{ - struct sta_info *sta, *prev; - - sta = hapd->sta_list; - - while (sta) { - prev = sta; - if (sta->flags & WLAN_STA_AUTH) { - mlme_deauthenticate_indication( - hapd, sta, WLAN_REASON_UNSPECIFIED); - } - sta = sta->next; - wpa_printf(MSG_DEBUG, "Removing station " MACSTR, - MAC2STR(prev->addr)); - ap_free_sta(hapd, prev); - } -} - - -/** - * ap_handle_timer - Per STA timer handler - * @eloop_ctx: struct hostapd_data * - * @timeout_ctx: struct sta_info * - * - * This function is called to check station activity and to remove inactive - * stations. - */ -void ap_handle_timer(void *eloop_ctx, void *timeout_ctx) -{ - struct hostapd_data *hapd = eloop_ctx; - struct sta_info *sta = timeout_ctx; - unsigned long next_time = 0; - - if (sta->timeout_next == STA_REMOVE) { - hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211, - HOSTAPD_LEVEL_INFO, "deauthenticated due to " - "local deauth request"); - ap_free_sta(hapd, sta); - return; - } - - if ((sta->flags & WLAN_STA_ASSOC) && - (sta->timeout_next == STA_NULLFUNC || - sta->timeout_next == STA_DISASSOC)) { - int inactive_sec; - inactive_sec = hostapd_drv_get_inact_sec(hapd, sta->addr); - if (inactive_sec == -1) { - wpa_msg(hapd, MSG_DEBUG, "Check inactivity: Could not " - "get station info rom kernel driver for " - MACSTR, MAC2STR(sta->addr)); - } else if (inactive_sec < hapd->conf->ap_max_inactivity && - sta->flags & WLAN_STA_ASSOC) { - /* station activity detected; reset timeout state */ - wpa_msg(hapd, MSG_DEBUG, "Station " MACSTR " has been " - "active %is ago", - MAC2STR(sta->addr), inactive_sec); - sta->timeout_next = STA_NULLFUNC; - next_time = hapd->conf->ap_max_inactivity - - inactive_sec; - } else { - wpa_msg(hapd, MSG_DEBUG, "Station " MACSTR " has been " - "inactive too long: %d sec, max allowed: %d", - MAC2STR(sta->addr), inactive_sec, - hapd->conf->ap_max_inactivity); - } - } - - if ((sta->flags & WLAN_STA_ASSOC) && - sta->timeout_next == STA_DISASSOC && - !(sta->flags & WLAN_STA_PENDING_POLL)) { - wpa_msg(hapd, MSG_DEBUG, "Station " MACSTR " has ACKed data " - "poll", MAC2STR(sta->addr)); - /* data nullfunc frame poll did not produce TX errors; assume - * station ACKed it */ - sta->timeout_next = STA_NULLFUNC; - next_time = hapd->conf->ap_max_inactivity; - } - - if (next_time) { - eloop_register_timeout(next_time, 0, ap_handle_timer, hapd, - sta); - return; - } - - if (sta->timeout_next == STA_NULLFUNC && - (sta->flags & WLAN_STA_ASSOC)) { -#ifndef CONFIG_NATIVE_WINDOWS - /* send data frame to poll STA and check whether this frame - * is ACKed */ - struct ieee80211_hdr hdr; - - wpa_printf(MSG_DEBUG, " Polling STA with data frame"); - sta->flags |= WLAN_STA_PENDING_POLL; - - os_memset(&hdr, 0, sizeof(hdr)); - if (hapd->driver && - os_strcmp(hapd->driver->name, "hostap") == 0) { - /* - * WLAN_FC_STYPE_NULLFUNC would be more appropriate, - * but it is apparently not retried so TX Exc events - * are not received for it. - */ - hdr.frame_control = - IEEE80211_FC(WLAN_FC_TYPE_DATA, - WLAN_FC_STYPE_DATA); - } else { - hdr.frame_control = - IEEE80211_FC(WLAN_FC_TYPE_DATA, - WLAN_FC_STYPE_NULLFUNC); - } - - hdr.frame_control |= host_to_le16(WLAN_FC_FROMDS); - os_memcpy(hdr.IEEE80211_DA_FROMDS, sta->addr, ETH_ALEN); - os_memcpy(hdr.IEEE80211_BSSID_FROMDS, hapd->own_addr, - ETH_ALEN); - os_memcpy(hdr.IEEE80211_SA_FROMDS, hapd->own_addr, ETH_ALEN); - - if (hostapd_drv_send_mlme(hapd, &hdr, sizeof(hdr)) < 0) - perror("ap_handle_timer: send"); -#endif /* CONFIG_NATIVE_WINDOWS */ - } else if (sta->timeout_next != STA_REMOVE) { - int deauth = sta->timeout_next == STA_DEAUTH; - - wpa_printf(MSG_DEBUG, "Sending %s info to STA " MACSTR, - deauth ? "deauthentication" : "disassociation", - MAC2STR(sta->addr)); - - if (deauth) { - hostapd_drv_sta_deauth( - hapd, sta->addr, - WLAN_REASON_PREV_AUTH_NOT_VALID); - } else { - hostapd_drv_sta_disassoc( - hapd, sta->addr, - WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY); - } - } - - switch (sta->timeout_next) { - case STA_NULLFUNC: - sta->timeout_next = STA_DISASSOC; - eloop_register_timeout(AP_DISASSOC_DELAY, 0, ap_handle_timer, - hapd, sta); - break; - case STA_DISASSOC: - sta->flags &= ~WLAN_STA_ASSOC; - ieee802_1x_notify_port_enabled(sta->eapol_sm, 0); - if (!sta->acct_terminate_cause) - sta->acct_terminate_cause = - RADIUS_ACCT_TERMINATE_CAUSE_IDLE_TIMEOUT; - accounting_sta_stop(hapd, sta); - ieee802_1x_free_station(sta); - hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211, - HOSTAPD_LEVEL_INFO, "disassociated due to " - "inactivity"); - sta->timeout_next = STA_DEAUTH; - eloop_register_timeout(AP_DEAUTH_DELAY, 0, ap_handle_timer, - hapd, sta); - mlme_disassociate_indication( - hapd, sta, WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY); - break; - case STA_DEAUTH: - case STA_REMOVE: - hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211, - HOSTAPD_LEVEL_INFO, "deauthenticated due to " - "inactivity"); - if (!sta->acct_terminate_cause) - sta->acct_terminate_cause = - RADIUS_ACCT_TERMINATE_CAUSE_IDLE_TIMEOUT; - mlme_deauthenticate_indication( - hapd, sta, - WLAN_REASON_PREV_AUTH_NOT_VALID); - ap_free_sta(hapd, sta); - break; - } -} - - -static void ap_handle_session_timer(void *eloop_ctx, void *timeout_ctx) -{ - struct hostapd_data *hapd = eloop_ctx; - struct sta_info *sta = timeout_ctx; - u8 addr[ETH_ALEN]; - - if (!(sta->flags & WLAN_STA_AUTH)) - return; - - mlme_deauthenticate_indication(hapd, sta, - WLAN_REASON_PREV_AUTH_NOT_VALID); - hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211, - HOSTAPD_LEVEL_INFO, "deauthenticated due to " - "session timeout"); - sta->acct_terminate_cause = - RADIUS_ACCT_TERMINATE_CAUSE_SESSION_TIMEOUT; - os_memcpy(addr, sta->addr, ETH_ALEN); - ap_free_sta(hapd, sta); - hostapd_drv_sta_deauth(hapd, addr, WLAN_REASON_PREV_AUTH_NOT_VALID); -} - - -void ap_sta_session_timeout(struct hostapd_data *hapd, struct sta_info *sta, - u32 session_timeout) -{ - hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211, - HOSTAPD_LEVEL_DEBUG, "setting session timeout to %d " - "seconds", session_timeout); - eloop_cancel_timeout(ap_handle_session_timer, hapd, sta); - eloop_register_timeout(session_timeout, 0, ap_handle_session_timer, - hapd, sta); -} - - -void ap_sta_no_session_timeout(struct hostapd_data *hapd, struct sta_info *sta) -{ - eloop_cancel_timeout(ap_handle_session_timer, hapd, sta); -} - - -struct sta_info * ap_sta_add(struct hostapd_data *hapd, const u8 *addr) -{ - struct sta_info *sta; - - sta = ap_get_sta(hapd, addr); - if (sta) - return sta; - - wpa_printf(MSG_DEBUG, " New STA"); - if (hapd->num_sta >= hapd->conf->max_num_sta) { - /* FIX: might try to remove some old STAs first? */ - wpa_printf(MSG_DEBUG, "no more room for new STAs (%d/%d)", - hapd->num_sta, hapd->conf->max_num_sta); - return NULL; - } - - sta = os_zalloc(sizeof(struct sta_info)); - if (sta == NULL) { - wpa_printf(MSG_ERROR, "malloc failed"); - return NULL; - } - sta->acct_interim_interval = hapd->conf->acct_interim_interval; - - /* initialize STA info data */ - eloop_register_timeout(hapd->conf->ap_max_inactivity, 0, - ap_handle_timer, hapd, sta); - os_memcpy(sta->addr, addr, ETH_ALEN); - sta->next = hapd->sta_list; - hapd->sta_list = sta; - hapd->num_sta++; - ap_sta_hash_add(hapd, sta); - sta->ssid = &hapd->conf->ssid; - ap_sta_remove_in_other_bss(hapd, sta); - - return sta; -} - - -static int ap_sta_remove(struct hostapd_data *hapd, struct sta_info *sta) -{ - ieee802_1x_notify_port_enabled(sta->eapol_sm, 0); - - wpa_printf(MSG_DEBUG, "Removing STA " MACSTR " from kernel driver", - MAC2STR(sta->addr)); - if (hostapd_drv_sta_remove(hapd, sta->addr) && - sta->flags & WLAN_STA_ASSOC) { - wpa_printf(MSG_DEBUG, "Could not remove station " MACSTR - " from kernel driver.", MAC2STR(sta->addr)); - return -1; - } - return 0; -} - - -static void ap_sta_remove_in_other_bss(struct hostapd_data *hapd, - struct sta_info *sta) -{ - struct hostapd_iface *iface = hapd->iface; - size_t i; - - for (i = 0; i < iface->num_bss; i++) { - struct hostapd_data *bss = iface->bss[i]; - struct sta_info *sta2; - /* bss should always be set during operation, but it may be - * NULL during reconfiguration. Assume the STA is not - * associated to another BSS in that case to avoid NULL pointer - * dereferences. */ - if (bss == hapd || bss == NULL) - continue; - sta2 = ap_get_sta(bss, sta->addr); - if (!sta2) - continue; - - ap_sta_disconnect(bss, sta2, sta2->addr, - WLAN_REASON_PREV_AUTH_NOT_VALID); - } -} - - -void ap_sta_disassociate(struct hostapd_data *hapd, struct sta_info *sta, - u16 reason) -{ - wpa_printf(MSG_DEBUG, "%s: disassociate STA " MACSTR, - hapd->conf->iface, MAC2STR(sta->addr)); - sta->flags &= ~WLAN_STA_ASSOC; - ap_sta_remove(hapd, sta); - sta->timeout_next = STA_DEAUTH; - eloop_cancel_timeout(ap_handle_timer, hapd, sta); - eloop_register_timeout(AP_MAX_INACTIVITY_AFTER_DISASSOC, 0, - ap_handle_timer, hapd, sta); - accounting_sta_stop(hapd, sta); - ieee802_1x_free_station(sta); - - mlme_disassociate_indication(hapd, sta, reason); -} - - -void ap_sta_deauthenticate(struct hostapd_data *hapd, struct sta_info *sta, - u16 reason) -{ - wpa_printf(MSG_DEBUG, "%s: deauthenticate STA " MACSTR, - hapd->conf->iface, MAC2STR(sta->addr)); - sta->flags &= ~(WLAN_STA_AUTH | WLAN_STA_ASSOC); - ap_sta_remove(hapd, sta); - sta->timeout_next = STA_REMOVE; - eloop_cancel_timeout(ap_handle_timer, hapd, sta); - eloop_register_timeout(AP_MAX_INACTIVITY_AFTER_DEAUTH, 0, - ap_handle_timer, hapd, sta); - accounting_sta_stop(hapd, sta); - ieee802_1x_free_station(sta); - - mlme_deauthenticate_indication(hapd, sta, reason); -} - - -int ap_sta_bind_vlan(struct hostapd_data *hapd, struct sta_info *sta, - int old_vlanid) -{ -#ifndef CONFIG_NO_VLAN - const char *iface; - struct hostapd_vlan *vlan = NULL; - int ret; - - /* - * Do not proceed furthur if the vlan id remains same. We do not want - * duplicate dynamic vlan entries. - */ - if (sta->vlan_id == old_vlanid) - return 0; - - /* - * During 1x reauth, if the vlan id changes, then remove the old id and - * proceed furthur to add the new one. - */ - if (old_vlanid > 0) - vlan_remove_dynamic(hapd, old_vlanid); - - iface = hapd->conf->iface; - if (sta->ssid->vlan[0]) - iface = sta->ssid->vlan; - - if (sta->ssid->dynamic_vlan == DYNAMIC_VLAN_DISABLED) - sta->vlan_id = 0; - else if (sta->vlan_id > 0) { - vlan = hapd->conf->vlan; - while (vlan) { - if (vlan->vlan_id == sta->vlan_id || - vlan->vlan_id == VLAN_ID_WILDCARD) { - iface = vlan->ifname; - break; - } - vlan = vlan->next; - } - } - - if (sta->vlan_id > 0 && vlan == NULL) { - hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211, - HOSTAPD_LEVEL_DEBUG, "could not find VLAN for " - "binding station to (vlan_id=%d)", - sta->vlan_id); - return -1; - } else if (sta->vlan_id > 0 && vlan->vlan_id == VLAN_ID_WILDCARD) { - vlan = vlan_add_dynamic(hapd, vlan, sta->vlan_id); - if (vlan == NULL) { - hostapd_logger(hapd, sta->addr, - HOSTAPD_MODULE_IEEE80211, - HOSTAPD_LEVEL_DEBUG, "could not add " - "dynamic VLAN interface for vlan_id=%d", - sta->vlan_id); - return -1; - } - - iface = vlan->ifname; - if (vlan_setup_encryption_dyn(hapd, sta->ssid, iface) != 0) { - hostapd_logger(hapd, sta->addr, - HOSTAPD_MODULE_IEEE80211, - HOSTAPD_LEVEL_DEBUG, "could not " - "configure encryption for dynamic VLAN " - "interface for vlan_id=%d", - sta->vlan_id); - } - - hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211, - HOSTAPD_LEVEL_DEBUG, "added new dynamic VLAN " - "interface '%s'", iface); - } else if (vlan && vlan->vlan_id == sta->vlan_id) { - if (sta->vlan_id > 0) { - vlan->dynamic_vlan++; - hostapd_logger(hapd, sta->addr, - HOSTAPD_MODULE_IEEE80211, - HOSTAPD_LEVEL_DEBUG, "updated existing " - "dynamic VLAN interface '%s'", iface); - } - - /* - * Update encryption configuration for statically generated - * VLAN interface. This is only used for static WEP - * configuration for the case where hostapd did not yet know - * which keys are to be used when the interface was added. - */ - if (vlan_setup_encryption_dyn(hapd, sta->ssid, iface) != 0) { - hostapd_logger(hapd, sta->addr, - HOSTAPD_MODULE_IEEE80211, - HOSTAPD_LEVEL_DEBUG, "could not " - "configure encryption for VLAN " - "interface for vlan_id=%d", - sta->vlan_id); - } - } - - hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211, - HOSTAPD_LEVEL_DEBUG, "binding station to interface " - "'%s'", iface); - - if (wpa_auth_sta_set_vlan(sta->wpa_sm, sta->vlan_id) < 0) - wpa_printf(MSG_INFO, "Failed to update VLAN-ID for WPA"); - - ret = hostapd_drv_set_sta_vlan(iface, hapd, sta->addr, sta->vlan_id); - if (ret < 0) { - hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211, - HOSTAPD_LEVEL_DEBUG, "could not bind the STA " - "entry to vlan_id=%d", sta->vlan_id); - } - return ret; -#else /* CONFIG_NO_VLAN */ - return 0; -#endif /* CONFIG_NO_VLAN */ -} - - -#ifdef CONFIG_IEEE80211W - -int ap_check_sa_query_timeout(struct hostapd_data *hapd, struct sta_info *sta) -{ - u32 tu; - struct os_time now, passed; - os_get_time(&now); - os_time_sub(&now, &sta->sa_query_start, &passed); - tu = (passed.sec * 1000000 + passed.usec) / 1024; - if (hapd->conf->assoc_sa_query_max_timeout < tu) { - hostapd_logger(hapd, sta->addr, - HOSTAPD_MODULE_IEEE80211, - HOSTAPD_LEVEL_DEBUG, - "association SA Query timed out"); - sta->sa_query_timed_out = 1; - os_free(sta->sa_query_trans_id); - sta->sa_query_trans_id = NULL; - sta->sa_query_count = 0; - eloop_cancel_timeout(ap_sa_query_timer, hapd, sta); - return 1; - } - - return 0; -} - - -static void ap_sa_query_timer(void *eloop_ctx, void *timeout_ctx) -{ - struct hostapd_data *hapd = eloop_ctx; - struct sta_info *sta = timeout_ctx; - unsigned int timeout, sec, usec; - u8 *trans_id, *nbuf; - - if (sta->sa_query_count > 0 && - ap_check_sa_query_timeout(hapd, sta)) - return; - - nbuf = os_realloc(sta->sa_query_trans_id, - (sta->sa_query_count + 1) * WLAN_SA_QUERY_TR_ID_LEN); - if (nbuf == NULL) - return; - if (sta->sa_query_count == 0) { - /* Starting a new SA Query procedure */ - os_get_time(&sta->sa_query_start); - } - trans_id = nbuf + sta->sa_query_count * WLAN_SA_QUERY_TR_ID_LEN; - sta->sa_query_trans_id = nbuf; - sta->sa_query_count++; - - os_get_random(trans_id, WLAN_SA_QUERY_TR_ID_LEN); - - timeout = hapd->conf->assoc_sa_query_retry_timeout; - sec = ((timeout / 1000) * 1024) / 1000; - usec = (timeout % 1000) * 1024; - eloop_register_timeout(sec, usec, ap_sa_query_timer, hapd, sta); - - hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211, - HOSTAPD_LEVEL_DEBUG, - "association SA Query attempt %d", sta->sa_query_count); - -#ifdef NEED_AP_MLME - ieee802_11_send_sa_query_req(hapd, sta->addr, trans_id); -#endif /* NEED_AP_MLME */ -} - - -void ap_sta_start_sa_query(struct hostapd_data *hapd, struct sta_info *sta) -{ - ap_sa_query_timer(hapd, sta); -} - - -void ap_sta_stop_sa_query(struct hostapd_data *hapd, struct sta_info *sta) -{ - eloop_cancel_timeout(ap_sa_query_timer, hapd, sta); - os_free(sta->sa_query_trans_id); - sta->sa_query_trans_id = NULL; - sta->sa_query_count = 0; -} - -#endif /* CONFIG_IEEE80211W */ - - -void ap_sta_set_authorized(struct hostapd_data *hapd, struct sta_info *sta, - int authorized) -{ - if (!!authorized == !!(sta->flags & WLAN_STA_AUTHORIZED)) - return; - - if (authorized) - sta->flags |= WLAN_STA_AUTHORIZED; - else - sta->flags &= ~WLAN_STA_AUTHORIZED; - - if (hapd->sta_authorized_cb) - hapd->sta_authorized_cb(hapd->sta_authorized_cb_ctx, - sta->addr, authorized); -} - - -void ap_sta_disconnect(struct hostapd_data *hapd, struct sta_info *sta, - const u8 *addr, u16 reason) -{ - - if (sta == NULL && addr) - sta = ap_get_sta(hapd, addr); - - if (addr) - hostapd_drv_sta_deauth(hapd, addr, reason); - - if (sta == NULL) - return; - ap_sta_set_authorized(hapd, sta, 0); - sta->flags &= ~(WLAN_STA_AUTH | WLAN_STA_ASSOC); - eloop_cancel_timeout(ap_handle_timer, hapd, sta); - eloop_register_timeout(0, 0, ap_handle_timer, hapd, sta); - sta->timeout_next = STA_REMOVE; -} diff --git a/hostapd-0.8/src/ap/sta_info.h b/hostapd-0.8/src/ap/sta_info.h deleted file mode 100644 index 9ec4fe3..0000000 --- a/hostapd-0.8/src/ap/sta_info.h +++ /dev/null @@ -1,165 +0,0 @@ -/* - * hostapd / Station table - * Copyright (c) 2002-2009, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#ifndef STA_INFO_H -#define STA_INFO_H - -/* STA flags */ -#define WLAN_STA_AUTH BIT(0) -#define WLAN_STA_ASSOC BIT(1) -#define WLAN_STA_PS BIT(2) -#define WLAN_STA_TIM BIT(3) -#define WLAN_STA_PERM BIT(4) -#define WLAN_STA_AUTHORIZED BIT(5) -#define WLAN_STA_PENDING_POLL BIT(6) /* pending activity poll not ACKed */ -#define WLAN_STA_SHORT_PREAMBLE BIT(7) -#define WLAN_STA_PREAUTH BIT(8) -#define WLAN_STA_WMM BIT(9) -#define WLAN_STA_MFP BIT(10) -#define WLAN_STA_HT BIT(11) -#define WLAN_STA_WPS BIT(12) -#define WLAN_STA_MAYBE_WPS BIT(13) -#define WLAN_STA_WDS BIT(14) -#define WLAN_STA_ASSOC_REQ_OK BIT(15) -#define WLAN_STA_NONERP BIT(31) - -/* Maximum number of supported rates (from both Supported Rates and Extended - * Supported Rates IEs). */ -#define WLAN_SUPP_RATES_MAX 32 - - -struct sta_info { - struct sta_info *next; /* next entry in sta list */ - struct sta_info *hnext; /* next entry in hash table list */ - u8 addr[6]; - u16 aid; /* STA's unique AID (1 .. 2007) or 0 if not yet assigned */ - u32 flags; /* Bitfield of WLAN_STA_* */ - u16 capability; - u16 listen_interval; /* or beacon_int for APs */ - u8 supported_rates[WLAN_SUPP_RATES_MAX]; - int supported_rates_len; - - unsigned int nonerp_set:1; - unsigned int no_short_slot_time_set:1; - unsigned int no_short_preamble_set:1; - unsigned int no_ht_gf_set:1; - unsigned int no_ht_set:1; - unsigned int ht_20mhz_set:1; - unsigned int no_p2p_set:1; - - u16 auth_alg; - u8 previous_ap[6]; - - enum { - STA_NULLFUNC = 0, STA_DISASSOC, STA_DEAUTH, STA_REMOVE - } timeout_next; - - /* IEEE 802.1X related data */ - struct eapol_state_machine *eapol_sm; - - /* IEEE 802.11f (IAPP) related data */ - struct ieee80211_mgmt *last_assoc_req; - - u32 acct_session_id_hi; - u32 acct_session_id_lo; - time_t acct_session_start; - int acct_session_started; - int acct_terminate_cause; /* Acct-Terminate-Cause */ - int acct_interim_interval; /* Acct-Interim-Interval */ - - unsigned long last_rx_bytes; - unsigned long last_tx_bytes; - u32 acct_input_gigawords; /* Acct-Input-Gigawords */ - u32 acct_output_gigawords; /* Acct-Output-Gigawords */ - - u8 *challenge; /* IEEE 802.11 Shared Key Authentication Challenge */ - - struct wpa_state_machine *wpa_sm; - struct rsn_preauth_interface *preauth_iface; - - struct hostapd_ssid *ssid; /* SSID selection based on (Re)AssocReq */ - struct hostapd_ssid *ssid_probe; /* SSID selection based on ProbeReq */ - - int vlan_id; - - struct ieee80211_ht_capabilities *ht_capabilities; - -#ifdef CONFIG_IEEE80211W - int sa_query_count; /* number of pending SA Query requests; - * 0 = no SA Query in progress */ - int sa_query_timed_out; - u8 *sa_query_trans_id; /* buffer of WLAN_SA_QUERY_TR_ID_LEN * - * sa_query_count octets of pending SA Query - * transaction identifiers */ - struct os_time sa_query_start; -#endif /* CONFIG_IEEE80211W */ - - struct wpabuf *wps_ie; /* WPS IE from (Re)Association Request */ - struct wpabuf *p2p_ie; /* P2P IE from (Re)Association Request */ -}; - - -/* Default value for maximum station inactivity. After AP_MAX_INACTIVITY has - * passed since last received frame from the station, a nullfunc data frame is - * sent to the station. If this frame is not acknowledged and no other frames - * have been received, the station will be disassociated after - * AP_DISASSOC_DELAY seconds. Similarily, the station will be deauthenticated - * after AP_DEAUTH_DELAY seconds has passed after disassociation. */ -#define AP_MAX_INACTIVITY (5 * 60) -#define AP_DISASSOC_DELAY (1) -#define AP_DEAUTH_DELAY (1) -/* Number of seconds to keep STA entry with Authenticated flag after it has - * been disassociated. */ -#define AP_MAX_INACTIVITY_AFTER_DISASSOC (1 * 30) -/* Number of seconds to keep STA entry after it has been deauthenticated. */ -#define AP_MAX_INACTIVITY_AFTER_DEAUTH (1 * 5) - - -struct hostapd_data; - -int ap_for_each_sta(struct hostapd_data *hapd, - int (*cb)(struct hostapd_data *hapd, struct sta_info *sta, - void *ctx), - void *ctx); -struct sta_info * ap_get_sta(struct hostapd_data *hapd, const u8 *sta); -void ap_sta_hash_add(struct hostapd_data *hapd, struct sta_info *sta); -void ap_free_sta(struct hostapd_data *hapd, struct sta_info *sta); -void ap_free_sta(struct hostapd_data *hapd, struct sta_info *sta); -void hostapd_free_stas(struct hostapd_data *hapd); -void ap_handle_timer(void *eloop_ctx, void *timeout_ctx); -void ap_sta_session_timeout(struct hostapd_data *hapd, struct sta_info *sta, - u32 session_timeout); -void ap_sta_no_session_timeout(struct hostapd_data *hapd, - struct sta_info *sta); -struct sta_info * ap_sta_add(struct hostapd_data *hapd, const u8 *addr); -void ap_sta_disassociate(struct hostapd_data *hapd, struct sta_info *sta, - u16 reason); -void ap_sta_deauthenticate(struct hostapd_data *hapd, struct sta_info *sta, - u16 reason); -int ap_sta_bind_vlan(struct hostapd_data *hapd, struct sta_info *sta, - int old_vlanid); -void ap_sta_start_sa_query(struct hostapd_data *hapd, struct sta_info *sta); -void ap_sta_stop_sa_query(struct hostapd_data *hapd, struct sta_info *sta); -int ap_check_sa_query_timeout(struct hostapd_data *hapd, struct sta_info *sta); -void ap_sta_disconnect(struct hostapd_data *hapd, struct sta_info *sta, - const u8 *addr, u16 reason); - -void ap_sta_set_authorized(struct hostapd_data *hapd, - struct sta_info *sta, int authorized); -static inline int ap_sta_is_authorized(struct sta_info *sta) -{ - return sta->flags & WLAN_STA_AUTHORIZED; -} - -#endif /* STA_INFO_H */ diff --git a/hostapd-0.8/src/ap/tkip_countermeasures.c b/hostapd-0.8/src/ap/tkip_countermeasures.c deleted file mode 100644 index 1925217..0000000 --- a/hostapd-0.8/src/ap/tkip_countermeasures.c +++ /dev/null @@ -1,94 +0,0 @@ -/* - * hostapd / TKIP countermeasures - * Copyright (c) 2002-2009, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#include "utils/includes.h" - -#include "utils/common.h" -#include "utils/eloop.h" -#include "common/ieee802_11_defs.h" -#include "hostapd.h" -#include "sta_info.h" -#include "ap_mlme.h" -#include "wpa_auth.h" -#include "ap_drv_ops.h" -#include "tkip_countermeasures.h" - - -static void ieee80211_tkip_countermeasures_stop(void *eloop_ctx, - void *timeout_ctx) -{ - struct hostapd_data *hapd = eloop_ctx; - hapd->tkip_countermeasures = 0; - hostapd_drv_set_countermeasures(hapd, 0); - hostapd_logger(hapd, NULL, HOSTAPD_MODULE_IEEE80211, - HOSTAPD_LEVEL_INFO, "TKIP countermeasures ended"); -} - - -static void ieee80211_tkip_countermeasures_start(struct hostapd_data *hapd) -{ - struct sta_info *sta; - - hostapd_logger(hapd, NULL, HOSTAPD_MODULE_IEEE80211, - HOSTAPD_LEVEL_INFO, "TKIP countermeasures initiated"); - - wpa_auth_countermeasures_start(hapd->wpa_auth); - hapd->tkip_countermeasures = 1; - hostapd_drv_set_countermeasures(hapd, 1); - wpa_gtk_rekey(hapd->wpa_auth); - eloop_cancel_timeout(ieee80211_tkip_countermeasures_stop, hapd, NULL); - eloop_register_timeout(60, 0, ieee80211_tkip_countermeasures_stop, - hapd, NULL); - for (sta = hapd->sta_list; sta != NULL; sta = sta->next) { - hostapd_drv_sta_deauth(hapd, sta->addr, - WLAN_REASON_MICHAEL_MIC_FAILURE); - ap_sta_set_authorized(hapd, sta, 0); - sta->flags &= ~(WLAN_STA_AUTH | WLAN_STA_ASSOC); - hostapd_drv_sta_remove(hapd, sta->addr); - } -} - - -void michael_mic_failure(struct hostapd_data *hapd, const u8 *addr, int local) -{ - time_t now; - - if (addr && local) { - struct sta_info *sta = ap_get_sta(hapd, addr); - if (sta != NULL) { - wpa_auth_sta_local_mic_failure_report(sta->wpa_sm); - hostapd_logger(hapd, addr, HOSTAPD_MODULE_IEEE80211, - HOSTAPD_LEVEL_INFO, - "Michael MIC failure detected in " - "received frame"); - mlme_michaelmicfailure_indication(hapd, addr); - } else { - wpa_printf(MSG_DEBUG, - "MLME-MICHAELMICFAILURE.indication " - "for not associated STA (" MACSTR - ") ignored", MAC2STR(addr)); - return; - } - } - - time(&now); - if (now > hapd->michael_mic_failure + 60) { - hapd->michael_mic_failures = 1; - } else { - hapd->michael_mic_failures++; - if (hapd->michael_mic_failures > 1) - ieee80211_tkip_countermeasures_start(hapd); - } - hapd->michael_mic_failure = now; -} diff --git a/hostapd-0.8/src/ap/tkip_countermeasures.h b/hostapd-0.8/src/ap/tkip_countermeasures.h deleted file mode 100644 index 5a1afce..0000000 --- a/hostapd-0.8/src/ap/tkip_countermeasures.h +++ /dev/null @@ -1,20 +0,0 @@ -/* - * hostapd / TKIP countermeasures - * Copyright (c) 2002-2009, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#ifndef TKIP_COUNTERMEASURES_H -#define TKIP_COUNTERMEASURES_H - -void michael_mic_failure(struct hostapd_data *hapd, const u8 *addr, int local); - -#endif /* TKIP_COUNTERMEASURES_H */ diff --git a/hostapd-0.8/src/ap/utils.c b/hostapd-0.8/src/ap/utils.c deleted file mode 100644 index 0ff48ae..0000000 --- a/hostapd-0.8/src/ap/utils.c +++ /dev/null @@ -1,88 +0,0 @@ -/* - * AP mode helper functions - * Copyright (c) 2009, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#include "includes.h" - -#include "common.h" -#include "common/ieee802_11_defs.h" -#include "sta_info.h" -#include "hostapd.h" - - -int hostapd_register_probereq_cb(struct hostapd_data *hapd, - int (*cb)(void *ctx, const u8 *sa, - const u8 *ie, size_t ie_len), - void *ctx) -{ - struct hostapd_probereq_cb *n; - - n = os_realloc(hapd->probereq_cb, (hapd->num_probereq_cb + 1) * - sizeof(struct hostapd_probereq_cb)); - if (n == NULL) - return -1; - - hapd->probereq_cb = n; - n = &hapd->probereq_cb[hapd->num_probereq_cb]; - hapd->num_probereq_cb++; - - n->cb = cb; - n->ctx = ctx; - - return 0; -} - - -struct prune_data { - struct hostapd_data *hapd; - const u8 *addr; -}; - -static int prune_associations(struct hostapd_iface *iface, void *ctx) -{ - struct prune_data *data = ctx; - struct sta_info *osta; - struct hostapd_data *ohapd; - size_t j; - - for (j = 0; j < iface->num_bss; j++) { - ohapd = iface->bss[j]; - if (ohapd == data->hapd) - continue; - osta = ap_get_sta(ohapd, data->addr); - if (!osta) - continue; - - ap_sta_disassociate(ohapd, osta, WLAN_REASON_UNSPECIFIED); - } - - return 0; -} - -/** - * hostapd_prune_associations - Remove extraneous associations - * @hapd: Pointer to BSS data for the most recent association - * @addr: Associated STA address - * - * This function looks through all radios and BSS's for previous - * (stale) associations of STA. If any are found they are removed. - */ -void hostapd_prune_associations(struct hostapd_data *hapd, const u8 *addr) -{ - struct prune_data data; - data.hapd = hapd; - data.addr = addr; - if (hapd->iface->for_each_interface) - hapd->iface->for_each_interface(hapd->iface->interfaces, - prune_associations, &data); -} diff --git a/hostapd-0.8/src/ap/vlan_init.c b/hostapd-0.8/src/ap/vlan_init.c deleted file mode 100644 index f2f766f..0000000 --- a/hostapd-0.8/src/ap/vlan_init.c +++ /dev/null @@ -1,905 +0,0 @@ -/* - * hostapd / VLAN initialization - * Copyright 2003, Instant802 Networks, Inc. - * Copyright 2005-2006, Devicescape Software, Inc. - * Copyright (c) 2009, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#include "utils/includes.h" - -#include "utils/common.h" -#include "hostapd.h" -#include "ap_config.h" -#include "ap_drv_ops.h" -#include "vlan_init.h" - - -#ifdef CONFIG_FULL_DYNAMIC_VLAN - -#include -#include -#include -#include -#include - -#include "drivers/priv_netlink.h" -#include "utils/eloop.h" - - -struct full_dynamic_vlan { - int s; /* socket on which to listen for new/removed interfaces. */ -}; - - -static int ifconfig_helper(const char *if_name, int up) -{ - int fd; - struct ifreq ifr; - - if ((fd = socket(AF_INET, SOCK_STREAM, 0)) < 0) { - wpa_printf(MSG_ERROR, "VLAN: %s: socket(AF_INET,SOCK_STREAM) " - "failed: %s", __func__, strerror(errno)); - return -1; - } - - os_memset(&ifr, 0, sizeof(ifr)); - os_strlcpy(ifr.ifr_name, if_name, IFNAMSIZ); - - if (ioctl(fd, SIOCGIFFLAGS, &ifr) != 0) { - wpa_printf(MSG_ERROR, "VLAN: %s: ioctl(SIOCGIFFLAGS) failed " - "for interface %s: %s", - __func__, if_name, strerror(errno)); - close(fd); - return -1; - } - - if (up) - ifr.ifr_flags |= IFF_UP; - else - ifr.ifr_flags &= ~IFF_UP; - - if (ioctl(fd, SIOCSIFFLAGS, &ifr) != 0) { - wpa_printf(MSG_ERROR, "VLAN: %s: ioctl(SIOCSIFFLAGS) failed " - "for interface %s (up=%d): %s", - __func__, if_name, up, strerror(errno)); - close(fd); - return -1; - } - - close(fd); - return 0; -} - - -static int ifconfig_up(const char *if_name) -{ - wpa_printf(MSG_DEBUG, "VLAN: Set interface %s up", if_name); - return ifconfig_helper(if_name, 1); -} - - -static int ifconfig_down(const char *if_name) -{ - wpa_printf(MSG_DEBUG, "VLAN: Set interface %s down", if_name); - return ifconfig_helper(if_name, 0); -} - - -/* - * These are only available in recent linux headers (without the leading - * underscore). - */ -#define _GET_VLAN_REALDEV_NAME_CMD 8 -#define _GET_VLAN_VID_CMD 9 - -/* This value should be 256 ONLY. If it is something else, then hostapd - * might crash!, as this value has been hard-coded in 2.4.x kernel - * bridging code. - */ -#define MAX_BR_PORTS 256 - -static int br_delif(const char *br_name, const char *if_name) -{ - int fd; - struct ifreq ifr; - unsigned long args[2]; - int if_index; - - wpa_printf(MSG_DEBUG, "VLAN: br_delif(%s, %s)", br_name, if_name); - if ((fd = socket(AF_INET, SOCK_STREAM, 0)) < 0) { - wpa_printf(MSG_ERROR, "VLAN: %s: socket(AF_INET,SOCK_STREAM) " - "failed: %s", __func__, strerror(errno)); - return -1; - } - - if_index = if_nametoindex(if_name); - - if (if_index == 0) { - wpa_printf(MSG_ERROR, "VLAN: %s: Failure determining " - "interface index for '%s'", - __func__, if_name); - close(fd); - return -1; - } - - args[0] = BRCTL_DEL_IF; - args[1] = if_index; - - os_strlcpy(ifr.ifr_name, br_name, sizeof(ifr.ifr_name)); - ifr.ifr_data = (__caddr_t) args; - - if (ioctl(fd, SIOCDEVPRIVATE, &ifr) < 0 && errno != EINVAL) { - /* No error if interface already removed. */ - wpa_printf(MSG_ERROR, "VLAN: %s: ioctl[SIOCDEVPRIVATE," - "BRCTL_DEL_IF] failed for br_name=%s if_name=%s: " - "%s", __func__, br_name, if_name, strerror(errno)); - close(fd); - return -1; - } - - close(fd); - return 0; -} - - -/* - Add interface 'if_name' to the bridge 'br_name' - - returns -1 on error - returns 1 if the interface is already part of the bridge - returns 0 otherwise -*/ -static int br_addif(const char *br_name, const char *if_name) -{ - int fd; - struct ifreq ifr; - unsigned long args[2]; - int if_index; - - wpa_printf(MSG_DEBUG, "VLAN: br_addif(%s, %s)", br_name, if_name); - if ((fd = socket(AF_INET, SOCK_STREAM, 0)) < 0) { - wpa_printf(MSG_ERROR, "VLAN: %s: socket(AF_INET,SOCK_STREAM) " - "failed: %s", __func__, strerror(errno)); - return -1; - } - - if_index = if_nametoindex(if_name); - - if (if_index == 0) { - wpa_printf(MSG_ERROR, "VLAN: %s: Failure determining " - "interface index for '%s'", - __func__, if_name); - close(fd); - return -1; - } - - args[0] = BRCTL_ADD_IF; - args[1] = if_index; - - os_strlcpy(ifr.ifr_name, br_name, sizeof(ifr.ifr_name)); - ifr.ifr_data = (__caddr_t) args; - - if (ioctl(fd, SIOCDEVPRIVATE, &ifr) < 0) { - if (errno == EBUSY) { - /* The interface is already added. */ - close(fd); - return 1; - } - - wpa_printf(MSG_ERROR, "VLAN: %s: ioctl[SIOCDEVPRIVATE," - "BRCTL_ADD_IF] failed for br_name=%s if_name=%s: " - "%s", __func__, br_name, if_name, strerror(errno)); - close(fd); - return -1; - } - - close(fd); - return 0; -} - - -static int br_delbr(const char *br_name) -{ - int fd; - unsigned long arg[2]; - - wpa_printf(MSG_DEBUG, "VLAN: br_delbr(%s)", br_name); - if ((fd = socket(AF_INET, SOCK_STREAM, 0)) < 0) { - wpa_printf(MSG_ERROR, "VLAN: %s: socket(AF_INET,SOCK_STREAM) " - "failed: %s", __func__, strerror(errno)); - return -1; - } - - arg[0] = BRCTL_DEL_BRIDGE; - arg[1] = (unsigned long) br_name; - - if (ioctl(fd, SIOCGIFBR, arg) < 0 && errno != ENXIO) { - /* No error if bridge already removed. */ - wpa_printf(MSG_ERROR, "VLAN: %s: BRCTL_DEL_BRIDGE failed for " - "%s: %s", __func__, br_name, strerror(errno)); - close(fd); - return -1; - } - - close(fd); - return 0; -} - - -/* - Add a bridge with the name 'br_name'. - - returns -1 on error - returns 1 if the bridge already exists - returns 0 otherwise -*/ -static int br_addbr(const char *br_name) -{ - int fd; - unsigned long arg[4]; - struct ifreq ifr; - - wpa_printf(MSG_DEBUG, "VLAN: br_addbr(%s)", br_name); - if ((fd = socket(AF_INET, SOCK_STREAM, 0)) < 0) { - wpa_printf(MSG_ERROR, "VLAN: %s: socket(AF_INET,SOCK_STREAM) " - "failed: %s", __func__, strerror(errno)); - return -1; - } - - arg[0] = BRCTL_ADD_BRIDGE; - arg[1] = (unsigned long) br_name; - - if (ioctl(fd, SIOCGIFBR, arg) < 0) { - if (errno == EEXIST) { - /* The bridge is already added. */ - close(fd); - return 1; - } else { - wpa_printf(MSG_ERROR, "VLAN: %s: BRCTL_ADD_BRIDGE " - "failed for %s: %s", - __func__, br_name, strerror(errno)); - close(fd); - return -1; - } - } - - /* Decrease forwarding delay to avoid EAPOL timeouts. */ - os_memset(&ifr, 0, sizeof(ifr)); - os_strlcpy(ifr.ifr_name, br_name, IFNAMSIZ); - arg[0] = BRCTL_SET_BRIDGE_FORWARD_DELAY; - arg[1] = 1; - arg[2] = 0; - arg[3] = 0; - ifr.ifr_data = (char *) &arg; - if (ioctl(fd, SIOCDEVPRIVATE, &ifr) < 0) { - wpa_printf(MSG_ERROR, "VLAN: %s: " - "BRCTL_SET_BRIDGE_FORWARD_DELAY (1 sec) failed for " - "%s: %s", __func__, br_name, strerror(errno)); - /* Continue anyway */ - } - - close(fd); - return 0; -} - - -static int br_getnumports(const char *br_name) -{ - int fd; - int i; - int port_cnt = 0; - unsigned long arg[4]; - int ifindices[MAX_BR_PORTS]; - struct ifreq ifr; - - if ((fd = socket(AF_INET, SOCK_STREAM, 0)) < 0) { - wpa_printf(MSG_ERROR, "VLAN: %s: socket(AF_INET,SOCK_STREAM) " - "failed: %s", __func__, strerror(errno)); - return -1; - } - - arg[0] = BRCTL_GET_PORT_LIST; - arg[1] = (unsigned long) ifindices; - arg[2] = MAX_BR_PORTS; - arg[3] = 0; - - os_memset(ifindices, 0, sizeof(ifindices)); - os_strlcpy(ifr.ifr_name, br_name, sizeof(ifr.ifr_name)); - ifr.ifr_data = (__caddr_t) arg; - - if (ioctl(fd, SIOCDEVPRIVATE, &ifr) < 0) { - wpa_printf(MSG_ERROR, "VLAN: %s: BRCTL_GET_PORT_LIST " - "failed for %s: %s", - __func__, br_name, strerror(errno)); - close(fd); - return -1; - } - - for (i = 1; i < MAX_BR_PORTS; i++) { - if (ifindices[i] > 0) { - port_cnt++; - } - } - - close(fd); - return port_cnt; -} - - -static int vlan_rem(const char *if_name) -{ - int fd; - struct vlan_ioctl_args if_request; - - wpa_printf(MSG_DEBUG, "VLAN: vlan_rem(%s)", if_name); - if ((os_strlen(if_name) + 1) > sizeof(if_request.device1)) { - wpa_printf(MSG_ERROR, "VLAN: Interface name too long: '%s'", - if_name); - return -1; - } - - if ((fd = socket(AF_INET, SOCK_STREAM, 0)) < 0) { - wpa_printf(MSG_ERROR, "VLAN: %s: socket(AF_INET,SOCK_STREAM) " - "failed: %s", __func__, strerror(errno)); - return -1; - } - - os_memset(&if_request, 0, sizeof(if_request)); - - os_strlcpy(if_request.device1, if_name, sizeof(if_request.device1)); - if_request.cmd = DEL_VLAN_CMD; - - if (ioctl(fd, SIOCSIFVLAN, &if_request) < 0) { - wpa_printf(MSG_ERROR, "VLAN: %s: DEL_VLAN_CMD failed for %s: " - "%s", __func__, if_name, strerror(errno)); - close(fd); - return -1; - } - - close(fd); - return 0; -} - - -/* - Add a vlan interface with VLAN ID 'vid' and tagged interface - 'if_name'. - - returns -1 on error - returns 1 if the interface already exists - returns 0 otherwise -*/ -static int vlan_add(const char *if_name, int vid) -{ - int fd; - struct vlan_ioctl_args if_request; - - wpa_printf(MSG_DEBUG, "VLAN: vlan_add(if_name=%s, vid=%d)", - if_name, vid); - ifconfig_up(if_name); - - if ((os_strlen(if_name) + 1) > sizeof(if_request.device1)) { - wpa_printf(MSG_ERROR, "VLAN: Interface name too long: '%s'", - if_name); - return -1; - } - - if ((fd = socket(AF_INET, SOCK_STREAM, 0)) < 0) { - wpa_printf(MSG_ERROR, "VLAN: %s: socket(AF_INET,SOCK_STREAM) " - "failed: %s", __func__, strerror(errno)); - return -1; - } - - os_memset(&if_request, 0, sizeof(if_request)); - - /* Determine if a suitable vlan device already exists. */ - - os_snprintf(if_request.device1, sizeof(if_request.device1), "vlan%d", - vid); - - if_request.cmd = _GET_VLAN_VID_CMD; - - if (ioctl(fd, SIOCSIFVLAN, &if_request) == 0) { - - if (if_request.u.VID == vid) { - if_request.cmd = _GET_VLAN_REALDEV_NAME_CMD; - - if (ioctl(fd, SIOCSIFVLAN, &if_request) == 0 && - os_strncmp(if_request.u.device2, if_name, - sizeof(if_request.u.device2)) == 0) { - close(fd); - wpa_printf(MSG_DEBUG, "VLAN: vlan_add: " - "if_name %s exists already", - if_request.device1); - return 1; - } - } - } - - /* A suitable vlan device does not already exist, add one. */ - - os_memset(&if_request, 0, sizeof(if_request)); - os_strlcpy(if_request.device1, if_name, sizeof(if_request.device1)); - if_request.u.VID = vid; - if_request.cmd = ADD_VLAN_CMD; - - if (ioctl(fd, SIOCSIFVLAN, &if_request) < 0) { - wpa_printf(MSG_ERROR, "VLAN: %s: ADD_VLAN_CMD failed for %s: " - "%s", - __func__, if_request.device1, strerror(errno)); - close(fd); - return -1; - } - - close(fd); - return 0; -} - - -static int vlan_set_name_type(unsigned int name_type) -{ - int fd; - struct vlan_ioctl_args if_request; - - wpa_printf(MSG_DEBUG, "VLAN: vlan_set_name_type(name_type=%u)", - name_type); - if ((fd = socket(AF_INET, SOCK_STREAM, 0)) < 0) { - wpa_printf(MSG_ERROR, "VLAN: %s: socket(AF_INET,SOCK_STREAM) " - "failed: %s", __func__, strerror(errno)); - return -1; - } - - os_memset(&if_request, 0, sizeof(if_request)); - - if_request.u.name_type = name_type; - if_request.cmd = SET_VLAN_NAME_TYPE_CMD; - if (ioctl(fd, SIOCSIFVLAN, &if_request) < 0) { - wpa_printf(MSG_ERROR, "VLAN: %s: SET_VLAN_NAME_TYPE_CMD " - "name_type=%u failed: %s", - __func__, name_type, strerror(errno)); - close(fd); - return -1; - } - - close(fd); - return 0; -} - - -static void vlan_newlink(char *ifname, struct hostapd_data *hapd) -{ - char vlan_ifname[IFNAMSIZ]; - char br_name[IFNAMSIZ]; - struct hostapd_vlan *vlan = hapd->conf->vlan; - char *tagged_interface = hapd->conf->ssid.vlan_tagged_interface; - - wpa_printf(MSG_DEBUG, "VLAN: vlan_newlink(%s)", ifname); - - while (vlan) { - if (os_strcmp(ifname, vlan->ifname) == 0) { - - os_snprintf(br_name, sizeof(br_name), "brvlan%d", - vlan->vlan_id); - - if (!br_addbr(br_name)) - vlan->clean |= DVLAN_CLEAN_BR; - - ifconfig_up(br_name); - - if (tagged_interface) { - - if (!vlan_add(tagged_interface, vlan->vlan_id)) - vlan->clean |= DVLAN_CLEAN_VLAN; - - os_snprintf(vlan_ifname, sizeof(vlan_ifname), - "vlan%d", vlan->vlan_id); - - if (!br_addif(br_name, vlan_ifname)) - vlan->clean |= DVLAN_CLEAN_VLAN_PORT; - - ifconfig_up(vlan_ifname); - } - - if (!br_addif(br_name, ifname)) - vlan->clean |= DVLAN_CLEAN_WLAN_PORT; - - ifconfig_up(ifname); - - break; - } - vlan = vlan->next; - } -} - - -static void vlan_dellink(char *ifname, struct hostapd_data *hapd) -{ - char vlan_ifname[IFNAMSIZ]; - char br_name[IFNAMSIZ]; - struct hostapd_vlan *first, *prev, *vlan = hapd->conf->vlan; - char *tagged_interface = hapd->conf->ssid.vlan_tagged_interface; - - wpa_printf(MSG_DEBUG, "VLAN: vlan_dellink(%s)", ifname); - - first = prev = vlan; - - while (vlan) { - if (os_strcmp(ifname, vlan->ifname) == 0) { - os_snprintf(br_name, sizeof(br_name), "brvlan%d", - vlan->vlan_id); - - if (vlan->clean & DVLAN_CLEAN_WLAN_PORT) - br_delif(br_name, vlan->ifname); - - if (tagged_interface) { - os_snprintf(vlan_ifname, sizeof(vlan_ifname), - "vlan%d", vlan->vlan_id); - if (vlan->clean & DVLAN_CLEAN_VLAN_PORT) - br_delif(br_name, vlan_ifname); - ifconfig_down(vlan_ifname); - - if (vlan->clean & DVLAN_CLEAN_VLAN) - vlan_rem(vlan_ifname); - } - - if ((vlan->clean & DVLAN_CLEAN_BR) && - br_getnumports(br_name) == 0) { - ifconfig_down(br_name); - br_delbr(br_name); - } - - if (vlan == first) { - hapd->conf->vlan = vlan->next; - } else { - prev->next = vlan->next; - } - os_free(vlan); - - break; - } - prev = vlan; - vlan = vlan->next; - } -} - - -static void -vlan_read_ifnames(struct nlmsghdr *h, size_t len, int del, - struct hostapd_data *hapd) -{ - struct ifinfomsg *ifi; - int attrlen, nlmsg_len, rta_len; - struct rtattr *attr; - - if (len < sizeof(*ifi)) - return; - - ifi = NLMSG_DATA(h); - - nlmsg_len = NLMSG_ALIGN(sizeof(struct ifinfomsg)); - - attrlen = h->nlmsg_len - nlmsg_len; - if (attrlen < 0) - return; - - attr = (struct rtattr *) (((char *) ifi) + nlmsg_len); - - rta_len = RTA_ALIGN(sizeof(struct rtattr)); - while (RTA_OK(attr, attrlen)) { - char ifname[IFNAMSIZ + 1]; - - if (attr->rta_type == IFLA_IFNAME) { - int n = attr->rta_len - rta_len; - if (n < 0) - break; - - os_memset(ifname, 0, sizeof(ifname)); - - if ((size_t) n > sizeof(ifname)) - n = sizeof(ifname); - os_memcpy(ifname, ((char *) attr) + rta_len, n); - - if (del) - vlan_dellink(ifname, hapd); - else - vlan_newlink(ifname, hapd); - } - - attr = RTA_NEXT(attr, attrlen); - } -} - - -static void vlan_event_receive(int sock, void *eloop_ctx, void *sock_ctx) -{ - char buf[8192]; - int left; - struct sockaddr_nl from; - socklen_t fromlen; - struct nlmsghdr *h; - struct hostapd_data *hapd = eloop_ctx; - - fromlen = sizeof(from); - left = recvfrom(sock, buf, sizeof(buf), MSG_DONTWAIT, - (struct sockaddr *) &from, &fromlen); - if (left < 0) { - if (errno != EINTR && errno != EAGAIN) - wpa_printf(MSG_ERROR, "VLAN: %s: recvfrom failed: %s", - __func__, strerror(errno)); - return; - } - - h = (struct nlmsghdr *) buf; - while (left >= (int) sizeof(*h)) { - int len, plen; - - len = h->nlmsg_len; - plen = len - sizeof(*h); - if (len > left || plen < 0) { - wpa_printf(MSG_DEBUG, "VLAN: Malformed netlink " - "message: len=%d left=%d plen=%d", - len, left, plen); - break; - } - - switch (h->nlmsg_type) { - case RTM_NEWLINK: - vlan_read_ifnames(h, plen, 0, hapd); - break; - case RTM_DELLINK: - vlan_read_ifnames(h, plen, 1, hapd); - break; - } - - len = NLMSG_ALIGN(len); - left -= len; - h = (struct nlmsghdr *) ((char *) h + len); - } - - if (left > 0) { - wpa_printf(MSG_DEBUG, "VLAN: %s: %d extra bytes in the end of " - "netlink message", __func__, left); - } -} - - -static struct full_dynamic_vlan * -full_dynamic_vlan_init(struct hostapd_data *hapd) -{ - struct sockaddr_nl local; - struct full_dynamic_vlan *priv; - - priv = os_zalloc(sizeof(*priv)); - if (priv == NULL) - return NULL; - - vlan_set_name_type(VLAN_NAME_TYPE_PLUS_VID_NO_PAD); - - priv->s = socket(PF_NETLINK, SOCK_RAW, NETLINK_ROUTE); - if (priv->s < 0) { - wpa_printf(MSG_ERROR, "VLAN: %s: socket(PF_NETLINK,SOCK_RAW," - "NETLINK_ROUTE) failed: %s", - __func__, strerror(errno)); - os_free(priv); - return NULL; - } - - os_memset(&local, 0, sizeof(local)); - local.nl_family = AF_NETLINK; - local.nl_groups = RTMGRP_LINK; - if (bind(priv->s, (struct sockaddr *) &local, sizeof(local)) < 0) { - wpa_printf(MSG_ERROR, "VLAN: %s: bind(netlink) failed: %s", - __func__, strerror(errno)); - close(priv->s); - os_free(priv); - return NULL; - } - - if (eloop_register_read_sock(priv->s, vlan_event_receive, hapd, NULL)) - { - close(priv->s); - os_free(priv); - return NULL; - } - - return priv; -} - - -static void full_dynamic_vlan_deinit(struct full_dynamic_vlan *priv) -{ - if (priv == NULL) - return; - eloop_unregister_read_sock(priv->s); - close(priv->s); - os_free(priv); -} -#endif /* CONFIG_FULL_DYNAMIC_VLAN */ - - -int vlan_setup_encryption_dyn(struct hostapd_data *hapd, - struct hostapd_ssid *mssid, const char *dyn_vlan) -{ - int i; - - if (dyn_vlan == NULL) - return 0; - - /* Static WEP keys are set here; IEEE 802.1X and WPA uses their own - * functions for setting up dynamic broadcast keys. */ - for (i = 0; i < 4; i++) { - if (mssid->wep.key[i] && - hostapd_drv_set_key(dyn_vlan, hapd, WPA_ALG_WEP, NULL, i, - i == mssid->wep.idx, NULL, 0, - mssid->wep.key[i], mssid->wep.len[i])) - { - wpa_printf(MSG_ERROR, "VLAN: Could not set WEP " - "encryption for dynamic VLAN"); - return -1; - } - } - - return 0; -} - - -static int vlan_dynamic_add(struct hostapd_data *hapd, - struct hostapd_vlan *vlan) -{ - while (vlan) { - if (vlan->vlan_id != VLAN_ID_WILDCARD) { - if (hostapd_vlan_if_add(hapd, vlan->ifname)) { - if (errno != EEXIST) { - wpa_printf(MSG_ERROR, "VLAN: Could " - "not add VLAN %s: %s", - vlan->ifname, - strerror(errno)); - return -1; - } - } -#ifdef CONFIG_FULL_DYNAMIC_VLAN - ifconfig_up(vlan->ifname); -#endif /* CONFIG_FULL_DYNAMIC_VLAN */ - } - - vlan = vlan->next; - } - - return 0; -} - - -static void vlan_dynamic_remove(struct hostapd_data *hapd, - struct hostapd_vlan *vlan) -{ - struct hostapd_vlan *next; - - while (vlan) { - next = vlan->next; - - if (vlan->vlan_id != VLAN_ID_WILDCARD && - hostapd_vlan_if_remove(hapd, vlan->ifname)) { - wpa_printf(MSG_ERROR, "VLAN: Could not remove VLAN " - "iface: %s: %s", - vlan->ifname, strerror(errno)); - } -#ifdef CONFIG_FULL_DYNAMIC_VLAN - if (vlan->clean) - vlan_dellink(vlan->ifname, hapd); -#endif /* CONFIG_FULL_DYNAMIC_VLAN */ - - vlan = next; - } -} - - -int vlan_init(struct hostapd_data *hapd) -{ -#ifdef CONFIG_FULL_DYNAMIC_VLAN - hapd->full_dynamic_vlan = full_dynamic_vlan_init(hapd); -#endif /* CONFIG_FULL_DYNAMIC_VLAN */ - - if (vlan_dynamic_add(hapd, hapd->conf->vlan)) - return -1; - - return 0; -} - - -void vlan_deinit(struct hostapd_data *hapd) -{ - vlan_dynamic_remove(hapd, hapd->conf->vlan); - -#ifdef CONFIG_FULL_DYNAMIC_VLAN - full_dynamic_vlan_deinit(hapd->full_dynamic_vlan); -#endif /* CONFIG_FULL_DYNAMIC_VLAN */ -} - - -struct hostapd_vlan * vlan_add_dynamic(struct hostapd_data *hapd, - struct hostapd_vlan *vlan, - int vlan_id) -{ - struct hostapd_vlan *n; - char *ifname, *pos; - - if (vlan == NULL || vlan_id <= 0 || vlan_id > MAX_VLAN_ID || - vlan->vlan_id != VLAN_ID_WILDCARD) - return NULL; - - wpa_printf(MSG_DEBUG, "VLAN: %s(vlan_id=%d ifname=%s)", - __func__, vlan_id, vlan->ifname); - ifname = os_strdup(vlan->ifname); - if (ifname == NULL) - return NULL; - pos = os_strchr(ifname, '#'); - if (pos == NULL) { - os_free(ifname); - return NULL; - } - *pos++ = '\0'; - - n = os_zalloc(sizeof(*n)); - if (n == NULL) { - os_free(ifname); - return NULL; - } - - n->vlan_id = vlan_id; - n->dynamic_vlan = 1; - - os_snprintf(n->ifname, sizeof(n->ifname), "%s%d%s", ifname, vlan_id, - pos); - os_free(ifname); - - if (hostapd_vlan_if_add(hapd, n->ifname)) { - os_free(n); - return NULL; - } - - n->next = hapd->conf->vlan; - hapd->conf->vlan = n; - -#ifdef CONFIG_FULL_DYNAMIC_VLAN - ifconfig_up(n->ifname); -#endif /* CONFIG_FULL_DYNAMIC_VLAN */ - - return n; -} - - -int vlan_remove_dynamic(struct hostapd_data *hapd, int vlan_id) -{ - struct hostapd_vlan *vlan; - - if (vlan_id <= 0 || vlan_id > MAX_VLAN_ID) - return 1; - - wpa_printf(MSG_DEBUG, "VLAN: %s(vlan_id=%d)", __func__, vlan_id); - - vlan = hapd->conf->vlan; - while (vlan) { - if (vlan->vlan_id == vlan_id && vlan->dynamic_vlan > 0) { - vlan->dynamic_vlan--; - break; - } - vlan = vlan->next; - } - - if (vlan == NULL) - return 1; - - if (vlan->dynamic_vlan == 0) - hostapd_vlan_if_remove(hapd, vlan->ifname); - - return 0; -} diff --git a/hostapd-0.8/src/ap/vlan_init.h b/hostapd-0.8/src/ap/vlan_init.h deleted file mode 100644 index 382d5de..0000000 --- a/hostapd-0.8/src/ap/vlan_init.h +++ /dev/null @@ -1,59 +0,0 @@ -/* - * hostapd / VLAN initialization - * Copyright 2003, Instant802 Networks, Inc. - * Copyright 2005, Devicescape Software, Inc. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#ifndef VLAN_INIT_H -#define VLAN_INIT_H - -#ifndef CONFIG_NO_VLAN -int vlan_init(struct hostapd_data *hapd); -void vlan_deinit(struct hostapd_data *hapd); -struct hostapd_vlan * vlan_add_dynamic(struct hostapd_data *hapd, - struct hostapd_vlan *vlan, - int vlan_id); -int vlan_remove_dynamic(struct hostapd_data *hapd, int vlan_id); -int vlan_setup_encryption_dyn(struct hostapd_data *hapd, - struct hostapd_ssid *mssid, - const char *dyn_vlan); -#else /* CONFIG_NO_VLAN */ -static inline int vlan_init(struct hostapd_data *hapd) -{ - return 0; -} - -static inline void vlan_deinit(struct hostapd_data *hapd) -{ -} - -static inline struct hostapd_vlan * vlan_add_dynamic(struct hostapd_data *hapd, - struct hostapd_vlan *vlan, - int vlan_id) -{ - return NULL; -} - -static inline int vlan_remove_dynamic(struct hostapd_data *hapd, int vlan_id) -{ - return -1; -} - -static inline int vlan_setup_encryption_dyn(struct hostapd_data *hapd, - struct hostapd_ssid *mssid, - const char *dyn_vlan) -{ - return -1; -} -#endif /* CONFIG_NO_VLAN */ - -#endif /* VLAN_INIT_H */ diff --git a/hostapd-0.8/src/ap/wmm.c b/hostapd-0.8/src/ap/wmm.c deleted file mode 100644 index a6d9b89..0000000 --- a/hostapd-0.8/src/ap/wmm.c +++ /dev/null @@ -1,327 +0,0 @@ -/* - * hostapd / WMM (Wi-Fi Multimedia) - * Copyright 2002-2003, Instant802 Networks, Inc. - * Copyright 2005-2006, Devicescape Software, Inc. - * Copyright (c) 2009, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#include "utils/includes.h" - -#include "utils/common.h" -#include "common/ieee802_11_defs.h" -#include "common/ieee802_11_common.h" -#include "hostapd.h" -#include "ieee802_11.h" -#include "sta_info.h" -#include "ap_config.h" -#include "ap_drv_ops.h" -#include "wmm.h" - - -/* TODO: maintain separate sequence and fragment numbers for each AC - * TODO: IGMP snooping to track which multicasts to forward - and use QOS-DATA - * if only WMM stations are receiving a certain group */ - - -static inline u8 wmm_aci_aifsn(int aifsn, int acm, int aci) -{ - u8 ret; - ret = (aifsn << WMM_AC_AIFNS_SHIFT) & WMM_AC_AIFSN_MASK; - if (acm) - ret |= WMM_AC_ACM; - ret |= (aci << WMM_AC_ACI_SHIFT) & WMM_AC_ACI_MASK; - return ret; -} - - -static inline u8 wmm_ecw(int ecwmin, int ecwmax) -{ - return ((ecwmin << WMM_AC_ECWMIN_SHIFT) & WMM_AC_ECWMIN_MASK) | - ((ecwmax << WMM_AC_ECWMAX_SHIFT) & WMM_AC_ECWMAX_MASK); -} - - -/* - * Add WMM Parameter Element to Beacon, Probe Response, and (Re)Association - * Response frames. - */ -u8 * hostapd_eid_wmm(struct hostapd_data *hapd, u8 *eid) -{ - u8 *pos = eid; - struct wmm_parameter_element *wmm = - (struct wmm_parameter_element *) (pos + 2); - int e; - - if (!hapd->conf->wmm_enabled) - return eid; - eid[0] = WLAN_EID_VENDOR_SPECIFIC; - wmm->oui[0] = 0x00; - wmm->oui[1] = 0x50; - wmm->oui[2] = 0xf2; - wmm->oui_type = WMM_OUI_TYPE; - wmm->oui_subtype = WMM_OUI_SUBTYPE_PARAMETER_ELEMENT; - wmm->version = WMM_VERSION; - wmm->qos_info = hapd->parameter_set_count & 0xf; - - if (hapd->conf->wmm_uapsd) - wmm->qos_info |= 0x80; - - wmm->reserved = 0; - - /* fill in a parameter set record for each AC */ - for (e = 0; e < 4; e++) { - struct wmm_ac_parameter *ac = &wmm->ac[e]; - struct hostapd_wmm_ac_params *acp = - &hapd->iconf->wmm_ac_params[e]; - - ac->aci_aifsn = wmm_aci_aifsn(acp->aifs, - acp->admission_control_mandatory, - e); - ac->cw = wmm_ecw(acp->cwmin, acp->cwmax); - ac->txop_limit = host_to_le16(acp->txop_limit); - } - - pos = (u8 *) (wmm + 1); - eid[1] = pos - eid - 2; /* element length */ - - return pos; -} - - -/* This function is called when a station sends an association request with - * WMM info element. The function returns zero on success or non-zero on any - * error in WMM element. eid does not include Element ID and Length octets. */ -int hostapd_eid_wmm_valid(struct hostapd_data *hapd, const u8 *eid, size_t len) -{ - struct wmm_information_element *wmm; - - wpa_hexdump(MSG_MSGDUMP, "WMM IE", eid, len); - - if (len < sizeof(struct wmm_information_element)) { - wpa_printf(MSG_DEBUG, "Too short WMM IE (len=%lu)", - (unsigned long) len); - return -1; - } - - wmm = (struct wmm_information_element *) eid; - wpa_printf(MSG_DEBUG, "Validating WMM IE: OUI %02x:%02x:%02x " - "OUI type %d OUI sub-type %d version %d QoS info 0x%x", - wmm->oui[0], wmm->oui[1], wmm->oui[2], wmm->oui_type, - wmm->oui_subtype, wmm->version, wmm->qos_info); - if (wmm->oui_subtype != WMM_OUI_SUBTYPE_INFORMATION_ELEMENT || - wmm->version != WMM_VERSION) { - wpa_printf(MSG_DEBUG, "Unsupported WMM IE Subtype/Version"); - return -1; - } - - return 0; -} - - -static void wmm_send_action(struct hostapd_data *hapd, const u8 *addr, - const struct wmm_tspec_element *tspec, - u8 action_code, u8 dialogue_token, u8 status_code) -{ - u8 buf[256]; - struct ieee80211_mgmt *m = (struct ieee80211_mgmt *) buf; - struct wmm_tspec_element *t = (struct wmm_tspec_element *) - m->u.action.u.wmm_action.variable; - int len; - - hostapd_logger(hapd, addr, HOSTAPD_MODULE_IEEE80211, - HOSTAPD_LEVEL_DEBUG, - "action response - reason %d", status_code); - os_memset(buf, 0, sizeof(buf)); - m->frame_control = IEEE80211_FC(WLAN_FC_TYPE_MGMT, - WLAN_FC_STYPE_ACTION); - os_memcpy(m->da, addr, ETH_ALEN); - os_memcpy(m->sa, hapd->own_addr, ETH_ALEN); - os_memcpy(m->bssid, hapd->own_addr, ETH_ALEN); - m->u.action.category = WLAN_ACTION_WMM; - m->u.action.u.wmm_action.action_code = action_code; - m->u.action.u.wmm_action.dialog_token = dialogue_token; - m->u.action.u.wmm_action.status_code = status_code; - os_memcpy(t, tspec, sizeof(struct wmm_tspec_element)); - len = ((u8 *) (t + 1)) - buf; - - if (hostapd_drv_send_mlme(hapd, m, len) < 0) - perror("wmm_send_action: send"); -} - - -int wmm_process_tspec(struct wmm_tspec_element *tspec) -{ - int medium_time, pps, duration; - int up, psb, dir, tid; - u16 val, surplus; - - up = (tspec->ts_info[1] >> 3) & 0x07; - psb = (tspec->ts_info[1] >> 2) & 0x01; - dir = (tspec->ts_info[0] >> 5) & 0x03; - tid = (tspec->ts_info[0] >> 1) & 0x0f; - wpa_printf(MSG_DEBUG, "WMM: TS Info: UP=%d PSB=%d Direction=%d TID=%d", - up, psb, dir, tid); - val = le_to_host16(tspec->nominal_msdu_size); - wpa_printf(MSG_DEBUG, "WMM: Nominal MSDU Size: %d%s", - val & 0x7fff, val & 0x8000 ? " (fixed)" : ""); - wpa_printf(MSG_DEBUG, "WMM: Mean Data Rate: %u bps", - le_to_host32(tspec->mean_data_rate)); - wpa_printf(MSG_DEBUG, "WMM: Minimum PHY Rate: %u bps", - le_to_host32(tspec->minimum_phy_rate)); - val = le_to_host16(tspec->surplus_bandwidth_allowance); - wpa_printf(MSG_DEBUG, "WMM: Surplus Bandwidth Allowance: %u.%04u", - val >> 13, 10000 * (val & 0x1fff) / 0x2000); - - val = le_to_host16(tspec->nominal_msdu_size); - if (val == 0) { - wpa_printf(MSG_DEBUG, "WMM: Invalid Nominal MSDU Size (0)"); - return WMM_ADDTS_STATUS_INVALID_PARAMETERS; - } - /* pps = Ceiling((Mean Data Rate / 8) / Nominal MSDU Size) */ - pps = ((le_to_host32(tspec->mean_data_rate) / 8) + val - 1) / val; - wpa_printf(MSG_DEBUG, "WMM: Packets-per-second estimate for TSPEC: %d", - pps); - - if (le_to_host32(tspec->minimum_phy_rate) < 1000000) { - wpa_printf(MSG_DEBUG, "WMM: Too small Minimum PHY Rate"); - return WMM_ADDTS_STATUS_INVALID_PARAMETERS; - } - - duration = (le_to_host16(tspec->nominal_msdu_size) & 0x7fff) * 8 / - (le_to_host32(tspec->minimum_phy_rate) / 1000000) + - 50 /* FIX: proper SIFS + ACK duration */; - - /* unsigned binary number with an implicit binary point after the - * leftmost 3 bits, i.e., 0x2000 = 1.0 */ - surplus = le_to_host16(tspec->surplus_bandwidth_allowance); - if (surplus <= 0x2000) { - wpa_printf(MSG_DEBUG, "WMM: Surplus Bandwidth Allowance not " - "greater than unity"); - return WMM_ADDTS_STATUS_INVALID_PARAMETERS; - } - - medium_time = surplus * pps * duration / 0x2000; - wpa_printf(MSG_DEBUG, "WMM: Estimated medium time: %u", medium_time); - - /* - * TODO: store list of granted (and still active) TSPECs and check - * whether there is available medium time for this request. For now, - * just refuse requests that would by themselves take very large - * portion of the available bandwidth. - */ - if (medium_time > 750000) { - wpa_printf(MSG_DEBUG, "WMM: Refuse TSPEC request for over " - "75%% of available bandwidth"); - return WMM_ADDTS_STATUS_REFUSED; - } - - /* Convert to 32 microseconds per second unit */ - tspec->medium_time = host_to_le16(medium_time / 32); - - return WMM_ADDTS_STATUS_ADMISSION_ACCEPTED; -} - - -static void wmm_addts_req(struct hostapd_data *hapd, - const struct ieee80211_mgmt *mgmt, - struct wmm_tspec_element *tspec, size_t len) -{ - const u8 *end = ((const u8 *) mgmt) + len; - int res; - - if ((const u8 *) (tspec + 1) > end) { - wpa_printf(MSG_DEBUG, "WMM: TSPEC overflow in ADDTS Request"); - return; - } - - wpa_printf(MSG_DEBUG, "WMM: ADDTS Request (Dialog Token %d) for TSPEC " - "from " MACSTR, - mgmt->u.action.u.wmm_action.dialog_token, - MAC2STR(mgmt->sa)); - - res = wmm_process_tspec(tspec); - wpa_printf(MSG_DEBUG, "WMM: ADDTS processing result: %d", res); - - wmm_send_action(hapd, mgmt->sa, tspec, WMM_ACTION_CODE_ADDTS_RESP, - mgmt->u.action.u.wmm_action.dialog_token, res); -} - - -void hostapd_wmm_action(struct hostapd_data *hapd, - const struct ieee80211_mgmt *mgmt, size_t len) -{ - int action_code; - int left = len - IEEE80211_HDRLEN - 4; - const u8 *pos = ((const u8 *) mgmt) + IEEE80211_HDRLEN + 4; - struct ieee802_11_elems elems; - struct sta_info *sta = ap_get_sta(hapd, mgmt->sa); - - /* check that the request comes from a valid station */ - if (!sta || - (sta->flags & (WLAN_STA_ASSOC | WLAN_STA_WMM)) != - (WLAN_STA_ASSOC | WLAN_STA_WMM)) { - hostapd_logger(hapd, mgmt->sa, HOSTAPD_MODULE_IEEE80211, - HOSTAPD_LEVEL_DEBUG, - "wmm action received is not from associated wmm" - " station"); - /* TODO: respond with action frame refused status code */ - return; - } - - /* extract the tspec info element */ - if (ieee802_11_parse_elems(pos, left, &elems, 1) == ParseFailed) { - hostapd_logger(hapd, mgmt->sa, HOSTAPD_MODULE_IEEE80211, - HOSTAPD_LEVEL_DEBUG, - "hostapd_wmm_action - could not parse wmm " - "action"); - /* TODO: respond with action frame invalid parameters status - * code */ - return; - } - - if (!elems.wmm_tspec || - elems.wmm_tspec_len != (sizeof(struct wmm_tspec_element) - 2)) { - hostapd_logger(hapd, mgmt->sa, HOSTAPD_MODULE_IEEE80211, - HOSTAPD_LEVEL_DEBUG, - "hostapd_wmm_action - missing or wrong length " - "tspec"); - /* TODO: respond with action frame invalid parameters status - * code */ - return; - } - - /* TODO: check the request is for an AC with ACM set, if not, refuse - * request */ - - action_code = mgmt->u.action.u.wmm_action.action_code; - switch (action_code) { - case WMM_ACTION_CODE_ADDTS_REQ: - wmm_addts_req(hapd, mgmt, (struct wmm_tspec_element *) - (elems.wmm_tspec - 2), len); - return; -#if 0 - /* TODO: needed for client implementation */ - case WMM_ACTION_CODE_ADDTS_RESP: - wmm_setup_request(hapd, mgmt, len); - return; - /* TODO: handle station teardown requests */ - case WMM_ACTION_CODE_DELTS: - wmm_teardown(hapd, mgmt, len); - return; -#endif - } - - hostapd_logger(hapd, mgmt->sa, HOSTAPD_MODULE_IEEE80211, - HOSTAPD_LEVEL_DEBUG, - "hostapd_wmm_action - unknown action code %d", - action_code); -} diff --git a/hostapd-0.8/src/ap/wmm.h b/hostapd-0.8/src/ap/wmm.h deleted file mode 100644 index 96b04e8..0000000 --- a/hostapd-0.8/src/ap/wmm.h +++ /dev/null @@ -1,29 +0,0 @@ -/* - * hostapd / WMM (Wi-Fi Multimedia) - * Copyright 2002-2003, Instant802 Networks, Inc. - * Copyright 2005-2006, Devicescape Software, Inc. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#ifndef WME_H -#define WME_H - -struct ieee80211_mgmt; -struct wmm_tspec_element; - -u8 * hostapd_eid_wmm(struct hostapd_data *hapd, u8 *eid); -int hostapd_eid_wmm_valid(struct hostapd_data *hapd, const u8 *eid, - size_t len); -void hostapd_wmm_action(struct hostapd_data *hapd, - const struct ieee80211_mgmt *mgmt, size_t len); -int wmm_process_tspec(struct wmm_tspec_element *tspec); - -#endif /* WME_H */ diff --git a/hostapd-0.8/src/ap/wpa_auth.c b/hostapd-0.8/src/ap/wpa_auth.c deleted file mode 100644 index cfb2cad..0000000 --- a/hostapd-0.8/src/ap/wpa_auth.c +++ /dev/null @@ -1,2838 +0,0 @@ -/* - * hostapd - IEEE 802.11i-2004 / WPA Authenticator - * Copyright (c) 2004-2009, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#include "utils/includes.h" - -#include "utils/common.h" -#include "utils/eloop.h" -#include "utils/state_machine.h" -#include "common/ieee802_11_defs.h" -#include "crypto/aes_wrap.h" -#include "crypto/crypto.h" -#include "crypto/sha1.h" -#include "crypto/sha256.h" -#include "crypto/random.h" -#include "eapol_auth/eapol_auth_sm.h" -#include "ap_config.h" -#include "ieee802_11.h" -#include "wpa_auth.h" -#include "pmksa_cache_auth.h" -#include "wpa_auth_i.h" -#include "wpa_auth_ie.h" - -#define STATE_MACHINE_DATA struct wpa_state_machine -#define STATE_MACHINE_DEBUG_PREFIX "WPA" -#define STATE_MACHINE_ADDR sm->addr - - -static void wpa_send_eapol_timeout(void *eloop_ctx, void *timeout_ctx); -static int wpa_sm_step(struct wpa_state_machine *sm); -static int wpa_verify_key_mic(struct wpa_ptk *PTK, u8 *data, size_t data_len); -static void wpa_sm_call_step(void *eloop_ctx, void *timeout_ctx); -static void wpa_group_sm_step(struct wpa_authenticator *wpa_auth, - struct wpa_group *group); -static void wpa_request_new_ptk(struct wpa_state_machine *sm); -static int wpa_gtk_update(struct wpa_authenticator *wpa_auth, - struct wpa_group *group); -static int wpa_group_config_group_keys(struct wpa_authenticator *wpa_auth, - struct wpa_group *group); - -static const u32 dot11RSNAConfigGroupUpdateCount = 4; -static const u32 dot11RSNAConfigPairwiseUpdateCount = 4; -static const u32 eapol_key_timeout_first = 100; /* ms */ -static const u32 eapol_key_timeout_subseq = 1000; /* ms */ - -/* TODO: make these configurable */ -static const int dot11RSNAConfigPMKLifetime = 43200; -static const int dot11RSNAConfigPMKReauthThreshold = 70; -static const int dot11RSNAConfigSATimeout = 60; - - -static inline void wpa_auth_mic_failure_report( - struct wpa_authenticator *wpa_auth, const u8 *addr) -{ - if (wpa_auth->cb.mic_failure_report) - wpa_auth->cb.mic_failure_report(wpa_auth->cb.ctx, addr); -} - - -static inline void wpa_auth_set_eapol(struct wpa_authenticator *wpa_auth, - const u8 *addr, wpa_eapol_variable var, - int value) -{ - if (wpa_auth->cb.set_eapol) - wpa_auth->cb.set_eapol(wpa_auth->cb.ctx, addr, var, value); -} - - -static inline int wpa_auth_get_eapol(struct wpa_authenticator *wpa_auth, - const u8 *addr, wpa_eapol_variable var) -{ - if (wpa_auth->cb.get_eapol == NULL) - return -1; - return wpa_auth->cb.get_eapol(wpa_auth->cb.ctx, addr, var); -} - - -static inline const u8 * wpa_auth_get_psk(struct wpa_authenticator *wpa_auth, - const u8 *addr, const u8 *prev_psk) -{ - if (wpa_auth->cb.get_psk == NULL) - return NULL; - return wpa_auth->cb.get_psk(wpa_auth->cb.ctx, addr, prev_psk); -} - - -static inline int wpa_auth_get_msk(struct wpa_authenticator *wpa_auth, - const u8 *addr, u8 *msk, size_t *len) -{ - if (wpa_auth->cb.get_msk == NULL) - return -1; - return wpa_auth->cb.get_msk(wpa_auth->cb.ctx, addr, msk, len); -} - - -static inline int wpa_auth_set_key(struct wpa_authenticator *wpa_auth, - int vlan_id, - enum wpa_alg alg, const u8 *addr, int idx, - u8 *key, size_t key_len) -{ - if (wpa_auth->cb.set_key == NULL) - return -1; - return wpa_auth->cb.set_key(wpa_auth->cb.ctx, vlan_id, alg, addr, idx, - key, key_len); -} - - -static inline int wpa_auth_get_seqnum(struct wpa_authenticator *wpa_auth, - const u8 *addr, int idx, u8 *seq) -{ - if (wpa_auth->cb.get_seqnum == NULL) - return -1; - return wpa_auth->cb.get_seqnum(wpa_auth->cb.ctx, addr, idx, seq); -} - - -static inline int -wpa_auth_send_eapol(struct wpa_authenticator *wpa_auth, const u8 *addr, - const u8 *data, size_t data_len, int encrypt) -{ - if (wpa_auth->cb.send_eapol == NULL) - return -1; - return wpa_auth->cb.send_eapol(wpa_auth->cb.ctx, addr, data, data_len, - encrypt); -} - - -int wpa_auth_for_each_sta(struct wpa_authenticator *wpa_auth, - int (*cb)(struct wpa_state_machine *sm, void *ctx), - void *cb_ctx) -{ - if (wpa_auth->cb.for_each_sta == NULL) - return 0; - return wpa_auth->cb.for_each_sta(wpa_auth->cb.ctx, cb, cb_ctx); -} - - -int wpa_auth_for_each_auth(struct wpa_authenticator *wpa_auth, - int (*cb)(struct wpa_authenticator *a, void *ctx), - void *cb_ctx) -{ - if (wpa_auth->cb.for_each_auth == NULL) - return 0; - return wpa_auth->cb.for_each_auth(wpa_auth->cb.ctx, cb, cb_ctx); -} - - -void wpa_auth_logger(struct wpa_authenticator *wpa_auth, const u8 *addr, - logger_level level, const char *txt) -{ - if (wpa_auth->cb.logger == NULL) - return; - wpa_auth->cb.logger(wpa_auth->cb.ctx, addr, level, txt); -} - - -void wpa_auth_vlogger(struct wpa_authenticator *wpa_auth, const u8 *addr, - logger_level level, const char *fmt, ...) -{ - char *format; - int maxlen; - va_list ap; - - if (wpa_auth->cb.logger == NULL) - return; - - maxlen = os_strlen(fmt) + 100; - format = os_malloc(maxlen); - if (!format) - return; - - va_start(ap, fmt); - vsnprintf(format, maxlen, fmt, ap); - va_end(ap); - - wpa_auth_logger(wpa_auth, addr, level, format); - - os_free(format); -} - - -static void wpa_sta_disconnect(struct wpa_authenticator *wpa_auth, - const u8 *addr) -{ - if (wpa_auth->cb.disconnect == NULL) - return; - wpa_auth->cb.disconnect(wpa_auth->cb.ctx, addr, - WLAN_REASON_PREV_AUTH_NOT_VALID); -} - - -static int wpa_use_aes_cmac(struct wpa_state_machine *sm) -{ - int ret = 0; -#ifdef CONFIG_IEEE80211R - if (wpa_key_mgmt_ft(sm->wpa_key_mgmt)) - ret = 1; -#endif /* CONFIG_IEEE80211R */ -#ifdef CONFIG_IEEE80211W - if (wpa_key_mgmt_sha256(sm->wpa_key_mgmt)) - ret = 1; -#endif /* CONFIG_IEEE80211W */ - return ret; -} - - -static void wpa_rekey_gmk(void *eloop_ctx, void *timeout_ctx) -{ - struct wpa_authenticator *wpa_auth = eloop_ctx; - - if (random_get_bytes(wpa_auth->group->GMK, WPA_GMK_LEN)) { - wpa_printf(MSG_ERROR, "Failed to get random data for WPA " - "initialization."); - } else { - wpa_auth_logger(wpa_auth, NULL, LOGGER_DEBUG, "GMK rekeyd"); - wpa_hexdump_key(MSG_DEBUG, "GMK", - wpa_auth->group->GMK, WPA_GMK_LEN); - } - - if (wpa_auth->conf.wpa_gmk_rekey) { - eloop_register_timeout(wpa_auth->conf.wpa_gmk_rekey, 0, - wpa_rekey_gmk, wpa_auth, NULL); - } -} - - -static void wpa_rekey_gtk(void *eloop_ctx, void *timeout_ctx) -{ - struct wpa_authenticator *wpa_auth = eloop_ctx; - struct wpa_group *group; - - wpa_auth_logger(wpa_auth, NULL, LOGGER_DEBUG, "rekeying GTK"); - for (group = wpa_auth->group; group; group = group->next) { - group->GTKReKey = TRUE; - do { - group->changed = FALSE; - wpa_group_sm_step(wpa_auth, group); - } while (group->changed); - } - - if (wpa_auth->conf.wpa_group_rekey) { - eloop_register_timeout(wpa_auth->conf.wpa_group_rekey, - 0, wpa_rekey_gtk, wpa_auth, NULL); - } -} - - -static void wpa_rekey_ptk(void *eloop_ctx, void *timeout_ctx) -{ - struct wpa_authenticator *wpa_auth = eloop_ctx; - struct wpa_state_machine *sm = timeout_ctx; - - wpa_auth_logger(wpa_auth, sm->addr, LOGGER_DEBUG, "rekeying PTK"); - wpa_request_new_ptk(sm); - wpa_sm_step(sm); -} - - -static int wpa_auth_pmksa_clear_cb(struct wpa_state_machine *sm, void *ctx) -{ - if (sm->pmksa == ctx) - sm->pmksa = NULL; - return 0; -} - - -static void wpa_auth_pmksa_free_cb(struct rsn_pmksa_cache_entry *entry, - void *ctx) -{ - struct wpa_authenticator *wpa_auth = ctx; - wpa_auth_for_each_sta(wpa_auth, wpa_auth_pmksa_clear_cb, entry); -} - - -static void wpa_group_set_key_len(struct wpa_group *group, int cipher) -{ - switch (cipher) { - case WPA_CIPHER_CCMP: - group->GTK_len = 16; - break; - case WPA_CIPHER_TKIP: - group->GTK_len = 32; - break; - case WPA_CIPHER_WEP104: - group->GTK_len = 13; - break; - case WPA_CIPHER_WEP40: - group->GTK_len = 5; - break; - } -} - - -static int wpa_group_init_gmk_and_counter(struct wpa_authenticator *wpa_auth, - struct wpa_group *group) -{ - u8 buf[ETH_ALEN + 8 + sizeof(group)]; - u8 rkey[32]; - - if (random_get_bytes(group->GMK, WPA_GMK_LEN) < 0) - return -1; - wpa_hexdump_key(MSG_DEBUG, "GMK", group->GMK, WPA_GMK_LEN); - - /* - * Counter = PRF-256(Random number, "Init Counter", - * Local MAC Address || Time) - */ - os_memcpy(buf, wpa_auth->addr, ETH_ALEN); - wpa_get_ntp_timestamp(buf + ETH_ALEN); - os_memcpy(buf + ETH_ALEN + 8, &group, sizeof(group)); - if (random_get_bytes(rkey, sizeof(rkey)) < 0) - return -1; - - if (sha1_prf(rkey, sizeof(rkey), "Init Counter", buf, sizeof(buf), - group->Counter, WPA_NONCE_LEN) < 0) - return -1; - wpa_hexdump_key(MSG_DEBUG, "Key Counter", - group->Counter, WPA_NONCE_LEN); - - return 0; -} - - -static struct wpa_group * wpa_group_init(struct wpa_authenticator *wpa_auth, - int vlan_id) -{ - struct wpa_group *group; - - group = os_zalloc(sizeof(struct wpa_group)); - if (group == NULL) - return NULL; - - group->GTKAuthenticator = TRUE; - group->vlan_id = vlan_id; - - wpa_group_set_key_len(group, wpa_auth->conf.wpa_group); - - if (random_pool_ready() != 1) { - wpa_printf(MSG_INFO, "WPA: Not enough entropy in random pool " - "for secure operations - update keys later when " - "the first station connects"); - } - - /* - * Set initial GMK/Counter value here. The actual values that will be - * used in negotiations will be set once the first station tries to - * connect. This allows more time for collecting additional randomness - * on embedded devices. - */ - if (wpa_group_init_gmk_and_counter(wpa_auth, group) < 0) { - wpa_printf(MSG_ERROR, "Failed to get random data for WPA " - "initialization."); - os_free(group); - return NULL; - } - - group->GInit = TRUE; - wpa_group_sm_step(wpa_auth, group); - group->GInit = FALSE; - wpa_group_sm_step(wpa_auth, group); - - return group; -} - - -/** - * wpa_init - Initialize WPA authenticator - * @addr: Authenticator address - * @conf: Configuration for WPA authenticator - * @cb: Callback functions for WPA authenticator - * Returns: Pointer to WPA authenticator data or %NULL on failure - */ -struct wpa_authenticator * wpa_init(const u8 *addr, - struct wpa_auth_config *conf, - struct wpa_auth_callbacks *cb) -{ - struct wpa_authenticator *wpa_auth; - - wpa_auth = os_zalloc(sizeof(struct wpa_authenticator)); - if (wpa_auth == NULL) - return NULL; - os_memcpy(wpa_auth->addr, addr, ETH_ALEN); - os_memcpy(&wpa_auth->conf, conf, sizeof(*conf)); - os_memcpy(&wpa_auth->cb, cb, sizeof(*cb)); - - if (wpa_auth_gen_wpa_ie(wpa_auth)) { - wpa_printf(MSG_ERROR, "Could not generate WPA IE."); - os_free(wpa_auth); - return NULL; - } - - wpa_auth->group = wpa_group_init(wpa_auth, 0); - if (wpa_auth->group == NULL) { - os_free(wpa_auth->wpa_ie); - os_free(wpa_auth); - return NULL; - } - - wpa_auth->pmksa = pmksa_cache_auth_init(wpa_auth_pmksa_free_cb, - wpa_auth); - if (wpa_auth->pmksa == NULL) { - wpa_printf(MSG_ERROR, "PMKSA cache initialization failed."); - os_free(wpa_auth->wpa_ie); - os_free(wpa_auth); - return NULL; - } - -#ifdef CONFIG_IEEE80211R - wpa_auth->ft_pmk_cache = wpa_ft_pmk_cache_init(); - if (wpa_auth->ft_pmk_cache == NULL) { - wpa_printf(MSG_ERROR, "FT PMK cache initialization failed."); - os_free(wpa_auth->wpa_ie); - pmksa_cache_auth_deinit(wpa_auth->pmksa); - os_free(wpa_auth); - return NULL; - } -#endif /* CONFIG_IEEE80211R */ - - if (wpa_auth->conf.wpa_gmk_rekey) { - eloop_register_timeout(wpa_auth->conf.wpa_gmk_rekey, 0, - wpa_rekey_gmk, wpa_auth, NULL); - } - - if (wpa_auth->conf.wpa_group_rekey) { - eloop_register_timeout(wpa_auth->conf.wpa_group_rekey, 0, - wpa_rekey_gtk, wpa_auth, NULL); - } - - return wpa_auth; -} - - -/** - * wpa_deinit - Deinitialize WPA authenticator - * @wpa_auth: Pointer to WPA authenticator data from wpa_init() - */ -void wpa_deinit(struct wpa_authenticator *wpa_auth) -{ - struct wpa_group *group, *prev; - - eloop_cancel_timeout(wpa_rekey_gmk, wpa_auth, NULL); - eloop_cancel_timeout(wpa_rekey_gtk, wpa_auth, NULL); - -#ifdef CONFIG_PEERKEY - while (wpa_auth->stsl_negotiations) - wpa_stsl_remove(wpa_auth, wpa_auth->stsl_negotiations); -#endif /* CONFIG_PEERKEY */ - - pmksa_cache_auth_deinit(wpa_auth->pmksa); - -#ifdef CONFIG_IEEE80211R - wpa_ft_pmk_cache_deinit(wpa_auth->ft_pmk_cache); - wpa_auth->ft_pmk_cache = NULL; -#endif /* CONFIG_IEEE80211R */ - - os_free(wpa_auth->wpa_ie); - - group = wpa_auth->group; - while (group) { - prev = group; - group = group->next; - os_free(prev); - } - - os_free(wpa_auth); -} - - -/** - * wpa_reconfig - Update WPA authenticator configuration - * @wpa_auth: Pointer to WPA authenticator data from wpa_init() - * @conf: Configuration for WPA authenticator - */ -int wpa_reconfig(struct wpa_authenticator *wpa_auth, - struct wpa_auth_config *conf) -{ - struct wpa_group *group; - if (wpa_auth == NULL) - return 0; - - os_memcpy(&wpa_auth->conf, conf, sizeof(*conf)); - if (wpa_auth_gen_wpa_ie(wpa_auth)) { - wpa_printf(MSG_ERROR, "Could not generate WPA IE."); - return -1; - } - - /* - * Reinitialize GTK to make sure it is suitable for the new - * configuration. - */ - group = wpa_auth->group; - wpa_group_set_key_len(group, wpa_auth->conf.wpa_group); - group->GInit = TRUE; - wpa_group_sm_step(wpa_auth, group); - group->GInit = FALSE; - wpa_group_sm_step(wpa_auth, group); - - return 0; -} - - -struct wpa_state_machine * -wpa_auth_sta_init(struct wpa_authenticator *wpa_auth, const u8 *addr) -{ - struct wpa_state_machine *sm; - - sm = os_zalloc(sizeof(struct wpa_state_machine)); - if (sm == NULL) - return NULL; - os_memcpy(sm->addr, addr, ETH_ALEN); - - sm->wpa_auth = wpa_auth; - sm->group = wpa_auth->group; - - return sm; -} - - -int wpa_auth_sta_associated(struct wpa_authenticator *wpa_auth, - struct wpa_state_machine *sm) -{ - if (wpa_auth == NULL || !wpa_auth->conf.wpa || sm == NULL) - return -1; - -#ifdef CONFIG_IEEE80211R - if (sm->ft_completed) { - wpa_auth_logger(wpa_auth, sm->addr, LOGGER_DEBUG, - "FT authentication already completed - do not " - "start 4-way handshake"); - return 0; - } -#endif /* CONFIG_IEEE80211R */ - - if (sm->started) { - os_memset(&sm->key_replay, 0, sizeof(sm->key_replay)); - sm->ReAuthenticationRequest = TRUE; - return wpa_sm_step(sm); - } - - wpa_auth_logger(wpa_auth, sm->addr, LOGGER_DEBUG, - "start authentication"); - sm->started = 1; - - sm->Init = TRUE; - if (wpa_sm_step(sm) == 1) - return 1; /* should not really happen */ - sm->Init = FALSE; - sm->AuthenticationRequest = TRUE; - return wpa_sm_step(sm); -} - - -void wpa_auth_sta_no_wpa(struct wpa_state_machine *sm) -{ - /* WPA/RSN was not used - clear WPA state. This is needed if the STA - * reassociates back to the same AP while the previous entry for the - * STA has not yet been removed. */ - if (sm == NULL) - return; - - sm->wpa_key_mgmt = 0; -} - - -static void wpa_free_sta_sm(struct wpa_state_machine *sm) -{ - if (sm->GUpdateStationKeys) { - sm->group->GKeyDoneStations--; - sm->GUpdateStationKeys = FALSE; - } -#ifdef CONFIG_IEEE80211R - os_free(sm->assoc_resp_ftie); -#endif /* CONFIG_IEEE80211R */ - os_free(sm->last_rx_eapol_key); - os_free(sm->wpa_ie); - os_free(sm); -} - - -void wpa_auth_sta_deinit(struct wpa_state_machine *sm) -{ - if (sm == NULL) - return; - - if (sm->wpa_auth->conf.wpa_strict_rekey && sm->has_GTK) { - wpa_auth_logger(sm->wpa_auth, sm->addr, LOGGER_DEBUG, - "strict rekeying - force GTK rekey since STA " - "is leaving"); - eloop_cancel_timeout(wpa_rekey_gtk, sm->wpa_auth, NULL); - eloop_register_timeout(0, 500000, wpa_rekey_gtk, sm->wpa_auth, - NULL); - } - - eloop_cancel_timeout(wpa_send_eapol_timeout, sm->wpa_auth, sm); - sm->pending_1_of_4_timeout = 0; - eloop_cancel_timeout(wpa_sm_call_step, sm, NULL); - eloop_cancel_timeout(wpa_rekey_ptk, sm->wpa_auth, sm); - if (sm->in_step_loop) { - /* Must not free state machine while wpa_sm_step() is running. - * Freeing will be completed in the end of wpa_sm_step(). */ - wpa_printf(MSG_DEBUG, "WPA: Registering pending STA state " - "machine deinit for " MACSTR, MAC2STR(sm->addr)); - sm->pending_deinit = 1; - } else - wpa_free_sta_sm(sm); -} - - -static void wpa_request_new_ptk(struct wpa_state_machine *sm) -{ - if (sm == NULL) - return; - - sm->PTKRequest = TRUE; - sm->PTK_valid = 0; -} - - -static int wpa_replay_counter_valid(struct wpa_state_machine *sm, - const u8 *replay_counter) -{ - int i; - for (i = 0; i < RSNA_MAX_EAPOL_RETRIES; i++) { - if (!sm->key_replay[i].valid) - break; - if (os_memcmp(replay_counter, sm->key_replay[i].counter, - WPA_REPLAY_COUNTER_LEN) == 0) - return 1; - } - return 0; -} - - -#ifdef CONFIG_IEEE80211R -static int ft_check_msg_2_of_4(struct wpa_authenticator *wpa_auth, - struct wpa_state_machine *sm, - struct wpa_eapol_ie_parse *kde) -{ - struct wpa_ie_data ie; - struct rsn_mdie *mdie; - - if (wpa_parse_wpa_ie_rsn(kde->rsn_ie, kde->rsn_ie_len, &ie) < 0 || - ie.num_pmkid != 1 || ie.pmkid == NULL) { - wpa_printf(MSG_DEBUG, "FT: No PMKR1Name in " - "FT 4-way handshake message 2/4"); - return -1; - } - - os_memcpy(sm->sup_pmk_r1_name, ie.pmkid, PMKID_LEN); - wpa_hexdump(MSG_DEBUG, "FT: PMKR1Name from Supplicant", - sm->sup_pmk_r1_name, PMKID_LEN); - - if (!kde->mdie || !kde->ftie) { - wpa_printf(MSG_DEBUG, "FT: No %s in FT 4-way handshake " - "message 2/4", kde->mdie ? "FTIE" : "MDIE"); - return -1; - } - - mdie = (struct rsn_mdie *) (kde->mdie + 2); - if (kde->mdie[1] < sizeof(struct rsn_mdie) || - os_memcmp(wpa_auth->conf.mobility_domain, mdie->mobility_domain, - MOBILITY_DOMAIN_ID_LEN) != 0) { - wpa_printf(MSG_DEBUG, "FT: MDIE mismatch"); - return -1; - } - - if (sm->assoc_resp_ftie && - (kde->ftie[1] != sm->assoc_resp_ftie[1] || - os_memcmp(kde->ftie, sm->assoc_resp_ftie, - 2 + sm->assoc_resp_ftie[1]) != 0)) { - wpa_printf(MSG_DEBUG, "FT: FTIE mismatch"); - wpa_hexdump(MSG_DEBUG, "FT: FTIE in EAPOL-Key msg 2/4", - kde->ftie, kde->ftie_len); - wpa_hexdump(MSG_DEBUG, "FT: FTIE in (Re)AssocResp", - sm->assoc_resp_ftie, 2 + sm->assoc_resp_ftie[1]); - return -1; - } - - return 0; -} -#endif /* CONFIG_IEEE80211R */ - - -void wpa_receive(struct wpa_authenticator *wpa_auth, - struct wpa_state_machine *sm, - u8 *data, size_t data_len) -{ - struct ieee802_1x_hdr *hdr; - struct wpa_eapol_key *key; - u16 key_info, key_data_length; - enum { PAIRWISE_2, PAIRWISE_4, GROUP_2, REQUEST, - SMK_M1, SMK_M3, SMK_ERROR } msg; - char *msgtxt; - struct wpa_eapol_ie_parse kde; - int ft; - const u8 *eapol_key_ie; - size_t eapol_key_ie_len; - - if (wpa_auth == NULL || !wpa_auth->conf.wpa || sm == NULL) - return; - - if (data_len < sizeof(*hdr) + sizeof(*key)) - return; - - hdr = (struct ieee802_1x_hdr *) data; - key = (struct wpa_eapol_key *) (hdr + 1); - key_info = WPA_GET_BE16(key->key_info); - key_data_length = WPA_GET_BE16(key->key_data_length); - if (key_data_length > data_len - sizeof(*hdr) - sizeof(*key)) { - wpa_printf(MSG_INFO, "WPA: Invalid EAPOL-Key frame - " - "key_data overflow (%d > %lu)", - key_data_length, - (unsigned long) (data_len - sizeof(*hdr) - - sizeof(*key))); - return; - } - - if (sm->wpa == WPA_VERSION_WPA2) { - if (key->type != EAPOL_KEY_TYPE_RSN) { - wpa_printf(MSG_DEBUG, "Ignore EAPOL-Key with " - "unexpected type %d in RSN mode", - key->type); - return; - } - } else { - if (key->type != EAPOL_KEY_TYPE_WPA) { - wpa_printf(MSG_DEBUG, "Ignore EAPOL-Key with " - "unexpected type %d in WPA mode", - key->type); - return; - } - } - - wpa_hexdump(MSG_DEBUG, "WPA: Received Key Nonce", key->key_nonce, - WPA_NONCE_LEN); - wpa_hexdump(MSG_DEBUG, "WPA: Received Replay Counter", - key->replay_counter, WPA_REPLAY_COUNTER_LEN); - - /* FIX: verify that the EAPOL-Key frame was encrypted if pairwise keys - * are set */ - - if ((key_info & (WPA_KEY_INFO_SMK_MESSAGE | WPA_KEY_INFO_REQUEST)) == - (WPA_KEY_INFO_SMK_MESSAGE | WPA_KEY_INFO_REQUEST)) { - if (key_info & WPA_KEY_INFO_ERROR) { - msg = SMK_ERROR; - msgtxt = "SMK Error"; - } else { - msg = SMK_M1; - msgtxt = "SMK M1"; - } - } else if (key_info & WPA_KEY_INFO_SMK_MESSAGE) { - msg = SMK_M3; - msgtxt = "SMK M3"; - } else if (key_info & WPA_KEY_INFO_REQUEST) { - msg = REQUEST; - msgtxt = "Request"; - } else if (!(key_info & WPA_KEY_INFO_KEY_TYPE)) { - msg = GROUP_2; - msgtxt = "2/2 Group"; - } else if (key_data_length == 0) { - msg = PAIRWISE_4; - msgtxt = "4/4 Pairwise"; - } else { - msg = PAIRWISE_2; - msgtxt = "2/4 Pairwise"; - } - - /* TODO: key_info type validation for PeerKey */ - if (msg == REQUEST || msg == PAIRWISE_2 || msg == PAIRWISE_4 || - msg == GROUP_2) { - u16 ver = key_info & WPA_KEY_INFO_TYPE_MASK; - if (sm->pairwise == WPA_CIPHER_CCMP) { - if (wpa_use_aes_cmac(sm) && - ver != WPA_KEY_INFO_TYPE_AES_128_CMAC) { - wpa_auth_logger(wpa_auth, sm->addr, - LOGGER_WARNING, - "advertised support for " - "AES-128-CMAC, but did not " - "use it"); - return; - } - - if (!wpa_use_aes_cmac(sm) && - ver != WPA_KEY_INFO_TYPE_HMAC_SHA1_AES) { - wpa_auth_logger(wpa_auth, sm->addr, - LOGGER_WARNING, - "did not use HMAC-SHA1-AES " - "with CCMP"); - return; - } - } - } - - if (key_info & WPA_KEY_INFO_REQUEST) { - if (sm->req_replay_counter_used && - os_memcmp(key->replay_counter, sm->req_replay_counter, - WPA_REPLAY_COUNTER_LEN) <= 0) { - wpa_auth_logger(wpa_auth, sm->addr, LOGGER_WARNING, - "received EAPOL-Key request with " - "replayed counter"); - return; - } - } - - if (!(key_info & WPA_KEY_INFO_REQUEST) && - !wpa_replay_counter_valid(sm, key->replay_counter)) { - int i; - wpa_auth_vlogger(wpa_auth, sm->addr, LOGGER_INFO, - "received EAPOL-Key %s with unexpected " - "replay counter", msgtxt); - for (i = 0; i < RSNA_MAX_EAPOL_RETRIES; i++) { - if (!sm->key_replay[i].valid) - break; - wpa_hexdump(MSG_DEBUG, "pending replay counter", - sm->key_replay[i].counter, - WPA_REPLAY_COUNTER_LEN); - } - wpa_hexdump(MSG_DEBUG, "received replay counter", - key->replay_counter, WPA_REPLAY_COUNTER_LEN); - return; - } - - switch (msg) { - case PAIRWISE_2: - if (sm->wpa_ptk_state != WPA_PTK_PTKSTART && - sm->wpa_ptk_state != WPA_PTK_PTKCALCNEGOTIATING) { - wpa_auth_vlogger(wpa_auth, sm->addr, LOGGER_INFO, - "received EAPOL-Key msg 2/4 in " - "invalid state (%d) - dropped", - sm->wpa_ptk_state); - return; - } - random_add_randomness(key->key_nonce, WPA_NONCE_LEN); - if (sm->group->reject_4way_hs_for_entropy) { - /* - * The system did not have enough entropy to generate - * strong random numbers. Reject the first 4-way - * handshake(s) and collect some entropy based on the - * information from it. Once enough entropy is - * available, the next atempt will trigger GMK/Key - * Counter update and the station will be allowed to - * continue. - */ - wpa_printf(MSG_DEBUG, "WPA: Reject 4-way handshake to " - "collect more entropy for random number " - "generation"); - sm->group->reject_4way_hs_for_entropy = FALSE; - random_mark_pool_ready(); - sm->group->first_sta_seen = FALSE; - wpa_sta_disconnect(wpa_auth, sm->addr); - return; - } - if (wpa_parse_kde_ies((u8 *) (key + 1), key_data_length, - &kde) < 0) { - wpa_auth_vlogger(wpa_auth, sm->addr, LOGGER_INFO, - "received EAPOL-Key msg 2/4 with " - "invalid Key Data contents"); - return; - } - if (kde.rsn_ie) { - eapol_key_ie = kde.rsn_ie; - eapol_key_ie_len = kde.rsn_ie_len; - } else { - eapol_key_ie = kde.wpa_ie; - eapol_key_ie_len = kde.wpa_ie_len; - } - ft = sm->wpa == WPA_VERSION_WPA2 && - wpa_key_mgmt_ft(sm->wpa_key_mgmt); - if (sm->wpa_ie == NULL || - wpa_compare_rsn_ie(ft, - sm->wpa_ie, sm->wpa_ie_len, - eapol_key_ie, eapol_key_ie_len)) { - wpa_auth_logger(wpa_auth, sm->addr, LOGGER_INFO, - "WPA IE from (Re)AssocReq did not " - "match with msg 2/4"); - if (sm->wpa_ie) { - wpa_hexdump(MSG_DEBUG, "WPA IE in AssocReq", - sm->wpa_ie, sm->wpa_ie_len); - } - wpa_hexdump(MSG_DEBUG, "WPA IE in msg 2/4", - eapol_key_ie, eapol_key_ie_len); - /* MLME-DEAUTHENTICATE.request */ - wpa_sta_disconnect(wpa_auth, sm->addr); - return; - } -#ifdef CONFIG_IEEE80211R - if (ft && ft_check_msg_2_of_4(wpa_auth, sm, &kde) < 0) { - wpa_sta_disconnect(wpa_auth, sm->addr); - return; - } -#endif /* CONFIG_IEEE80211R */ - break; - case PAIRWISE_4: - if (sm->wpa_ptk_state != WPA_PTK_PTKINITNEGOTIATING || - !sm->PTK_valid) { - wpa_auth_vlogger(wpa_auth, sm->addr, LOGGER_INFO, - "received EAPOL-Key msg 4/4 in " - "invalid state (%d) - dropped", - sm->wpa_ptk_state); - return; - } - break; - case GROUP_2: - if (sm->wpa_ptk_group_state != WPA_PTK_GROUP_REKEYNEGOTIATING - || !sm->PTK_valid) { - wpa_auth_vlogger(wpa_auth, sm->addr, LOGGER_INFO, - "received EAPOL-Key msg 2/2 in " - "invalid state (%d) - dropped", - sm->wpa_ptk_group_state); - return; - } - break; -#ifdef CONFIG_PEERKEY - case SMK_M1: - case SMK_M3: - case SMK_ERROR: - if (!wpa_auth->conf.peerkey) { - wpa_printf(MSG_DEBUG, "RSN: SMK M1/M3/Error, but " - "PeerKey use disabled - ignoring message"); - return; - } - if (!sm->PTK_valid) { - wpa_auth_logger(wpa_auth, sm->addr, LOGGER_INFO, - "received EAPOL-Key msg SMK in " - "invalid state - dropped"); - return; - } - break; -#else /* CONFIG_PEERKEY */ - case SMK_M1: - case SMK_M3: - case SMK_ERROR: - return; /* STSL disabled - ignore SMK messages */ -#endif /* CONFIG_PEERKEY */ - case REQUEST: - break; - } - - wpa_auth_vlogger(wpa_auth, sm->addr, LOGGER_DEBUG, - "received EAPOL-Key frame (%s)", msgtxt); - - if (key_info & WPA_KEY_INFO_ACK) { - wpa_auth_logger(wpa_auth, sm->addr, LOGGER_INFO, - "received invalid EAPOL-Key: Key Ack set"); - return; - } - - if (!(key_info & WPA_KEY_INFO_MIC)) { - wpa_auth_logger(wpa_auth, sm->addr, LOGGER_INFO, - "received invalid EAPOL-Key: Key MIC not set"); - return; - } - - sm->MICVerified = FALSE; - if (sm->PTK_valid) { - if (wpa_verify_key_mic(&sm->PTK, data, data_len)) { - wpa_auth_logger(wpa_auth, sm->addr, LOGGER_INFO, - "received EAPOL-Key with invalid MIC"); - return; - } - sm->MICVerified = TRUE; - eloop_cancel_timeout(wpa_send_eapol_timeout, wpa_auth, sm); - sm->pending_1_of_4_timeout = 0; - } - - if (key_info & WPA_KEY_INFO_REQUEST) { - if (sm->MICVerified) { - sm->req_replay_counter_used = 1; - os_memcpy(sm->req_replay_counter, key->replay_counter, - WPA_REPLAY_COUNTER_LEN); - } else { - wpa_auth_logger(wpa_auth, sm->addr, LOGGER_INFO, - "received EAPOL-Key request with " - "invalid MIC"); - return; - } - - /* - * TODO: should decrypt key data field if encryption was used; - * even though MAC address KDE is not normally encrypted, - * supplicant is allowed to encrypt it. - */ - if (msg == SMK_ERROR) { -#ifdef CONFIG_PEERKEY - wpa_smk_error(wpa_auth, sm, key); -#endif /* CONFIG_PEERKEY */ - return; - } else if (key_info & WPA_KEY_INFO_ERROR) { - /* Supplicant reported a Michael MIC error */ - wpa_auth_logger(wpa_auth, sm->addr, LOGGER_INFO, - "received EAPOL-Key Error Request " - "(STA detected Michael MIC failure)"); - wpa_auth_mic_failure_report(wpa_auth, sm->addr); - sm->dot11RSNAStatsTKIPRemoteMICFailures++; - wpa_auth->dot11RSNAStatsTKIPRemoteMICFailures++; - /* Error report is not a request for a new key - * handshake, but since Authenticator may do it, let's - * change the keys now anyway. */ - wpa_request_new_ptk(sm); - } else if (key_info & WPA_KEY_INFO_KEY_TYPE) { - wpa_auth_logger(wpa_auth, sm->addr, LOGGER_INFO, - "received EAPOL-Key Request for new " - "4-Way Handshake"); - wpa_request_new_ptk(sm); -#ifdef CONFIG_PEERKEY - } else if (msg == SMK_M1) { - wpa_smk_m1(wpa_auth, sm, key); -#endif /* CONFIG_PEERKEY */ - } else if (key_data_length > 0 && - wpa_parse_kde_ies((const u8 *) (key + 1), - key_data_length, &kde) == 0 && - kde.mac_addr) { - } else { - wpa_auth_logger(wpa_auth, sm->addr, LOGGER_INFO, - "received EAPOL-Key Request for GTK " - "rekeying"); - /* FIX: why was this triggering PTK rekeying for the - * STA that requested Group Key rekeying?? */ - /* wpa_request_new_ptk(sta->wpa_sm); */ - eloop_cancel_timeout(wpa_rekey_gtk, wpa_auth, NULL); - wpa_rekey_gtk(wpa_auth, NULL); - } - } else { - /* Do not allow the same key replay counter to be reused. This - * does also invalidate all other pending replay counters if - * retransmissions were used, i.e., we will only process one of - * the pending replies and ignore rest if more than one is - * received. */ - sm->key_replay[0].valid = FALSE; - } - -#ifdef CONFIG_PEERKEY - if (msg == SMK_M3) { - wpa_smk_m3(wpa_auth, sm, key); - return; - } -#endif /* CONFIG_PEERKEY */ - - os_free(sm->last_rx_eapol_key); - sm->last_rx_eapol_key = os_malloc(data_len); - if (sm->last_rx_eapol_key == NULL) - return; - os_memcpy(sm->last_rx_eapol_key, data, data_len); - sm->last_rx_eapol_key_len = data_len; - - sm->EAPOLKeyReceived = TRUE; - sm->EAPOLKeyPairwise = !!(key_info & WPA_KEY_INFO_KEY_TYPE); - sm->EAPOLKeyRequest = !!(key_info & WPA_KEY_INFO_REQUEST); - os_memcpy(sm->SNonce, key->key_nonce, WPA_NONCE_LEN); - wpa_sm_step(sm); -} - - -static int wpa_gmk_to_gtk(const u8 *gmk, const char *label, const u8 *addr, - const u8 *gnonce, u8 *gtk, size_t gtk_len) -{ - u8 data[ETH_ALEN + WPA_NONCE_LEN + 8 + 16]; - u8 *pos; - int ret = 0; - - /* GTK = PRF-X(GMK, "Group key expansion", - * AA || GNonce || Time || random data) - * The example described in the IEEE 802.11 standard uses only AA and - * GNonce as inputs here. Add some more entropy since this derivation - * is done only at the Authenticator and as such, does not need to be - * exactly same. - */ - os_memcpy(data, addr, ETH_ALEN); - os_memcpy(data + ETH_ALEN, gnonce, WPA_NONCE_LEN); - pos = data + ETH_ALEN + WPA_NONCE_LEN; - wpa_get_ntp_timestamp(pos); - pos += 8; - if (random_get_bytes(pos, 16) < 0) - ret = -1; - -#ifdef CONFIG_IEEE80211W - sha256_prf(gmk, WPA_GMK_LEN, label, data, sizeof(data), gtk, gtk_len); -#else /* CONFIG_IEEE80211W */ - if (sha1_prf(gmk, WPA_GMK_LEN, label, data, sizeof(data), gtk, gtk_len) - < 0) - ret = -1; -#endif /* CONFIG_IEEE80211W */ - - return ret; -} - - -static void wpa_send_eapol_timeout(void *eloop_ctx, void *timeout_ctx) -{ - struct wpa_authenticator *wpa_auth = eloop_ctx; - struct wpa_state_machine *sm = timeout_ctx; - - sm->pending_1_of_4_timeout = 0; - wpa_auth_logger(wpa_auth, sm->addr, LOGGER_DEBUG, "EAPOL-Key timeout"); - sm->TimeoutEvt = TRUE; - wpa_sm_step(sm); -} - - -void __wpa_send_eapol(struct wpa_authenticator *wpa_auth, - struct wpa_state_machine *sm, int key_info, - const u8 *key_rsc, const u8 *nonce, - const u8 *kde, size_t kde_len, - int keyidx, int encr, int force_version) -{ - struct ieee802_1x_hdr *hdr; - struct wpa_eapol_key *key; - size_t len; - int alg; - int key_data_len, pad_len = 0; - u8 *buf, *pos; - int version, pairwise; - int i; - - len = sizeof(struct ieee802_1x_hdr) + sizeof(struct wpa_eapol_key); - - if (force_version) - version = force_version; - else if (wpa_use_aes_cmac(sm)) - version = WPA_KEY_INFO_TYPE_AES_128_CMAC; - else if (sm->pairwise == WPA_CIPHER_CCMP) - version = WPA_KEY_INFO_TYPE_HMAC_SHA1_AES; - else - version = WPA_KEY_INFO_TYPE_HMAC_MD5_RC4; - - pairwise = key_info & WPA_KEY_INFO_KEY_TYPE; - - wpa_printf(MSG_DEBUG, "WPA: Send EAPOL(version=%d secure=%d mic=%d " - "ack=%d install=%d pairwise=%d kde_len=%lu keyidx=%d " - "encr=%d)", - version, - (key_info & WPA_KEY_INFO_SECURE) ? 1 : 0, - (key_info & WPA_KEY_INFO_MIC) ? 1 : 0, - (key_info & WPA_KEY_INFO_ACK) ? 1 : 0, - (key_info & WPA_KEY_INFO_INSTALL) ? 1 : 0, - pairwise, (unsigned long) kde_len, keyidx, encr); - - key_data_len = kde_len; - - if ((version == WPA_KEY_INFO_TYPE_HMAC_SHA1_AES || - version == WPA_KEY_INFO_TYPE_AES_128_CMAC) && encr) { - pad_len = key_data_len % 8; - if (pad_len) - pad_len = 8 - pad_len; - key_data_len += pad_len + 8; - } - - len += key_data_len; - - hdr = os_zalloc(len); - if (hdr == NULL) - return; - hdr->version = wpa_auth->conf.eapol_version; - hdr->type = IEEE802_1X_TYPE_EAPOL_KEY; - hdr->length = host_to_be16(len - sizeof(*hdr)); - key = (struct wpa_eapol_key *) (hdr + 1); - - key->type = sm->wpa == WPA_VERSION_WPA2 ? - EAPOL_KEY_TYPE_RSN : EAPOL_KEY_TYPE_WPA; - key_info |= version; - if (encr && sm->wpa == WPA_VERSION_WPA2) - key_info |= WPA_KEY_INFO_ENCR_KEY_DATA; - if (sm->wpa != WPA_VERSION_WPA2) - key_info |= keyidx << WPA_KEY_INFO_KEY_INDEX_SHIFT; - WPA_PUT_BE16(key->key_info, key_info); - - alg = pairwise ? sm->pairwise : wpa_auth->conf.wpa_group; - switch (alg) { - case WPA_CIPHER_CCMP: - WPA_PUT_BE16(key->key_length, 16); - break; - case WPA_CIPHER_TKIP: - WPA_PUT_BE16(key->key_length, 32); - break; - case WPA_CIPHER_WEP40: - WPA_PUT_BE16(key->key_length, 5); - break; - case WPA_CIPHER_WEP104: - WPA_PUT_BE16(key->key_length, 13); - break; - } - if (key_info & WPA_KEY_INFO_SMK_MESSAGE) - WPA_PUT_BE16(key->key_length, 0); - - /* FIX: STSL: what to use as key_replay_counter? */ - for (i = RSNA_MAX_EAPOL_RETRIES - 1; i > 0; i--) { - sm->key_replay[i].valid = sm->key_replay[i - 1].valid; - os_memcpy(sm->key_replay[i].counter, - sm->key_replay[i - 1].counter, - WPA_REPLAY_COUNTER_LEN); - } - inc_byte_array(sm->key_replay[0].counter, WPA_REPLAY_COUNTER_LEN); - os_memcpy(key->replay_counter, sm->key_replay[0].counter, - WPA_REPLAY_COUNTER_LEN); - sm->key_replay[0].valid = TRUE; - - if (nonce) - os_memcpy(key->key_nonce, nonce, WPA_NONCE_LEN); - - if (key_rsc) - os_memcpy(key->key_rsc, key_rsc, WPA_KEY_RSC_LEN); - - if (kde && !encr) { - os_memcpy(key + 1, kde, kde_len); - WPA_PUT_BE16(key->key_data_length, kde_len); - } else if (encr && kde) { - buf = os_zalloc(key_data_len); - if (buf == NULL) { - os_free(hdr); - return; - } - pos = buf; - os_memcpy(pos, kde, kde_len); - pos += kde_len; - - if (pad_len) - *pos++ = 0xdd; - - wpa_hexdump_key(MSG_DEBUG, "Plaintext EAPOL-Key Key Data", - buf, key_data_len); - if (version == WPA_KEY_INFO_TYPE_HMAC_SHA1_AES || - version == WPA_KEY_INFO_TYPE_AES_128_CMAC) { - if (aes_wrap(sm->PTK.kek, (key_data_len - 8) / 8, buf, - (u8 *) (key + 1))) { - os_free(hdr); - os_free(buf); - return; - } - WPA_PUT_BE16(key->key_data_length, key_data_len); - } else { - u8 ek[32]; - os_memcpy(key->key_iv, - sm->group->Counter + WPA_NONCE_LEN - 16, 16); - inc_byte_array(sm->group->Counter, WPA_NONCE_LEN); - os_memcpy(ek, key->key_iv, 16); - os_memcpy(ek + 16, sm->PTK.kek, 16); - os_memcpy(key + 1, buf, key_data_len); - rc4_skip(ek, 32, 256, (u8 *) (key + 1), key_data_len); - WPA_PUT_BE16(key->key_data_length, key_data_len); - } - os_free(buf); - } - - if (key_info & WPA_KEY_INFO_MIC) { - if (!sm->PTK_valid) { - wpa_auth_logger(wpa_auth, sm->addr, LOGGER_DEBUG, - "PTK not valid when sending EAPOL-Key " - "frame"); - os_free(hdr); - return; - } - wpa_eapol_key_mic(sm->PTK.kck, version, (u8 *) hdr, len, - key->key_mic); - } - - wpa_auth_set_eapol(sm->wpa_auth, sm->addr, WPA_EAPOL_inc_EapolFramesTx, - 1); - wpa_auth_send_eapol(wpa_auth, sm->addr, (u8 *) hdr, len, - sm->pairwise_set); - os_free(hdr); -} - - -static void wpa_send_eapol(struct wpa_authenticator *wpa_auth, - struct wpa_state_machine *sm, int key_info, - const u8 *key_rsc, const u8 *nonce, - const u8 *kde, size_t kde_len, - int keyidx, int encr) -{ - int timeout_ms; - int pairwise = key_info & WPA_KEY_INFO_KEY_TYPE; - int ctr; - - if (sm == NULL) - return; - - __wpa_send_eapol(wpa_auth, sm, key_info, key_rsc, nonce, kde, kde_len, - keyidx, encr, 0); - - ctr = pairwise ? sm->TimeoutCtr : sm->GTimeoutCtr; - if (ctr == 1 && wpa_auth->conf.tx_status) - timeout_ms = eapol_key_timeout_first; - else - timeout_ms = eapol_key_timeout_subseq; - if (pairwise && ctr == 1 && !(key_info & WPA_KEY_INFO_MIC)) - sm->pending_1_of_4_timeout = 1; - wpa_printf(MSG_DEBUG, "WPA: Use EAPOL-Key timeout of %u ms (retry " - "counter %d)", timeout_ms, ctr); - eloop_register_timeout(timeout_ms / 1000, (timeout_ms % 1000) * 1000, - wpa_send_eapol_timeout, wpa_auth, sm); -} - - -static int wpa_verify_key_mic(struct wpa_ptk *PTK, u8 *data, size_t data_len) -{ - struct ieee802_1x_hdr *hdr; - struct wpa_eapol_key *key; - u16 key_info; - int ret = 0; - u8 mic[16]; - - if (data_len < sizeof(*hdr) + sizeof(*key)) - return -1; - - hdr = (struct ieee802_1x_hdr *) data; - key = (struct wpa_eapol_key *) (hdr + 1); - key_info = WPA_GET_BE16(key->key_info); - os_memcpy(mic, key->key_mic, 16); - os_memset(key->key_mic, 0, 16); - if (wpa_eapol_key_mic(PTK->kck, key_info & WPA_KEY_INFO_TYPE_MASK, - data, data_len, key->key_mic) || - os_memcmp(mic, key->key_mic, 16) != 0) - ret = -1; - os_memcpy(key->key_mic, mic, 16); - return ret; -} - - -void wpa_remove_ptk(struct wpa_state_machine *sm) -{ - sm->PTK_valid = FALSE; - os_memset(&sm->PTK, 0, sizeof(sm->PTK)); - wpa_auth_set_key(sm->wpa_auth, 0, WPA_ALG_NONE, sm->addr, 0, NULL, 0); - sm->pairwise_set = FALSE; - eloop_cancel_timeout(wpa_rekey_ptk, sm->wpa_auth, sm); -} - - -int wpa_auth_sm_event(struct wpa_state_machine *sm, wpa_event event) -{ - int remove_ptk = 1; - - if (sm == NULL) - return -1; - - wpa_auth_vlogger(sm->wpa_auth, sm->addr, LOGGER_DEBUG, - "event %d notification", event); - - switch (event) { - case WPA_AUTH: - case WPA_ASSOC: - break; - case WPA_DEAUTH: - case WPA_DISASSOC: - sm->DeauthenticationRequest = TRUE; - break; - case WPA_REAUTH: - case WPA_REAUTH_EAPOL: - if (!sm->started) { - /* - * When using WPS, we may end up here if the STA - * manages to re-associate without the previous STA - * entry getting removed. Consequently, we need to make - * sure that the WPA state machines gets initialized - * properly at this point. - */ - wpa_printf(MSG_DEBUG, "WPA state machine had not been " - "started - initialize now"); - sm->started = 1; - sm->Init = TRUE; - if (wpa_sm_step(sm) == 1) - return 1; /* should not really happen */ - sm->Init = FALSE; - sm->AuthenticationRequest = TRUE; - break; - } - if (sm->GUpdateStationKeys) { - /* - * Reauthentication cancels the pending group key - * update for this STA. - */ - sm->group->GKeyDoneStations--; - sm->GUpdateStationKeys = FALSE; - sm->PtkGroupInit = TRUE; - } - sm->ReAuthenticationRequest = TRUE; - break; - case WPA_ASSOC_FT: -#ifdef CONFIG_IEEE80211R - wpa_printf(MSG_DEBUG, "FT: Retry PTK configuration " - "after association"); - wpa_ft_install_ptk(sm); - - /* Using FT protocol, not WPA auth state machine */ - sm->ft_completed = 1; - return 0; -#else /* CONFIG_IEEE80211R */ - break; -#endif /* CONFIG_IEEE80211R */ - } - -#ifdef CONFIG_IEEE80211R - sm->ft_completed = 0; -#endif /* CONFIG_IEEE80211R */ - -#ifdef CONFIG_IEEE80211W - if (sm->mgmt_frame_prot && event == WPA_AUTH) - remove_ptk = 0; -#endif /* CONFIG_IEEE80211W */ - - if (remove_ptk) { - sm->PTK_valid = FALSE; - os_memset(&sm->PTK, 0, sizeof(sm->PTK)); - - if (event != WPA_REAUTH_EAPOL) - wpa_remove_ptk(sm); - } - - return wpa_sm_step(sm); -} - - -static enum wpa_alg wpa_alg_enum(int alg) -{ - switch (alg) { - case WPA_CIPHER_CCMP: - return WPA_ALG_CCMP; - case WPA_CIPHER_TKIP: - return WPA_ALG_TKIP; - case WPA_CIPHER_WEP104: - case WPA_CIPHER_WEP40: - return WPA_ALG_WEP; - default: - return WPA_ALG_NONE; - } -} - - -SM_STATE(WPA_PTK, INITIALIZE) -{ - SM_ENTRY_MA(WPA_PTK, INITIALIZE, wpa_ptk); - if (sm->Init) { - /* Init flag is not cleared here, so avoid busy - * loop by claiming nothing changed. */ - sm->changed = FALSE; - } - - sm->keycount = 0; - if (sm->GUpdateStationKeys) - sm->group->GKeyDoneStations--; - sm->GUpdateStationKeys = FALSE; - if (sm->wpa == WPA_VERSION_WPA) - sm->PInitAKeys = FALSE; - if (1 /* Unicast cipher supported AND (ESS OR ((IBSS or WDS) and - * Local AA > Remote AA)) */) { - sm->Pair = TRUE; - } - wpa_auth_set_eapol(sm->wpa_auth, sm->addr, WPA_EAPOL_portEnabled, 0); - wpa_remove_ptk(sm); - wpa_auth_set_eapol(sm->wpa_auth, sm->addr, WPA_EAPOL_portValid, 0); - sm->TimeoutCtr = 0; - if (wpa_key_mgmt_wpa_psk(sm->wpa_key_mgmt)) { - wpa_auth_set_eapol(sm->wpa_auth, sm->addr, - WPA_EAPOL_authorized, 0); - } -} - - -SM_STATE(WPA_PTK, DISCONNECT) -{ - SM_ENTRY_MA(WPA_PTK, DISCONNECT, wpa_ptk); - sm->Disconnect = FALSE; - wpa_sta_disconnect(sm->wpa_auth, sm->addr); -} - - -SM_STATE(WPA_PTK, DISCONNECTED) -{ - SM_ENTRY_MA(WPA_PTK, DISCONNECTED, wpa_ptk); - sm->DeauthenticationRequest = FALSE; -} - - -SM_STATE(WPA_PTK, AUTHENTICATION) -{ - SM_ENTRY_MA(WPA_PTK, AUTHENTICATION, wpa_ptk); - os_memset(&sm->PTK, 0, sizeof(sm->PTK)); - sm->PTK_valid = FALSE; - wpa_auth_set_eapol(sm->wpa_auth, sm->addr, WPA_EAPOL_portControl_Auto, - 1); - wpa_auth_set_eapol(sm->wpa_auth, sm->addr, WPA_EAPOL_portEnabled, 1); - sm->AuthenticationRequest = FALSE; -} - - -static void wpa_group_first_station(struct wpa_authenticator *wpa_auth, - struct wpa_group *group) -{ - /* - * System has run bit further than at the time hostapd was started - * potentially very early during boot up. This provides better chances - * of collecting more randomness on embedded systems. Re-initialize the - * GMK and Counter here to improve their strength if there was not - * enough entropy available immediately after system startup. - */ - wpa_printf(MSG_DEBUG, "WPA: Re-initialize GMK/Counter on first " - "station"); - if (random_pool_ready() != 1) { - wpa_printf(MSG_INFO, "WPA: Not enough entropy in random pool " - "to proceed - reject first 4-way handshake"); - group->reject_4way_hs_for_entropy = TRUE; - } - wpa_group_init_gmk_and_counter(wpa_auth, group); - wpa_gtk_update(wpa_auth, group); - wpa_group_config_group_keys(wpa_auth, group); -} - - -SM_STATE(WPA_PTK, AUTHENTICATION2) -{ - SM_ENTRY_MA(WPA_PTK, AUTHENTICATION2, wpa_ptk); - - if (!sm->group->first_sta_seen) { - wpa_group_first_station(sm->wpa_auth, sm->group); - sm->group->first_sta_seen = TRUE; - } - - os_memcpy(sm->ANonce, sm->group->Counter, WPA_NONCE_LEN); - wpa_hexdump(MSG_DEBUG, "WPA: Assign ANonce", sm->ANonce, - WPA_NONCE_LEN); - inc_byte_array(sm->group->Counter, WPA_NONCE_LEN); - sm->ReAuthenticationRequest = FALSE; - /* IEEE 802.11i does not clear TimeoutCtr here, but this is more - * logical place than INITIALIZE since AUTHENTICATION2 can be - * re-entered on ReAuthenticationRequest without going through - * INITIALIZE. */ - sm->TimeoutCtr = 0; -} - - -SM_STATE(WPA_PTK, INITPMK) -{ - u8 msk[2 * PMK_LEN]; - size_t len = 2 * PMK_LEN; - - SM_ENTRY_MA(WPA_PTK, INITPMK, wpa_ptk); -#ifdef CONFIG_IEEE80211R - sm->xxkey_len = 0; -#endif /* CONFIG_IEEE80211R */ - if (sm->pmksa) { - wpa_printf(MSG_DEBUG, "WPA: PMK from PMKSA cache"); - os_memcpy(sm->PMK, sm->pmksa->pmk, PMK_LEN); - } else if (wpa_auth_get_msk(sm->wpa_auth, sm->addr, msk, &len) == 0) { - wpa_printf(MSG_DEBUG, "WPA: PMK from EAPOL state machine " - "(len=%lu)", (unsigned long) len); - os_memcpy(sm->PMK, msk, PMK_LEN); -#ifdef CONFIG_IEEE80211R - if (len >= 2 * PMK_LEN) { - os_memcpy(sm->xxkey, msk + PMK_LEN, PMK_LEN); - sm->xxkey_len = PMK_LEN; - } -#endif /* CONFIG_IEEE80211R */ - } else { - wpa_printf(MSG_DEBUG, "WPA: Could not get PMK"); - } - - sm->req_replay_counter_used = 0; - /* IEEE 802.11i does not set keyRun to FALSE, but not doing this - * will break reauthentication since EAPOL state machines may not be - * get into AUTHENTICATING state that clears keyRun before WPA state - * machine enters AUTHENTICATION2 state and goes immediately to INITPMK - * state and takes PMK from the previously used AAA Key. This will - * eventually fail in 4-Way Handshake because Supplicant uses PMK - * derived from the new AAA Key. Setting keyRun = FALSE here seems to - * be good workaround for this issue. */ - wpa_auth_set_eapol(sm->wpa_auth, sm->addr, WPA_EAPOL_keyRun, 0); -} - - -SM_STATE(WPA_PTK, INITPSK) -{ - const u8 *psk; - SM_ENTRY_MA(WPA_PTK, INITPSK, wpa_ptk); - psk = wpa_auth_get_psk(sm->wpa_auth, sm->addr, NULL); - if (psk) { - os_memcpy(sm->PMK, psk, PMK_LEN); -#ifdef CONFIG_IEEE80211R - os_memcpy(sm->xxkey, psk, PMK_LEN); - sm->xxkey_len = PMK_LEN; -#endif /* CONFIG_IEEE80211R */ - } - sm->req_replay_counter_used = 0; -} - - -SM_STATE(WPA_PTK, PTKSTART) -{ - u8 buf[2 + RSN_SELECTOR_LEN + PMKID_LEN], *pmkid = NULL; - size_t pmkid_len = 0; - - SM_ENTRY_MA(WPA_PTK, PTKSTART, wpa_ptk); - sm->PTKRequest = FALSE; - sm->TimeoutEvt = FALSE; - - sm->TimeoutCtr++; - if (sm->TimeoutCtr > (int) dot11RSNAConfigPairwiseUpdateCount) { - /* No point in sending the EAPOL-Key - we will disconnect - * immediately following this. */ - return; - } - - wpa_auth_logger(sm->wpa_auth, sm->addr, LOGGER_DEBUG, - "sending 1/4 msg of 4-Way Handshake"); - /* - * TODO: Could add PMKID even with WPA2-PSK, but only if there is only - * one possible PSK for this STA. - */ - if (sm->wpa == WPA_VERSION_WPA2 && - wpa_key_mgmt_wpa_ieee8021x(sm->wpa_key_mgmt)) { - pmkid = buf; - pmkid_len = 2 + RSN_SELECTOR_LEN + PMKID_LEN; - pmkid[0] = WLAN_EID_VENDOR_SPECIFIC; - pmkid[1] = RSN_SELECTOR_LEN + PMKID_LEN; - RSN_SELECTOR_PUT(&pmkid[2], RSN_KEY_DATA_PMKID); - if (sm->pmksa) - os_memcpy(&pmkid[2 + RSN_SELECTOR_LEN], - sm->pmksa->pmkid, PMKID_LEN); - else { - /* - * Calculate PMKID since no PMKSA cache entry was - * available with pre-calculated PMKID. - */ - rsn_pmkid(sm->PMK, PMK_LEN, sm->wpa_auth->addr, - sm->addr, &pmkid[2 + RSN_SELECTOR_LEN], - wpa_key_mgmt_sha256(sm->wpa_key_mgmt)); - } - } - wpa_send_eapol(sm->wpa_auth, sm, - WPA_KEY_INFO_ACK | WPA_KEY_INFO_KEY_TYPE, NULL, - sm->ANonce, pmkid, pmkid_len, 0, 0); -} - - -static int wpa_derive_ptk(struct wpa_state_machine *sm, const u8 *pmk, - struct wpa_ptk *ptk) -{ - size_t ptk_len = sm->pairwise == WPA_CIPHER_CCMP ? 48 : 64; -#ifdef CONFIG_IEEE80211R - if (wpa_key_mgmt_ft(sm->wpa_key_mgmt)) - return wpa_auth_derive_ptk_ft(sm, pmk, ptk, ptk_len); -#endif /* CONFIG_IEEE80211R */ - - wpa_pmk_to_ptk(pmk, PMK_LEN, "Pairwise key expansion", - sm->wpa_auth->addr, sm->addr, sm->ANonce, sm->SNonce, - (u8 *) ptk, ptk_len, - wpa_key_mgmt_sha256(sm->wpa_key_mgmt)); - - return 0; -} - - -SM_STATE(WPA_PTK, PTKCALCNEGOTIATING) -{ - struct wpa_ptk PTK; - int ok = 0; - const u8 *pmk = NULL; - - SM_ENTRY_MA(WPA_PTK, PTKCALCNEGOTIATING, wpa_ptk); - sm->EAPOLKeyReceived = FALSE; - - /* WPA with IEEE 802.1X: use the derived PMK from EAP - * WPA-PSK: iterate through possible PSKs and select the one matching - * the packet */ - for (;;) { - if (wpa_key_mgmt_wpa_psk(sm->wpa_key_mgmt)) { - pmk = wpa_auth_get_psk(sm->wpa_auth, sm->addr, pmk); - if (pmk == NULL) - break; - } else - pmk = sm->PMK; - - wpa_derive_ptk(sm, pmk, &PTK); - - if (wpa_verify_key_mic(&PTK, sm->last_rx_eapol_key, - sm->last_rx_eapol_key_len) == 0) { - ok = 1; - break; - } - - if (!wpa_key_mgmt_wpa_psk(sm->wpa_key_mgmt)) - break; - } - - if (!ok) { - wpa_auth_logger(sm->wpa_auth, sm->addr, LOGGER_DEBUG, - "invalid MIC in msg 2/4 of 4-Way Handshake"); - return; - } - -#ifdef CONFIG_IEEE80211R - if (sm->wpa == WPA_VERSION_WPA2 && wpa_key_mgmt_ft(sm->wpa_key_mgmt)) { - /* - * Verify that PMKR1Name from EAPOL-Key message 2/4 matches - * with the value we derived. - */ - if (os_memcmp(sm->sup_pmk_r1_name, sm->pmk_r1_name, - WPA_PMK_NAME_LEN) != 0) { - wpa_auth_logger(sm->wpa_auth, sm->addr, LOGGER_DEBUG, - "PMKR1Name mismatch in FT 4-way " - "handshake"); - wpa_hexdump(MSG_DEBUG, "FT: PMKR1Name from " - "Supplicant", - sm->sup_pmk_r1_name, WPA_PMK_NAME_LEN); - wpa_hexdump(MSG_DEBUG, "FT: Derived PMKR1Name", - sm->pmk_r1_name, WPA_PMK_NAME_LEN); - return; - } - } -#endif /* CONFIG_IEEE80211R */ - - sm->pending_1_of_4_timeout = 0; - eloop_cancel_timeout(wpa_send_eapol_timeout, sm->wpa_auth, sm); - - if (wpa_key_mgmt_wpa_psk(sm->wpa_key_mgmt)) { - /* PSK may have changed from the previous choice, so update - * state machine data based on whatever PSK was selected here. - */ - os_memcpy(sm->PMK, pmk, PMK_LEN); - } - - sm->MICVerified = TRUE; - - os_memcpy(&sm->PTK, &PTK, sizeof(PTK)); - sm->PTK_valid = TRUE; -} - - -SM_STATE(WPA_PTK, PTKCALCNEGOTIATING2) -{ - SM_ENTRY_MA(WPA_PTK, PTKCALCNEGOTIATING2, wpa_ptk); - sm->TimeoutCtr = 0; -} - - -#ifdef CONFIG_IEEE80211W - -static int ieee80211w_kde_len(struct wpa_state_machine *sm) -{ - if (sm->mgmt_frame_prot) { - return 2 + RSN_SELECTOR_LEN + sizeof(struct wpa_igtk_kde); - } - - return 0; -} - - -static u8 * ieee80211w_kde_add(struct wpa_state_machine *sm, u8 *pos) -{ - struct wpa_igtk_kde igtk; - struct wpa_group *gsm = sm->group; - - if (!sm->mgmt_frame_prot) - return pos; - - igtk.keyid[0] = gsm->GN_igtk; - igtk.keyid[1] = 0; - if (gsm->wpa_group_state != WPA_GROUP_SETKEYSDONE || - wpa_auth_get_seqnum(sm->wpa_auth, NULL, gsm->GN_igtk, igtk.pn) < 0) - os_memset(igtk.pn, 0, sizeof(igtk.pn)); - os_memcpy(igtk.igtk, gsm->IGTK[gsm->GN_igtk - 4], WPA_IGTK_LEN); - pos = wpa_add_kde(pos, RSN_KEY_DATA_IGTK, - (const u8 *) &igtk, sizeof(igtk), NULL, 0); - - return pos; -} - -#else /* CONFIG_IEEE80211W */ - -static int ieee80211w_kde_len(struct wpa_state_machine *sm) -{ - return 0; -} - - -static u8 * ieee80211w_kde_add(struct wpa_state_machine *sm, u8 *pos) -{ - return pos; -} - -#endif /* CONFIG_IEEE80211W */ - - -SM_STATE(WPA_PTK, PTKINITNEGOTIATING) -{ - u8 rsc[WPA_KEY_RSC_LEN], *_rsc, *gtk, *kde, *pos; - size_t gtk_len, kde_len; - struct wpa_group *gsm = sm->group; - u8 *wpa_ie; - int wpa_ie_len, secure, keyidx, encr = 0; - - SM_ENTRY_MA(WPA_PTK, PTKINITNEGOTIATING, wpa_ptk); - sm->TimeoutEvt = FALSE; - - sm->TimeoutCtr++; - if (sm->TimeoutCtr > (int) dot11RSNAConfigPairwiseUpdateCount) { - /* No point in sending the EAPOL-Key - we will disconnect - * immediately following this. */ - return; - } - - /* Send EAPOL(1, 1, 1, Pair, P, RSC, ANonce, MIC(PTK), RSNIE, [MDIE], - GTK[GN], IGTK, [FTIE], [TIE * 2]) - */ - os_memset(rsc, 0, WPA_KEY_RSC_LEN); - wpa_auth_get_seqnum(sm->wpa_auth, NULL, gsm->GN, rsc); - /* If FT is used, wpa_auth->wpa_ie includes both RSNIE and MDIE */ - wpa_ie = sm->wpa_auth->wpa_ie; - wpa_ie_len = sm->wpa_auth->wpa_ie_len; - if (sm->wpa == WPA_VERSION_WPA && - (sm->wpa_auth->conf.wpa & WPA_PROTO_RSN) && - wpa_ie_len > wpa_ie[1] + 2 && wpa_ie[0] == WLAN_EID_RSN) { - /* WPA-only STA, remove RSN IE */ - wpa_ie = wpa_ie + wpa_ie[1] + 2; - wpa_ie_len = wpa_ie[1] + 2; - } - wpa_auth_logger(sm->wpa_auth, sm->addr, LOGGER_DEBUG, - "sending 3/4 msg of 4-Way Handshake"); - if (sm->wpa == WPA_VERSION_WPA2) { - /* WPA2 send GTK in the 4-way handshake */ - secure = 1; - gtk = gsm->GTK[gsm->GN - 1]; - gtk_len = gsm->GTK_len; - keyidx = gsm->GN; - _rsc = rsc; - encr = 1; - } else { - /* WPA does not include GTK in msg 3/4 */ - secure = 0; - gtk = NULL; - gtk_len = 0; - keyidx = 0; - _rsc = NULL; - } - - kde_len = wpa_ie_len + ieee80211w_kde_len(sm); - if (gtk) - kde_len += 2 + RSN_SELECTOR_LEN + 2 + gtk_len; -#ifdef CONFIG_IEEE80211R - if (wpa_key_mgmt_ft(sm->wpa_key_mgmt)) { - kde_len += 2 + PMKID_LEN; /* PMKR1Name into RSN IE */ - kde_len += 300; /* FTIE + 2 * TIE */ - } -#endif /* CONFIG_IEEE80211R */ - kde = os_malloc(kde_len); - if (kde == NULL) - return; - - pos = kde; - os_memcpy(pos, wpa_ie, wpa_ie_len); - pos += wpa_ie_len; -#ifdef CONFIG_IEEE80211R - if (wpa_key_mgmt_ft(sm->wpa_key_mgmt)) { - int res = wpa_insert_pmkid(kde, pos - kde, sm->pmk_r1_name); - if (res < 0) { - wpa_printf(MSG_ERROR, "FT: Failed to insert " - "PMKR1Name into RSN IE in EAPOL-Key data"); - os_free(kde); - return; - } - pos += res; - } -#endif /* CONFIG_IEEE80211R */ - if (gtk) { - u8 hdr[2]; - hdr[0] = keyidx & 0x03; - hdr[1] = 0; - pos = wpa_add_kde(pos, RSN_KEY_DATA_GROUPKEY, hdr, 2, - gtk, gtk_len); - } - pos = ieee80211w_kde_add(sm, pos); - -#ifdef CONFIG_IEEE80211R - if (wpa_key_mgmt_ft(sm->wpa_key_mgmt)) { - int res; - struct wpa_auth_config *conf; - - conf = &sm->wpa_auth->conf; - res = wpa_write_ftie(conf, conf->r0_key_holder, - conf->r0_key_holder_len, - NULL, NULL, pos, kde + kde_len - pos, - NULL, 0); - if (res < 0) { - wpa_printf(MSG_ERROR, "FT: Failed to insert FTIE " - "into EAPOL-Key Key Data"); - os_free(kde); - return; - } - pos += res; - - /* TIE[ReassociationDeadline] (TU) */ - *pos++ = WLAN_EID_TIMEOUT_INTERVAL; - *pos++ = 5; - *pos++ = WLAN_TIMEOUT_REASSOC_DEADLINE; - WPA_PUT_LE32(pos, conf->reassociation_deadline); - pos += 4; - - /* TIE[KeyLifetime] (seconds) */ - *pos++ = WLAN_EID_TIMEOUT_INTERVAL; - *pos++ = 5; - *pos++ = WLAN_TIMEOUT_KEY_LIFETIME; - WPA_PUT_LE32(pos, conf->r0_key_lifetime * 60); - pos += 4; - } -#endif /* CONFIG_IEEE80211R */ - - wpa_send_eapol(sm->wpa_auth, sm, - (secure ? WPA_KEY_INFO_SECURE : 0) | WPA_KEY_INFO_MIC | - WPA_KEY_INFO_ACK | WPA_KEY_INFO_INSTALL | - WPA_KEY_INFO_KEY_TYPE, - _rsc, sm->ANonce, kde, pos - kde, keyidx, encr); - os_free(kde); -} - - -SM_STATE(WPA_PTK, PTKINITDONE) -{ - SM_ENTRY_MA(WPA_PTK, PTKINITDONE, wpa_ptk); - sm->EAPOLKeyReceived = FALSE; - if (sm->Pair) { - enum wpa_alg alg; - int klen; - if (sm->pairwise == WPA_CIPHER_TKIP) { - alg = WPA_ALG_TKIP; - klen = 32; - } else { - alg = WPA_ALG_CCMP; - klen = 16; - } - if (wpa_auth_set_key(sm->wpa_auth, 0, alg, sm->addr, 0, - sm->PTK.tk1, klen)) { - wpa_sta_disconnect(sm->wpa_auth, sm->addr); - return; - } - /* FIX: MLME-SetProtection.Request(TA, Tx_Rx) */ - sm->pairwise_set = TRUE; - - if (sm->wpa_auth->conf.wpa_ptk_rekey) { - eloop_cancel_timeout(wpa_rekey_ptk, sm->wpa_auth, sm); - eloop_register_timeout(sm->wpa_auth->conf. - wpa_ptk_rekey, 0, wpa_rekey_ptk, - sm->wpa_auth, sm); - } - - if (wpa_key_mgmt_wpa_psk(sm->wpa_key_mgmt)) { - wpa_auth_set_eapol(sm->wpa_auth, sm->addr, - WPA_EAPOL_authorized, 1); - } - } - - if (0 /* IBSS == TRUE */) { - sm->keycount++; - if (sm->keycount == 2) { - wpa_auth_set_eapol(sm->wpa_auth, sm->addr, - WPA_EAPOL_portValid, 1); - } - } else { - wpa_auth_set_eapol(sm->wpa_auth, sm->addr, WPA_EAPOL_portValid, - 1); - } - wpa_auth_set_eapol(sm->wpa_auth, sm->addr, WPA_EAPOL_keyAvailable, 0); - wpa_auth_set_eapol(sm->wpa_auth, sm->addr, WPA_EAPOL_keyDone, 1); - if (sm->wpa == WPA_VERSION_WPA) - sm->PInitAKeys = TRUE; - else - sm->has_GTK = TRUE; - wpa_auth_vlogger(sm->wpa_auth, sm->addr, LOGGER_INFO, - "pairwise key handshake completed (%s)", - sm->wpa == WPA_VERSION_WPA ? "WPA" : "RSN"); - -#ifdef CONFIG_IEEE80211R - wpa_ft_push_pmk_r1(sm->wpa_auth, sm->addr); -#endif /* CONFIG_IEEE80211R */ -} - - -SM_STEP(WPA_PTK) -{ - struct wpa_authenticator *wpa_auth = sm->wpa_auth; - - if (sm->Init) - SM_ENTER(WPA_PTK, INITIALIZE); - else if (sm->Disconnect - /* || FIX: dot11RSNAConfigSALifetime timeout */) { - wpa_auth_logger(wpa_auth, sm->addr, LOGGER_DEBUG, - "WPA_PTK: sm->Disconnect"); - SM_ENTER(WPA_PTK, DISCONNECT); - } - else if (sm->DeauthenticationRequest) - SM_ENTER(WPA_PTK, DISCONNECTED); - else if (sm->AuthenticationRequest) - SM_ENTER(WPA_PTK, AUTHENTICATION); - else if (sm->ReAuthenticationRequest) - SM_ENTER(WPA_PTK, AUTHENTICATION2); - else if (sm->PTKRequest) - SM_ENTER(WPA_PTK, PTKSTART); - else switch (sm->wpa_ptk_state) { - case WPA_PTK_INITIALIZE: - break; - case WPA_PTK_DISCONNECT: - SM_ENTER(WPA_PTK, DISCONNECTED); - break; - case WPA_PTK_DISCONNECTED: - SM_ENTER(WPA_PTK, INITIALIZE); - break; - case WPA_PTK_AUTHENTICATION: - SM_ENTER(WPA_PTK, AUTHENTICATION2); - break; - case WPA_PTK_AUTHENTICATION2: - if (wpa_key_mgmt_wpa_ieee8021x(sm->wpa_key_mgmt) && - wpa_auth_get_eapol(sm->wpa_auth, sm->addr, - WPA_EAPOL_keyRun) > 0) - SM_ENTER(WPA_PTK, INITPMK); - else if (wpa_key_mgmt_wpa_psk(sm->wpa_key_mgmt) - /* FIX: && 802.1X::keyRun */) - SM_ENTER(WPA_PTK, INITPSK); - break; - case WPA_PTK_INITPMK: - if (wpa_auth_get_eapol(sm->wpa_auth, sm->addr, - WPA_EAPOL_keyAvailable) > 0) - SM_ENTER(WPA_PTK, PTKSTART); - else { - wpa_auth->dot11RSNA4WayHandshakeFailures++; - wpa_auth_logger(sm->wpa_auth, sm->addr, LOGGER_INFO, - "INITPMK - keyAvailable = false"); - SM_ENTER(WPA_PTK, DISCONNECT); - } - break; - case WPA_PTK_INITPSK: - if (wpa_auth_get_psk(sm->wpa_auth, sm->addr, NULL)) - SM_ENTER(WPA_PTK, PTKSTART); - else { - wpa_auth_logger(sm->wpa_auth, sm->addr, LOGGER_INFO, - "no PSK configured for the STA"); - wpa_auth->dot11RSNA4WayHandshakeFailures++; - SM_ENTER(WPA_PTK, DISCONNECT); - } - break; - case WPA_PTK_PTKSTART: - if (sm->EAPOLKeyReceived && !sm->EAPOLKeyRequest && - sm->EAPOLKeyPairwise) - SM_ENTER(WPA_PTK, PTKCALCNEGOTIATING); - else if (sm->TimeoutCtr > - (int) dot11RSNAConfigPairwiseUpdateCount) { - wpa_auth->dot11RSNA4WayHandshakeFailures++; - wpa_auth_vlogger(sm->wpa_auth, sm->addr, LOGGER_DEBUG, - "PTKSTART: Retry limit %d reached", - dot11RSNAConfigPairwiseUpdateCount); - SM_ENTER(WPA_PTK, DISCONNECT); - } else if (sm->TimeoutEvt) - SM_ENTER(WPA_PTK, PTKSTART); - break; - case WPA_PTK_PTKCALCNEGOTIATING: - if (sm->MICVerified) - SM_ENTER(WPA_PTK, PTKCALCNEGOTIATING2); - else if (sm->EAPOLKeyReceived && !sm->EAPOLKeyRequest && - sm->EAPOLKeyPairwise) - SM_ENTER(WPA_PTK, PTKCALCNEGOTIATING); - else if (sm->TimeoutEvt) - SM_ENTER(WPA_PTK, PTKSTART); - break; - case WPA_PTK_PTKCALCNEGOTIATING2: - SM_ENTER(WPA_PTK, PTKINITNEGOTIATING); - break; - case WPA_PTK_PTKINITNEGOTIATING: - if (sm->EAPOLKeyReceived && !sm->EAPOLKeyRequest && - sm->EAPOLKeyPairwise && sm->MICVerified) - SM_ENTER(WPA_PTK, PTKINITDONE); - else if (sm->TimeoutCtr > - (int) dot11RSNAConfigPairwiseUpdateCount) { - wpa_auth->dot11RSNA4WayHandshakeFailures++; - wpa_auth_vlogger(sm->wpa_auth, sm->addr, LOGGER_DEBUG, - "PTKINITNEGOTIATING: Retry limit %d " - "reached", - dot11RSNAConfigPairwiseUpdateCount); - SM_ENTER(WPA_PTK, DISCONNECT); - } else if (sm->TimeoutEvt) - SM_ENTER(WPA_PTK, PTKINITNEGOTIATING); - break; - case WPA_PTK_PTKINITDONE: - break; - } -} - - -SM_STATE(WPA_PTK_GROUP, IDLE) -{ - SM_ENTRY_MA(WPA_PTK_GROUP, IDLE, wpa_ptk_group); - if (sm->Init) { - /* Init flag is not cleared here, so avoid busy - * loop by claiming nothing changed. */ - sm->changed = FALSE; - } - sm->GTimeoutCtr = 0; -} - - -SM_STATE(WPA_PTK_GROUP, REKEYNEGOTIATING) -{ - u8 rsc[WPA_KEY_RSC_LEN]; - struct wpa_group *gsm = sm->group; - u8 *kde, *pos, hdr[2]; - size_t kde_len; - - SM_ENTRY_MA(WPA_PTK_GROUP, REKEYNEGOTIATING, wpa_ptk_group); - - sm->GTimeoutCtr++; - if (sm->GTimeoutCtr > (int) dot11RSNAConfigGroupUpdateCount) { - /* No point in sending the EAPOL-Key - we will disconnect - * immediately following this. */ - return; - } - - if (sm->wpa == WPA_VERSION_WPA) - sm->PInitAKeys = FALSE; - sm->TimeoutEvt = FALSE; - /* Send EAPOL(1, 1, 1, !Pair, G, RSC, GNonce, MIC(PTK), GTK[GN]) */ - os_memset(rsc, 0, WPA_KEY_RSC_LEN); - if (gsm->wpa_group_state == WPA_GROUP_SETKEYSDONE) - wpa_auth_get_seqnum(sm->wpa_auth, NULL, gsm->GN, rsc); - wpa_auth_logger(sm->wpa_auth, sm->addr, LOGGER_DEBUG, - "sending 1/2 msg of Group Key Handshake"); - - if (sm->wpa == WPA_VERSION_WPA2) { - kde_len = 2 + RSN_SELECTOR_LEN + 2 + gsm->GTK_len + - ieee80211w_kde_len(sm); - kde = os_malloc(kde_len); - if (kde == NULL) - return; - - pos = kde; - hdr[0] = gsm->GN & 0x03; - hdr[1] = 0; - pos = wpa_add_kde(pos, RSN_KEY_DATA_GROUPKEY, hdr, 2, - gsm->GTK[gsm->GN - 1], gsm->GTK_len); - pos = ieee80211w_kde_add(sm, pos); - } else { - kde = gsm->GTK[gsm->GN - 1]; - pos = kde + gsm->GTK_len; - } - - wpa_send_eapol(sm->wpa_auth, sm, - WPA_KEY_INFO_SECURE | WPA_KEY_INFO_MIC | - WPA_KEY_INFO_ACK | - (!sm->Pair ? WPA_KEY_INFO_INSTALL : 0), - rsc, gsm->GNonce, kde, pos - kde, gsm->GN, 1); - if (sm->wpa == WPA_VERSION_WPA2) - os_free(kde); -} - - -SM_STATE(WPA_PTK_GROUP, REKEYESTABLISHED) -{ - SM_ENTRY_MA(WPA_PTK_GROUP, REKEYESTABLISHED, wpa_ptk_group); - sm->EAPOLKeyReceived = FALSE; - if (sm->GUpdateStationKeys) - sm->group->GKeyDoneStations--; - sm->GUpdateStationKeys = FALSE; - sm->GTimeoutCtr = 0; - /* FIX: MLME.SetProtection.Request(TA, Tx_Rx) */ - wpa_auth_vlogger(sm->wpa_auth, sm->addr, LOGGER_INFO, - "group key handshake completed (%s)", - sm->wpa == WPA_VERSION_WPA ? "WPA" : "RSN"); - sm->has_GTK = TRUE; -} - - -SM_STATE(WPA_PTK_GROUP, KEYERROR) -{ - SM_ENTRY_MA(WPA_PTK_GROUP, KEYERROR, wpa_ptk_group); - if (sm->GUpdateStationKeys) - sm->group->GKeyDoneStations--; - sm->GUpdateStationKeys = FALSE; - sm->Disconnect = TRUE; -} - - -SM_STEP(WPA_PTK_GROUP) -{ - if (sm->Init || sm->PtkGroupInit) { - SM_ENTER(WPA_PTK_GROUP, IDLE); - sm->PtkGroupInit = FALSE; - } else switch (sm->wpa_ptk_group_state) { - case WPA_PTK_GROUP_IDLE: - if (sm->GUpdateStationKeys || - (sm->wpa == WPA_VERSION_WPA && sm->PInitAKeys)) - SM_ENTER(WPA_PTK_GROUP, REKEYNEGOTIATING); - break; - case WPA_PTK_GROUP_REKEYNEGOTIATING: - if (sm->EAPOLKeyReceived && !sm->EAPOLKeyRequest && - !sm->EAPOLKeyPairwise && sm->MICVerified) - SM_ENTER(WPA_PTK_GROUP, REKEYESTABLISHED); - else if (sm->GTimeoutCtr > - (int) dot11RSNAConfigGroupUpdateCount) - SM_ENTER(WPA_PTK_GROUP, KEYERROR); - else if (sm->TimeoutEvt) - SM_ENTER(WPA_PTK_GROUP, REKEYNEGOTIATING); - break; - case WPA_PTK_GROUP_KEYERROR: - SM_ENTER(WPA_PTK_GROUP, IDLE); - break; - case WPA_PTK_GROUP_REKEYESTABLISHED: - SM_ENTER(WPA_PTK_GROUP, IDLE); - break; - } -} - - -static int wpa_gtk_update(struct wpa_authenticator *wpa_auth, - struct wpa_group *group) -{ - int ret = 0; - - os_memcpy(group->GNonce, group->Counter, WPA_NONCE_LEN); - inc_byte_array(group->Counter, WPA_NONCE_LEN); - if (wpa_gmk_to_gtk(group->GMK, "Group key expansion", - wpa_auth->addr, group->GNonce, - group->GTK[group->GN - 1], group->GTK_len) < 0) - ret = -1; - wpa_hexdump_key(MSG_DEBUG, "GTK", - group->GTK[group->GN - 1], group->GTK_len); - -#ifdef CONFIG_IEEE80211W - if (wpa_auth->conf.ieee80211w != NO_MGMT_FRAME_PROTECTION) { - os_memcpy(group->GNonce, group->Counter, WPA_NONCE_LEN); - inc_byte_array(group->Counter, WPA_NONCE_LEN); - if (wpa_gmk_to_gtk(group->GMK, "IGTK key expansion", - wpa_auth->addr, group->GNonce, - group->IGTK[group->GN_igtk - 4], - WPA_IGTK_LEN) < 0) - ret = -1; - wpa_hexdump_key(MSG_DEBUG, "IGTK", - group->IGTK[group->GN_igtk - 4], WPA_IGTK_LEN); - } -#endif /* CONFIG_IEEE80211W */ - - return ret; -} - - -static void wpa_group_gtk_init(struct wpa_authenticator *wpa_auth, - struct wpa_group *group) -{ - wpa_printf(MSG_DEBUG, "WPA: group state machine entering state " - "GTK_INIT (VLAN-ID %d)", group->vlan_id); - group->changed = FALSE; /* GInit is not cleared here; avoid loop */ - group->wpa_group_state = WPA_GROUP_GTK_INIT; - - /* GTK[0..N] = 0 */ - os_memset(group->GTK, 0, sizeof(group->GTK)); - group->GN = 1; - group->GM = 2; -#ifdef CONFIG_IEEE80211W - group->GN_igtk = 4; - group->GM_igtk = 5; -#endif /* CONFIG_IEEE80211W */ - /* GTK[GN] = CalcGTK() */ - wpa_gtk_update(wpa_auth, group); -} - - -static int wpa_group_update_sta(struct wpa_state_machine *sm, void *ctx) -{ - if (sm->wpa_ptk_state != WPA_PTK_PTKINITDONE) { - wpa_auth_logger(sm->wpa_auth, sm->addr, LOGGER_DEBUG, - "Not in PTKINITDONE; skip Group Key update"); - sm->GUpdateStationKeys = FALSE; - return 0; - } - if (sm->GUpdateStationKeys) { - /* - * This should not really happen, so add a debug log entry. - * Since we clear the GKeyDoneStations before the loop, the - * station needs to be counted here anyway. - */ - wpa_auth_logger(sm->wpa_auth, sm->addr, LOGGER_DEBUG, - "GUpdateStationKeys was already set when " - "marking station for GTK rekeying"); - } - - sm->group->GKeyDoneStations++; - sm->GUpdateStationKeys = TRUE; - - wpa_sm_step(sm); - return 0; -} - - -static void wpa_group_setkeys(struct wpa_authenticator *wpa_auth, - struct wpa_group *group) -{ - int tmp; - - wpa_printf(MSG_DEBUG, "WPA: group state machine entering state " - "SETKEYS (VLAN-ID %d)", group->vlan_id); - group->changed = TRUE; - group->wpa_group_state = WPA_GROUP_SETKEYS; - group->GTKReKey = FALSE; - tmp = group->GM; - group->GM = group->GN; - group->GN = tmp; -#ifdef CONFIG_IEEE80211W - tmp = group->GM_igtk; - group->GM_igtk = group->GN_igtk; - group->GN_igtk = tmp; -#endif /* CONFIG_IEEE80211W */ - /* "GKeyDoneStations = GNoStations" is done in more robust way by - * counting the STAs that are marked with GUpdateStationKeys instead of - * including all STAs that could be in not-yet-completed state. */ - wpa_gtk_update(wpa_auth, group); - - if (group->GKeyDoneStations) { - wpa_printf(MSG_DEBUG, "wpa_group_setkeys: Unexpected " - "GKeyDoneStations=%d when starting new GTK rekey", - group->GKeyDoneStations); - group->GKeyDoneStations = 0; - } - wpa_auth_for_each_sta(wpa_auth, wpa_group_update_sta, NULL); - wpa_printf(MSG_DEBUG, "wpa_group_setkeys: GKeyDoneStations=%d", - group->GKeyDoneStations); -} - - -static int wpa_group_config_group_keys(struct wpa_authenticator *wpa_auth, - struct wpa_group *group) -{ - int ret = 0; - - if (wpa_auth_set_key(wpa_auth, group->vlan_id, - wpa_alg_enum(wpa_auth->conf.wpa_group), - broadcast_ether_addr, group->GN, - group->GTK[group->GN - 1], group->GTK_len) < 0) - ret = -1; - -#ifdef CONFIG_IEEE80211W - if (wpa_auth->conf.ieee80211w != NO_MGMT_FRAME_PROTECTION && - wpa_auth_set_key(wpa_auth, group->vlan_id, WPA_ALG_IGTK, - broadcast_ether_addr, group->GN_igtk, - group->IGTK[group->GN_igtk - 4], - WPA_IGTK_LEN) < 0) - ret = -1; -#endif /* CONFIG_IEEE80211W */ - - return ret; -} - - -static int wpa_group_setkeysdone(struct wpa_authenticator *wpa_auth, - struct wpa_group *group) -{ - wpa_printf(MSG_DEBUG, "WPA: group state machine entering state " - "SETKEYSDONE (VLAN-ID %d)", group->vlan_id); - group->changed = TRUE; - group->wpa_group_state = WPA_GROUP_SETKEYSDONE; - - if (wpa_group_config_group_keys(wpa_auth, group) < 0) - return -1; - - return 0; -} - - -static void wpa_group_sm_step(struct wpa_authenticator *wpa_auth, - struct wpa_group *group) -{ - if (group->GInit) { - wpa_group_gtk_init(wpa_auth, group); - } else if (group->wpa_group_state == WPA_GROUP_GTK_INIT && - group->GTKAuthenticator) { - wpa_group_setkeysdone(wpa_auth, group); - } else if (group->wpa_group_state == WPA_GROUP_SETKEYSDONE && - group->GTKReKey) { - wpa_group_setkeys(wpa_auth, group); - } else if (group->wpa_group_state == WPA_GROUP_SETKEYS) { - if (group->GKeyDoneStations == 0) - wpa_group_setkeysdone(wpa_auth, group); - else if (group->GTKReKey) - wpa_group_setkeys(wpa_auth, group); - } -} - - -static int wpa_sm_step(struct wpa_state_machine *sm) -{ - if (sm == NULL) - return 0; - - if (sm->in_step_loop) { - /* This should not happen, but if it does, make sure we do not - * end up freeing the state machine too early by exiting the - * recursive call. */ - wpa_printf(MSG_ERROR, "WPA: wpa_sm_step() called recursively"); - return 0; - } - - sm->in_step_loop = 1; - do { - if (sm->pending_deinit) - break; - - sm->changed = FALSE; - sm->wpa_auth->group->changed = FALSE; - - SM_STEP_RUN(WPA_PTK); - if (sm->pending_deinit) - break; - SM_STEP_RUN(WPA_PTK_GROUP); - if (sm->pending_deinit) - break; - wpa_group_sm_step(sm->wpa_auth, sm->group); - } while (sm->changed || sm->wpa_auth->group->changed); - sm->in_step_loop = 0; - - if (sm->pending_deinit) { - wpa_printf(MSG_DEBUG, "WPA: Completing pending STA state " - "machine deinit for " MACSTR, MAC2STR(sm->addr)); - wpa_free_sta_sm(sm); - return 1; - } - return 0; -} - - -static void wpa_sm_call_step(void *eloop_ctx, void *timeout_ctx) -{ - struct wpa_state_machine *sm = eloop_ctx; - wpa_sm_step(sm); -} - - -void wpa_auth_sm_notify(struct wpa_state_machine *sm) -{ - if (sm == NULL) - return; - eloop_register_timeout(0, 0, wpa_sm_call_step, sm, NULL); -} - - -void wpa_gtk_rekey(struct wpa_authenticator *wpa_auth) -{ - int tmp, i; - struct wpa_group *group; - - if (wpa_auth == NULL) - return; - - group = wpa_auth->group; - - for (i = 0; i < 2; i++) { - tmp = group->GM; - group->GM = group->GN; - group->GN = tmp; -#ifdef CONFIG_IEEE80211W - tmp = group->GM_igtk; - group->GM_igtk = group->GN_igtk; - group->GN_igtk = tmp; -#endif /* CONFIG_IEEE80211W */ - wpa_gtk_update(wpa_auth, group); - } -} - - -static const char * wpa_bool_txt(int bool) -{ - return bool ? "TRUE" : "FALSE"; -} - - -static int wpa_cipher_bits(int cipher) -{ - switch (cipher) { - case WPA_CIPHER_CCMP: - return 128; - case WPA_CIPHER_TKIP: - return 256; - case WPA_CIPHER_WEP104: - return 104; - case WPA_CIPHER_WEP40: - return 40; - default: - return 0; - } -} - - -#define RSN_SUITE "%02x-%02x-%02x-%d" -#define RSN_SUITE_ARG(s) \ -((s) >> 24) & 0xff, ((s) >> 16) & 0xff, ((s) >> 8) & 0xff, (s) & 0xff - -int wpa_get_mib(struct wpa_authenticator *wpa_auth, char *buf, size_t buflen) -{ - int len = 0, ret; - char pmkid_txt[PMKID_LEN * 2 + 1]; -#ifdef CONFIG_RSN_PREAUTH - const int preauth = 1; -#else /* CONFIG_RSN_PREAUTH */ - const int preauth = 0; -#endif /* CONFIG_RSN_PREAUTH */ - - if (wpa_auth == NULL) - return len; - - ret = os_snprintf(buf + len, buflen - len, - "dot11RSNAOptionImplemented=TRUE\n" - "dot11RSNAPreauthenticationImplemented=%s\n" - "dot11RSNAEnabled=%s\n" - "dot11RSNAPreauthenticationEnabled=%s\n", - wpa_bool_txt(preauth), - wpa_bool_txt(wpa_auth->conf.wpa & WPA_PROTO_RSN), - wpa_bool_txt(wpa_auth->conf.rsn_preauth)); - if (ret < 0 || (size_t) ret >= buflen - len) - return len; - len += ret; - - wpa_snprintf_hex(pmkid_txt, sizeof(pmkid_txt), - wpa_auth->dot11RSNAPMKIDUsed, PMKID_LEN); - - ret = os_snprintf( - buf + len, buflen - len, - "dot11RSNAConfigVersion=%u\n" - "dot11RSNAConfigPairwiseKeysSupported=9999\n" - /* FIX: dot11RSNAConfigGroupCipher */ - /* FIX: dot11RSNAConfigGroupRekeyMethod */ - /* FIX: dot11RSNAConfigGroupRekeyTime */ - /* FIX: dot11RSNAConfigGroupRekeyPackets */ - "dot11RSNAConfigGroupRekeyStrict=%u\n" - "dot11RSNAConfigGroupUpdateCount=%u\n" - "dot11RSNAConfigPairwiseUpdateCount=%u\n" - "dot11RSNAConfigGroupCipherSize=%u\n" - "dot11RSNAConfigPMKLifetime=%u\n" - "dot11RSNAConfigPMKReauthThreshold=%u\n" - "dot11RSNAConfigNumberOfPTKSAReplayCounters=0\n" - "dot11RSNAConfigSATimeout=%u\n" - "dot11RSNAAuthenticationSuiteSelected=" RSN_SUITE "\n" - "dot11RSNAPairwiseCipherSelected=" RSN_SUITE "\n" - "dot11RSNAGroupCipherSelected=" RSN_SUITE "\n" - "dot11RSNAPMKIDUsed=%s\n" - "dot11RSNAAuthenticationSuiteRequested=" RSN_SUITE "\n" - "dot11RSNAPairwiseCipherRequested=" RSN_SUITE "\n" - "dot11RSNAGroupCipherRequested=" RSN_SUITE "\n" - "dot11RSNATKIPCounterMeasuresInvoked=%u\n" - "dot11RSNA4WayHandshakeFailures=%u\n" - "dot11RSNAConfigNumberOfGTKSAReplayCounters=0\n", - RSN_VERSION, - !!wpa_auth->conf.wpa_strict_rekey, - dot11RSNAConfigGroupUpdateCount, - dot11RSNAConfigPairwiseUpdateCount, - wpa_cipher_bits(wpa_auth->conf.wpa_group), - dot11RSNAConfigPMKLifetime, - dot11RSNAConfigPMKReauthThreshold, - dot11RSNAConfigSATimeout, - RSN_SUITE_ARG(wpa_auth->dot11RSNAAuthenticationSuiteSelected), - RSN_SUITE_ARG(wpa_auth->dot11RSNAPairwiseCipherSelected), - RSN_SUITE_ARG(wpa_auth->dot11RSNAGroupCipherSelected), - pmkid_txt, - RSN_SUITE_ARG(wpa_auth->dot11RSNAAuthenticationSuiteRequested), - RSN_SUITE_ARG(wpa_auth->dot11RSNAPairwiseCipherRequested), - RSN_SUITE_ARG(wpa_auth->dot11RSNAGroupCipherRequested), - wpa_auth->dot11RSNATKIPCounterMeasuresInvoked, - wpa_auth->dot11RSNA4WayHandshakeFailures); - if (ret < 0 || (size_t) ret >= buflen - len) - return len; - len += ret; - - /* TODO: dot11RSNAConfigPairwiseCiphersTable */ - /* TODO: dot11RSNAConfigAuthenticationSuitesTable */ - - /* Private MIB */ - ret = os_snprintf(buf + len, buflen - len, "hostapdWPAGroupState=%d\n", - wpa_auth->group->wpa_group_state); - if (ret < 0 || (size_t) ret >= buflen - len) - return len; - len += ret; - - return len; -} - - -int wpa_get_mib_sta(struct wpa_state_machine *sm, char *buf, size_t buflen) -{ - int len = 0, ret; - u32 pairwise = 0; - - if (sm == NULL) - return 0; - - /* TODO: FF-FF-FF-FF-FF-FF entry for broadcast/multicast stats */ - - /* dot11RSNAStatsEntry */ - - if (sm->wpa == WPA_VERSION_WPA) { - if (sm->pairwise == WPA_CIPHER_CCMP) - pairwise = WPA_CIPHER_SUITE_CCMP; - else if (sm->pairwise == WPA_CIPHER_TKIP) - pairwise = WPA_CIPHER_SUITE_TKIP; - else if (sm->pairwise == WPA_CIPHER_WEP104) - pairwise = WPA_CIPHER_SUITE_WEP104; - else if (sm->pairwise == WPA_CIPHER_WEP40) - pairwise = WPA_CIPHER_SUITE_WEP40; - else if (sm->pairwise == WPA_CIPHER_NONE) - pairwise = WPA_CIPHER_SUITE_NONE; - } else if (sm->wpa == WPA_VERSION_WPA2) { - if (sm->pairwise == WPA_CIPHER_CCMP) - pairwise = RSN_CIPHER_SUITE_CCMP; - else if (sm->pairwise == WPA_CIPHER_TKIP) - pairwise = RSN_CIPHER_SUITE_TKIP; - else if (sm->pairwise == WPA_CIPHER_WEP104) - pairwise = RSN_CIPHER_SUITE_WEP104; - else if (sm->pairwise == WPA_CIPHER_WEP40) - pairwise = RSN_CIPHER_SUITE_WEP40; - else if (sm->pairwise == WPA_CIPHER_NONE) - pairwise = RSN_CIPHER_SUITE_NONE; - } else - return 0; - - ret = os_snprintf( - buf + len, buflen - len, - /* TODO: dot11RSNAStatsIndex */ - "dot11RSNAStatsSTAAddress=" MACSTR "\n" - "dot11RSNAStatsVersion=1\n" - "dot11RSNAStatsSelectedPairwiseCipher=" RSN_SUITE "\n" - /* TODO: dot11RSNAStatsTKIPICVErrors */ - "dot11RSNAStatsTKIPLocalMICFailures=%u\n" - "dot11RSNAStatsTKIPRemoteMICFailures=%u\n" - /* TODO: dot11RSNAStatsCCMPReplays */ - /* TODO: dot11RSNAStatsCCMPDecryptErrors */ - /* TODO: dot11RSNAStatsTKIPReplays */, - MAC2STR(sm->addr), - RSN_SUITE_ARG(pairwise), - sm->dot11RSNAStatsTKIPLocalMICFailures, - sm->dot11RSNAStatsTKIPRemoteMICFailures); - if (ret < 0 || (size_t) ret >= buflen - len) - return len; - len += ret; - - /* Private MIB */ - ret = os_snprintf(buf + len, buflen - len, - "hostapdWPAPTKState=%d\n" - "hostapdWPAPTKGroupState=%d\n", - sm->wpa_ptk_state, - sm->wpa_ptk_group_state); - if (ret < 0 || (size_t) ret >= buflen - len) - return len; - len += ret; - - return len; -} - - -void wpa_auth_countermeasures_start(struct wpa_authenticator *wpa_auth) -{ - if (wpa_auth) - wpa_auth->dot11RSNATKIPCounterMeasuresInvoked++; -} - - -int wpa_auth_pairwise_set(struct wpa_state_machine *sm) -{ - return sm && sm->pairwise_set; -} - - -int wpa_auth_get_pairwise(struct wpa_state_machine *sm) -{ - return sm->pairwise; -} - - -int wpa_auth_sta_key_mgmt(struct wpa_state_machine *sm) -{ - if (sm == NULL) - return -1; - return sm->wpa_key_mgmt; -} - - -int wpa_auth_sta_wpa_version(struct wpa_state_machine *sm) -{ - if (sm == NULL) - return 0; - return sm->wpa; -} - - -int wpa_auth_sta_clear_pmksa(struct wpa_state_machine *sm, - struct rsn_pmksa_cache_entry *entry) -{ - if (sm == NULL || sm->pmksa != entry) - return -1; - sm->pmksa = NULL; - return 0; -} - - -struct rsn_pmksa_cache_entry * -wpa_auth_sta_get_pmksa(struct wpa_state_machine *sm) -{ - return sm ? sm->pmksa : NULL; -} - - -void wpa_auth_sta_local_mic_failure_report(struct wpa_state_machine *sm) -{ - if (sm) - sm->dot11RSNAStatsTKIPLocalMICFailures++; -} - - -const u8 * wpa_auth_get_wpa_ie(struct wpa_authenticator *wpa_auth, size_t *len) -{ - if (wpa_auth == NULL) - return NULL; - *len = wpa_auth->wpa_ie_len; - return wpa_auth->wpa_ie; -} - - -int wpa_auth_pmksa_add(struct wpa_state_machine *sm, const u8 *pmk, - int session_timeout, struct eapol_state_machine *eapol) -{ - if (sm == NULL || sm->wpa != WPA_VERSION_WPA2) - return -1; - - if (pmksa_cache_auth_add(sm->wpa_auth->pmksa, pmk, PMK_LEN, - sm->wpa_auth->addr, sm->addr, session_timeout, - eapol, sm->wpa_key_mgmt)) - return 0; - - return -1; -} - - -int wpa_auth_pmksa_add_preauth(struct wpa_authenticator *wpa_auth, - const u8 *pmk, size_t len, const u8 *sta_addr, - int session_timeout, - struct eapol_state_machine *eapol) -{ - if (wpa_auth == NULL) - return -1; - - if (pmksa_cache_auth_add(wpa_auth->pmksa, pmk, len, wpa_auth->addr, - sta_addr, session_timeout, eapol, - WPA_KEY_MGMT_IEEE8021X)) - return 0; - - return -1; -} - - -static struct wpa_group * -wpa_auth_add_group(struct wpa_authenticator *wpa_auth, int vlan_id) -{ - struct wpa_group *group; - - if (wpa_auth == NULL || wpa_auth->group == NULL) - return NULL; - - wpa_printf(MSG_DEBUG, "WPA: Add group state machine for VLAN-ID %d", - vlan_id); - group = wpa_group_init(wpa_auth, vlan_id); - if (group == NULL) - return NULL; - - group->next = wpa_auth->group->next; - wpa_auth->group->next = group; - - return group; -} - - -int wpa_auth_sta_set_vlan(struct wpa_state_machine *sm, int vlan_id) -{ - struct wpa_group *group; - - if (sm == NULL || sm->wpa_auth == NULL) - return 0; - - group = sm->wpa_auth->group; - while (group) { - if (group->vlan_id == vlan_id) - break; - group = group->next; - } - - if (group == NULL) { - group = wpa_auth_add_group(sm->wpa_auth, vlan_id); - if (group == NULL) - return -1; - } - - if (sm->group == group) - return 0; - - wpa_printf(MSG_DEBUG, "WPA: Moving STA " MACSTR " to use group state " - "machine for VLAN ID %d", MAC2STR(sm->addr), vlan_id); - - sm->group = group; - return 0; -} - - -void wpa_auth_eapol_key_tx_status(struct wpa_authenticator *wpa_auth, - struct wpa_state_machine *sm, int ack) -{ - if (wpa_auth == NULL || sm == NULL) - return; - wpa_printf(MSG_DEBUG, "WPA: EAPOL-Key TX status for STA " MACSTR - " ack=%d", MAC2STR(sm->addr), ack); - if (sm->pending_1_of_4_timeout && ack) { - /* - * Some deployed supplicant implementations update their SNonce - * for each EAPOL-Key 2/4 message even within the same 4-way - * handshake and then fail to use the first SNonce when - * deriving the PTK. This results in unsuccessful 4-way - * handshake whenever the relatively short initial timeout is - * reached and EAPOL-Key 1/4 is retransmitted. Try to work - * around this by increasing the timeout now that we know that - * the station has received the frame. - */ - int timeout_ms = eapol_key_timeout_subseq; - wpa_printf(MSG_DEBUG, "WPA: Increase initial EAPOL-Key 1/4 " - "timeout by %u ms because of acknowledged frame", - timeout_ms); - eloop_cancel_timeout(wpa_send_eapol_timeout, wpa_auth, sm); - eloop_register_timeout(timeout_ms / 1000, - (timeout_ms % 1000) * 1000, - wpa_send_eapol_timeout, wpa_auth, sm); - } -} diff --git a/hostapd-0.8/src/ap/wpa_auth.h b/hostapd-0.8/src/ap/wpa_auth.h deleted file mode 100644 index b3e1ff0..0000000 --- a/hostapd-0.8/src/ap/wpa_auth.h +++ /dev/null @@ -1,285 +0,0 @@ -/* - * hostapd - IEEE 802.11i-2004 / WPA Authenticator - * Copyright (c) 2004-2007, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#ifndef WPA_AUTH_H -#define WPA_AUTH_H - -#include "common/defs.h" -#include "common/eapol_common.h" -#include "common/wpa_common.h" - -#ifdef _MSC_VER -#pragma pack(push, 1) -#endif /* _MSC_VER */ - -/* IEEE Std 802.11r-2008, 11A.10.3 - Remote request/response frame definition - */ -struct ft_rrb_frame { - u8 frame_type; /* RSN_REMOTE_FRAME_TYPE_FT_RRB */ - u8 packet_type; /* FT_PACKET_REQUEST/FT_PACKET_RESPONSE */ - le16 action_length; /* little endian length of action_frame */ - u8 ap_address[ETH_ALEN]; - /* - * Followed by action_length bytes of FT Action frame (from Category - * field to the end of Action Frame body. - */ -} STRUCT_PACKED; - -#define RSN_REMOTE_FRAME_TYPE_FT_RRB 1 - -#define FT_PACKET_REQUEST 0 -#define FT_PACKET_RESPONSE 1 -/* Vendor-specific types for R0KH-R1KH protocol; not defined in 802.11r */ -#define FT_PACKET_R0KH_R1KH_PULL 200 -#define FT_PACKET_R0KH_R1KH_RESP 201 -#define FT_PACKET_R0KH_R1KH_PUSH 202 - -#define FT_R0KH_R1KH_PULL_DATA_LEN 44 -#define FT_R0KH_R1KH_RESP_DATA_LEN 76 -#define FT_R0KH_R1KH_PUSH_DATA_LEN 88 - -struct ft_r0kh_r1kh_pull_frame { - u8 frame_type; /* RSN_REMOTE_FRAME_TYPE_FT_RRB */ - u8 packet_type; /* FT_PACKET_R0KH_R1KH_PULL */ - le16 data_length; /* little endian length of data (44) */ - u8 ap_address[ETH_ALEN]; - - u8 nonce[16]; - u8 pmk_r0_name[WPA_PMK_NAME_LEN]; - u8 r1kh_id[FT_R1KH_ID_LEN]; - u8 s1kh_id[ETH_ALEN]; - u8 pad[4]; /* 8-octet boundary for AES key wrap */ - u8 key_wrap_extra[8]; -} STRUCT_PACKED; - -struct ft_r0kh_r1kh_resp_frame { - u8 frame_type; /* RSN_REMOTE_FRAME_TYPE_FT_RRB */ - u8 packet_type; /* FT_PACKET_R0KH_R1KH_RESP */ - le16 data_length; /* little endian length of data (76) */ - u8 ap_address[ETH_ALEN]; - - u8 nonce[16]; /* copied from pull */ - u8 r1kh_id[FT_R1KH_ID_LEN]; /* copied from pull */ - u8 s1kh_id[ETH_ALEN]; /* copied from pull */ - u8 pmk_r1[PMK_LEN]; - u8 pmk_r1_name[WPA_PMK_NAME_LEN]; - le16 pairwise; - u8 pad[2]; /* 8-octet boundary for AES key wrap */ - u8 key_wrap_extra[8]; -} STRUCT_PACKED; - -struct ft_r0kh_r1kh_push_frame { - u8 frame_type; /* RSN_REMOTE_FRAME_TYPE_FT_RRB */ - u8 packet_type; /* FT_PACKET_R0KH_R1KH_PUSH */ - le16 data_length; /* little endian length of data (88) */ - u8 ap_address[ETH_ALEN]; - - /* Encrypted with AES key-wrap */ - u8 timestamp[4]; /* current time in seconds since unix epoch, little - * endian */ - u8 r1kh_id[FT_R1KH_ID_LEN]; - u8 s1kh_id[ETH_ALEN]; - u8 pmk_r0_name[WPA_PMK_NAME_LEN]; - u8 pmk_r1[PMK_LEN]; - u8 pmk_r1_name[WPA_PMK_NAME_LEN]; - le16 pairwise; - u8 pad[6]; /* 8-octet boundary for AES key wrap */ - u8 key_wrap_extra[8]; -} STRUCT_PACKED; - -#ifdef _MSC_VER -#pragma pack(pop) -#endif /* _MSC_VER */ - - -/* per STA state machine data */ - -struct wpa_authenticator; -struct wpa_state_machine; -struct rsn_pmksa_cache_entry; -struct eapol_state_machine; - - -struct ft_remote_r0kh { - struct ft_remote_r0kh *next; - u8 addr[ETH_ALEN]; - u8 id[FT_R0KH_ID_MAX_LEN]; - size_t id_len; - u8 key[16]; -}; - - -struct ft_remote_r1kh { - struct ft_remote_r1kh *next; - u8 addr[ETH_ALEN]; - u8 id[FT_R1KH_ID_LEN]; - u8 key[16]; -}; - - -struct wpa_auth_config { - int wpa; - int wpa_key_mgmt; - int wpa_pairwise; - int wpa_group; - int wpa_group_rekey; - int wpa_strict_rekey; - int wpa_gmk_rekey; - int wpa_ptk_rekey; - int rsn_pairwise; - int rsn_preauth; - int eapol_version; - int peerkey; - int wmm_enabled; - int wmm_uapsd; - int okc; - int tx_status; -#ifdef CONFIG_IEEE80211W - enum mfp_options ieee80211w; -#endif /* CONFIG_IEEE80211W */ -#ifdef CONFIG_IEEE80211R -#define SSID_LEN 32 - u8 ssid[SSID_LEN]; - size_t ssid_len; - u8 mobility_domain[MOBILITY_DOMAIN_ID_LEN]; - u8 r0_key_holder[FT_R0KH_ID_MAX_LEN]; - size_t r0_key_holder_len; - u8 r1_key_holder[FT_R1KH_ID_LEN]; - u32 r0_key_lifetime; - u32 reassociation_deadline; - struct ft_remote_r0kh *r0kh_list; - struct ft_remote_r1kh *r1kh_list; - int pmk_r1_push; - int ft_over_ds; -#endif /* CONFIG_IEEE80211R */ -}; - -typedef enum { - LOGGER_DEBUG, LOGGER_INFO, LOGGER_WARNING -} logger_level; - -typedef enum { - WPA_EAPOL_portEnabled, WPA_EAPOL_portValid, WPA_EAPOL_authorized, - WPA_EAPOL_portControl_Auto, WPA_EAPOL_keyRun, WPA_EAPOL_keyAvailable, - WPA_EAPOL_keyDone, WPA_EAPOL_inc_EapolFramesTx -} wpa_eapol_variable; - -struct wpa_auth_callbacks { - void *ctx; - void (*logger)(void *ctx, const u8 *addr, logger_level level, - const char *txt); - void (*disconnect)(void *ctx, const u8 *addr, u16 reason); - void (*mic_failure_report)(void *ctx, const u8 *addr); - void (*set_eapol)(void *ctx, const u8 *addr, wpa_eapol_variable var, - int value); - int (*get_eapol)(void *ctx, const u8 *addr, wpa_eapol_variable var); - const u8 * (*get_psk)(void *ctx, const u8 *addr, const u8 *prev_psk); - int (*get_msk)(void *ctx, const u8 *addr, u8 *msk, size_t *len); - int (*set_key)(void *ctx, int vlan_id, enum wpa_alg alg, - const u8 *addr, int idx, u8 *key, size_t key_len); - int (*get_seqnum)(void *ctx, const u8 *addr, int idx, u8 *seq); - int (*send_eapol)(void *ctx, const u8 *addr, const u8 *data, - size_t data_len, int encrypt); - int (*for_each_sta)(void *ctx, int (*cb)(struct wpa_state_machine *sm, - void *ctx), void *cb_ctx); - int (*for_each_auth)(void *ctx, int (*cb)(struct wpa_authenticator *a, - void *ctx), void *cb_ctx); - int (*send_ether)(void *ctx, const u8 *dst, u16 proto, const u8 *data, - size_t data_len); -#ifdef CONFIG_IEEE80211R - struct wpa_state_machine * (*add_sta)(void *ctx, const u8 *sta_addr); - int (*send_ft_action)(void *ctx, const u8 *dst, - const u8 *data, size_t data_len); -#endif /* CONFIG_IEEE80211R */ -}; - -struct wpa_authenticator * wpa_init(const u8 *addr, - struct wpa_auth_config *conf, - struct wpa_auth_callbacks *cb); -void wpa_deinit(struct wpa_authenticator *wpa_auth); -int wpa_reconfig(struct wpa_authenticator *wpa_auth, - struct wpa_auth_config *conf); - -enum { - WPA_IE_OK, WPA_INVALID_IE, WPA_INVALID_GROUP, WPA_INVALID_PAIRWISE, - WPA_INVALID_AKMP, WPA_NOT_ENABLED, WPA_ALLOC_FAIL, - WPA_MGMT_FRAME_PROTECTION_VIOLATION, WPA_INVALID_MGMT_GROUP_CIPHER, - WPA_INVALID_MDIE, WPA_INVALID_PROTO -}; - -int wpa_validate_wpa_ie(struct wpa_authenticator *wpa_auth, - struct wpa_state_machine *sm, - const u8 *wpa_ie, size_t wpa_ie_len, - const u8 *mdie, size_t mdie_len); -int wpa_auth_uses_mfp(struct wpa_state_machine *sm); -struct wpa_state_machine * -wpa_auth_sta_init(struct wpa_authenticator *wpa_auth, const u8 *addr); -int wpa_auth_sta_associated(struct wpa_authenticator *wpa_auth, - struct wpa_state_machine *sm); -void wpa_auth_sta_no_wpa(struct wpa_state_machine *sm); -void wpa_auth_sta_deinit(struct wpa_state_machine *sm); -void wpa_receive(struct wpa_authenticator *wpa_auth, - struct wpa_state_machine *sm, - u8 *data, size_t data_len); -typedef enum { - WPA_AUTH, WPA_ASSOC, WPA_DISASSOC, WPA_DEAUTH, WPA_REAUTH, - WPA_REAUTH_EAPOL, WPA_ASSOC_FT -} wpa_event; -void wpa_remove_ptk(struct wpa_state_machine *sm); -int wpa_auth_sm_event(struct wpa_state_machine *sm, wpa_event event); -void wpa_auth_sm_notify(struct wpa_state_machine *sm); -void wpa_gtk_rekey(struct wpa_authenticator *wpa_auth); -int wpa_get_mib(struct wpa_authenticator *wpa_auth, char *buf, size_t buflen); -int wpa_get_mib_sta(struct wpa_state_machine *sm, char *buf, size_t buflen); -void wpa_auth_countermeasures_start(struct wpa_authenticator *wpa_auth); -int wpa_auth_pairwise_set(struct wpa_state_machine *sm); -int wpa_auth_get_pairwise(struct wpa_state_machine *sm); -int wpa_auth_sta_key_mgmt(struct wpa_state_machine *sm); -int wpa_auth_sta_wpa_version(struct wpa_state_machine *sm); -int wpa_auth_sta_clear_pmksa(struct wpa_state_machine *sm, - struct rsn_pmksa_cache_entry *entry); -struct rsn_pmksa_cache_entry * -wpa_auth_sta_get_pmksa(struct wpa_state_machine *sm); -void wpa_auth_sta_local_mic_failure_report(struct wpa_state_machine *sm); -const u8 * wpa_auth_get_wpa_ie(struct wpa_authenticator *wpa_auth, - size_t *len); -int wpa_auth_pmksa_add(struct wpa_state_machine *sm, const u8 *pmk, - int session_timeout, struct eapol_state_machine *eapol); -int wpa_auth_pmksa_add_preauth(struct wpa_authenticator *wpa_auth, - const u8 *pmk, size_t len, const u8 *sta_addr, - int session_timeout, - struct eapol_state_machine *eapol); -int wpa_auth_sta_set_vlan(struct wpa_state_machine *sm, int vlan_id); -void wpa_auth_eapol_key_tx_status(struct wpa_authenticator *wpa_auth, - struct wpa_state_machine *sm, int ack); - -#ifdef CONFIG_IEEE80211R -u8 * wpa_sm_write_assoc_resp_ies(struct wpa_state_machine *sm, u8 *pos, - size_t max_len, int auth_alg, - const u8 *req_ies, size_t req_ies_len); -void wpa_ft_process_auth(struct wpa_state_machine *sm, const u8 *bssid, - u16 auth_transaction, const u8 *ies, size_t ies_len, - void (*cb)(void *ctx, const u8 *dst, const u8 *bssid, - u16 auth_transaction, u16 resp, - const u8 *ies, size_t ies_len), - void *ctx); -u16 wpa_ft_validate_reassoc(struct wpa_state_machine *sm, const u8 *ies, - size_t ies_len); -int wpa_ft_action_rx(struct wpa_state_machine *sm, const u8 *data, size_t len); -int wpa_ft_rrb_rx(struct wpa_authenticator *wpa_auth, const u8 *src_addr, - const u8 *data, size_t data_len); -void wpa_ft_push_pmk_r1(struct wpa_authenticator *wpa_auth, const u8 *addr); -#endif /* CONFIG_IEEE80211R */ - -#endif /* WPA_AUTH_H */ diff --git a/hostapd-0.8/src/ap/wpa_auth_ft.c b/hostapd-0.8/src/ap/wpa_auth_ft.c deleted file mode 100644 index 65f5f4c..0000000 --- a/hostapd-0.8/src/ap/wpa_auth_ft.c +++ /dev/null @@ -1,1779 +0,0 @@ -/* - * hostapd - IEEE 802.11r - Fast BSS Transition - * Copyright (c) 2004-2009, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#include "utils/includes.h" - -#include "utils/common.h" -#include "common/ieee802_11_defs.h" -#include "common/ieee802_11_common.h" -#include "crypto/aes_wrap.h" -#include "crypto/random.h" -#include "ap_config.h" -#include "ieee802_11.h" -#include "wmm.h" -#include "wpa_auth.h" -#include "wpa_auth_i.h" -#include "wpa_auth_ie.h" - - -#ifdef CONFIG_IEEE80211R - -struct wpa_ft_ies { - const u8 *mdie; - size_t mdie_len; - const u8 *ftie; - size_t ftie_len; - const u8 *r1kh_id; - const u8 *gtk; - size_t gtk_len; - const u8 *r0kh_id; - size_t r0kh_id_len; - const u8 *rsn; - size_t rsn_len; - const u8 *rsn_pmkid; - const u8 *ric; - size_t ric_len; -}; - - -static int wpa_ft_parse_ies(const u8 *ies, size_t ies_len, - struct wpa_ft_ies *parse); - - -static int wpa_ft_rrb_send(struct wpa_authenticator *wpa_auth, const u8 *dst, - const u8 *data, size_t data_len) -{ - if (wpa_auth->cb.send_ether == NULL) - return -1; - wpa_printf(MSG_DEBUG, "FT: RRB send to " MACSTR, MAC2STR(dst)); - return wpa_auth->cb.send_ether(wpa_auth->cb.ctx, dst, ETH_P_RRB, - data, data_len); -} - - -static int wpa_ft_action_send(struct wpa_authenticator *wpa_auth, - const u8 *dst, const u8 *data, size_t data_len) -{ - if (wpa_auth->cb.send_ft_action == NULL) - return -1; - return wpa_auth->cb.send_ft_action(wpa_auth->cb.ctx, dst, - data, data_len); -} - - -static struct wpa_state_machine * -wpa_ft_add_sta(struct wpa_authenticator *wpa_auth, const u8 *sta_addr) -{ - if (wpa_auth->cb.add_sta == NULL) - return NULL; - return wpa_auth->cb.add_sta(wpa_auth->cb.ctx, sta_addr); -} - - -int wpa_write_mdie(struct wpa_auth_config *conf, u8 *buf, size_t len) -{ - u8 *pos = buf; - u8 capab; - if (len < 2 + sizeof(struct rsn_mdie)) - return -1; - - *pos++ = WLAN_EID_MOBILITY_DOMAIN; - *pos++ = MOBILITY_DOMAIN_ID_LEN + 1; - os_memcpy(pos, conf->mobility_domain, MOBILITY_DOMAIN_ID_LEN); - pos += MOBILITY_DOMAIN_ID_LEN; - capab = 0; - if (conf->ft_over_ds) - capab |= RSN_FT_CAPAB_FT_OVER_DS; - *pos++ = capab; - - return pos - buf; -} - - -int wpa_write_ftie(struct wpa_auth_config *conf, const u8 *r0kh_id, - size_t r0kh_id_len, - const u8 *anonce, const u8 *snonce, - u8 *buf, size_t len, const u8 *subelem, - size_t subelem_len) -{ - u8 *pos = buf, *ielen; - struct rsn_ftie *hdr; - - if (len < 2 + sizeof(*hdr) + 2 + FT_R1KH_ID_LEN + 2 + r0kh_id_len + - subelem_len) - return -1; - - *pos++ = WLAN_EID_FAST_BSS_TRANSITION; - ielen = pos++; - - hdr = (struct rsn_ftie *) pos; - os_memset(hdr, 0, sizeof(*hdr)); - pos += sizeof(*hdr); - WPA_PUT_LE16(hdr->mic_control, 0); - if (anonce) - os_memcpy(hdr->anonce, anonce, WPA_NONCE_LEN); - if (snonce) - os_memcpy(hdr->snonce, snonce, WPA_NONCE_LEN); - - /* Optional Parameters */ - *pos++ = FTIE_SUBELEM_R1KH_ID; - *pos++ = FT_R1KH_ID_LEN; - os_memcpy(pos, conf->r1_key_holder, FT_R1KH_ID_LEN); - pos += FT_R1KH_ID_LEN; - - if (r0kh_id) { - *pos++ = FTIE_SUBELEM_R0KH_ID; - *pos++ = r0kh_id_len; - os_memcpy(pos, r0kh_id, r0kh_id_len); - pos += r0kh_id_len; - } - - if (subelem) { - os_memcpy(pos, subelem, subelem_len); - pos += subelem_len; - } - - *ielen = pos - buf - 2; - - return pos - buf; -} - - -struct wpa_ft_pmk_r0_sa { - struct wpa_ft_pmk_r0_sa *next; - u8 pmk_r0[PMK_LEN]; - u8 pmk_r0_name[WPA_PMK_NAME_LEN]; - u8 spa[ETH_ALEN]; - int pairwise; /* Pairwise cipher suite, WPA_CIPHER_* */ - /* TODO: expiration, identity, radius_class, EAP type, VLAN ID */ - int pmk_r1_pushed; -}; - -struct wpa_ft_pmk_r1_sa { - struct wpa_ft_pmk_r1_sa *next; - u8 pmk_r1[PMK_LEN]; - u8 pmk_r1_name[WPA_PMK_NAME_LEN]; - u8 spa[ETH_ALEN]; - int pairwise; /* Pairwise cipher suite, WPA_CIPHER_* */ - /* TODO: expiration, identity, radius_class, EAP type, VLAN ID */ -}; - -struct wpa_ft_pmk_cache { - struct wpa_ft_pmk_r0_sa *pmk_r0; - struct wpa_ft_pmk_r1_sa *pmk_r1; -}; - -struct wpa_ft_pmk_cache * wpa_ft_pmk_cache_init(void) -{ - struct wpa_ft_pmk_cache *cache; - - cache = os_zalloc(sizeof(*cache)); - - return cache; -} - - -void wpa_ft_pmk_cache_deinit(struct wpa_ft_pmk_cache *cache) -{ - struct wpa_ft_pmk_r0_sa *r0, *r0prev; - struct wpa_ft_pmk_r1_sa *r1, *r1prev; - - r0 = cache->pmk_r0; - while (r0) { - r0prev = r0; - r0 = r0->next; - os_memset(r0prev->pmk_r0, 0, PMK_LEN); - os_free(r0prev); - } - - r1 = cache->pmk_r1; - while (r1) { - r1prev = r1; - r1 = r1->next; - os_memset(r1prev->pmk_r1, 0, PMK_LEN); - os_free(r1prev); - } - - os_free(cache); -} - - -static int wpa_ft_store_pmk_r0(struct wpa_authenticator *wpa_auth, - const u8 *spa, const u8 *pmk_r0, - const u8 *pmk_r0_name, int pairwise) -{ - struct wpa_ft_pmk_cache *cache = wpa_auth->ft_pmk_cache; - struct wpa_ft_pmk_r0_sa *r0; - - /* TODO: add expiration and limit on number of entries in cache */ - - r0 = os_zalloc(sizeof(*r0)); - if (r0 == NULL) - return -1; - - os_memcpy(r0->pmk_r0, pmk_r0, PMK_LEN); - os_memcpy(r0->pmk_r0_name, pmk_r0_name, WPA_PMK_NAME_LEN); - os_memcpy(r0->spa, spa, ETH_ALEN); - r0->pairwise = pairwise; - - r0->next = cache->pmk_r0; - cache->pmk_r0 = r0; - - return 0; -} - - -static int wpa_ft_fetch_pmk_r0(struct wpa_authenticator *wpa_auth, - const u8 *spa, const u8 *pmk_r0_name, - u8 *pmk_r0, int *pairwise) -{ - struct wpa_ft_pmk_cache *cache = wpa_auth->ft_pmk_cache; - struct wpa_ft_pmk_r0_sa *r0; - - r0 = cache->pmk_r0; - while (r0) { - if (os_memcmp(r0->spa, spa, ETH_ALEN) == 0 && - os_memcmp(r0->pmk_r0_name, pmk_r0_name, WPA_PMK_NAME_LEN) - == 0) { - os_memcpy(pmk_r0, r0->pmk_r0, PMK_LEN); - if (pairwise) - *pairwise = r0->pairwise; - return 0; - } - - r0 = r0->next; - } - - return -1; -} - - -static int wpa_ft_store_pmk_r1(struct wpa_authenticator *wpa_auth, - const u8 *spa, const u8 *pmk_r1, - const u8 *pmk_r1_name, int pairwise) -{ - struct wpa_ft_pmk_cache *cache = wpa_auth->ft_pmk_cache; - struct wpa_ft_pmk_r1_sa *r1; - - /* TODO: add expiration and limit on number of entries in cache */ - - r1 = os_zalloc(sizeof(*r1)); - if (r1 == NULL) - return -1; - - os_memcpy(r1->pmk_r1, pmk_r1, PMK_LEN); - os_memcpy(r1->pmk_r1_name, pmk_r1_name, WPA_PMK_NAME_LEN); - os_memcpy(r1->spa, spa, ETH_ALEN); - r1->pairwise = pairwise; - - r1->next = cache->pmk_r1; - cache->pmk_r1 = r1; - - return 0; -} - - -static int wpa_ft_fetch_pmk_r1(struct wpa_authenticator *wpa_auth, - const u8 *spa, const u8 *pmk_r1_name, - u8 *pmk_r1, int *pairwise) -{ - struct wpa_ft_pmk_cache *cache = wpa_auth->ft_pmk_cache; - struct wpa_ft_pmk_r1_sa *r1; - - r1 = cache->pmk_r1; - while (r1) { - if (os_memcmp(r1->spa, spa, ETH_ALEN) == 0 && - os_memcmp(r1->pmk_r1_name, pmk_r1_name, WPA_PMK_NAME_LEN) - == 0) { - os_memcpy(pmk_r1, r1->pmk_r1, PMK_LEN); - if (pairwise) - *pairwise = r1->pairwise; - return 0; - } - - r1 = r1->next; - } - - return -1; -} - - -static int wpa_ft_pull_pmk_r1(struct wpa_authenticator *wpa_auth, - const u8 *s1kh_id, const u8 *r0kh_id, - size_t r0kh_id_len, const u8 *pmk_r0_name) -{ - struct ft_remote_r0kh *r0kh; - struct ft_r0kh_r1kh_pull_frame frame, f; - - r0kh = wpa_auth->conf.r0kh_list; - while (r0kh) { - if (r0kh->id_len == r0kh_id_len && - os_memcmp(r0kh->id, r0kh_id, r0kh_id_len) == 0) - break; - r0kh = r0kh->next; - } - if (r0kh == NULL) - return -1; - - wpa_printf(MSG_DEBUG, "FT: Send PMK-R1 pull request to remote R0KH " - "address " MACSTR, MAC2STR(r0kh->addr)); - - os_memset(&frame, 0, sizeof(frame)); - frame.frame_type = RSN_REMOTE_FRAME_TYPE_FT_RRB; - frame.packet_type = FT_PACKET_R0KH_R1KH_PULL; - frame.data_length = host_to_le16(FT_R0KH_R1KH_PULL_DATA_LEN); - os_memcpy(frame.ap_address, wpa_auth->addr, ETH_ALEN); - - /* aes_wrap() does not support inplace encryption, so use a temporary - * buffer for the data. */ - if (random_get_bytes(f.nonce, sizeof(f.nonce))) { - wpa_printf(MSG_DEBUG, "FT: Failed to get random data for " - "nonce"); - return -1; - } - os_memcpy(f.pmk_r0_name, pmk_r0_name, WPA_PMK_NAME_LEN); - os_memcpy(f.r1kh_id, wpa_auth->conf.r1_key_holder, FT_R1KH_ID_LEN); - os_memcpy(f.s1kh_id, s1kh_id, ETH_ALEN); - - if (aes_wrap(r0kh->key, (FT_R0KH_R1KH_PULL_DATA_LEN + 7) / 8, - f.nonce, frame.nonce) < 0) - return -1; - - wpa_ft_rrb_send(wpa_auth, r0kh->addr, (u8 *) &frame, sizeof(frame)); - - return 0; -} - - -int wpa_auth_derive_ptk_ft(struct wpa_state_machine *sm, const u8 *pmk, - struct wpa_ptk *ptk, size_t ptk_len) -{ - u8 pmk_r0[PMK_LEN], pmk_r0_name[WPA_PMK_NAME_LEN]; - u8 pmk_r1[PMK_LEN]; - u8 ptk_name[WPA_PMK_NAME_LEN]; - const u8 *mdid = sm->wpa_auth->conf.mobility_domain; - const u8 *r0kh = sm->wpa_auth->conf.r0_key_holder; - size_t r0kh_len = sm->wpa_auth->conf.r0_key_holder_len; - const u8 *r1kh = sm->wpa_auth->conf.r1_key_holder; - const u8 *ssid = sm->wpa_auth->conf.ssid; - size_t ssid_len = sm->wpa_auth->conf.ssid_len; - - - if (sm->xxkey_len == 0) { - wpa_printf(MSG_DEBUG, "FT: XXKey not available for key " - "derivation"); - return -1; - } - - wpa_derive_pmk_r0(sm->xxkey, sm->xxkey_len, ssid, ssid_len, mdid, - r0kh, r0kh_len, sm->addr, pmk_r0, pmk_r0_name); - wpa_hexdump_key(MSG_DEBUG, "FT: PMK-R0", pmk_r0, PMK_LEN); - wpa_hexdump(MSG_DEBUG, "FT: PMKR0Name", pmk_r0_name, WPA_PMK_NAME_LEN); - wpa_ft_store_pmk_r0(sm->wpa_auth, sm->addr, pmk_r0, pmk_r0_name, - sm->pairwise); - - wpa_derive_pmk_r1(pmk_r0, pmk_r0_name, r1kh, sm->addr, - pmk_r1, sm->pmk_r1_name); - wpa_hexdump_key(MSG_DEBUG, "FT: PMK-R1", pmk_r1, PMK_LEN); - wpa_hexdump(MSG_DEBUG, "FT: PMKR1Name", sm->pmk_r1_name, - WPA_PMK_NAME_LEN); - wpa_ft_store_pmk_r1(sm->wpa_auth, sm->addr, pmk_r1, sm->pmk_r1_name, - sm->pairwise); - - wpa_pmk_r1_to_ptk(pmk_r1, sm->SNonce, sm->ANonce, sm->addr, - sm->wpa_auth->addr, sm->pmk_r1_name, - (u8 *) ptk, ptk_len, ptk_name); - wpa_hexdump_key(MSG_DEBUG, "FT: PTK", (u8 *) ptk, ptk_len); - wpa_hexdump(MSG_DEBUG, "FT: PTKName", ptk_name, WPA_PMK_NAME_LEN); - - return 0; -} - - -static inline int wpa_auth_get_seqnum(struct wpa_authenticator *wpa_auth, - const u8 *addr, int idx, u8 *seq) -{ - if (wpa_auth->cb.get_seqnum == NULL) - return -1; - return wpa_auth->cb.get_seqnum(wpa_auth->cb.ctx, addr, idx, seq); -} - - -static u8 * wpa_ft_gtk_subelem(struct wpa_state_machine *sm, size_t *len) -{ - u8 *subelem; - struct wpa_group *gsm = sm->group; - size_t subelem_len, pad_len; - const u8 *key; - size_t key_len; - u8 keybuf[32]; - - key_len = gsm->GTK_len; - if (key_len > sizeof(keybuf)) - return NULL; - - /* - * Pad key for AES Key Wrap if it is not multiple of 8 bytes or is less - * than 16 bytes. - */ - pad_len = key_len % 8; - if (pad_len) - pad_len = 8 - pad_len; - if (key_len + pad_len < 16) - pad_len += 8; - if (pad_len) { - os_memcpy(keybuf, gsm->GTK[gsm->GN - 1], key_len); - os_memset(keybuf + key_len, 0, pad_len); - keybuf[key_len] = 0xdd; - key_len += pad_len; - key = keybuf; - } else - key = gsm->GTK[gsm->GN - 1]; - - /* - * Sub-elem ID[1] | Length[1] | Key Info[2] | Key Length[1] | RSC[8] | - * Key[5..32]. - */ - subelem_len = 13 + key_len + 8; - subelem = os_zalloc(subelem_len); - if (subelem == NULL) - return NULL; - - subelem[0] = FTIE_SUBELEM_GTK; - subelem[1] = 11 + key_len + 8; - /* Key ID in B0-B1 of Key Info */ - WPA_PUT_LE16(&subelem[2], gsm->GN & 0x03); - subelem[4] = gsm->GTK_len; - wpa_auth_get_seqnum(sm->wpa_auth, NULL, gsm->GN, subelem + 5); - if (aes_wrap(sm->PTK.kek, key_len / 8, key, subelem + 13)) { - os_free(subelem); - return NULL; - } - - *len = subelem_len; - return subelem; -} - - -#ifdef CONFIG_IEEE80211W -static u8 * wpa_ft_igtk_subelem(struct wpa_state_machine *sm, size_t *len) -{ - u8 *subelem, *pos; - struct wpa_group *gsm = sm->group; - size_t subelem_len; - - /* Sub-elem ID[1] | Length[1] | KeyID[2] | IPN[6] | Key Length[1] | - * Key[16+8] */ - subelem_len = 1 + 1 + 2 + 6 + 1 + WPA_IGTK_LEN + 8; - subelem = os_zalloc(subelem_len); - if (subelem == NULL) - return NULL; - - pos = subelem; - *pos++ = FTIE_SUBELEM_IGTK; - *pos++ = subelem_len - 2; - WPA_PUT_LE16(pos, gsm->GN_igtk); - pos += 2; - wpa_auth_get_seqnum(sm->wpa_auth, NULL, gsm->GN_igtk, pos); - pos += 6; - *pos++ = WPA_IGTK_LEN; - if (aes_wrap(sm->PTK.kek, WPA_IGTK_LEN / 8, - gsm->IGTK[gsm->GN_igtk - 4], pos)) { - os_free(subelem); - return NULL; - } - - *len = subelem_len; - return subelem; -} -#endif /* CONFIG_IEEE80211W */ - - -static u8 * wpa_ft_process_rdie(u8 *pos, u8 *end, u8 id, u8 descr_count, - const u8 *ies, size_t ies_len) -{ - struct ieee802_11_elems parse; - struct rsn_rdie *rdie; - - wpa_printf(MSG_DEBUG, "FT: Resource Request: id=%d descr_count=%d", - id, descr_count); - wpa_hexdump(MSG_MSGDUMP, "FT: Resource descriptor IE(s)", - ies, ies_len); - - if (end - pos < (int) sizeof(*rdie)) { - wpa_printf(MSG_ERROR, "FT: Not enough room for response RDIE"); - return pos; - } - - *pos++ = WLAN_EID_RIC_DATA; - *pos++ = sizeof(*rdie); - rdie = (struct rsn_rdie *) pos; - rdie->id = id; - rdie->descr_count = 0; - rdie->status_code = host_to_le16(WLAN_STATUS_SUCCESS); - pos += sizeof(*rdie); - - if (ieee802_11_parse_elems((u8 *) ies, ies_len, &parse, 1) == - ParseFailed) { - wpa_printf(MSG_DEBUG, "FT: Failed to parse request IEs"); - rdie->status_code = - host_to_le16(WLAN_STATUS_UNSPECIFIED_FAILURE); - return pos; - } - -#ifdef NEED_AP_MLME - if (parse.wmm_tspec) { - struct wmm_tspec_element *tspec; - int res; - - if (parse.wmm_tspec_len + 2 < (int) sizeof(*tspec)) { - wpa_printf(MSG_DEBUG, "FT: Too short WMM TSPEC IE " - "(%d)", (int) parse.wmm_tspec_len); - rdie->status_code = - host_to_le16(WLAN_STATUS_UNSPECIFIED_FAILURE); - return pos; - } - if (end - pos < (int) sizeof(*tspec)) { - wpa_printf(MSG_ERROR, "FT: Not enough room for " - "response TSPEC"); - rdie->status_code = - host_to_le16(WLAN_STATUS_UNSPECIFIED_FAILURE); - return pos; - } - tspec = (struct wmm_tspec_element *) pos; - os_memcpy(tspec, parse.wmm_tspec - 2, sizeof(*tspec)); - res = wmm_process_tspec(tspec); - wpa_printf(MSG_DEBUG, "FT: ADDTS processing result: %d", res); - if (res == WMM_ADDTS_STATUS_INVALID_PARAMETERS) - rdie->status_code = - host_to_le16(WLAN_STATUS_INVALID_PARAMETERS); - else if (res == WMM_ADDTS_STATUS_REFUSED) - rdie->status_code = - host_to_le16(WLAN_STATUS_REQUEST_DECLINED); - else { - /* TSPEC accepted; include updated TSPEC in response */ - rdie->descr_count = 1; - pos += sizeof(*tspec); - } - return pos; - } -#endif /* NEED_AP_MLME */ - - wpa_printf(MSG_DEBUG, "FT: No supported resource requested"); - rdie->status_code = host_to_le16(WLAN_STATUS_UNSPECIFIED_FAILURE); - return pos; -} - - -static u8 * wpa_ft_process_ric(u8 *pos, u8 *end, const u8 *ric, size_t ric_len) -{ - const u8 *rpos, *start; - const struct rsn_rdie *rdie; - - wpa_hexdump(MSG_MSGDUMP, "FT: RIC Request", ric, ric_len); - - rpos = ric; - while (rpos + sizeof(*rdie) < ric + ric_len) { - if (rpos[0] != WLAN_EID_RIC_DATA || rpos[1] < sizeof(*rdie) || - rpos + 2 + rpos[1] > ric + ric_len) - break; - rdie = (const struct rsn_rdie *) (rpos + 2); - rpos += 2 + rpos[1]; - start = rpos; - - while (rpos + 2 <= ric + ric_len && - rpos + 2 + rpos[1] <= ric + ric_len) { - if (rpos[0] == WLAN_EID_RIC_DATA) - break; - rpos += 2 + rpos[1]; - } - pos = wpa_ft_process_rdie(pos, end, rdie->id, - rdie->descr_count, - start, rpos - start); - } - - return pos; -} - - -u8 * wpa_sm_write_assoc_resp_ies(struct wpa_state_machine *sm, u8 *pos, - size_t max_len, int auth_alg, - const u8 *req_ies, size_t req_ies_len) -{ - u8 *end, *mdie, *ftie, *rsnie = NULL, *r0kh_id, *subelem = NULL; - size_t mdie_len, ftie_len, rsnie_len = 0, r0kh_id_len, subelem_len = 0; - int res; - struct wpa_auth_config *conf; - struct rsn_ftie *_ftie; - struct wpa_ft_ies parse; - u8 *ric_start; - u8 *anonce, *snonce; - - if (sm == NULL) - return pos; - - conf = &sm->wpa_auth->conf; - - if (sm->wpa_key_mgmt != WPA_KEY_MGMT_FT_IEEE8021X && - sm->wpa_key_mgmt != WPA_KEY_MGMT_FT_PSK) - return pos; - - end = pos + max_len; - - if (auth_alg == WLAN_AUTH_FT) { - /* - * RSN (only present if this is a Reassociation Response and - * part of a fast BSS transition) - */ - res = wpa_write_rsn_ie(conf, pos, end - pos, sm->pmk_r1_name); - if (res < 0) - return pos; - rsnie = pos; - rsnie_len = res; - pos += res; - } - - /* Mobility Domain Information */ - res = wpa_write_mdie(conf, pos, end - pos); - if (res < 0) - return pos; - mdie = pos; - mdie_len = res; - pos += res; - - /* Fast BSS Transition Information */ - if (auth_alg == WLAN_AUTH_FT) { - subelem = wpa_ft_gtk_subelem(sm, &subelem_len); - r0kh_id = sm->r0kh_id; - r0kh_id_len = sm->r0kh_id_len; - anonce = sm->ANonce; - snonce = sm->SNonce; -#ifdef CONFIG_IEEE80211W - if (sm->mgmt_frame_prot) { - u8 *igtk; - size_t igtk_len; - u8 *nbuf; - igtk = wpa_ft_igtk_subelem(sm, &igtk_len); - if (igtk == NULL) { - os_free(subelem); - return pos; - } - nbuf = os_realloc(subelem, subelem_len + igtk_len); - if (nbuf == NULL) { - os_free(subelem); - os_free(igtk); - return pos; - } - subelem = nbuf; - os_memcpy(subelem + subelem_len, igtk, igtk_len); - subelem_len += igtk_len; - os_free(igtk); - } -#endif /* CONFIG_IEEE80211W */ - } else { - r0kh_id = conf->r0_key_holder; - r0kh_id_len = conf->r0_key_holder_len; - anonce = NULL; - snonce = NULL; - } - res = wpa_write_ftie(conf, r0kh_id, r0kh_id_len, anonce, snonce, pos, - end - pos, subelem, subelem_len); - os_free(subelem); - if (res < 0) - return pos; - ftie = pos; - ftie_len = res; - pos += res; - - os_free(sm->assoc_resp_ftie); - sm->assoc_resp_ftie = os_malloc(ftie_len); - if (sm->assoc_resp_ftie) - os_memcpy(sm->assoc_resp_ftie, ftie, ftie_len); - - _ftie = (struct rsn_ftie *) (ftie + 2); - if (auth_alg == WLAN_AUTH_FT) - _ftie->mic_control[1] = 3; /* Information element count */ - - ric_start = pos; - if (wpa_ft_parse_ies(req_ies, req_ies_len, &parse) == 0 && parse.ric) { - pos = wpa_ft_process_ric(pos, end, parse.ric, parse.ric_len); - if (auth_alg == WLAN_AUTH_FT) - _ftie->mic_control[1] += - ieee802_11_ie_count(ric_start, - pos - ric_start); - } - if (ric_start == pos) - ric_start = NULL; - - if (auth_alg == WLAN_AUTH_FT && - wpa_ft_mic(sm->PTK.kck, sm->addr, sm->wpa_auth->addr, 6, - mdie, mdie_len, ftie, ftie_len, - rsnie, rsnie_len, - ric_start, ric_start ? pos - ric_start : 0, - _ftie->mic) < 0) - wpa_printf(MSG_DEBUG, "FT: Failed to calculate MIC"); - - return pos; -} - - -static int wpa_ft_parse_ftie(const u8 *ie, size_t ie_len, - struct wpa_ft_ies *parse) -{ - const u8 *end, *pos; - - parse->ftie = ie; - parse->ftie_len = ie_len; - - pos = ie + sizeof(struct rsn_ftie); - end = ie + ie_len; - - while (pos + 2 <= end && pos + 2 + pos[1] <= end) { - switch (pos[0]) { - case FTIE_SUBELEM_R1KH_ID: - if (pos[1] != FT_R1KH_ID_LEN) { - wpa_printf(MSG_DEBUG, "FT: Invalid R1KH-ID " - "length in FTIE: %d", pos[1]); - return -1; - } - parse->r1kh_id = pos + 2; - break; - case FTIE_SUBELEM_GTK: - parse->gtk = pos + 2; - parse->gtk_len = pos[1]; - break; - case FTIE_SUBELEM_R0KH_ID: - if (pos[1] < 1 || pos[1] > FT_R0KH_ID_MAX_LEN) { - wpa_printf(MSG_DEBUG, "FT: Invalid R0KH-ID " - "length in FTIE: %d", pos[1]); - return -1; - } - parse->r0kh_id = pos + 2; - parse->r0kh_id_len = pos[1]; - break; - } - - pos += 2 + pos[1]; - } - - return 0; -} - - -static int wpa_ft_parse_ies(const u8 *ies, size_t ies_len, - struct wpa_ft_ies *parse) -{ - const u8 *end, *pos; - struct wpa_ie_data data; - int ret; - const struct rsn_ftie *ftie; - int prot_ie_count = 0; - - os_memset(parse, 0, sizeof(*parse)); - if (ies == NULL) - return 0; - - pos = ies; - end = ies + ies_len; - while (pos + 2 <= end && pos + 2 + pos[1] <= end) { - switch (pos[0]) { - case WLAN_EID_RSN: - parse->rsn = pos + 2; - parse->rsn_len = pos[1]; - ret = wpa_parse_wpa_ie_rsn(parse->rsn - 2, - parse->rsn_len + 2, - &data); - if (ret < 0) { - wpa_printf(MSG_DEBUG, "FT: Failed to parse " - "RSN IE: %d", ret); - return -1; - } - if (data.num_pmkid == 1 && data.pmkid) - parse->rsn_pmkid = data.pmkid; - break; - case WLAN_EID_MOBILITY_DOMAIN: - parse->mdie = pos + 2; - parse->mdie_len = pos[1]; - break; - case WLAN_EID_FAST_BSS_TRANSITION: - if (pos[1] < sizeof(*ftie)) - return -1; - ftie = (const struct rsn_ftie *) (pos + 2); - prot_ie_count = ftie->mic_control[1]; - if (wpa_ft_parse_ftie(pos + 2, pos[1], parse) < 0) - return -1; - break; - case WLAN_EID_RIC_DATA: - if (parse->ric == NULL) - parse->ric = pos; - } - - pos += 2 + pos[1]; - } - - if (prot_ie_count == 0) - return 0; /* no MIC */ - - /* - * Check that the protected IE count matches with IEs included in the - * frame. - */ - if (parse->rsn) - prot_ie_count--; - if (parse->mdie) - prot_ie_count--; - if (parse->ftie) - prot_ie_count--; - if (prot_ie_count < 0) { - wpa_printf(MSG_DEBUG, "FT: Some required IEs not included in " - "the protected IE count"); - return -1; - } - - if (prot_ie_count == 0 && parse->ric) { - wpa_printf(MSG_DEBUG, "FT: RIC IE(s) in the frame, but not " - "included in protected IE count"); - return -1; - } - - /* Determine the end of the RIC IE(s) */ - pos = parse->ric; - while (pos && pos + 2 <= end && pos + 2 + pos[1] <= end && - prot_ie_count) { - prot_ie_count--; - pos += 2 + pos[1]; - } - parse->ric_len = pos - parse->ric; - if (prot_ie_count) { - wpa_printf(MSG_DEBUG, "FT: %d protected IEs missing from " - "frame", (int) prot_ie_count); - return -1; - } - - return 0; -} - - -static inline int wpa_auth_set_key(struct wpa_authenticator *wpa_auth, - int vlan_id, - enum wpa_alg alg, const u8 *addr, int idx, - u8 *key, size_t key_len) -{ - if (wpa_auth->cb.set_key == NULL) - return -1; - return wpa_auth->cb.set_key(wpa_auth->cb.ctx, vlan_id, alg, addr, idx, - key, key_len); -} - - -void wpa_ft_install_ptk(struct wpa_state_machine *sm) -{ - enum wpa_alg alg; - int klen; - - /* MLME-SETKEYS.request(PTK) */ - if (sm->pairwise == WPA_CIPHER_TKIP) { - alg = WPA_ALG_TKIP; - klen = 32; - } else if (sm->pairwise == WPA_CIPHER_CCMP) { - alg = WPA_ALG_CCMP; - klen = 16; - } else { - wpa_printf(MSG_DEBUG, "FT: Unknown pairwise alg 0x%x - skip " - "PTK configuration", sm->pairwise); - return; - } - - /* FIX: add STA entry to kernel/driver here? The set_key will fail - * most likely without this.. At the moment, STA entry is added only - * after association has been completed. This function will be called - * again after association to get the PTK configured, but that could be - * optimized by adding the STA entry earlier. - */ - if (wpa_auth_set_key(sm->wpa_auth, 0, alg, sm->addr, 0, - sm->PTK.tk1, klen)) - return; - - /* FIX: MLME-SetProtection.Request(TA, Tx_Rx) */ - sm->pairwise_set = TRUE; -} - - -static u16 wpa_ft_process_auth_req(struct wpa_state_machine *sm, - const u8 *ies, size_t ies_len, - u8 **resp_ies, size_t *resp_ies_len) -{ - struct rsn_mdie *mdie; - struct rsn_ftie *ftie; - u8 pmk_r1[PMK_LEN], pmk_r1_name[WPA_PMK_NAME_LEN]; - u8 ptk_name[WPA_PMK_NAME_LEN]; - struct wpa_auth_config *conf; - struct wpa_ft_ies parse; - size_t buflen, ptk_len; - int ret; - u8 *pos, *end; - int pairwise; - - *resp_ies = NULL; - *resp_ies_len = 0; - - sm->pmk_r1_name_valid = 0; - conf = &sm->wpa_auth->conf; - - wpa_hexdump(MSG_DEBUG, "FT: Received authentication frame IEs", - ies, ies_len); - - if (wpa_ft_parse_ies(ies, ies_len, &parse) < 0) { - wpa_printf(MSG_DEBUG, "FT: Failed to parse FT IEs"); - return WLAN_STATUS_UNSPECIFIED_FAILURE; - } - - mdie = (struct rsn_mdie *) parse.mdie; - if (mdie == NULL || parse.mdie_len < sizeof(*mdie) || - os_memcmp(mdie->mobility_domain, - sm->wpa_auth->conf.mobility_domain, - MOBILITY_DOMAIN_ID_LEN) != 0) { - wpa_printf(MSG_DEBUG, "FT: Invalid MDIE"); - return WLAN_STATUS_INVALID_MDIE; - } - - ftie = (struct rsn_ftie *) parse.ftie; - if (ftie == NULL || parse.ftie_len < sizeof(*ftie)) { - wpa_printf(MSG_DEBUG, "FT: Invalid FTIE"); - return WLAN_STATUS_INVALID_FTIE; - } - - os_memcpy(sm->SNonce, ftie->snonce, WPA_NONCE_LEN); - - if (parse.r0kh_id == NULL) { - wpa_printf(MSG_DEBUG, "FT: Invalid FTIE - no R0KH-ID"); - return WLAN_STATUS_INVALID_FTIE; - } - - wpa_hexdump(MSG_DEBUG, "FT: STA R0KH-ID", - parse.r0kh_id, parse.r0kh_id_len); - os_memcpy(sm->r0kh_id, parse.r0kh_id, parse.r0kh_id_len); - sm->r0kh_id_len = parse.r0kh_id_len; - - if (parse.rsn_pmkid == NULL) { - wpa_printf(MSG_DEBUG, "FT: No PMKID in RSNIE"); - return WLAN_STATUS_INVALID_PMKID; - } - - wpa_hexdump(MSG_DEBUG, "FT: Requested PMKR0Name", - parse.rsn_pmkid, WPA_PMK_NAME_LEN); - wpa_derive_pmk_r1_name(parse.rsn_pmkid, - sm->wpa_auth->conf.r1_key_holder, sm->addr, - pmk_r1_name); - wpa_hexdump(MSG_DEBUG, "FT: Derived requested PMKR1Name", - pmk_r1_name, WPA_PMK_NAME_LEN); - - if (wpa_ft_fetch_pmk_r1(sm->wpa_auth, sm->addr, pmk_r1_name, pmk_r1, - &pairwise) < 0) { - if (wpa_ft_pull_pmk_r1(sm->wpa_auth, sm->addr, sm->r0kh_id, - sm->r0kh_id_len, parse.rsn_pmkid) < 0) { - wpa_printf(MSG_DEBUG, "FT: Did not have matching " - "PMK-R1 and unknown R0KH-ID"); - return WLAN_STATUS_INVALID_PMKID; - } - - /* - * TODO: Should return "status pending" (and the caller should - * not send out response now). The real response will be sent - * once the response from R0KH is received. - */ - return WLAN_STATUS_INVALID_PMKID; - } - - wpa_hexdump_key(MSG_DEBUG, "FT: Selected PMK-R1", pmk_r1, PMK_LEN); - sm->pmk_r1_name_valid = 1; - os_memcpy(sm->pmk_r1_name, pmk_r1_name, WPA_PMK_NAME_LEN); - - if (random_get_bytes(sm->ANonce, WPA_NONCE_LEN)) { - wpa_printf(MSG_DEBUG, "FT: Failed to get random data for " - "ANonce"); - return WLAN_STATUS_UNSPECIFIED_FAILURE; - } - - wpa_hexdump(MSG_DEBUG, "FT: Received SNonce", - sm->SNonce, WPA_NONCE_LEN); - wpa_hexdump(MSG_DEBUG, "FT: Generated ANonce", - sm->ANonce, WPA_NONCE_LEN); - - ptk_len = pairwise != WPA_CIPHER_CCMP ? 64 : 48; - wpa_pmk_r1_to_ptk(pmk_r1, sm->SNonce, sm->ANonce, sm->addr, - sm->wpa_auth->addr, pmk_r1_name, - (u8 *) &sm->PTK, ptk_len, ptk_name); - wpa_hexdump_key(MSG_DEBUG, "FT: PTK", - (u8 *) &sm->PTK, ptk_len); - wpa_hexdump(MSG_DEBUG, "FT: PTKName", ptk_name, WPA_PMK_NAME_LEN); - - sm->pairwise = pairwise; - wpa_ft_install_ptk(sm); - - buflen = 2 + sizeof(struct rsn_mdie) + 2 + sizeof(struct rsn_ftie) + - 2 + FT_R1KH_ID_LEN + 200; - *resp_ies = os_zalloc(buflen); - if (*resp_ies == NULL) { - return WLAN_STATUS_UNSPECIFIED_FAILURE; - } - - pos = *resp_ies; - end = *resp_ies + buflen; - - ret = wpa_write_rsn_ie(conf, pos, end - pos, parse.rsn_pmkid); - if (ret < 0) { - os_free(*resp_ies); - *resp_ies = NULL; - return WLAN_STATUS_UNSPECIFIED_FAILURE; - } - pos += ret; - - ret = wpa_write_mdie(conf, pos, end - pos); - if (ret < 0) { - os_free(*resp_ies); - *resp_ies = NULL; - return WLAN_STATUS_UNSPECIFIED_FAILURE; - } - pos += ret; - - ret = wpa_write_ftie(conf, parse.r0kh_id, parse.r0kh_id_len, - sm->ANonce, sm->SNonce, pos, end - pos, NULL, 0); - if (ret < 0) { - os_free(*resp_ies); - *resp_ies = NULL; - return WLAN_STATUS_UNSPECIFIED_FAILURE; - } - pos += ret; - - *resp_ies_len = pos - *resp_ies; - - return WLAN_STATUS_SUCCESS; -} - - -void wpa_ft_process_auth(struct wpa_state_machine *sm, const u8 *bssid, - u16 auth_transaction, const u8 *ies, size_t ies_len, - void (*cb)(void *ctx, const u8 *dst, const u8 *bssid, - u16 auth_transaction, u16 status, - const u8 *ies, size_t ies_len), - void *ctx) -{ - u16 status; - u8 *resp_ies; - size_t resp_ies_len; - - if (sm == NULL) { - wpa_printf(MSG_DEBUG, "FT: Received authentication frame, but " - "WPA SM not available"); - return; - } - - wpa_printf(MSG_DEBUG, "FT: Received authentication frame: STA=" MACSTR - " BSSID=" MACSTR " transaction=%d", - MAC2STR(sm->addr), MAC2STR(bssid), auth_transaction); - status = wpa_ft_process_auth_req(sm, ies, ies_len, &resp_ies, - &resp_ies_len); - - wpa_printf(MSG_DEBUG, "FT: FT authentication response: dst=" MACSTR - " auth_transaction=%d status=%d", - MAC2STR(sm->addr), auth_transaction + 1, status); - wpa_hexdump(MSG_DEBUG, "FT: Response IEs", resp_ies, resp_ies_len); - cb(ctx, sm->addr, bssid, auth_transaction + 1, status, - resp_ies, resp_ies_len); - os_free(resp_ies); -} - - -u16 wpa_ft_validate_reassoc(struct wpa_state_machine *sm, const u8 *ies, - size_t ies_len) -{ - struct wpa_ft_ies parse; - struct rsn_mdie *mdie; - struct rsn_ftie *ftie; - u8 mic[16]; - unsigned int count; - - if (sm == NULL) - return WLAN_STATUS_UNSPECIFIED_FAILURE; - - wpa_hexdump(MSG_DEBUG, "FT: Reassoc Req IEs", ies, ies_len); - - if (wpa_ft_parse_ies(ies, ies_len, &parse) < 0) { - wpa_printf(MSG_DEBUG, "FT: Failed to parse FT IEs"); - return WLAN_STATUS_UNSPECIFIED_FAILURE; - } - - if (parse.rsn == NULL) { - wpa_printf(MSG_DEBUG, "FT: No RSNIE in Reassoc Req"); - return WLAN_STATUS_UNSPECIFIED_FAILURE; - } - - if (parse.rsn_pmkid == NULL) { - wpa_printf(MSG_DEBUG, "FT: No PMKID in RSNIE"); - return WLAN_STATUS_INVALID_PMKID; - } - - if (os_memcmp(parse.rsn_pmkid, sm->pmk_r1_name, WPA_PMK_NAME_LEN) != 0) - { - wpa_printf(MSG_DEBUG, "FT: PMKID in Reassoc Req did not match " - "with the PMKR1Name derived from auth request"); - return WLAN_STATUS_INVALID_PMKID; - } - - mdie = (struct rsn_mdie *) parse.mdie; - if (mdie == NULL || parse.mdie_len < sizeof(*mdie) || - os_memcmp(mdie->mobility_domain, - sm->wpa_auth->conf.mobility_domain, - MOBILITY_DOMAIN_ID_LEN) != 0) { - wpa_printf(MSG_DEBUG, "FT: Invalid MDIE"); - return WLAN_STATUS_INVALID_MDIE; - } - - ftie = (struct rsn_ftie *) parse.ftie; - if (ftie == NULL || parse.ftie_len < sizeof(*ftie)) { - wpa_printf(MSG_DEBUG, "FT: Invalid FTIE"); - return WLAN_STATUS_INVALID_FTIE; - } - - if (os_memcmp(ftie->snonce, sm->SNonce, WPA_NONCE_LEN) != 0) { - wpa_printf(MSG_DEBUG, "FT: SNonce mismatch in FTIE"); - wpa_hexdump(MSG_DEBUG, "FT: Received SNonce", - ftie->snonce, WPA_NONCE_LEN); - wpa_hexdump(MSG_DEBUG, "FT: Expected SNonce", - sm->SNonce, WPA_NONCE_LEN); - return -1; - } - - if (os_memcmp(ftie->anonce, sm->ANonce, WPA_NONCE_LEN) != 0) { - wpa_printf(MSG_DEBUG, "FT: ANonce mismatch in FTIE"); - wpa_hexdump(MSG_DEBUG, "FT: Received ANonce", - ftie->anonce, WPA_NONCE_LEN); - wpa_hexdump(MSG_DEBUG, "FT: Expected ANonce", - sm->ANonce, WPA_NONCE_LEN); - return -1; - } - - - if (parse.r0kh_id == NULL) { - wpa_printf(MSG_DEBUG, "FT: No R0KH-ID subelem in FTIE"); - return -1; - } - - if (parse.r0kh_id_len != sm->r0kh_id_len || - os_memcmp(parse.r0kh_id, sm->r0kh_id, parse.r0kh_id_len) != 0) { - wpa_printf(MSG_DEBUG, "FT: R0KH-ID in FTIE did not match with " - "the current R0KH-ID"); - wpa_hexdump(MSG_DEBUG, "FT: R0KH-ID in FTIE", - parse.r0kh_id, parse.r0kh_id_len); - wpa_hexdump(MSG_DEBUG, "FT: The current R0KH-ID", - sm->r0kh_id, sm->r0kh_id_len); - return -1; - } - - if (parse.r1kh_id == NULL) { - wpa_printf(MSG_DEBUG, "FT: No R1KH-ID subelem in FTIE"); - return -1; - } - - if (os_memcmp(parse.r1kh_id, sm->wpa_auth->conf.r1_key_holder, - FT_R1KH_ID_LEN) != 0) { - wpa_printf(MSG_DEBUG, "FT: Unknown R1KH-ID used in " - "ReassocReq"); - wpa_hexdump(MSG_DEBUG, "FT: R1KH-ID in FTIE", - parse.r1kh_id, FT_R1KH_ID_LEN); - wpa_hexdump(MSG_DEBUG, "FT: Expected R1KH-ID", - sm->wpa_auth->conf.r1_key_holder, FT_R1KH_ID_LEN); - return -1; - } - - if (parse.rsn_pmkid == NULL || - os_memcmp(parse.rsn_pmkid, sm->pmk_r1_name, WPA_PMK_NAME_LEN)) { - wpa_printf(MSG_DEBUG, "FT: No matching PMKR1Name (PMKID) in " - "RSNIE (pmkid=%d)", !!parse.rsn_pmkid); - return -1; - } - - count = 3; - if (parse.ric) - count++; - if (ftie->mic_control[1] != count) { - wpa_printf(MSG_DEBUG, "FT: Unexpected IE count in MIC " - "Control: received %u expected %u", - ftie->mic_control[1], count); - return -1; - } - - if (wpa_ft_mic(sm->PTK.kck, sm->addr, sm->wpa_auth->addr, 5, - parse.mdie - 2, parse.mdie_len + 2, - parse.ftie - 2, parse.ftie_len + 2, - parse.rsn - 2, parse.rsn_len + 2, - parse.ric, parse.ric_len, - mic) < 0) { - wpa_printf(MSG_DEBUG, "FT: Failed to calculate MIC"); - return WLAN_STATUS_UNSPECIFIED_FAILURE; - } - - if (os_memcmp(mic, ftie->mic, 16) != 0) { - wpa_printf(MSG_DEBUG, "FT: Invalid MIC in FTIE"); - wpa_hexdump(MSG_MSGDUMP, "FT: Received MIC", ftie->mic, 16); - wpa_hexdump(MSG_MSGDUMP, "FT: Calculated MIC", mic, 16); - return WLAN_STATUS_INVALID_FTIE; - } - - return WLAN_STATUS_SUCCESS; -} - - -int wpa_ft_action_rx(struct wpa_state_machine *sm, const u8 *data, size_t len) -{ - const u8 *sta_addr, *target_ap; - const u8 *ies; - size_t ies_len; - u8 action; - struct ft_rrb_frame *frame; - - if (sm == NULL) - return -1; - - /* - * data: Category[1] Action[1] STA_Address[6] Target_AP_Address[6] - * FT Request action frame body[variable] - */ - - if (len < 14) { - wpa_printf(MSG_DEBUG, "FT: Too short FT Action frame " - "(len=%lu)", (unsigned long) len); - return -1; - } - - action = data[1]; - sta_addr = data + 2; - target_ap = data + 8; - ies = data + 14; - ies_len = len - 14; - - wpa_printf(MSG_DEBUG, "FT: Received FT Action frame (STA=" MACSTR - " Target AP=" MACSTR " Action=%d)", - MAC2STR(sta_addr), MAC2STR(target_ap), action); - - if (os_memcmp(sta_addr, sm->addr, ETH_ALEN) != 0) { - wpa_printf(MSG_DEBUG, "FT: Mismatch in FT Action STA address: " - "STA=" MACSTR " STA-Address=" MACSTR, - MAC2STR(sm->addr), MAC2STR(sta_addr)); - return -1; - } - - /* - * Do some sanity checking on the target AP address (not own and not - * broadcast. This could be extended to filter based on a list of known - * APs in the MD (if such a list were configured). - */ - if ((target_ap[0] & 0x01) || - os_memcmp(target_ap, sm->wpa_auth->addr, ETH_ALEN) == 0) { - wpa_printf(MSG_DEBUG, "FT: Invalid Target AP in FT Action " - "frame"); - return -1; - } - - wpa_hexdump(MSG_MSGDUMP, "FT: Action frame body", ies, ies_len); - - /* RRB - Forward action frame to the target AP */ - frame = os_malloc(sizeof(*frame) + len); - frame->frame_type = RSN_REMOTE_FRAME_TYPE_FT_RRB; - frame->packet_type = FT_PACKET_REQUEST; - frame->action_length = host_to_le16(len); - os_memcpy(frame->ap_address, sm->wpa_auth->addr, ETH_ALEN); - os_memcpy(frame + 1, data, len); - - wpa_ft_rrb_send(sm->wpa_auth, target_ap, (u8 *) frame, - sizeof(*frame) + len); - os_free(frame); - - return 0; -} - - -static int wpa_ft_rrb_rx_request(struct wpa_authenticator *wpa_auth, - const u8 *current_ap, const u8 *sta_addr, - const u8 *body, size_t len) -{ - struct wpa_state_machine *sm; - u16 status; - u8 *resp_ies, *pos; - size_t resp_ies_len, rlen; - struct ft_rrb_frame *frame; - - sm = wpa_ft_add_sta(wpa_auth, sta_addr); - if (sm == NULL) { - wpa_printf(MSG_DEBUG, "FT: Failed to add new STA based on " - "RRB Request"); - return -1; - } - - wpa_hexdump(MSG_MSGDUMP, "FT: RRB Request Frame body", body, len); - - status = wpa_ft_process_auth_req(sm, body, len, &resp_ies, - &resp_ies_len); - - wpa_printf(MSG_DEBUG, "FT: RRB authentication response: STA=" MACSTR - " CurrentAP=" MACSTR " status=%d", - MAC2STR(sm->addr), MAC2STR(current_ap), status); - wpa_hexdump(MSG_DEBUG, "FT: Response IEs", resp_ies, resp_ies_len); - - /* RRB - Forward action frame response to the Current AP */ - - /* - * data: Category[1] Action[1] STA_Address[6] Target_AP_Address[6] - * Status_Code[2] FT Request action frame body[variable] - */ - rlen = 2 + 2 * ETH_ALEN + 2 + resp_ies_len; - - frame = os_malloc(sizeof(*frame) + rlen); - frame->frame_type = RSN_REMOTE_FRAME_TYPE_FT_RRB; - frame->packet_type = FT_PACKET_RESPONSE; - frame->action_length = host_to_le16(rlen); - os_memcpy(frame->ap_address, wpa_auth->addr, ETH_ALEN); - pos = (u8 *) (frame + 1); - *pos++ = WLAN_ACTION_FT; - *pos++ = 2; /* Action: Response */ - os_memcpy(pos, sta_addr, ETH_ALEN); - pos += ETH_ALEN; - os_memcpy(pos, wpa_auth->addr, ETH_ALEN); - pos += ETH_ALEN; - WPA_PUT_LE16(pos, status); - pos += 2; - if (resp_ies) { - os_memcpy(pos, resp_ies, resp_ies_len); - os_free(resp_ies); - } - - wpa_ft_rrb_send(wpa_auth, current_ap, (u8 *) frame, - sizeof(*frame) + rlen); - os_free(frame); - - return 0; -} - - -static int wpa_ft_rrb_rx_pull(struct wpa_authenticator *wpa_auth, - const u8 *src_addr, - const u8 *data, size_t data_len) -{ - struct ft_r0kh_r1kh_pull_frame *frame, f; - struct ft_remote_r1kh *r1kh; - struct ft_r0kh_r1kh_resp_frame resp, r; - u8 pmk_r0[PMK_LEN]; - int pairwise; - - wpa_printf(MSG_DEBUG, "FT: Received PMK-R1 pull"); - - if (data_len < sizeof(*frame)) - return -1; - - r1kh = wpa_auth->conf.r1kh_list; - while (r1kh) { - if (os_memcmp(r1kh->addr, src_addr, ETH_ALEN) == 0) - break; - r1kh = r1kh->next; - } - if (r1kh == NULL) { - wpa_printf(MSG_DEBUG, "FT: No matching R1KH address found for " - "PMK-R1 pull source address " MACSTR, - MAC2STR(src_addr)); - return -1; - } - - frame = (struct ft_r0kh_r1kh_pull_frame *) data; - /* aes_unwrap() does not support inplace decryption, so use a temporary - * buffer for the data. */ - if (aes_unwrap(r1kh->key, (FT_R0KH_R1KH_PULL_DATA_LEN + 7) / 8, - frame->nonce, f.nonce) < 0) { - wpa_printf(MSG_DEBUG, "FT: Failed to decrypt PMK-R1 pull " - "request from " MACSTR, MAC2STR(src_addr)); - return -1; - } - - wpa_hexdump(MSG_DEBUG, "FT: PMK-R1 pull - nonce", - f.nonce, sizeof(f.nonce)); - wpa_hexdump(MSG_DEBUG, "FT: PMK-R1 pull - PMKR0Name", - f.pmk_r0_name, WPA_PMK_NAME_LEN); - wpa_printf(MSG_DEBUG, "FT: PMK-R1 pull - R1KH-ID=" MACSTR "S1KH-ID=" - MACSTR, MAC2STR(f.r1kh_id), MAC2STR(f.s1kh_id)); - - os_memset(&resp, 0, sizeof(resp)); - resp.frame_type = RSN_REMOTE_FRAME_TYPE_FT_RRB; - resp.packet_type = FT_PACKET_R0KH_R1KH_RESP; - resp.data_length = host_to_le16(FT_R0KH_R1KH_RESP_DATA_LEN); - os_memcpy(resp.ap_address, wpa_auth->addr, ETH_ALEN); - - /* aes_wrap() does not support inplace encryption, so use a temporary - * buffer for the data. */ - os_memcpy(r.nonce, f.nonce, sizeof(f.nonce)); - os_memcpy(r.r1kh_id, f.r1kh_id, FT_R1KH_ID_LEN); - os_memcpy(r.s1kh_id, f.s1kh_id, ETH_ALEN); - if (wpa_ft_fetch_pmk_r0(wpa_auth, f.s1kh_id, f.pmk_r0_name, pmk_r0, - &pairwise) < 0) { - wpa_printf(MSG_DEBUG, "FT: No matching PMKR0Name found for " - "PMK-R1 pull"); - return -1; - } - - wpa_derive_pmk_r1(pmk_r0, f.pmk_r0_name, f.r1kh_id, f.s1kh_id, - r.pmk_r1, r.pmk_r1_name); - wpa_hexdump_key(MSG_DEBUG, "FT: PMK-R1", r.pmk_r1, PMK_LEN); - wpa_hexdump(MSG_DEBUG, "FT: PMKR1Name", r.pmk_r1_name, - WPA_PMK_NAME_LEN); - r.pairwise = host_to_le16(pairwise); - - if (aes_wrap(r1kh->key, (FT_R0KH_R1KH_RESP_DATA_LEN + 7) / 8, - r.nonce, resp.nonce) < 0) { - os_memset(pmk_r0, 0, PMK_LEN); - return -1; - } - - os_memset(pmk_r0, 0, PMK_LEN); - - wpa_ft_rrb_send(wpa_auth, src_addr, (u8 *) &resp, sizeof(resp)); - - return 0; -} - - -static int wpa_ft_rrb_rx_resp(struct wpa_authenticator *wpa_auth, - const u8 *src_addr, - const u8 *data, size_t data_len) -{ - struct ft_r0kh_r1kh_resp_frame *frame, f; - struct ft_remote_r0kh *r0kh; - int pairwise; - - wpa_printf(MSG_DEBUG, "FT: Received PMK-R1 pull response"); - - if (data_len < sizeof(*frame)) - return -1; - - r0kh = wpa_auth->conf.r0kh_list; - while (r0kh) { - if (os_memcmp(r0kh->addr, src_addr, ETH_ALEN) == 0) - break; - r0kh = r0kh->next; - } - if (r0kh == NULL) { - wpa_printf(MSG_DEBUG, "FT: No matching R0KH address found for " - "PMK-R0 pull response source address " MACSTR, - MAC2STR(src_addr)); - return -1; - } - - frame = (struct ft_r0kh_r1kh_resp_frame *) data; - /* aes_unwrap() does not support inplace decryption, so use a temporary - * buffer for the data. */ - if (aes_unwrap(r0kh->key, (FT_R0KH_R1KH_RESP_DATA_LEN + 7) / 8, - frame->nonce, f.nonce) < 0) { - wpa_printf(MSG_DEBUG, "FT: Failed to decrypt PMK-R1 pull " - "response from " MACSTR, MAC2STR(src_addr)); - return -1; - } - - if (os_memcmp(f.r1kh_id, wpa_auth->conf.r1_key_holder, FT_R1KH_ID_LEN) - != 0) { - wpa_printf(MSG_DEBUG, "FT: PMK-R1 pull response did not use a " - "matching R1KH-ID"); - return -1; - } - - /* TODO: verify that matches with a pending request - * and call this requests callback function to finish request - * processing */ - - pairwise = le_to_host16(f.pairwise); - wpa_hexdump(MSG_DEBUG, "FT: PMK-R1 pull - nonce", - f.nonce, sizeof(f.nonce)); - wpa_printf(MSG_DEBUG, "FT: PMK-R1 pull - R1KH-ID=" MACSTR "S1KH-ID=" - MACSTR " pairwise=0x%x", - MAC2STR(f.r1kh_id), MAC2STR(f.s1kh_id), pairwise); - wpa_hexdump_key(MSG_DEBUG, "FT: PMK-R1 pull - PMK-R1", - f.pmk_r1, PMK_LEN); - wpa_hexdump(MSG_DEBUG, "FT: PMK-R1 pull - PMKR1Name", - f.pmk_r1_name, WPA_PMK_NAME_LEN); - - wpa_ft_store_pmk_r1(wpa_auth, f.s1kh_id, f.pmk_r1, f.pmk_r1_name, - pairwise); - os_memset(f.pmk_r1, 0, PMK_LEN); - - return 0; -} - - -static int wpa_ft_rrb_rx_push(struct wpa_authenticator *wpa_auth, - const u8 *src_addr, - const u8 *data, size_t data_len) -{ - struct ft_r0kh_r1kh_push_frame *frame, f; - struct ft_remote_r0kh *r0kh; - struct os_time now; - os_time_t tsend; - int pairwise; - - wpa_printf(MSG_DEBUG, "FT: Received PMK-R1 push"); - - if (data_len < sizeof(*frame)) - return -1; - - r0kh = wpa_auth->conf.r0kh_list; - while (r0kh) { - if (os_memcmp(r0kh->addr, src_addr, ETH_ALEN) == 0) - break; - r0kh = r0kh->next; - } - if (r0kh == NULL) { - wpa_printf(MSG_DEBUG, "FT: No matching R0KH address found for " - "PMK-R0 push source address " MACSTR, - MAC2STR(src_addr)); - return -1; - } - - frame = (struct ft_r0kh_r1kh_push_frame *) data; - /* aes_unwrap() does not support inplace decryption, so use a temporary - * buffer for the data. */ - if (aes_unwrap(r0kh->key, (FT_R0KH_R1KH_PUSH_DATA_LEN + 7) / 8, - frame->timestamp, f.timestamp) < 0) { - wpa_printf(MSG_DEBUG, "FT: Failed to decrypt PMK-R1 push from " - MACSTR, MAC2STR(src_addr)); - return -1; - } - - os_get_time(&now); - tsend = WPA_GET_LE32(f.timestamp); - if ((now.sec > tsend && now.sec - tsend > 60) || - (now.sec < tsend && tsend - now.sec > 60)) { - wpa_printf(MSG_DEBUG, "FT: PMK-R1 push did not have a valid " - "timestamp: sender time %d own time %d\n", - (int) tsend, (int) now.sec); - return -1; - } - - if (os_memcmp(f.r1kh_id, wpa_auth->conf.r1_key_holder, FT_R1KH_ID_LEN) - != 0) { - wpa_printf(MSG_DEBUG, "FT: PMK-R1 push did not use a matching " - "R1KH-ID (received " MACSTR " own " MACSTR ")", - MAC2STR(f.r1kh_id), - MAC2STR(wpa_auth->conf.r1_key_holder)); - return -1; - } - - pairwise = le_to_host16(f.pairwise); - wpa_printf(MSG_DEBUG, "FT: PMK-R1 push - R1KH-ID=" MACSTR " S1KH-ID=" - MACSTR " pairwise=0x%x", - MAC2STR(f.r1kh_id), MAC2STR(f.s1kh_id), pairwise); - wpa_hexdump_key(MSG_DEBUG, "FT: PMK-R1 push - PMK-R1", - f.pmk_r1, PMK_LEN); - wpa_hexdump(MSG_DEBUG, "FT: PMK-R1 push - PMKR1Name", - f.pmk_r1_name, WPA_PMK_NAME_LEN); - - wpa_ft_store_pmk_r1(wpa_auth, f.s1kh_id, f.pmk_r1, f.pmk_r1_name, - pairwise); - os_memset(f.pmk_r1, 0, PMK_LEN); - - return 0; -} - - -int wpa_ft_rrb_rx(struct wpa_authenticator *wpa_auth, const u8 *src_addr, - const u8 *data, size_t data_len) -{ - struct ft_rrb_frame *frame; - u16 alen; - const u8 *pos, *end, *start; - u8 action; - const u8 *sta_addr, *target_ap_addr; - - wpa_printf(MSG_DEBUG, "FT: RRB received frame from remote AP " MACSTR, - MAC2STR(src_addr)); - - if (data_len < sizeof(*frame)) { - wpa_printf(MSG_DEBUG, "FT: Too short RRB frame (data_len=%lu)", - (unsigned long) data_len); - return -1; - } - - pos = data; - frame = (struct ft_rrb_frame *) pos; - pos += sizeof(*frame); - - alen = le_to_host16(frame->action_length); - wpa_printf(MSG_DEBUG, "FT: RRB frame - frame_type=%d packet_type=%d " - "action_length=%d ap_address=" MACSTR, - frame->frame_type, frame->packet_type, alen, - MAC2STR(frame->ap_address)); - - if (frame->frame_type != RSN_REMOTE_FRAME_TYPE_FT_RRB) { - /* Discard frame per IEEE Std 802.11r-2008, 11A.10.3 */ - wpa_printf(MSG_DEBUG, "FT: RRB discarded frame with " - "unrecognized type %d", frame->frame_type); - return -1; - } - - if (alen > data_len - sizeof(*frame)) { - wpa_printf(MSG_DEBUG, "FT: RRB frame too short for action " - "frame"); - return -1; - } - - if (frame->packet_type == FT_PACKET_R0KH_R1KH_PULL) - return wpa_ft_rrb_rx_pull(wpa_auth, src_addr, data, data_len); - if (frame->packet_type == FT_PACKET_R0KH_R1KH_RESP) - return wpa_ft_rrb_rx_resp(wpa_auth, src_addr, data, data_len); - if (frame->packet_type == FT_PACKET_R0KH_R1KH_PUSH) - return wpa_ft_rrb_rx_push(wpa_auth, src_addr, data, data_len); - - wpa_hexdump(MSG_MSGDUMP, "FT: RRB - FT Action frame", pos, alen); - - if (alen < 1 + 1 + 2 * ETH_ALEN) { - wpa_printf(MSG_DEBUG, "FT: Too short RRB frame (not enough " - "room for Action Frame body); alen=%lu", - (unsigned long) alen); - return -1; - } - start = pos; - end = pos + alen; - - if (*pos != WLAN_ACTION_FT) { - wpa_printf(MSG_DEBUG, "FT: Unexpected Action frame category " - "%d", *pos); - return -1; - } - - pos++; - action = *pos++; - sta_addr = pos; - pos += ETH_ALEN; - target_ap_addr = pos; - pos += ETH_ALEN; - wpa_printf(MSG_DEBUG, "FT: RRB Action Frame: action=%d sta_addr=" - MACSTR " target_ap_addr=" MACSTR, - action, MAC2STR(sta_addr), MAC2STR(target_ap_addr)); - - if (frame->packet_type == FT_PACKET_REQUEST) { - wpa_printf(MSG_DEBUG, "FT: FT Packet Type - Request"); - - if (action != 1) { - wpa_printf(MSG_DEBUG, "FT: Unexpected Action %d in " - "RRB Request", action); - return -1; - } - - if (os_memcmp(target_ap_addr, wpa_auth->addr, ETH_ALEN) != 0) { - wpa_printf(MSG_DEBUG, "FT: Target AP address in the " - "RRB Request does not match with own " - "address"); - return -1; - } - - if (wpa_ft_rrb_rx_request(wpa_auth, frame->ap_address, - sta_addr, pos, end - pos) < 0) - return -1; - } else if (frame->packet_type == FT_PACKET_RESPONSE) { - u16 status_code; - - if (end - pos < 2) { - wpa_printf(MSG_DEBUG, "FT: Not enough room for status " - "code in RRB Response"); - return -1; - } - status_code = WPA_GET_LE16(pos); - pos += 2; - - wpa_printf(MSG_DEBUG, "FT: FT Packet Type - Response " - "(status_code=%d)", status_code); - - if (wpa_ft_action_send(wpa_auth, sta_addr, start, alen) < 0) - return -1; - } else { - wpa_printf(MSG_DEBUG, "FT: RRB discarded frame with unknown " - "packet_type %d", frame->packet_type); - return -1; - } - - return 0; -} - - -static void wpa_ft_generate_pmk_r1(struct wpa_authenticator *wpa_auth, - struct wpa_ft_pmk_r0_sa *pmk_r0, - struct ft_remote_r1kh *r1kh, - const u8 *s1kh_id, int pairwise) -{ - struct ft_r0kh_r1kh_push_frame frame, f; - struct os_time now; - - os_memset(&frame, 0, sizeof(frame)); - frame.frame_type = RSN_REMOTE_FRAME_TYPE_FT_RRB; - frame.packet_type = FT_PACKET_R0KH_R1KH_PUSH; - frame.data_length = host_to_le16(FT_R0KH_R1KH_PUSH_DATA_LEN); - os_memcpy(frame.ap_address, wpa_auth->addr, ETH_ALEN); - - /* aes_wrap() does not support inplace encryption, so use a temporary - * buffer for the data. */ - os_memcpy(f.r1kh_id, r1kh->id, FT_R1KH_ID_LEN); - os_memcpy(f.s1kh_id, s1kh_id, ETH_ALEN); - os_memcpy(f.pmk_r0_name, pmk_r0->pmk_r0_name, WPA_PMK_NAME_LEN); - wpa_derive_pmk_r1(pmk_r0->pmk_r0, pmk_r0->pmk_r0_name, r1kh->id, - s1kh_id, f.pmk_r1, f.pmk_r1_name); - wpa_printf(MSG_DEBUG, "FT: R1KH-ID " MACSTR, MAC2STR(r1kh->id)); - wpa_hexdump_key(MSG_DEBUG, "FT: PMK-R1", f.pmk_r1, PMK_LEN); - wpa_hexdump(MSG_DEBUG, "FT: PMKR1Name", f.pmk_r1_name, - WPA_PMK_NAME_LEN); - os_get_time(&now); - WPA_PUT_LE32(f.timestamp, now.sec); - f.pairwise = host_to_le16(pairwise); - if (aes_wrap(r1kh->key, (FT_R0KH_R1KH_PUSH_DATA_LEN + 7) / 8, - f.timestamp, frame.timestamp) < 0) - return; - - wpa_ft_rrb_send(wpa_auth, r1kh->addr, (u8 *) &frame, sizeof(frame)); -} - - -void wpa_ft_push_pmk_r1(struct wpa_authenticator *wpa_auth, const u8 *addr) -{ - struct wpa_ft_pmk_r0_sa *r0; - struct ft_remote_r1kh *r1kh; - - if (!wpa_auth->conf.pmk_r1_push) - return; - - r0 = wpa_auth->ft_pmk_cache->pmk_r0; - while (r0) { - if (os_memcmp(r0->spa, addr, ETH_ALEN) == 0) - break; - r0 = r0->next; - } - - if (r0 == NULL || r0->pmk_r1_pushed) - return; - r0->pmk_r1_pushed = 1; - - wpa_printf(MSG_DEBUG, "FT: Deriving and pushing PMK-R1 keys to R1KHs " - "for STA " MACSTR, MAC2STR(addr)); - - r1kh = wpa_auth->conf.r1kh_list; - while (r1kh) { - wpa_ft_generate_pmk_r1(wpa_auth, r0, r1kh, addr, r0->pairwise); - r1kh = r1kh->next; - } -} - -#endif /* CONFIG_IEEE80211R */ diff --git a/hostapd-0.8/src/ap/wpa_auth_glue.c b/hostapd-0.8/src/ap/wpa_auth_glue.c deleted file mode 100644 index bdb3ed2..0000000 --- a/hostapd-0.8/src/ap/wpa_auth_glue.c +++ /dev/null @@ -1,571 +0,0 @@ -/* - * hostapd / WPA authenticator glue code - * Copyright (c) 2002-2011, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#include "utils/includes.h" - -#include "utils/common.h" -#include "common/ieee802_11_defs.h" -#include "eapol_auth/eapol_auth_sm.h" -#include "eapol_auth/eapol_auth_sm_i.h" -#include "eap_server/eap.h" -#include "l2_packet/l2_packet.h" -#include "drivers/driver.h" -#include "hostapd.h" -#include "ieee802_1x.h" -#include "preauth_auth.h" -#include "sta_info.h" -#include "tkip_countermeasures.h" -#include "ap_drv_ops.h" -#include "ap_config.h" -#include "wpa_auth.h" - - -static void hostapd_wpa_auth_conf(struct hostapd_bss_config *conf, - struct wpa_auth_config *wconf) -{ - wconf->wpa = conf->wpa; - wconf->wpa_key_mgmt = conf->wpa_key_mgmt; - wconf->wpa_pairwise = conf->wpa_pairwise; - wconf->wpa_group = conf->wpa_group; - wconf->wpa_group_rekey = conf->wpa_group_rekey; - wconf->wpa_strict_rekey = conf->wpa_strict_rekey; - wconf->wpa_gmk_rekey = conf->wpa_gmk_rekey; - wconf->wpa_ptk_rekey = conf->wpa_ptk_rekey; - wconf->rsn_pairwise = conf->rsn_pairwise; - wconf->rsn_preauth = conf->rsn_preauth; - wconf->eapol_version = conf->eapol_version; - wconf->peerkey = conf->peerkey; - wconf->wmm_enabled = conf->wmm_enabled; - wconf->wmm_uapsd = conf->wmm_uapsd; - wconf->okc = conf->okc; -#ifdef CONFIG_IEEE80211W - wconf->ieee80211w = conf->ieee80211w; -#endif /* CONFIG_IEEE80211W */ -#ifdef CONFIG_IEEE80211R - wconf->ssid_len = conf->ssid.ssid_len; - if (wconf->ssid_len > SSID_LEN) - wconf->ssid_len = SSID_LEN; - os_memcpy(wconf->ssid, conf->ssid.ssid, wconf->ssid_len); - os_memcpy(wconf->mobility_domain, conf->mobility_domain, - MOBILITY_DOMAIN_ID_LEN); - if (conf->nas_identifier && - os_strlen(conf->nas_identifier) <= FT_R0KH_ID_MAX_LEN) { - wconf->r0_key_holder_len = os_strlen(conf->nas_identifier); - os_memcpy(wconf->r0_key_holder, conf->nas_identifier, - wconf->r0_key_holder_len); - } - os_memcpy(wconf->r1_key_holder, conf->r1_key_holder, FT_R1KH_ID_LEN); - wconf->r0_key_lifetime = conf->r0_key_lifetime; - wconf->reassociation_deadline = conf->reassociation_deadline; - wconf->r0kh_list = conf->r0kh_list; - wconf->r1kh_list = conf->r1kh_list; - wconf->pmk_r1_push = conf->pmk_r1_push; - wconf->ft_over_ds = conf->ft_over_ds; -#endif /* CONFIG_IEEE80211R */ -} - - -static void hostapd_wpa_auth_logger(void *ctx, const u8 *addr, - logger_level level, const char *txt) -{ -#ifndef CONFIG_NO_HOSTAPD_LOGGER - struct hostapd_data *hapd = ctx; - int hlevel; - - switch (level) { - case LOGGER_WARNING: - hlevel = HOSTAPD_LEVEL_WARNING; - break; - case LOGGER_INFO: - hlevel = HOSTAPD_LEVEL_INFO; - break; - case LOGGER_DEBUG: - default: - hlevel = HOSTAPD_LEVEL_DEBUG; - break; - } - - hostapd_logger(hapd, addr, HOSTAPD_MODULE_WPA, hlevel, "%s", txt); -#endif /* CONFIG_NO_HOSTAPD_LOGGER */ -} - - -static void hostapd_wpa_auth_disconnect(void *ctx, const u8 *addr, - u16 reason) -{ - struct hostapd_data *hapd = ctx; - wpa_printf(MSG_DEBUG, "%s: WPA authenticator requests disconnect: " - "STA " MACSTR " reason %d", - __func__, MAC2STR(addr), reason); - ap_sta_disconnect(hapd, NULL, addr, reason); -} - - -static void hostapd_wpa_auth_mic_failure_report(void *ctx, const u8 *addr) -{ - struct hostapd_data *hapd = ctx; - michael_mic_failure(hapd, addr, 0); -} - - -static void hostapd_wpa_auth_set_eapol(void *ctx, const u8 *addr, - wpa_eapol_variable var, int value) -{ - struct hostapd_data *hapd = ctx; - struct sta_info *sta = ap_get_sta(hapd, addr); - if (sta == NULL) - return; - switch (var) { - case WPA_EAPOL_portEnabled: - ieee802_1x_notify_port_enabled(sta->eapol_sm, value); - break; - case WPA_EAPOL_portValid: - ieee802_1x_notify_port_valid(sta->eapol_sm, value); - break; - case WPA_EAPOL_authorized: - ieee802_1x_set_sta_authorized(hapd, sta, value); - break; - case WPA_EAPOL_portControl_Auto: - if (sta->eapol_sm) - sta->eapol_sm->portControl = Auto; - break; - case WPA_EAPOL_keyRun: - if (sta->eapol_sm) - sta->eapol_sm->keyRun = value ? TRUE : FALSE; - break; - case WPA_EAPOL_keyAvailable: - if (sta->eapol_sm) - sta->eapol_sm->eap_if->eapKeyAvailable = - value ? TRUE : FALSE; - break; - case WPA_EAPOL_keyDone: - if (sta->eapol_sm) - sta->eapol_sm->keyDone = value ? TRUE : FALSE; - break; - case WPA_EAPOL_inc_EapolFramesTx: - if (sta->eapol_sm) - sta->eapol_sm->dot1xAuthEapolFramesTx++; - break; - } -} - - -static int hostapd_wpa_auth_get_eapol(void *ctx, const u8 *addr, - wpa_eapol_variable var) -{ - struct hostapd_data *hapd = ctx; - struct sta_info *sta = ap_get_sta(hapd, addr); - if (sta == NULL || sta->eapol_sm == NULL) - return -1; - switch (var) { - case WPA_EAPOL_keyRun: - return sta->eapol_sm->keyRun; - case WPA_EAPOL_keyAvailable: - return sta->eapol_sm->eap_if->eapKeyAvailable; - default: - return -1; - } -} - - -static const u8 * hostapd_wpa_auth_get_psk(void *ctx, const u8 *addr, - const u8 *prev_psk) -{ - struct hostapd_data *hapd = ctx; - return hostapd_get_psk(hapd->conf, addr, prev_psk); -} - - -static int hostapd_wpa_auth_get_msk(void *ctx, const u8 *addr, u8 *msk, - size_t *len) -{ - struct hostapd_data *hapd = ctx; - const u8 *key; - size_t keylen; - struct sta_info *sta; - - sta = ap_get_sta(hapd, addr); - if (sta == NULL) - return -1; - - key = ieee802_1x_get_key(sta->eapol_sm, &keylen); - if (key == NULL) - return -1; - - if (keylen > *len) - keylen = *len; - os_memcpy(msk, key, keylen); - *len = keylen; - - return 0; -} - - -static int hostapd_wpa_auth_set_key(void *ctx, int vlan_id, enum wpa_alg alg, - const u8 *addr, int idx, u8 *key, - size_t key_len) -{ - struct hostapd_data *hapd = ctx; - const char *ifname = hapd->conf->iface; - - if (vlan_id > 0) { - ifname = hostapd_get_vlan_id_ifname(hapd->conf->vlan, vlan_id); - if (ifname == NULL) - return -1; - } - - return hostapd_drv_set_key(ifname, hapd, alg, addr, idx, 1, NULL, 0, - key, key_len); -} - - -static int hostapd_wpa_auth_get_seqnum(void *ctx, const u8 *addr, int idx, - u8 *seq) -{ - struct hostapd_data *hapd = ctx; - return hostapd_get_seqnum(hapd->conf->iface, hapd, addr, idx, seq); -} - - -static int hostapd_wpa_auth_send_eapol(void *ctx, const u8 *addr, - const u8 *data, size_t data_len, - int encrypt) -{ - struct hostapd_data *hapd = ctx; - struct sta_info *sta; - u32 flags = 0; - - sta = ap_get_sta(hapd, addr); - if (sta) - flags = hostapd_sta_flags_to_drv(sta->flags); - - return hostapd_drv_hapd_send_eapol(hapd, addr, data, data_len, - encrypt, flags); -} - - -static int hostapd_wpa_auth_for_each_sta( - void *ctx, int (*cb)(struct wpa_state_machine *sm, void *ctx), - void *cb_ctx) -{ - struct hostapd_data *hapd = ctx; - struct sta_info *sta; - - for (sta = hapd->sta_list; sta; sta = sta->next) { - if (sta->wpa_sm && cb(sta->wpa_sm, cb_ctx)) - return 1; - } - return 0; -} - - -struct wpa_auth_iface_iter_data { - int (*cb)(struct wpa_authenticator *sm, void *ctx); - void *cb_ctx; -}; - -static int wpa_auth_iface_iter(struct hostapd_iface *iface, void *ctx) -{ - struct wpa_auth_iface_iter_data *data = ctx; - size_t i; - for (i = 0; i < iface->num_bss; i++) { - if (iface->bss[i]->wpa_auth && - data->cb(iface->bss[i]->wpa_auth, data->cb_ctx)) - return 1; - } - return 0; -} - - -static int hostapd_wpa_auth_for_each_auth( - void *ctx, int (*cb)(struct wpa_authenticator *sm, void *ctx), - void *cb_ctx) -{ - struct hostapd_data *hapd = ctx; - struct wpa_auth_iface_iter_data data; - if (hapd->iface->for_each_interface == NULL) - return -1; - data.cb = cb; - data.cb_ctx = cb_ctx; - return hapd->iface->for_each_interface(hapd->iface->interfaces, - wpa_auth_iface_iter, &data); -} - - -#ifdef CONFIG_IEEE80211R - -struct wpa_auth_ft_iface_iter_data { - struct hostapd_data *src_hapd; - const u8 *dst; - const u8 *data; - size_t data_len; -}; - - -static int hostapd_wpa_auth_ft_iter(struct hostapd_iface *iface, void *ctx) -{ - struct wpa_auth_ft_iface_iter_data *idata = ctx; - struct hostapd_data *hapd; - size_t j; - - for (j = 0; j < iface->num_bss; j++) { - hapd = iface->bss[j]; - if (hapd == idata->src_hapd) - continue; - if (os_memcmp(hapd->own_addr, idata->dst, ETH_ALEN) == 0) { - wpa_printf(MSG_DEBUG, "FT: Send RRB data directly to " - "locally managed BSS " MACSTR "@%s -> " - MACSTR "@%s", - MAC2STR(idata->src_hapd->own_addr), - idata->src_hapd->conf->iface, - MAC2STR(hapd->own_addr), hapd->conf->iface); - wpa_ft_rrb_rx(hapd->wpa_auth, - idata->src_hapd->own_addr, - idata->data, idata->data_len); - return 1; - } - } - - return 0; -} - -#endif /* CONFIG_IEEE80211R */ - - -static int hostapd_wpa_auth_send_ether(void *ctx, const u8 *dst, u16 proto, - const u8 *data, size_t data_len) -{ - struct hostapd_data *hapd = ctx; - struct l2_ethhdr *buf; - int ret; - -#ifdef CONFIG_IEEE80211R - if (proto == ETH_P_RRB && hapd->iface->for_each_interface) { - int res; - struct wpa_auth_ft_iface_iter_data idata; - idata.src_hapd = hapd; - idata.dst = dst; - idata.data = data; - idata.data_len = data_len; - res = hapd->iface->for_each_interface(hapd->iface->interfaces, - hostapd_wpa_auth_ft_iter, - &idata); - if (res == 1) - return data_len; - } -#endif /* CONFIG_IEEE80211R */ - - if (hapd->driver && hapd->driver->send_ether) - return hapd->driver->send_ether(hapd->drv_priv, dst, - hapd->own_addr, proto, - data, data_len); - if (hapd->l2 == NULL) - return -1; - - buf = os_malloc(sizeof(*buf) + data_len); - if (buf == NULL) - return -1; - os_memcpy(buf->h_dest, dst, ETH_ALEN); - os_memcpy(buf->h_source, hapd->own_addr, ETH_ALEN); - buf->h_proto = host_to_be16(proto); - os_memcpy(buf + 1, data, data_len); - ret = l2_packet_send(hapd->l2, dst, proto, (u8 *) buf, - sizeof(*buf) + data_len); - os_free(buf); - return ret; -} - - -#ifdef CONFIG_IEEE80211R - -static int hostapd_wpa_auth_send_ft_action(void *ctx, const u8 *dst, - const u8 *data, size_t data_len) -{ - struct hostapd_data *hapd = ctx; - int res; - struct ieee80211_mgmt *m; - size_t mlen; - struct sta_info *sta; - - sta = ap_get_sta(hapd, dst); - if (sta == NULL || sta->wpa_sm == NULL) - return -1; - - m = os_zalloc(sizeof(*m) + data_len); - if (m == NULL) - return -1; - mlen = ((u8 *) &m->u - (u8 *) m) + data_len; - m->frame_control = IEEE80211_FC(WLAN_FC_TYPE_MGMT, - WLAN_FC_STYPE_ACTION); - os_memcpy(m->da, dst, ETH_ALEN); - os_memcpy(m->sa, hapd->own_addr, ETH_ALEN); - os_memcpy(m->bssid, hapd->own_addr, ETH_ALEN); - os_memcpy(&m->u, data, data_len); - - res = hostapd_drv_send_mlme(hapd, (u8 *) m, mlen); - os_free(m); - return res; -} - - -static struct wpa_state_machine * -hostapd_wpa_auth_add_sta(void *ctx, const u8 *sta_addr) -{ - struct hostapd_data *hapd = ctx; - struct sta_info *sta; - - sta = ap_sta_add(hapd, sta_addr); - if (sta == NULL) - return NULL; - if (sta->wpa_sm) { - sta->auth_alg = WLAN_AUTH_FT; - return sta->wpa_sm; - } - - sta->wpa_sm = wpa_auth_sta_init(hapd->wpa_auth, sta->addr); - if (sta->wpa_sm == NULL) { - ap_free_sta(hapd, sta); - return NULL; - } - sta->auth_alg = WLAN_AUTH_FT; - - return sta->wpa_sm; -} - - -static void hostapd_rrb_receive(void *ctx, const u8 *src_addr, const u8 *buf, - size_t len) -{ - struct hostapd_data *hapd = ctx; - struct l2_ethhdr *ethhdr; - if (len < sizeof(*ethhdr)) - return; - ethhdr = (struct l2_ethhdr *) buf; - wpa_printf(MSG_DEBUG, "FT: RRB received packet " MACSTR " -> " - MACSTR, MAC2STR(ethhdr->h_source), MAC2STR(ethhdr->h_dest)); - wpa_ft_rrb_rx(hapd->wpa_auth, ethhdr->h_source, buf + sizeof(*ethhdr), - len - sizeof(*ethhdr)); -} - -#endif /* CONFIG_IEEE80211R */ - - -int hostapd_setup_wpa(struct hostapd_data *hapd) -{ - struct wpa_auth_config _conf; - struct wpa_auth_callbacks cb; - const u8 *wpa_ie; - size_t wpa_ie_len; - - hostapd_wpa_auth_conf(hapd->conf, &_conf); - if (hapd->iface->drv_flags & WPA_DRIVER_FLAGS_EAPOL_TX_STATUS) - _conf.tx_status = 1; - os_memset(&cb, 0, sizeof(cb)); - cb.ctx = hapd; - cb.logger = hostapd_wpa_auth_logger; - cb.disconnect = hostapd_wpa_auth_disconnect; - cb.mic_failure_report = hostapd_wpa_auth_mic_failure_report; - cb.set_eapol = hostapd_wpa_auth_set_eapol; - cb.get_eapol = hostapd_wpa_auth_get_eapol; - cb.get_psk = hostapd_wpa_auth_get_psk; - cb.get_msk = hostapd_wpa_auth_get_msk; - cb.set_key = hostapd_wpa_auth_set_key; - cb.get_seqnum = hostapd_wpa_auth_get_seqnum; - cb.send_eapol = hostapd_wpa_auth_send_eapol; - cb.for_each_sta = hostapd_wpa_auth_for_each_sta; - cb.for_each_auth = hostapd_wpa_auth_for_each_auth; - cb.send_ether = hostapd_wpa_auth_send_ether; -#ifdef CONFIG_IEEE80211R - cb.send_ft_action = hostapd_wpa_auth_send_ft_action; - cb.add_sta = hostapd_wpa_auth_add_sta; -#endif /* CONFIG_IEEE80211R */ - hapd->wpa_auth = wpa_init(hapd->own_addr, &_conf, &cb); - if (hapd->wpa_auth == NULL) { - wpa_printf(MSG_ERROR, "WPA initialization failed."); - return -1; - } - - if (hostapd_set_privacy(hapd, 1)) { - wpa_printf(MSG_ERROR, "Could not set PrivacyInvoked " - "for interface %s", hapd->conf->iface); - return -1; - } - - wpa_ie = wpa_auth_get_wpa_ie(hapd->wpa_auth, &wpa_ie_len); - if (hostapd_set_generic_elem(hapd, wpa_ie, wpa_ie_len)) { - wpa_printf(MSG_ERROR, "Failed to configure WPA IE for " - "the kernel driver."); - return -1; - } - - if (rsn_preauth_iface_init(hapd)) { - wpa_printf(MSG_ERROR, "Initialization of RSN " - "pre-authentication failed."); - return -1; - } - -#ifdef CONFIG_IEEE80211R - if (!hostapd_drv_none(hapd)) { - hapd->l2 = l2_packet_init(hapd->conf->bridge[0] ? - hapd->conf->bridge : - hapd->conf->iface, NULL, ETH_P_RRB, - hostapd_rrb_receive, hapd, 1); - if (hapd->l2 == NULL && - (hapd->driver == NULL || - hapd->driver->send_ether == NULL)) { - wpa_printf(MSG_ERROR, "Failed to open l2_packet " - "interface"); - return -1; - } - } -#endif /* CONFIG_IEEE80211R */ - - return 0; - -} - - -void hostapd_reconfig_wpa(struct hostapd_data *hapd) -{ - struct wpa_auth_config wpa_auth_conf; - hostapd_wpa_auth_conf(hapd->conf, &wpa_auth_conf); - wpa_reconfig(hapd->wpa_auth, &wpa_auth_conf); -} - - -void hostapd_deinit_wpa(struct hostapd_data *hapd) -{ - rsn_preauth_iface_deinit(hapd); - if (hapd->wpa_auth) { - wpa_deinit(hapd->wpa_auth); - hapd->wpa_auth = NULL; - - if (hostapd_set_privacy(hapd, 0)) { - wpa_printf(MSG_DEBUG, "Could not disable " - "PrivacyInvoked for interface %s", - hapd->conf->iface); - } - - if (hostapd_set_generic_elem(hapd, (u8 *) "", 0)) { - wpa_printf(MSG_DEBUG, "Could not remove generic " - "information element from interface %s", - hapd->conf->iface); - } - } - ieee802_1x_deinit(hapd); - -#ifdef CONFIG_IEEE80211R - l2_packet_deinit(hapd->l2); -#endif /* CONFIG_IEEE80211R */ -} diff --git a/hostapd-0.8/src/ap/wpa_auth_glue.h b/hostapd-0.8/src/ap/wpa_auth_glue.h deleted file mode 100644 index 79d7e05..0000000 --- a/hostapd-0.8/src/ap/wpa_auth_glue.h +++ /dev/null @@ -1,22 +0,0 @@ -/* - * hostapd / WPA authenticator glue code - * Copyright (c) 2002-2009, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#ifndef WPA_AUTH_GLUE_H -#define WPA_AUTH_GLUE_H - -int hostapd_setup_wpa(struct hostapd_data *hapd); -void hostapd_reconfig_wpa(struct hostapd_data *hapd); -void hostapd_deinit_wpa(struct hostapd_data *hapd); - -#endif /* WPA_AUTH_GLUE_H */ diff --git a/hostapd-0.8/src/ap/wpa_auth_i.h b/hostapd-0.8/src/ap/wpa_auth_i.h deleted file mode 100644 index 67a5c3b..0000000 --- a/hostapd-0.8/src/ap/wpa_auth_i.h +++ /dev/null @@ -1,234 +0,0 @@ -/* - * hostapd - IEEE 802.11i-2004 / WPA Authenticator: Internal definitions - * Copyright (c) 2004-2007, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#ifndef WPA_AUTH_I_H -#define WPA_AUTH_I_H - -/* max(dot11RSNAConfigGroupUpdateCount,dot11RSNAConfigPairwiseUpdateCount) */ -#define RSNA_MAX_EAPOL_RETRIES 4 - -struct wpa_group; - -struct wpa_stsl_negotiation { - struct wpa_stsl_negotiation *next; - u8 initiator[ETH_ALEN]; - u8 peer[ETH_ALEN]; -}; - - -struct wpa_state_machine { - struct wpa_authenticator *wpa_auth; - struct wpa_group *group; - - u8 addr[ETH_ALEN]; - - enum { - WPA_PTK_INITIALIZE, WPA_PTK_DISCONNECT, WPA_PTK_DISCONNECTED, - WPA_PTK_AUTHENTICATION, WPA_PTK_AUTHENTICATION2, - WPA_PTK_INITPMK, WPA_PTK_INITPSK, WPA_PTK_PTKSTART, - WPA_PTK_PTKCALCNEGOTIATING, WPA_PTK_PTKCALCNEGOTIATING2, - WPA_PTK_PTKINITNEGOTIATING, WPA_PTK_PTKINITDONE - } wpa_ptk_state; - - enum { - WPA_PTK_GROUP_IDLE = 0, - WPA_PTK_GROUP_REKEYNEGOTIATING, - WPA_PTK_GROUP_REKEYESTABLISHED, - WPA_PTK_GROUP_KEYERROR - } wpa_ptk_group_state; - - Boolean Init; - Boolean DeauthenticationRequest; - Boolean AuthenticationRequest; - Boolean ReAuthenticationRequest; - Boolean Disconnect; - int TimeoutCtr; - int GTimeoutCtr; - Boolean TimeoutEvt; - Boolean EAPOLKeyReceived; - Boolean EAPOLKeyPairwise; - Boolean EAPOLKeyRequest; - Boolean MICVerified; - Boolean GUpdateStationKeys; - u8 ANonce[WPA_NONCE_LEN]; - u8 SNonce[WPA_NONCE_LEN]; - u8 PMK[PMK_LEN]; - struct wpa_ptk PTK; - Boolean PTK_valid; - Boolean pairwise_set; - int keycount; - Boolean Pair; - struct { - u8 counter[WPA_REPLAY_COUNTER_LEN]; - Boolean valid; - } key_replay[RSNA_MAX_EAPOL_RETRIES]; - Boolean PInitAKeys; /* WPA only, not in IEEE 802.11i */ - Boolean PTKRequest; /* not in IEEE 802.11i state machine */ - Boolean has_GTK; - Boolean PtkGroupInit; /* init request for PTK Group state machine */ - - u8 *last_rx_eapol_key; /* starting from IEEE 802.1X header */ - size_t last_rx_eapol_key_len; - - unsigned int changed:1; - unsigned int in_step_loop:1; - unsigned int pending_deinit:1; - unsigned int started:1; - unsigned int mgmt_frame_prot:1; -#ifdef CONFIG_IEEE80211R - unsigned int ft_completed:1; - unsigned int pmk_r1_name_valid:1; -#endif /* CONFIG_IEEE80211R */ - - u8 req_replay_counter[WPA_REPLAY_COUNTER_LEN]; - int req_replay_counter_used; - - u8 *wpa_ie; - size_t wpa_ie_len; - - enum { - WPA_VERSION_NO_WPA = 0 /* WPA not used */, - WPA_VERSION_WPA = 1 /* WPA / IEEE 802.11i/D3.0 */, - WPA_VERSION_WPA2 = 2 /* WPA2 / IEEE 802.11i */ - } wpa; - int pairwise; /* Pairwise cipher suite, WPA_CIPHER_* */ - int wpa_key_mgmt; /* the selected WPA_KEY_MGMT_* */ - struct rsn_pmksa_cache_entry *pmksa; - - u32 dot11RSNAStatsTKIPLocalMICFailures; - u32 dot11RSNAStatsTKIPRemoteMICFailures; - -#ifdef CONFIG_IEEE80211R - u8 xxkey[PMK_LEN]; /* PSK or the second 256 bits of MSK */ - size_t xxkey_len; - u8 pmk_r1_name[WPA_PMK_NAME_LEN]; /* PMKR1Name derived from FT Auth - * Request */ - u8 r0kh_id[FT_R0KH_ID_MAX_LEN]; /* R0KH-ID from FT Auth Request */ - size_t r0kh_id_len; - u8 sup_pmk_r1_name[WPA_PMK_NAME_LEN]; /* PMKR1Name from EAPOL-Key - * message 2/4 */ - u8 *assoc_resp_ftie; -#endif /* CONFIG_IEEE80211R */ - - int pending_1_of_4_timeout; -}; - - -/* per group key state machine data */ -struct wpa_group { - struct wpa_group *next; - int vlan_id; - - Boolean GInit; - int GKeyDoneStations; - Boolean GTKReKey; - int GTK_len; - int GN, GM; - Boolean GTKAuthenticator; - u8 Counter[WPA_NONCE_LEN]; - - enum { - WPA_GROUP_GTK_INIT = 0, - WPA_GROUP_SETKEYS, WPA_GROUP_SETKEYSDONE - } wpa_group_state; - - u8 GMK[WPA_GMK_LEN]; - u8 GTK[2][WPA_GTK_MAX_LEN]; - u8 GNonce[WPA_NONCE_LEN]; - Boolean changed; - Boolean first_sta_seen; - Boolean reject_4way_hs_for_entropy; -#ifdef CONFIG_IEEE80211W - u8 IGTK[2][WPA_IGTK_LEN]; - int GN_igtk, GM_igtk; -#endif /* CONFIG_IEEE80211W */ -}; - - -struct wpa_ft_pmk_cache; - -/* per authenticator data */ -struct wpa_authenticator { - struct wpa_group *group; - - unsigned int dot11RSNAStatsTKIPRemoteMICFailures; - u32 dot11RSNAAuthenticationSuiteSelected; - u32 dot11RSNAPairwiseCipherSelected; - u32 dot11RSNAGroupCipherSelected; - u8 dot11RSNAPMKIDUsed[PMKID_LEN]; - u32 dot11RSNAAuthenticationSuiteRequested; /* FIX: update */ - u32 dot11RSNAPairwiseCipherRequested; /* FIX: update */ - u32 dot11RSNAGroupCipherRequested; /* FIX: update */ - unsigned int dot11RSNATKIPCounterMeasuresInvoked; - unsigned int dot11RSNA4WayHandshakeFailures; - - struct wpa_stsl_negotiation *stsl_negotiations; - - struct wpa_auth_config conf; - struct wpa_auth_callbacks cb; - - u8 *wpa_ie; - size_t wpa_ie_len; - - u8 addr[ETH_ALEN]; - - struct rsn_pmksa_cache *pmksa; - struct wpa_ft_pmk_cache *ft_pmk_cache; -}; - - -int wpa_write_rsn_ie(struct wpa_auth_config *conf, u8 *buf, size_t len, - const u8 *pmkid); -void wpa_auth_logger(struct wpa_authenticator *wpa_auth, const u8 *addr, - logger_level level, const char *txt); -void wpa_auth_vlogger(struct wpa_authenticator *wpa_auth, const u8 *addr, - logger_level level, const char *fmt, ...); -void __wpa_send_eapol(struct wpa_authenticator *wpa_auth, - struct wpa_state_machine *sm, int key_info, - const u8 *key_rsc, const u8 *nonce, - const u8 *kde, size_t kde_len, - int keyidx, int encr, int force_version); -int wpa_auth_for_each_sta(struct wpa_authenticator *wpa_auth, - int (*cb)(struct wpa_state_machine *sm, void *ctx), - void *cb_ctx); -int wpa_auth_for_each_auth(struct wpa_authenticator *wpa_auth, - int (*cb)(struct wpa_authenticator *a, void *ctx), - void *cb_ctx); - -#ifdef CONFIG_PEERKEY -int wpa_stsl_remove(struct wpa_authenticator *wpa_auth, - struct wpa_stsl_negotiation *neg); -void wpa_smk_error(struct wpa_authenticator *wpa_auth, - struct wpa_state_machine *sm, struct wpa_eapol_key *key); -void wpa_smk_m1(struct wpa_authenticator *wpa_auth, - struct wpa_state_machine *sm, struct wpa_eapol_key *key); -void wpa_smk_m3(struct wpa_authenticator *wpa_auth, - struct wpa_state_machine *sm, struct wpa_eapol_key *key); -#endif /* CONFIG_PEERKEY */ - -#ifdef CONFIG_IEEE80211R -int wpa_write_mdie(struct wpa_auth_config *conf, u8 *buf, size_t len); -int wpa_write_ftie(struct wpa_auth_config *conf, const u8 *r0kh_id, - size_t r0kh_id_len, - const u8 *anonce, const u8 *snonce, - u8 *buf, size_t len, const u8 *subelem, - size_t subelem_len); -int wpa_auth_derive_ptk_ft(struct wpa_state_machine *sm, const u8 *pmk, - struct wpa_ptk *ptk, size_t ptk_len); -struct wpa_ft_pmk_cache * wpa_ft_pmk_cache_init(void); -void wpa_ft_pmk_cache_deinit(struct wpa_ft_pmk_cache *cache); -void wpa_ft_install_ptk(struct wpa_state_machine *sm); -#endif /* CONFIG_IEEE80211R */ - -#endif /* WPA_AUTH_I_H */ diff --git a/hostapd-0.8/src/ap/wpa_auth_ie.c b/hostapd-0.8/src/ap/wpa_auth_ie.c deleted file mode 100644 index 5e8d134..0000000 --- a/hostapd-0.8/src/ap/wpa_auth_ie.c +++ /dev/null @@ -1,824 +0,0 @@ -/* - * hostapd - WPA/RSN IE and KDE definitions - * Copyright (c) 2004-2008, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#include "utils/includes.h" - -#include "utils/common.h" -#include "common/ieee802_11_defs.h" -#include "eapol_auth/eapol_auth_sm.h" -#include "ap_config.h" -#include "ieee802_11.h" -#include "wpa_auth.h" -#include "pmksa_cache_auth.h" -#include "wpa_auth_ie.h" -#include "wpa_auth_i.h" - - -#ifdef CONFIG_RSN_TESTING -int rsn_testing = 0; -#endif /* CONFIG_RSN_TESTING */ - - -static int wpa_write_wpa_ie(struct wpa_auth_config *conf, u8 *buf, size_t len) -{ - struct wpa_ie_hdr *hdr; - int num_suites; - u8 *pos, *count; - - hdr = (struct wpa_ie_hdr *) buf; - hdr->elem_id = WLAN_EID_VENDOR_SPECIFIC; - RSN_SELECTOR_PUT(hdr->oui, WPA_OUI_TYPE); - WPA_PUT_LE16(hdr->version, WPA_VERSION); - pos = (u8 *) (hdr + 1); - - if (conf->wpa_group == WPA_CIPHER_CCMP) { - RSN_SELECTOR_PUT(pos, WPA_CIPHER_SUITE_CCMP); - } else if (conf->wpa_group == WPA_CIPHER_TKIP) { - RSN_SELECTOR_PUT(pos, WPA_CIPHER_SUITE_TKIP); - } else if (conf->wpa_group == WPA_CIPHER_WEP104) { - RSN_SELECTOR_PUT(pos, WPA_CIPHER_SUITE_WEP104); - } else if (conf->wpa_group == WPA_CIPHER_WEP40) { - RSN_SELECTOR_PUT(pos, WPA_CIPHER_SUITE_WEP40); - } else { - wpa_printf(MSG_DEBUG, "Invalid group cipher (%d).", - conf->wpa_group); - return -1; - } - pos += WPA_SELECTOR_LEN; - - num_suites = 0; - count = pos; - pos += 2; - - if (conf->wpa_pairwise & WPA_CIPHER_CCMP) { - RSN_SELECTOR_PUT(pos, WPA_CIPHER_SUITE_CCMP); - pos += WPA_SELECTOR_LEN; - num_suites++; - } - if (conf->wpa_pairwise & WPA_CIPHER_TKIP) { - RSN_SELECTOR_PUT(pos, WPA_CIPHER_SUITE_TKIP); - pos += WPA_SELECTOR_LEN; - num_suites++; - } - if (conf->wpa_pairwise & WPA_CIPHER_NONE) { - RSN_SELECTOR_PUT(pos, WPA_CIPHER_SUITE_NONE); - pos += WPA_SELECTOR_LEN; - num_suites++; - } - - if (num_suites == 0) { - wpa_printf(MSG_DEBUG, "Invalid pairwise cipher (%d).", - conf->wpa_pairwise); - return -1; - } - WPA_PUT_LE16(count, num_suites); - - num_suites = 0; - count = pos; - pos += 2; - - if (conf->wpa_key_mgmt & WPA_KEY_MGMT_IEEE8021X) { - RSN_SELECTOR_PUT(pos, WPA_AUTH_KEY_MGMT_UNSPEC_802_1X); - pos += WPA_SELECTOR_LEN; - num_suites++; - } - if (conf->wpa_key_mgmt & WPA_KEY_MGMT_PSK) { - RSN_SELECTOR_PUT(pos, WPA_AUTH_KEY_MGMT_PSK_OVER_802_1X); - pos += WPA_SELECTOR_LEN; - num_suites++; - } - - if (num_suites == 0) { - wpa_printf(MSG_DEBUG, "Invalid key management type (%d).", - conf->wpa_key_mgmt); - return -1; - } - WPA_PUT_LE16(count, num_suites); - - /* WPA Capabilities; use defaults, so no need to include it */ - - hdr->len = (pos - buf) - 2; - - return pos - buf; -} - - -int wpa_write_rsn_ie(struct wpa_auth_config *conf, u8 *buf, size_t len, - const u8 *pmkid) -{ - struct rsn_ie_hdr *hdr; - int num_suites; - u8 *pos, *count; - u16 capab; - - hdr = (struct rsn_ie_hdr *) buf; - hdr->elem_id = WLAN_EID_RSN; - WPA_PUT_LE16(hdr->version, RSN_VERSION); - pos = (u8 *) (hdr + 1); - - if (conf->wpa_group == WPA_CIPHER_CCMP) { - RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_CCMP); - } else if (conf->wpa_group == WPA_CIPHER_TKIP) { - RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_TKIP); - } else if (conf->wpa_group == WPA_CIPHER_WEP104) { - RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_WEP104); - } else if (conf->wpa_group == WPA_CIPHER_WEP40) { - RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_WEP40); - } else { - wpa_printf(MSG_DEBUG, "Invalid group cipher (%d).", - conf->wpa_group); - return -1; - } - pos += RSN_SELECTOR_LEN; - - num_suites = 0; - count = pos; - pos += 2; - -#ifdef CONFIG_RSN_TESTING - if (rsn_testing) { - RSN_SELECTOR_PUT(pos, RSN_SELECTOR(0x12, 0x34, 0x56, 1)); - pos += RSN_SELECTOR_LEN; - num_suites++; - } -#endif /* CONFIG_RSN_TESTING */ - - if (conf->rsn_pairwise & WPA_CIPHER_CCMP) { - RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_CCMP); - pos += RSN_SELECTOR_LEN; - num_suites++; - } - if (conf->rsn_pairwise & WPA_CIPHER_TKIP) { - RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_TKIP); - pos += RSN_SELECTOR_LEN; - num_suites++; - } - if (conf->rsn_pairwise & WPA_CIPHER_NONE) { - RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_NONE); - pos += RSN_SELECTOR_LEN; - num_suites++; - } - -#ifdef CONFIG_RSN_TESTING - if (rsn_testing) { - RSN_SELECTOR_PUT(pos, RSN_SELECTOR(0x12, 0x34, 0x56, 2)); - pos += RSN_SELECTOR_LEN; - num_suites++; - } -#endif /* CONFIG_RSN_TESTING */ - - if (num_suites == 0) { - wpa_printf(MSG_DEBUG, "Invalid pairwise cipher (%d).", - conf->rsn_pairwise); - return -1; - } - WPA_PUT_LE16(count, num_suites); - - num_suites = 0; - count = pos; - pos += 2; - -#ifdef CONFIG_RSN_TESTING - if (rsn_testing) { - RSN_SELECTOR_PUT(pos, RSN_SELECTOR(0x12, 0x34, 0x56, 1)); - pos += RSN_SELECTOR_LEN; - num_suites++; - } -#endif /* CONFIG_RSN_TESTING */ - - if (conf->wpa_key_mgmt & WPA_KEY_MGMT_IEEE8021X) { - RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_UNSPEC_802_1X); - pos += RSN_SELECTOR_LEN; - num_suites++; - } - if (conf->wpa_key_mgmt & WPA_KEY_MGMT_PSK) { - RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_PSK_OVER_802_1X); - pos += RSN_SELECTOR_LEN; - num_suites++; - } -#ifdef CONFIG_IEEE80211R - if (conf->wpa_key_mgmt & WPA_KEY_MGMT_FT_IEEE8021X) { - RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_FT_802_1X); - pos += RSN_SELECTOR_LEN; - num_suites++; - } - if (conf->wpa_key_mgmt & WPA_KEY_MGMT_FT_PSK) { - RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_FT_PSK); - pos += RSN_SELECTOR_LEN; - num_suites++; - } -#endif /* CONFIG_IEEE80211R */ -#ifdef CONFIG_IEEE80211W - if (conf->wpa_key_mgmt & WPA_KEY_MGMT_IEEE8021X_SHA256) { - RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_802_1X_SHA256); - pos += RSN_SELECTOR_LEN; - num_suites++; - } - if (conf->wpa_key_mgmt & WPA_KEY_MGMT_PSK_SHA256) { - RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_PSK_SHA256); - pos += RSN_SELECTOR_LEN; - num_suites++; - } -#endif /* CONFIG_IEEE80211W */ - -#ifdef CONFIG_RSN_TESTING - if (rsn_testing) { - RSN_SELECTOR_PUT(pos, RSN_SELECTOR(0x12, 0x34, 0x56, 2)); - pos += RSN_SELECTOR_LEN; - num_suites++; - } -#endif /* CONFIG_RSN_TESTING */ - - if (num_suites == 0) { - wpa_printf(MSG_DEBUG, "Invalid key management type (%d).", - conf->wpa_key_mgmt); - return -1; - } - WPA_PUT_LE16(count, num_suites); - - /* RSN Capabilities */ - capab = 0; - if (conf->rsn_preauth) - capab |= WPA_CAPABILITY_PREAUTH; - if (conf->peerkey) - capab |= WPA_CAPABILITY_PEERKEY_ENABLED; - if (conf->wmm_enabled) { - /* 4 PTKSA replay counters when using WMM */ - capab |= (RSN_NUM_REPLAY_COUNTERS_16 << 2); - } -#ifdef CONFIG_IEEE80211W - if (conf->ieee80211w != NO_MGMT_FRAME_PROTECTION) { - capab |= WPA_CAPABILITY_MFPC; - if (conf->ieee80211w == MGMT_FRAME_PROTECTION_REQUIRED) - capab |= WPA_CAPABILITY_MFPR; - } -#endif /* CONFIG_IEEE80211W */ -#ifdef CONFIG_RSN_TESTING - if (rsn_testing) - capab |= BIT(8) | BIT(14) | BIT(15); -#endif /* CONFIG_RSN_TESTING */ - WPA_PUT_LE16(pos, capab); - pos += 2; - - if (pmkid) { - if (pos + 2 + PMKID_LEN > buf + len) - return -1; - /* PMKID Count */ - WPA_PUT_LE16(pos, 1); - pos += 2; - os_memcpy(pos, pmkid, PMKID_LEN); - pos += PMKID_LEN; - } - -#ifdef CONFIG_IEEE80211W - if (conf->ieee80211w != NO_MGMT_FRAME_PROTECTION) { - if (pos + 2 + 4 > buf + len) - return -1; - if (pmkid == NULL) { - /* PMKID Count */ - WPA_PUT_LE16(pos, 0); - pos += 2; - } - - /* Management Group Cipher Suite */ - RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_AES_128_CMAC); - pos += RSN_SELECTOR_LEN; - } -#endif /* CONFIG_IEEE80211W */ - -#ifdef CONFIG_RSN_TESTING - if (rsn_testing) { - /* - * Fill in any defined fields and add extra data to the end of - * the element. - */ - int pmkid_count_set = pmkid != NULL; - if (conf->ieee80211w != NO_MGMT_FRAME_PROTECTION) - pmkid_count_set = 1; - /* PMKID Count */ - WPA_PUT_LE16(pos, 0); - pos += 2; - if (conf->ieee80211w == NO_MGMT_FRAME_PROTECTION) { - /* Management Group Cipher Suite */ - RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_AES_128_CMAC); - pos += RSN_SELECTOR_LEN; - } - - os_memset(pos, 0x12, 17); - pos += 17; - } -#endif /* CONFIG_RSN_TESTING */ - - hdr->len = (pos - buf) - 2; - - return pos - buf; -} - - -int wpa_auth_gen_wpa_ie(struct wpa_authenticator *wpa_auth) -{ - u8 *pos, buf[128]; - int res; - - pos = buf; - - if (wpa_auth->conf.wpa & WPA_PROTO_RSN) { - res = wpa_write_rsn_ie(&wpa_auth->conf, - pos, buf + sizeof(buf) - pos, NULL); - if (res < 0) - return res; - pos += res; - } -#ifdef CONFIG_IEEE80211R - if (wpa_auth->conf.wpa_key_mgmt & - (WPA_KEY_MGMT_FT_IEEE8021X | WPA_KEY_MGMT_FT_PSK)) { - res = wpa_write_mdie(&wpa_auth->conf, pos, - buf + sizeof(buf) - pos); - if (res < 0) - return res; - pos += res; - } -#endif /* CONFIG_IEEE80211R */ - if (wpa_auth->conf.wpa & WPA_PROTO_WPA) { - res = wpa_write_wpa_ie(&wpa_auth->conf, - pos, buf + sizeof(buf) - pos); - if (res < 0) - return res; - pos += res; - } - - os_free(wpa_auth->wpa_ie); - wpa_auth->wpa_ie = os_malloc(pos - buf); - if (wpa_auth->wpa_ie == NULL) - return -1; - os_memcpy(wpa_auth->wpa_ie, buf, pos - buf); - wpa_auth->wpa_ie_len = pos - buf; - - return 0; -} - - -u8 * wpa_add_kde(u8 *pos, u32 kde, const u8 *data, size_t data_len, - const u8 *data2, size_t data2_len) -{ - *pos++ = WLAN_EID_VENDOR_SPECIFIC; - *pos++ = RSN_SELECTOR_LEN + data_len + data2_len; - RSN_SELECTOR_PUT(pos, kde); - pos += RSN_SELECTOR_LEN; - os_memcpy(pos, data, data_len); - pos += data_len; - if (data2) { - os_memcpy(pos, data2, data2_len); - pos += data2_len; - } - return pos; -} - - -struct wpa_auth_okc_iter_data { - struct rsn_pmksa_cache_entry *pmksa; - const u8 *aa; - const u8 *spa; - const u8 *pmkid; -}; - - -static int wpa_auth_okc_iter(struct wpa_authenticator *a, void *ctx) -{ - struct wpa_auth_okc_iter_data *data = ctx; - data->pmksa = pmksa_cache_get_okc(a->pmksa, data->aa, data->spa, - data->pmkid); - if (data->pmksa) - return 1; - return 0; -} - - -int wpa_validate_wpa_ie(struct wpa_authenticator *wpa_auth, - struct wpa_state_machine *sm, - const u8 *wpa_ie, size_t wpa_ie_len, - const u8 *mdie, size_t mdie_len) -{ - struct wpa_ie_data data; - int ciphers, key_mgmt, res, version; - u32 selector; - size_t i; - const u8 *pmkid = NULL; - - if (wpa_auth == NULL || sm == NULL) - return WPA_NOT_ENABLED; - - if (wpa_ie == NULL || wpa_ie_len < 1) - return WPA_INVALID_IE; - - if (wpa_ie[0] == WLAN_EID_RSN) - version = WPA_PROTO_RSN; - else - version = WPA_PROTO_WPA; - - if (!(wpa_auth->conf.wpa & version)) { - wpa_printf(MSG_DEBUG, "Invalid WPA proto (%d) from " MACSTR, - version, MAC2STR(sm->addr)); - return WPA_INVALID_PROTO; - } - - if (version == WPA_PROTO_RSN) { - res = wpa_parse_wpa_ie_rsn(wpa_ie, wpa_ie_len, &data); - - selector = RSN_AUTH_KEY_MGMT_UNSPEC_802_1X; - if (0) { - } -#ifdef CONFIG_IEEE80211R - else if (data.key_mgmt & WPA_KEY_MGMT_FT_IEEE8021X) - selector = RSN_AUTH_KEY_MGMT_FT_802_1X; - else if (data.key_mgmt & WPA_KEY_MGMT_FT_PSK) - selector = RSN_AUTH_KEY_MGMT_FT_PSK; -#endif /* CONFIG_IEEE80211R */ -#ifdef CONFIG_IEEE80211W - else if (data.key_mgmt & WPA_KEY_MGMT_IEEE8021X_SHA256) - selector = RSN_AUTH_KEY_MGMT_802_1X_SHA256; - else if (data.key_mgmt & WPA_KEY_MGMT_PSK_SHA256) - selector = RSN_AUTH_KEY_MGMT_PSK_SHA256; -#endif /* CONFIG_IEEE80211W */ - else if (data.key_mgmt & WPA_KEY_MGMT_IEEE8021X) - selector = RSN_AUTH_KEY_MGMT_UNSPEC_802_1X; - else if (data.key_mgmt & WPA_KEY_MGMT_PSK) - selector = RSN_AUTH_KEY_MGMT_PSK_OVER_802_1X; - wpa_auth->dot11RSNAAuthenticationSuiteSelected = selector; - - selector = RSN_CIPHER_SUITE_CCMP; - if (data.pairwise_cipher & WPA_CIPHER_CCMP) - selector = RSN_CIPHER_SUITE_CCMP; - else if (data.pairwise_cipher & WPA_CIPHER_TKIP) - selector = RSN_CIPHER_SUITE_TKIP; - else if (data.pairwise_cipher & WPA_CIPHER_WEP104) - selector = RSN_CIPHER_SUITE_WEP104; - else if (data.pairwise_cipher & WPA_CIPHER_WEP40) - selector = RSN_CIPHER_SUITE_WEP40; - else if (data.pairwise_cipher & WPA_CIPHER_NONE) - selector = RSN_CIPHER_SUITE_NONE; - wpa_auth->dot11RSNAPairwiseCipherSelected = selector; - - selector = RSN_CIPHER_SUITE_CCMP; - if (data.group_cipher & WPA_CIPHER_CCMP) - selector = RSN_CIPHER_SUITE_CCMP; - else if (data.group_cipher & WPA_CIPHER_TKIP) - selector = RSN_CIPHER_SUITE_TKIP; - else if (data.group_cipher & WPA_CIPHER_WEP104) - selector = RSN_CIPHER_SUITE_WEP104; - else if (data.group_cipher & WPA_CIPHER_WEP40) - selector = RSN_CIPHER_SUITE_WEP40; - else if (data.group_cipher & WPA_CIPHER_NONE) - selector = RSN_CIPHER_SUITE_NONE; - wpa_auth->dot11RSNAGroupCipherSelected = selector; - } else { - res = wpa_parse_wpa_ie_wpa(wpa_ie, wpa_ie_len, &data); - - selector = WPA_AUTH_KEY_MGMT_UNSPEC_802_1X; - if (data.key_mgmt & WPA_KEY_MGMT_IEEE8021X) - selector = WPA_AUTH_KEY_MGMT_UNSPEC_802_1X; - else if (data.key_mgmt & WPA_KEY_MGMT_PSK) - selector = WPA_AUTH_KEY_MGMT_PSK_OVER_802_1X; - wpa_auth->dot11RSNAAuthenticationSuiteSelected = selector; - - selector = WPA_CIPHER_SUITE_TKIP; - if (data.pairwise_cipher & WPA_CIPHER_CCMP) - selector = WPA_CIPHER_SUITE_CCMP; - else if (data.pairwise_cipher & WPA_CIPHER_TKIP) - selector = WPA_CIPHER_SUITE_TKIP; - else if (data.pairwise_cipher & WPA_CIPHER_WEP104) - selector = WPA_CIPHER_SUITE_WEP104; - else if (data.pairwise_cipher & WPA_CIPHER_WEP40) - selector = WPA_CIPHER_SUITE_WEP40; - else if (data.pairwise_cipher & WPA_CIPHER_NONE) - selector = WPA_CIPHER_SUITE_NONE; - wpa_auth->dot11RSNAPairwiseCipherSelected = selector; - - selector = WPA_CIPHER_SUITE_TKIP; - if (data.group_cipher & WPA_CIPHER_CCMP) - selector = WPA_CIPHER_SUITE_CCMP; - else if (data.group_cipher & WPA_CIPHER_TKIP) - selector = WPA_CIPHER_SUITE_TKIP; - else if (data.group_cipher & WPA_CIPHER_WEP104) - selector = WPA_CIPHER_SUITE_WEP104; - else if (data.group_cipher & WPA_CIPHER_WEP40) - selector = WPA_CIPHER_SUITE_WEP40; - else if (data.group_cipher & WPA_CIPHER_NONE) - selector = WPA_CIPHER_SUITE_NONE; - wpa_auth->dot11RSNAGroupCipherSelected = selector; - } - if (res) { - wpa_printf(MSG_DEBUG, "Failed to parse WPA/RSN IE from " - MACSTR " (res=%d)", MAC2STR(sm->addr), res); - wpa_hexdump(MSG_DEBUG, "WPA/RSN IE", wpa_ie, wpa_ie_len); - return WPA_INVALID_IE; - } - - if (data.group_cipher != wpa_auth->conf.wpa_group) { - wpa_printf(MSG_DEBUG, "Invalid WPA group cipher (0x%x) from " - MACSTR, data.group_cipher, MAC2STR(sm->addr)); - return WPA_INVALID_GROUP; - } - - key_mgmt = data.key_mgmt & wpa_auth->conf.wpa_key_mgmt; - if (!key_mgmt) { - wpa_printf(MSG_DEBUG, "Invalid WPA key mgmt (0x%x) from " - MACSTR, data.key_mgmt, MAC2STR(sm->addr)); - return WPA_INVALID_AKMP; - } - if (0) { - } -#ifdef CONFIG_IEEE80211R - else if (key_mgmt & WPA_KEY_MGMT_FT_IEEE8021X) - sm->wpa_key_mgmt = WPA_KEY_MGMT_FT_IEEE8021X; - else if (key_mgmt & WPA_KEY_MGMT_FT_PSK) - sm->wpa_key_mgmt = WPA_KEY_MGMT_FT_PSK; -#endif /* CONFIG_IEEE80211R */ -#ifdef CONFIG_IEEE80211W - else if (key_mgmt & WPA_KEY_MGMT_IEEE8021X_SHA256) - sm->wpa_key_mgmt = WPA_KEY_MGMT_IEEE8021X_SHA256; - else if (key_mgmt & WPA_KEY_MGMT_PSK_SHA256) - sm->wpa_key_mgmt = WPA_KEY_MGMT_PSK_SHA256; -#endif /* CONFIG_IEEE80211W */ - else if (key_mgmt & WPA_KEY_MGMT_IEEE8021X) - sm->wpa_key_mgmt = WPA_KEY_MGMT_IEEE8021X; - else - sm->wpa_key_mgmt = WPA_KEY_MGMT_PSK; - - if (version == WPA_PROTO_RSN) - ciphers = data.pairwise_cipher & wpa_auth->conf.rsn_pairwise; - else - ciphers = data.pairwise_cipher & wpa_auth->conf.wpa_pairwise; - if (!ciphers) { - wpa_printf(MSG_DEBUG, "Invalid %s pairwise cipher (0x%x) " - "from " MACSTR, - version == WPA_PROTO_RSN ? "RSN" : "WPA", - data.pairwise_cipher, MAC2STR(sm->addr)); - return WPA_INVALID_PAIRWISE; - } - -#ifdef CONFIG_IEEE80211W - if (wpa_auth->conf.ieee80211w == MGMT_FRAME_PROTECTION_REQUIRED) { - if (!(data.capabilities & WPA_CAPABILITY_MFPC)) { - wpa_printf(MSG_DEBUG, "Management frame protection " - "required, but client did not enable it"); - return WPA_MGMT_FRAME_PROTECTION_VIOLATION; - } - - if (ciphers & WPA_CIPHER_TKIP) { - wpa_printf(MSG_DEBUG, "Management frame protection " - "cannot use TKIP"); - return WPA_MGMT_FRAME_PROTECTION_VIOLATION; - } - - if (data.mgmt_group_cipher != WPA_CIPHER_AES_128_CMAC) { - wpa_printf(MSG_DEBUG, "Unsupported management group " - "cipher %d", data.mgmt_group_cipher); - return WPA_INVALID_MGMT_GROUP_CIPHER; - } - } - - if (wpa_auth->conf.ieee80211w == NO_MGMT_FRAME_PROTECTION || - !(data.capabilities & WPA_CAPABILITY_MFPC)) - sm->mgmt_frame_prot = 0; - else - sm->mgmt_frame_prot = 1; -#endif /* CONFIG_IEEE80211W */ - -#ifdef CONFIG_IEEE80211R - if (wpa_key_mgmt_ft(sm->wpa_key_mgmt)) { - if (mdie == NULL || mdie_len < MOBILITY_DOMAIN_ID_LEN + 1) { - wpa_printf(MSG_DEBUG, "RSN: Trying to use FT, but " - "MDIE not included"); - return WPA_INVALID_MDIE; - } - if (os_memcmp(mdie, wpa_auth->conf.mobility_domain, - MOBILITY_DOMAIN_ID_LEN) != 0) { - wpa_hexdump(MSG_DEBUG, "RSN: Attempted to use unknown " - "MDIE", mdie, MOBILITY_DOMAIN_ID_LEN); - return WPA_INVALID_MDIE; - } - } -#endif /* CONFIG_IEEE80211R */ - - if (ciphers & WPA_CIPHER_CCMP) - sm->pairwise = WPA_CIPHER_CCMP; - else - sm->pairwise = WPA_CIPHER_TKIP; - - /* TODO: clear WPA/WPA2 state if STA changes from one to another */ - if (wpa_ie[0] == WLAN_EID_RSN) - sm->wpa = WPA_VERSION_WPA2; - else - sm->wpa = WPA_VERSION_WPA; - - sm->pmksa = NULL; - for (i = 0; i < data.num_pmkid; i++) { - wpa_hexdump(MSG_DEBUG, "RSN IE: STA PMKID", - &data.pmkid[i * PMKID_LEN], PMKID_LEN); - sm->pmksa = pmksa_cache_auth_get(wpa_auth->pmksa, sm->addr, - &data.pmkid[i * PMKID_LEN]); - if (sm->pmksa) { - pmkid = sm->pmksa->pmkid; - break; - } - } - for (i = 0; sm->pmksa == NULL && wpa_auth->conf.okc && - i < data.num_pmkid; i++) { - struct wpa_auth_okc_iter_data idata; - idata.pmksa = NULL; - idata.aa = wpa_auth->addr; - idata.spa = sm->addr; - idata.pmkid = &data.pmkid[i * PMKID_LEN]; - wpa_auth_for_each_auth(wpa_auth, wpa_auth_okc_iter, &idata); - if (idata.pmksa) { - wpa_auth_vlogger(wpa_auth, sm->addr, LOGGER_DEBUG, - "OKC match for PMKID"); - sm->pmksa = pmksa_cache_add_okc(wpa_auth->pmksa, - idata.pmksa, - wpa_auth->addr, - idata.pmkid); - pmkid = idata.pmkid; - break; - } - } - if (sm->pmksa) { - wpa_auth_vlogger(wpa_auth, sm->addr, LOGGER_DEBUG, - "PMKID found from PMKSA cache " - "eap_type=%d vlan_id=%d", - sm->pmksa->eap_type_authsrv, - sm->pmksa->vlan_id); - os_memcpy(wpa_auth->dot11RSNAPMKIDUsed, pmkid, PMKID_LEN); - } - - if (sm->wpa_ie == NULL || sm->wpa_ie_len < wpa_ie_len) { - os_free(sm->wpa_ie); - sm->wpa_ie = os_malloc(wpa_ie_len); - if (sm->wpa_ie == NULL) - return WPA_ALLOC_FAIL; - } - os_memcpy(sm->wpa_ie, wpa_ie, wpa_ie_len); - sm->wpa_ie_len = wpa_ie_len; - - return WPA_IE_OK; -} - - -/** - * wpa_parse_generic - Parse EAPOL-Key Key Data Generic IEs - * @pos: Pointer to the IE header - * @end: Pointer to the end of the Key Data buffer - * @ie: Pointer to parsed IE data - * Returns: 0 on success, 1 if end mark is found, -1 on failure - */ -static int wpa_parse_generic(const u8 *pos, const u8 *end, - struct wpa_eapol_ie_parse *ie) -{ - if (pos[1] == 0) - return 1; - - if (pos[1] >= 6 && - RSN_SELECTOR_GET(pos + 2) == WPA_OUI_TYPE && - pos[2 + WPA_SELECTOR_LEN] == 1 && - pos[2 + WPA_SELECTOR_LEN + 1] == 0) { - ie->wpa_ie = pos; - ie->wpa_ie_len = pos[1] + 2; - return 0; - } - - if (pos + 1 + RSN_SELECTOR_LEN < end && - pos[1] >= RSN_SELECTOR_LEN + PMKID_LEN && - RSN_SELECTOR_GET(pos + 2) == RSN_KEY_DATA_PMKID) { - ie->pmkid = pos + 2 + RSN_SELECTOR_LEN; - return 0; - } - - if (pos[1] > RSN_SELECTOR_LEN + 2 && - RSN_SELECTOR_GET(pos + 2) == RSN_KEY_DATA_GROUPKEY) { - ie->gtk = pos + 2 + RSN_SELECTOR_LEN; - ie->gtk_len = pos[1] - RSN_SELECTOR_LEN; - return 0; - } - - if (pos[1] > RSN_SELECTOR_LEN + 2 && - RSN_SELECTOR_GET(pos + 2) == RSN_KEY_DATA_MAC_ADDR) { - ie->mac_addr = pos + 2 + RSN_SELECTOR_LEN; - ie->mac_addr_len = pos[1] - RSN_SELECTOR_LEN; - return 0; - } - -#ifdef CONFIG_PEERKEY - if (pos[1] > RSN_SELECTOR_LEN + 2 && - RSN_SELECTOR_GET(pos + 2) == RSN_KEY_DATA_SMK) { - ie->smk = pos + 2 + RSN_SELECTOR_LEN; - ie->smk_len = pos[1] - RSN_SELECTOR_LEN; - return 0; - } - - if (pos[1] > RSN_SELECTOR_LEN + 2 && - RSN_SELECTOR_GET(pos + 2) == RSN_KEY_DATA_NONCE) { - ie->nonce = pos + 2 + RSN_SELECTOR_LEN; - ie->nonce_len = pos[1] - RSN_SELECTOR_LEN; - return 0; - } - - if (pos[1] > RSN_SELECTOR_LEN + 2 && - RSN_SELECTOR_GET(pos + 2) == RSN_KEY_DATA_LIFETIME) { - ie->lifetime = pos + 2 + RSN_SELECTOR_LEN; - ie->lifetime_len = pos[1] - RSN_SELECTOR_LEN; - return 0; - } - - if (pos[1] > RSN_SELECTOR_LEN + 2 && - RSN_SELECTOR_GET(pos + 2) == RSN_KEY_DATA_ERROR) { - ie->error = pos + 2 + RSN_SELECTOR_LEN; - ie->error_len = pos[1] - RSN_SELECTOR_LEN; - return 0; - } -#endif /* CONFIG_PEERKEY */ - -#ifdef CONFIG_IEEE80211W - if (pos[1] > RSN_SELECTOR_LEN + 2 && - RSN_SELECTOR_GET(pos + 2) == RSN_KEY_DATA_IGTK) { - ie->igtk = pos + 2 + RSN_SELECTOR_LEN; - ie->igtk_len = pos[1] - RSN_SELECTOR_LEN; - return 0; - } -#endif /* CONFIG_IEEE80211W */ - - return 0; -} - - -/** - * wpa_parse_kde_ies - Parse EAPOL-Key Key Data IEs - * @buf: Pointer to the Key Data buffer - * @len: Key Data Length - * @ie: Pointer to parsed IE data - * Returns: 0 on success, -1 on failure - */ -int wpa_parse_kde_ies(const u8 *buf, size_t len, struct wpa_eapol_ie_parse *ie) -{ - const u8 *pos, *end; - int ret = 0; - - os_memset(ie, 0, sizeof(*ie)); - for (pos = buf, end = pos + len; pos + 1 < end; pos += 2 + pos[1]) { - if (pos[0] == 0xdd && - ((pos == buf + len - 1) || pos[1] == 0)) { - /* Ignore padding */ - break; - } - if (pos + 2 + pos[1] > end) { - wpa_printf(MSG_DEBUG, "WPA: EAPOL-Key Key Data " - "underflow (ie=%d len=%d pos=%d)", - pos[0], pos[1], (int) (pos - buf)); - wpa_hexdump_key(MSG_DEBUG, "WPA: Key Data", - buf, len); - ret = -1; - break; - } - if (*pos == WLAN_EID_RSN) { - ie->rsn_ie = pos; - ie->rsn_ie_len = pos[1] + 2; -#ifdef CONFIG_IEEE80211R - } else if (*pos == WLAN_EID_MOBILITY_DOMAIN) { - ie->mdie = pos; - ie->mdie_len = pos[1] + 2; - } else if (*pos == WLAN_EID_FAST_BSS_TRANSITION) { - ie->ftie = pos; - ie->ftie_len = pos[1] + 2; -#endif /* CONFIG_IEEE80211R */ - } else if (*pos == WLAN_EID_VENDOR_SPECIFIC) { - ret = wpa_parse_generic(pos, end, ie); - if (ret < 0) - break; - if (ret > 0) { - ret = 0; - break; - } - } else { - wpa_hexdump(MSG_DEBUG, "WPA: Unrecognized EAPOL-Key " - "Key Data IE", pos, 2 + pos[1]); - } - } - - return ret; -} - - -int wpa_auth_uses_mfp(struct wpa_state_machine *sm) -{ - return sm ? sm->mgmt_frame_prot : 0; -} diff --git a/hostapd-0.8/src/ap/wpa_auth_ie.h b/hostapd-0.8/src/ap/wpa_auth_ie.h deleted file mode 100644 index 61d4cb4..0000000 --- a/hostapd-0.8/src/ap/wpa_auth_ie.h +++ /dev/null @@ -1,56 +0,0 @@ -/* - * hostapd - WPA/RSN IE and KDE definitions - * Copyright (c) 2004-2007, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#ifndef WPA_AUTH_IE_H -#define WPA_AUTH_IE_H - -struct wpa_eapol_ie_parse { - const u8 *wpa_ie; - size_t wpa_ie_len; - const u8 *rsn_ie; - size_t rsn_ie_len; - const u8 *pmkid; - const u8 *gtk; - size_t gtk_len; - const u8 *mac_addr; - size_t mac_addr_len; -#ifdef CONFIG_PEERKEY - const u8 *smk; - size_t smk_len; - const u8 *nonce; - size_t nonce_len; - const u8 *lifetime; - size_t lifetime_len; - const u8 *error; - size_t error_len; -#endif /* CONFIG_PEERKEY */ -#ifdef CONFIG_IEEE80211W - const u8 *igtk; - size_t igtk_len; -#endif /* CONFIG_IEEE80211W */ -#ifdef CONFIG_IEEE80211R - const u8 *mdie; - size_t mdie_len; - const u8 *ftie; - size_t ftie_len; -#endif /* CONFIG_IEEE80211R */ -}; - -int wpa_parse_kde_ies(const u8 *buf, size_t len, - struct wpa_eapol_ie_parse *ie); -u8 * wpa_add_kde(u8 *pos, u32 kde, const u8 *data, size_t data_len, - const u8 *data2, size_t data2_len); -int wpa_auth_gen_wpa_ie(struct wpa_authenticator *wpa_auth); - -#endif /* WPA_AUTH_IE_H */ diff --git a/hostapd-0.8/src/ap/wps_hostapd.c b/hostapd-0.8/src/ap/wps_hostapd.c deleted file mode 100644 index fcbd89b..0000000 --- a/hostapd-0.8/src/ap/wps_hostapd.c +++ /dev/null @@ -1,1380 +0,0 @@ -/* - * hostapd / WPS integration - * Copyright (c) 2008-2010, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#include "utils/includes.h" - -#include "utils/common.h" -#include "utils/eloop.h" -#include "utils/uuid.h" -#include "crypto/dh_groups.h" -#include "common/wpa_ctrl.h" -#include "common/ieee802_11_defs.h" -#include "common/ieee802_11_common.h" -#include "eapol_auth/eapol_auth_sm.h" -#include "eapol_auth/eapol_auth_sm_i.h" -#include "wps/wps.h" -#include "wps/wps_defs.h" -#include "wps/wps_dev_attr.h" -#include "hostapd.h" -#include "ap_config.h" -#include "ap_drv_ops.h" -#include "beacon.h" -#include "sta_info.h" -#include "wps_hostapd.h" - - -#ifdef CONFIG_WPS_UPNP -#include "wps/wps_upnp.h" -static int hostapd_wps_upnp_init(struct hostapd_data *hapd, - struct wps_context *wps); -static void hostapd_wps_upnp_deinit(struct hostapd_data *hapd); -#endif /* CONFIG_WPS_UPNP */ - -static int hostapd_wps_probe_req_rx(void *ctx, const u8 *addr, - const u8 *ie, size_t ie_len); -static void hostapd_wps_ap_pin_timeout(void *eloop_data, void *user_ctx); - - -struct wps_for_each_data { - int (*func)(struct hostapd_data *h, void *ctx); - void *ctx; -}; - - -static int wps_for_each(struct hostapd_iface *iface, void *ctx) -{ - struct wps_for_each_data *data = ctx; - size_t j; - - if (iface == NULL) - return 0; - for (j = 0; j < iface->num_bss; j++) { - struct hostapd_data *hapd = iface->bss[j]; - int ret = data->func(hapd, data->ctx); - if (ret) - return ret; - } - - return 0; -} - - -static int hostapd_wps_for_each(struct hostapd_data *hapd, - int (*func)(struct hostapd_data *h, void *ctx), - void *ctx) -{ - struct hostapd_iface *iface = hapd->iface; - struct wps_for_each_data data; - data.func = func; - data.ctx = ctx; - if (iface->for_each_interface == NULL) - return wps_for_each(iface, &data); - return iface->for_each_interface(iface->interfaces, wps_for_each, - &data); -} - - -static int hostapd_wps_new_psk_cb(void *ctx, const u8 *mac_addr, const u8 *psk, - size_t psk_len) -{ - struct hostapd_data *hapd = ctx; - struct hostapd_wpa_psk *p; - struct hostapd_ssid *ssid = &hapd->conf->ssid; - - wpa_printf(MSG_DEBUG, "Received new WPA/WPA2-PSK from WPS for STA " - MACSTR, MAC2STR(mac_addr)); - wpa_hexdump_key(MSG_DEBUG, "Per-device PSK", psk, psk_len); - - if (psk_len != PMK_LEN) { - wpa_printf(MSG_DEBUG, "Unexpected PSK length %lu", - (unsigned long) psk_len); - return -1; - } - - /* Add the new PSK to runtime PSK list */ - p = os_zalloc(sizeof(*p)); - if (p == NULL) - return -1; - os_memcpy(p->addr, mac_addr, ETH_ALEN); - os_memcpy(p->psk, psk, PMK_LEN); - - p->next = ssid->wpa_psk; - ssid->wpa_psk = p; - - if (ssid->wpa_psk_file) { - FILE *f; - char hex[PMK_LEN * 2 + 1]; - /* Add the new PSK to PSK list file */ - f = fopen(ssid->wpa_psk_file, "a"); - if (f == NULL) { - wpa_printf(MSG_DEBUG, "Failed to add the PSK to " - "'%s'", ssid->wpa_psk_file); - return -1; - } - - wpa_snprintf_hex(hex, sizeof(hex), psk, psk_len); - fprintf(f, MACSTR " %s\n", MAC2STR(mac_addr), hex); - fclose(f); - } - - return 0; -} - - -static int hostapd_wps_set_ie_cb(void *ctx, struct wpabuf *beacon_ie, - struct wpabuf *probe_resp_ie) -{ - struct hostapd_data *hapd = ctx; - wpabuf_free(hapd->wps_beacon_ie); - hapd->wps_beacon_ie = beacon_ie; - wpabuf_free(hapd->wps_probe_resp_ie); - hapd->wps_probe_resp_ie = probe_resp_ie; - ieee802_11_set_beacon(hapd); - return hostapd_set_ap_wps_ie(hapd); -} - - -static void hostapd_wps_pin_needed_cb(void *ctx, const u8 *uuid_e, - const struct wps_device_data *dev) -{ - struct hostapd_data *hapd = ctx; - char uuid[40], txt[400]; - int len; - char devtype[WPS_DEV_TYPE_BUFSIZE]; - if (uuid_bin2str(uuid_e, uuid, sizeof(uuid))) - return; - wpa_printf(MSG_DEBUG, "WPS: PIN needed for E-UUID %s", uuid); - len = os_snprintf(txt, sizeof(txt), WPS_EVENT_PIN_NEEDED - "%s " MACSTR " [%s|%s|%s|%s|%s|%s]", - uuid, MAC2STR(dev->mac_addr), dev->device_name, - dev->manufacturer, dev->model_name, - dev->model_number, dev->serial_number, - wps_dev_type_bin2str(dev->pri_dev_type, devtype, - sizeof(devtype))); - if (len > 0 && len < (int) sizeof(txt)) - wpa_msg(hapd->msg_ctx, MSG_INFO, "%s", txt); - - if (hapd->conf->wps_pin_requests) { - FILE *f; - struct os_time t; - f = fopen(hapd->conf->wps_pin_requests, "a"); - if (f == NULL) - return; - os_get_time(&t); - fprintf(f, "%ld\t%s\t" MACSTR "\t%s\t%s\t%s\t%s\t%s" - "\t%s\n", - t.sec, uuid, MAC2STR(dev->mac_addr), dev->device_name, - dev->manufacturer, dev->model_name, dev->model_number, - dev->serial_number, - wps_dev_type_bin2str(dev->pri_dev_type, devtype, - sizeof(devtype))); - fclose(f); - } -} - - -static void hostapd_wps_reg_success_cb(void *ctx, const u8 *mac_addr, - const u8 *uuid_e) -{ - struct hostapd_data *hapd = ctx; - char uuid[40]; - if (uuid_bin2str(uuid_e, uuid, sizeof(uuid))) - return; - wpa_msg(hapd->msg_ctx, MSG_INFO, WPS_EVENT_REG_SUCCESS MACSTR " %s", - MAC2STR(mac_addr), uuid); - if (hapd->wps_reg_success_cb) - hapd->wps_reg_success_cb(hapd->wps_reg_success_cb_ctx, - mac_addr, uuid_e); -} - - -static void hostapd_wps_enrollee_seen_cb(void *ctx, const u8 *addr, - const u8 *uuid_e, - const u8 *pri_dev_type, - u16 config_methods, - u16 dev_password_id, u8 request_type, - const char *dev_name) -{ - struct hostapd_data *hapd = ctx; - char uuid[40]; - char devtype[WPS_DEV_TYPE_BUFSIZE]; - if (uuid_bin2str(uuid_e, uuid, sizeof(uuid))) - return; - if (dev_name == NULL) - dev_name = ""; - wpa_msg_ctrl(hapd->msg_ctx, MSG_INFO, WPS_EVENT_ENROLLEE_SEEN MACSTR - " %s %s 0x%x %u %u [%s]", - MAC2STR(addr), uuid, - wps_dev_type_bin2str(pri_dev_type, devtype, - sizeof(devtype)), - config_methods, dev_password_id, request_type, dev_name); -} - - -static int str_starts(const char *str, const char *start) -{ - return os_strncmp(str, start, os_strlen(start)) == 0; -} - - -static void wps_reload_config(void *eloop_data, void *user_ctx) -{ - struct hostapd_iface *iface = eloop_data; - - wpa_printf(MSG_DEBUG, "WPS: Reload configuration data"); - if (iface->reload_config(iface) < 0) { - wpa_printf(MSG_WARNING, "WPS: Failed to reload the updated " - "configuration"); - } -} - - -static int hapd_wps_cred_cb(struct hostapd_data *hapd, void *ctx) -{ - const struct wps_credential *cred = ctx; - FILE *oconf, *nconf; - size_t len, i; - char *tmp_fname; - char buf[1024]; - int multi_bss; - int wpa; - - if (hapd->wps == NULL) - return 0; - - wpa_hexdump_key(MSG_DEBUG, "WPS: Received Credential attribute", - cred->cred_attr, cred->cred_attr_len); - - wpa_printf(MSG_DEBUG, "WPS: Received new AP Settings"); - wpa_hexdump_ascii(MSG_DEBUG, "WPS: SSID", cred->ssid, cred->ssid_len); - wpa_printf(MSG_DEBUG, "WPS: Authentication Type 0x%x", - cred->auth_type); - wpa_printf(MSG_DEBUG, "WPS: Encryption Type 0x%x", cred->encr_type); - wpa_printf(MSG_DEBUG, "WPS: Network Key Index %d", cred->key_idx); - wpa_hexdump_key(MSG_DEBUG, "WPS: Network Key", - cred->key, cred->key_len); - wpa_printf(MSG_DEBUG, "WPS: MAC Address " MACSTR, - MAC2STR(cred->mac_addr)); - - if ((hapd->conf->wps_cred_processing == 1 || - hapd->conf->wps_cred_processing == 2) && cred->cred_attr) { - size_t blen = cred->cred_attr_len * 2 + 1; - char *_buf = os_malloc(blen); - if (_buf) { - wpa_snprintf_hex(_buf, blen, - cred->cred_attr, cred->cred_attr_len); - wpa_msg(hapd->msg_ctx, MSG_INFO, "%s%s", - WPS_EVENT_NEW_AP_SETTINGS, _buf); - os_free(_buf); - } - } else - wpa_msg(hapd->msg_ctx, MSG_INFO, WPS_EVENT_NEW_AP_SETTINGS); - - if (hapd->conf->wps_cred_processing == 1) - return 0; - - os_memcpy(hapd->wps->ssid, cred->ssid, cred->ssid_len); - hapd->wps->ssid_len = cred->ssid_len; - hapd->wps->encr_types = cred->encr_type; - hapd->wps->auth_types = cred->auth_type; - if (cred->key_len == 0) { - os_free(hapd->wps->network_key); - hapd->wps->network_key = NULL; - hapd->wps->network_key_len = 0; - } else { - if (hapd->wps->network_key == NULL || - hapd->wps->network_key_len < cred->key_len) { - hapd->wps->network_key_len = 0; - os_free(hapd->wps->network_key); - hapd->wps->network_key = os_malloc(cred->key_len); - if (hapd->wps->network_key == NULL) - return -1; - } - hapd->wps->network_key_len = cred->key_len; - os_memcpy(hapd->wps->network_key, cred->key, cred->key_len); - } - hapd->wps->wps_state = WPS_STATE_CONFIGURED; - - len = os_strlen(hapd->iface->config_fname) + 5; - tmp_fname = os_malloc(len); - if (tmp_fname == NULL) - return -1; - os_snprintf(tmp_fname, len, "%s-new", hapd->iface->config_fname); - - oconf = fopen(hapd->iface->config_fname, "r"); - if (oconf == NULL) { - wpa_printf(MSG_WARNING, "WPS: Could not open current " - "configuration file"); - os_free(tmp_fname); - return -1; - } - - nconf = fopen(tmp_fname, "w"); - if (nconf == NULL) { - wpa_printf(MSG_WARNING, "WPS: Could not write updated " - "configuration file"); - os_free(tmp_fname); - fclose(oconf); - return -1; - } - - fprintf(nconf, "# WPS configuration - START\n"); - - fprintf(nconf, "wps_state=2\n"); - - fprintf(nconf, "ssid="); - for (i = 0; i < cred->ssid_len; i++) - fputc(cred->ssid[i], nconf); - fprintf(nconf, "\n"); - - if ((cred->auth_type & (WPS_AUTH_WPA2 | WPS_AUTH_WPA2PSK)) && - (cred->auth_type & (WPS_AUTH_WPA | WPS_AUTH_WPAPSK))) - wpa = 3; - else if (cred->auth_type & (WPS_AUTH_WPA2 | WPS_AUTH_WPA2PSK)) - wpa = 2; - else if (cred->auth_type & (WPS_AUTH_WPA | WPS_AUTH_WPAPSK)) - wpa = 1; - else - wpa = 0; - - if (wpa) { - char *prefix; - fprintf(nconf, "wpa=%d\n", wpa); - - fprintf(nconf, "wpa_key_mgmt="); - prefix = ""; - if (cred->auth_type & (WPS_AUTH_WPA2 | WPS_AUTH_WPA)) { - fprintf(nconf, "WPA-EAP"); - prefix = " "; - } - if (cred->auth_type & (WPS_AUTH_WPA2PSK | WPS_AUTH_WPAPSK)) - fprintf(nconf, "%sWPA-PSK", prefix); - fprintf(nconf, "\n"); - - fprintf(nconf, "wpa_pairwise="); - prefix = ""; - if (cred->encr_type & WPS_ENCR_AES) { - fprintf(nconf, "CCMP"); - prefix = " "; - } - if (cred->encr_type & WPS_ENCR_TKIP) { - fprintf(nconf, "%sTKIP", prefix); - } - fprintf(nconf, "\n"); - - if (cred->key_len >= 8 && cred->key_len < 64) { - fprintf(nconf, "wpa_passphrase="); - for (i = 0; i < cred->key_len; i++) - fputc(cred->key[i], nconf); - fprintf(nconf, "\n"); - } else if (cred->key_len == 64) { - fprintf(nconf, "wpa_psk="); - for (i = 0; i < cred->key_len; i++) - fputc(cred->key[i], nconf); - fprintf(nconf, "\n"); - } else { - wpa_printf(MSG_WARNING, "WPS: Invalid key length %lu " - "for WPA/WPA2", - (unsigned long) cred->key_len); - } - - fprintf(nconf, "auth_algs=1\n"); - } else { - if ((cred->auth_type & WPS_AUTH_OPEN) && - (cred->auth_type & WPS_AUTH_SHARED)) - fprintf(nconf, "auth_algs=3\n"); - else if (cred->auth_type & WPS_AUTH_SHARED) - fprintf(nconf, "auth_algs=2\n"); - else - fprintf(nconf, "auth_algs=1\n"); - - if (cred->encr_type & WPS_ENCR_WEP && cred->key_idx <= 4) { - int key_idx = cred->key_idx; - if (key_idx) - key_idx--; - fprintf(nconf, "wep_default_key=%d\n", key_idx); - fprintf(nconf, "wep_key%d=", key_idx); - if (cred->key_len == 10 || cred->key_len == 26) { - /* WEP key as a hex string */ - for (i = 0; i < cred->key_len; i++) - fputc(cred->key[i], nconf); - } else { - /* Raw WEP key; convert to hex */ - for (i = 0; i < cred->key_len; i++) - fprintf(nconf, "%02x", cred->key[i]); - } - fprintf(nconf, "\n"); - } - } - - fprintf(nconf, "# WPS configuration - END\n"); - - multi_bss = 0; - while (fgets(buf, sizeof(buf), oconf)) { - if (os_strncmp(buf, "bss=", 4) == 0) - multi_bss = 1; - if (!multi_bss && - (str_starts(buf, "ssid=") || - str_starts(buf, "auth_algs=") || - str_starts(buf, "wep_default_key=") || - str_starts(buf, "wep_key") || - str_starts(buf, "wps_state=") || - str_starts(buf, "wpa=") || - str_starts(buf, "wpa_psk=") || - str_starts(buf, "wpa_pairwise=") || - str_starts(buf, "rsn_pairwise=") || - str_starts(buf, "wpa_key_mgmt=") || - str_starts(buf, "wpa_passphrase="))) { - fprintf(nconf, "#WPS# %s", buf); - } else - fprintf(nconf, "%s", buf); - } - - fclose(nconf); - fclose(oconf); - - if (rename(tmp_fname, hapd->iface->config_fname) < 0) { - wpa_printf(MSG_WARNING, "WPS: Failed to rename the updated " - "configuration file: %s", strerror(errno)); - os_free(tmp_fname); - return -1; - } - - os_free(tmp_fname); - - /* Schedule configuration reload after short period of time to allow - * EAP-WSC to be finished. - */ - eloop_register_timeout(0, 100000, wps_reload_config, hapd->iface, - NULL); - - wpa_printf(MSG_DEBUG, "WPS: AP configuration updated"); - - return 0; -} - - -static int hostapd_wps_cred_cb(void *ctx, const struct wps_credential *cred) -{ - struct hostapd_data *hapd = ctx; - return hostapd_wps_for_each(hapd, hapd_wps_cred_cb, (void *) cred); -} - - -static void hostapd_wps_reenable_ap_pin(void *eloop_data, void *user_ctx) -{ - struct hostapd_data *hapd = eloop_data; - - if (hapd->conf->ap_setup_locked) - return; - - wpa_printf(MSG_DEBUG, "WPS: Re-enable AP PIN"); - wpa_msg(hapd->msg_ctx, MSG_INFO, WPS_EVENT_AP_SETUP_UNLOCKED); - hapd->wps->ap_setup_locked = 0; - wps_registrar_update_ie(hapd->wps->registrar); -} - - -static int wps_pwd_auth_fail(struct hostapd_data *hapd, void *ctx) -{ - struct wps_event_pwd_auth_fail *data = ctx; - - if (!data->enrollee || hapd->conf->ap_pin == NULL || hapd->wps == NULL) - return 0; - - /* - * Registrar failed to prove its knowledge of the AP PIN. Lock AP setup - * for some time if this happens multiple times to slow down brute - * force attacks. - */ - hapd->ap_pin_failures++; - wpa_printf(MSG_DEBUG, "WPS: AP PIN authentication failure number %u", - hapd->ap_pin_failures); - if (hapd->ap_pin_failures < 3) - return 0; - - wpa_msg(hapd->msg_ctx, MSG_INFO, WPS_EVENT_AP_SETUP_LOCKED); - hapd->wps->ap_setup_locked = 1; - - wps_registrar_update_ie(hapd->wps->registrar); - - if (!hapd->conf->ap_setup_locked) { - if (hapd->ap_pin_lockout_time == 0) - hapd->ap_pin_lockout_time = 60; - else if (hapd->ap_pin_lockout_time < 365 * 24 * 60 * 60 && - (hapd->ap_pin_failures % 3) == 0) - hapd->ap_pin_lockout_time *= 2; - - wpa_printf(MSG_DEBUG, "WPS: Disable AP PIN for %u seconds", - hapd->ap_pin_lockout_time); - eloop_cancel_timeout(hostapd_wps_reenable_ap_pin, hapd, NULL); - eloop_register_timeout(hapd->ap_pin_lockout_time, 0, - hostapd_wps_reenable_ap_pin, hapd, - NULL); - } - - return 0; -} - - -static void hostapd_pwd_auth_fail(struct hostapd_data *hapd, - struct wps_event_pwd_auth_fail *data) -{ - hostapd_wps_for_each(hapd, wps_pwd_auth_fail, data); -} - - -static const char * wps_event_fail_reason[NUM_WPS_EI_VALUES] = { - "No Error", /* WPS_EI_NO_ERROR */ - "TKIP Only Prohibited", /* WPS_EI_SECURITY_TKIP_ONLY_PROHIBITED */ - "WEP Prohibited" /* WPS_EI_SECURITY_WEP_PROHIBITED */ -}; - -static void hostapd_wps_event_fail(struct hostapd_data *hapd, - struct wps_event_fail *fail) -{ - if (fail->error_indication > 0 && - fail->error_indication < NUM_WPS_EI_VALUES) { - wpa_msg(hapd->msg_ctx, MSG_INFO, - WPS_EVENT_FAIL "msg=%d config_error=%d reason=%d (%s)", - fail->msg, fail->config_error, fail->error_indication, - wps_event_fail_reason[fail->error_indication]); - } else { - wpa_msg(hapd->msg_ctx, MSG_INFO, - WPS_EVENT_FAIL "msg=%d config_error=%d", - fail->msg, fail->config_error); - } -} - - -static void hostapd_wps_event_cb(void *ctx, enum wps_event event, - union wps_event_data *data) -{ - struct hostapd_data *hapd = ctx; - - switch (event) { - case WPS_EV_M2D: - break; - case WPS_EV_FAIL: - hostapd_wps_event_fail(hapd, &data->fail); - break; - case WPS_EV_SUCCESS: - break; - case WPS_EV_PWD_AUTH_FAIL: - hostapd_pwd_auth_fail(hapd, &data->pwd_auth_fail); - break; - case WPS_EV_PBC_OVERLAP: - break; - case WPS_EV_PBC_TIMEOUT: - break; - case WPS_EV_ER_AP_ADD: - break; - case WPS_EV_ER_AP_REMOVE: - break; - case WPS_EV_ER_ENROLLEE_ADD: - break; - case WPS_EV_ER_ENROLLEE_REMOVE: - break; - case WPS_EV_ER_AP_SETTINGS: - break; - case WPS_EV_ER_SET_SELECTED_REGISTRAR: - break; - } - if (hapd->wps_event_cb) - hapd->wps_event_cb(hapd->wps_event_cb_ctx, event, data); -} - - -static void hostapd_wps_clear_ies(struct hostapd_data *hapd) -{ - wpabuf_free(hapd->wps_beacon_ie); - hapd->wps_beacon_ie = NULL; - - wpabuf_free(hapd->wps_probe_resp_ie); - hapd->wps_probe_resp_ie = NULL; - - hostapd_set_ap_wps_ie(hapd); -} - - -static int get_uuid_cb(struct hostapd_iface *iface, void *ctx) -{ - const u8 **uuid = ctx; - size_t j; - - if (iface == NULL) - return 0; - for (j = 0; j < iface->num_bss; j++) { - struct hostapd_data *hapd = iface->bss[j]; - if (hapd->wps && !is_nil_uuid(hapd->wps->uuid)) { - *uuid = hapd->wps->uuid; - return 1; - } - } - - return 0; -} - - -static const u8 * get_own_uuid(struct hostapd_iface *iface) -{ - const u8 *uuid; - if (iface->for_each_interface == NULL) - return NULL; - uuid = NULL; - iface->for_each_interface(iface->interfaces, get_uuid_cb, &uuid); - return uuid; -} - - -static int count_interface_cb(struct hostapd_iface *iface, void *ctx) -{ - int *count= ctx; - (*count)++; - return 0; -} - - -static int interface_count(struct hostapd_iface *iface) -{ - int count = 0; - if (iface->for_each_interface == NULL) - return 0; - iface->for_each_interface(iface->interfaces, count_interface_cb, - &count); - return count; -} - - -static int hostapd_wps_set_vendor_ext(struct hostapd_data *hapd, - struct wps_context *wps) -{ - int i; - - for (i = 0; i < MAX_WPS_VENDOR_EXTENSIONS; i++) { - wpabuf_free(wps->dev.vendor_ext[i]); - wps->dev.vendor_ext[i] = NULL; - - if (hapd->conf->wps_vendor_ext[i] == NULL) - continue; - - wps->dev.vendor_ext[i] = - wpabuf_dup(hapd->conf->wps_vendor_ext[i]); - if (wps->dev.vendor_ext[i] == NULL) { - while (--i >= 0) - wpabuf_free(wps->dev.vendor_ext[i]); - return -1; - } - } - - return 0; -} - - -int hostapd_init_wps(struct hostapd_data *hapd, - struct hostapd_bss_config *conf) -{ - struct wps_context *wps; - struct wps_registrar_config cfg; - - if (conf->wps_state == 0) { - hostapd_wps_clear_ies(hapd); - return 0; - } - - wps = os_zalloc(sizeof(*wps)); - if (wps == NULL) - return -1; - - wps->cred_cb = hostapd_wps_cred_cb; - wps->event_cb = hostapd_wps_event_cb; - wps->cb_ctx = hapd; - - os_memset(&cfg, 0, sizeof(cfg)); - wps->wps_state = hapd->conf->wps_state; - wps->ap_setup_locked = hapd->conf->ap_setup_locked; - if (is_nil_uuid(hapd->conf->uuid)) { - const u8 *uuid; - uuid = get_own_uuid(hapd->iface); - if (uuid) { - os_memcpy(wps->uuid, uuid, UUID_LEN); - wpa_hexdump(MSG_DEBUG, "WPS: Clone UUID from another " - "interface", wps->uuid, UUID_LEN); - } else { - uuid_gen_mac_addr(hapd->own_addr, wps->uuid); - wpa_hexdump(MSG_DEBUG, "WPS: UUID based on MAC " - "address", wps->uuid, UUID_LEN); - } - } else { - os_memcpy(wps->uuid, hapd->conf->uuid, UUID_LEN); - wpa_hexdump(MSG_DEBUG, "WPS: Use configured UUID", - wps->uuid, UUID_LEN); - } - wps->ssid_len = hapd->conf->ssid.ssid_len; - os_memcpy(wps->ssid, hapd->conf->ssid.ssid, wps->ssid_len); - wps->ap = 1; - os_memcpy(wps->dev.mac_addr, hapd->own_addr, ETH_ALEN); - wps->dev.device_name = hapd->conf->device_name ? - os_strdup(hapd->conf->device_name) : NULL; - wps->dev.manufacturer = hapd->conf->manufacturer ? - os_strdup(hapd->conf->manufacturer) : NULL; - wps->dev.model_name = hapd->conf->model_name ? - os_strdup(hapd->conf->model_name) : NULL; - wps->dev.model_number = hapd->conf->model_number ? - os_strdup(hapd->conf->model_number) : NULL; - wps->dev.serial_number = hapd->conf->serial_number ? - os_strdup(hapd->conf->serial_number) : NULL; - wps->config_methods = - wps_config_methods_str2bin(hapd->conf->config_methods); -#ifdef CONFIG_WPS2 - if ((wps->config_methods & - (WPS_CONFIG_DISPLAY | WPS_CONFIG_VIRT_DISPLAY | - WPS_CONFIG_PHY_DISPLAY)) == WPS_CONFIG_DISPLAY) { - wpa_printf(MSG_INFO, "WPS: Converting display to " - "virtual_display for WPS 2.0 compliance"); - wps->config_methods |= WPS_CONFIG_VIRT_DISPLAY; - } - if ((wps->config_methods & - (WPS_CONFIG_PUSHBUTTON | WPS_CONFIG_VIRT_PUSHBUTTON | - WPS_CONFIG_PHY_PUSHBUTTON)) == WPS_CONFIG_PUSHBUTTON) { - wpa_printf(MSG_INFO, "WPS: Converting push_button to " - "virtual_push_button for WPS 2.0 compliance"); - wps->config_methods |= WPS_CONFIG_VIRT_PUSHBUTTON; - } -#endif /* CONFIG_WPS2 */ - os_memcpy(wps->dev.pri_dev_type, hapd->conf->device_type, - WPS_DEV_TYPE_LEN); - - if (hostapd_wps_set_vendor_ext(hapd, wps) < 0) { - os_free(wps); - return -1; - } - - wps->dev.os_version = WPA_GET_BE32(hapd->conf->os_version); - wps->dev.rf_bands = hapd->iconf->hw_mode == HOSTAPD_MODE_IEEE80211A ? - WPS_RF_50GHZ : WPS_RF_24GHZ; /* FIX: dualband AP */ - - if (conf->wpa & WPA_PROTO_RSN) { - if (conf->wpa_key_mgmt & WPA_KEY_MGMT_PSK) - wps->auth_types |= WPS_AUTH_WPA2PSK; - if (conf->wpa_key_mgmt & WPA_KEY_MGMT_IEEE8021X) - wps->auth_types |= WPS_AUTH_WPA2; - - if (conf->rsn_pairwise & WPA_CIPHER_CCMP) - wps->encr_types |= WPS_ENCR_AES; - if (conf->rsn_pairwise & WPA_CIPHER_TKIP) - wps->encr_types |= WPS_ENCR_TKIP; - } - - if (conf->wpa & WPA_PROTO_WPA) { - if (conf->wpa_key_mgmt & WPA_KEY_MGMT_PSK) - wps->auth_types |= WPS_AUTH_WPAPSK; - if (conf->wpa_key_mgmt & WPA_KEY_MGMT_IEEE8021X) - wps->auth_types |= WPS_AUTH_WPA; - - if (conf->wpa_pairwise & WPA_CIPHER_CCMP) - wps->encr_types |= WPS_ENCR_AES; - if (conf->wpa_pairwise & WPA_CIPHER_TKIP) - wps->encr_types |= WPS_ENCR_TKIP; - } - - if (conf->ssid.security_policy == SECURITY_PLAINTEXT) { - wps->encr_types |= WPS_ENCR_NONE; - wps->auth_types |= WPS_AUTH_OPEN; - } else if (conf->ssid.security_policy == SECURITY_STATIC_WEP) { - wps->encr_types |= WPS_ENCR_WEP; - if (conf->auth_algs & WPA_AUTH_ALG_OPEN) - wps->auth_types |= WPS_AUTH_OPEN; - if (conf->auth_algs & WPA_AUTH_ALG_SHARED) - wps->auth_types |= WPS_AUTH_SHARED; - } else if (conf->ssid.security_policy == SECURITY_IEEE_802_1X) { - wps->auth_types |= WPS_AUTH_OPEN; - if (conf->default_wep_key_len) - wps->encr_types |= WPS_ENCR_WEP; - else - wps->encr_types |= WPS_ENCR_NONE; - } - - if (conf->ssid.wpa_psk_file) { - /* Use per-device PSKs */ - } else if (conf->ssid.wpa_passphrase) { - wps->network_key = (u8 *) os_strdup(conf->ssid.wpa_passphrase); - wps->network_key_len = os_strlen(conf->ssid.wpa_passphrase); - } else if (conf->ssid.wpa_psk) { - wps->network_key = os_malloc(2 * PMK_LEN + 1); - if (wps->network_key == NULL) { - os_free(wps); - return -1; - } - wpa_snprintf_hex((char *) wps->network_key, 2 * PMK_LEN + 1, - conf->ssid.wpa_psk->psk, PMK_LEN); - wps->network_key_len = 2 * PMK_LEN; - } else if (conf->ssid.wep.keys_set && conf->ssid.wep.key[0]) { - wps->network_key = os_malloc(conf->ssid.wep.len[0]); - if (wps->network_key == NULL) { - os_free(wps); - return -1; - } - os_memcpy(wps->network_key, conf->ssid.wep.key[0], - conf->ssid.wep.len[0]); - wps->network_key_len = conf->ssid.wep.len[0]; - } - - if (conf->ssid.wpa_psk) { - os_memcpy(wps->psk, conf->ssid.wpa_psk->psk, PMK_LEN); - wps->psk_set = 1; - } - - if (conf->wps_state == WPS_STATE_NOT_CONFIGURED) { - /* Override parameters to enable security by default */ - wps->auth_types = WPS_AUTH_WPA2PSK | WPS_AUTH_WPAPSK; - wps->encr_types = WPS_ENCR_AES | WPS_ENCR_TKIP; - } - - wps->ap_settings = conf->ap_settings; - wps->ap_settings_len = conf->ap_settings_len; - - cfg.new_psk_cb = hostapd_wps_new_psk_cb; - cfg.set_ie_cb = hostapd_wps_set_ie_cb; - cfg.pin_needed_cb = hostapd_wps_pin_needed_cb; - cfg.reg_success_cb = hostapd_wps_reg_success_cb; - cfg.enrollee_seen_cb = hostapd_wps_enrollee_seen_cb; - cfg.cb_ctx = hapd; - cfg.skip_cred_build = conf->skip_cred_build; - cfg.extra_cred = conf->extra_cred; - cfg.extra_cred_len = conf->extra_cred_len; - cfg.disable_auto_conf = (hapd->conf->wps_cred_processing == 1) && - conf->skip_cred_build; - if (conf->ssid.security_policy == SECURITY_STATIC_WEP) - cfg.static_wep_only = 1; - cfg.dualband = interface_count(hapd->iface) > 1; - if (cfg.dualband) - wpa_printf(MSG_DEBUG, "WPS: Dualband AP"); - - wps->registrar = wps_registrar_init(wps, &cfg); - if (wps->registrar == NULL) { - wpa_printf(MSG_ERROR, "Failed to initialize WPS Registrar"); - os_free(wps->network_key); - os_free(wps); - return -1; - } - -#ifdef CONFIG_WPS_UPNP - wps->friendly_name = hapd->conf->friendly_name; - wps->manufacturer_url = hapd->conf->manufacturer_url; - wps->model_description = hapd->conf->model_description; - wps->model_url = hapd->conf->model_url; - wps->upc = hapd->conf->upc; - - if (hostapd_wps_upnp_init(hapd, wps) < 0) { - wpa_printf(MSG_ERROR, "Failed to initialize WPS UPnP"); - wps_registrar_deinit(wps->registrar); - os_free(wps->network_key); - os_free(wps); - return -1; - } -#endif /* CONFIG_WPS_UPNP */ - - hostapd_register_probereq_cb(hapd, hostapd_wps_probe_req_rx, hapd); - - hapd->wps = wps; - - return 0; -} - - -void hostapd_deinit_wps(struct hostapd_data *hapd) -{ - eloop_cancel_timeout(hostapd_wps_reenable_ap_pin, hapd, NULL); - eloop_cancel_timeout(hostapd_wps_ap_pin_timeout, hapd, NULL); - if (hapd->wps == NULL) - return; -#ifdef CONFIG_WPS_UPNP - hostapd_wps_upnp_deinit(hapd); -#endif /* CONFIG_WPS_UPNP */ - wps_registrar_deinit(hapd->wps->registrar); - os_free(hapd->wps->network_key); - wps_device_data_free(&hapd->wps->dev); - wpabuf_free(hapd->wps->dh_pubkey); - wpabuf_free(hapd->wps->dh_privkey); - wpabuf_free(hapd->wps->oob_conf.pubkey_hash); - wpabuf_free(hapd->wps->oob_conf.dev_password); - wps_free_pending_msgs(hapd->wps->upnp_msgs); - os_free(hapd->wps); - hapd->wps = NULL; - hostapd_wps_clear_ies(hapd); -} - - -void hostapd_update_wps(struct hostapd_data *hapd) -{ - if (hapd->wps == NULL) - return; - -#ifdef CONFIG_WPS_UPNP - hapd->wps->friendly_name = hapd->conf->friendly_name; - hapd->wps->manufacturer_url = hapd->conf->manufacturer_url; - hapd->wps->model_description = hapd->conf->model_description; - hapd->wps->model_url = hapd->conf->model_url; - hapd->wps->upc = hapd->conf->upc; -#endif /* CONFIG_WPS_UPNP */ - - hostapd_wps_set_vendor_ext(hapd, hapd->wps); - - if (hapd->conf->wps_state) - wps_registrar_update_ie(hapd->wps->registrar); - else - hostapd_deinit_wps(hapd); -} - - -struct wps_add_pin_data { - const u8 *addr; - const u8 *uuid; - const u8 *pin; - size_t pin_len; - int timeout; - int added; -}; - - -static int wps_add_pin(struct hostapd_data *hapd, void *ctx) -{ - struct wps_add_pin_data *data = ctx; - int ret; - - if (hapd->wps == NULL) - return 0; - ret = wps_registrar_add_pin(hapd->wps->registrar, data->addr, - data->uuid, data->pin, data->pin_len, - data->timeout); - if (ret == 0) - data->added++; - return ret; -} - - -int hostapd_wps_add_pin(struct hostapd_data *hapd, const u8 *addr, - const char *uuid, const char *pin, int timeout) -{ - u8 u[UUID_LEN]; - struct wps_add_pin_data data; - - data.addr = addr; - data.uuid = u; - data.pin = (const u8 *) pin; - data.pin_len = os_strlen(pin); - data.timeout = timeout; - data.added = 0; - - if (os_strcmp(uuid, "any") == 0) - data.uuid = NULL; - else { - if (uuid_str2bin(uuid, u)) - return -1; - data.uuid = u; - } - if (hostapd_wps_for_each(hapd, wps_add_pin, &data) < 0) - return -1; - return data.added ? 0 : -1; -} - - -static int wps_button_pushed(struct hostapd_data *hapd, void *ctx) -{ - const u8 *p2p_dev_addr = ctx; - if (hapd->wps == NULL) - return 0; - return wps_registrar_button_pushed(hapd->wps->registrar, p2p_dev_addr); -} - - -int hostapd_wps_button_pushed(struct hostapd_data *hapd, - const u8 *p2p_dev_addr) -{ - return hostapd_wps_for_each(hapd, wps_button_pushed, - (void *) p2p_dev_addr); -} - - -#ifdef CONFIG_WPS_OOB -int hostapd_wps_start_oob(struct hostapd_data *hapd, char *device_type, - char *path, char *method, char *name) -{ - struct wps_context *wps = hapd->wps; - struct oob_device_data *oob_dev; - - oob_dev = wps_get_oob_device(device_type); - if (oob_dev == NULL) - return -1; - oob_dev->device_path = path; - oob_dev->device_name = name; - wps->oob_conf.oob_method = wps_get_oob_method(method); - - if (wps->oob_conf.oob_method == OOB_METHOD_DEV_PWD_R) { - /* - * Use pre-configured DH keys in order to be able to write the - * key hash into the OOB file. - */ - wpabuf_free(wps->dh_pubkey); - wpabuf_free(wps->dh_privkey); - wps->dh_privkey = NULL; - wps->dh_pubkey = dh_init(dh_groups_get(WPS_DH_GROUP), - &wps->dh_privkey); - wps->dh_pubkey = wpabuf_zeropad(wps->dh_pubkey, 192); - if (wps->dh_pubkey == NULL) { - wpa_printf(MSG_ERROR, "WPS: Failed to initialize " - "Diffie-Hellman handshake"); - return -1; - } - } - - if (wps_process_oob(wps, oob_dev, 1) < 0) - goto error; - - if ((wps->oob_conf.oob_method == OOB_METHOD_DEV_PWD_E || - wps->oob_conf.oob_method == OOB_METHOD_DEV_PWD_R) && - hostapd_wps_add_pin(hapd, NULL, "any", - wpabuf_head(wps->oob_conf.dev_password), 0) < - 0) - goto error; - - return 0; - -error: - wpabuf_free(wps->dh_pubkey); - wps->dh_pubkey = NULL; - wpabuf_free(wps->dh_privkey); - wps->dh_privkey = NULL; - return -1; -} -#endif /* CONFIG_WPS_OOB */ - - -static int hostapd_wps_probe_req_rx(void *ctx, const u8 *addr, - const u8 *ie, size_t ie_len) -{ - struct hostapd_data *hapd = ctx; - struct wpabuf *wps_ie; - struct ieee802_11_elems elems; - - if (hapd->wps == NULL) - return 0; - - if (ieee802_11_parse_elems(ie, ie_len, &elems, 0) == ParseFailed) { - wpa_printf(MSG_DEBUG, "WPS: Could not parse ProbeReq from " - MACSTR, MAC2STR(addr)); - return 0; - } - - if (elems.ssid && elems.ssid_len > 0 && - (elems.ssid_len != hapd->conf->ssid.ssid_len || - os_memcmp(elems.ssid, hapd->conf->ssid.ssid, elems.ssid_len) != - 0)) - return 0; /* Not for us */ - - wps_ie = ieee802_11_vendor_ie_concat(ie, ie_len, WPS_DEV_OUI_WFA); - if (wps_ie == NULL) - return 0; - if (wps_validate_probe_req(wps_ie, addr) < 0) { - wpabuf_free(wps_ie); - return 0; - } - - if (wpabuf_len(wps_ie) > 0) { - int p2p_wildcard = 0; -#ifdef CONFIG_P2P - if (elems.ssid && elems.ssid_len == P2P_WILDCARD_SSID_LEN && - os_memcmp(elems.ssid, P2P_WILDCARD_SSID, - P2P_WILDCARD_SSID_LEN) == 0) - p2p_wildcard = 1; -#endif /* CONFIG_P2P */ - wps_registrar_probe_req_rx(hapd->wps->registrar, addr, wps_ie, - p2p_wildcard); -#ifdef CONFIG_WPS_UPNP - /* FIX: what exactly should be included in the WLANEvent? - * WPS attributes? Full ProbeReq frame? */ - if (!p2p_wildcard) - upnp_wps_device_send_wlan_event( - hapd->wps_upnp, addr, - UPNP_WPS_WLANEVENT_TYPE_PROBE, wps_ie); -#endif /* CONFIG_WPS_UPNP */ - } - - wpabuf_free(wps_ie); - - return 0; -} - - -#ifdef CONFIG_WPS_UPNP - -static int hostapd_rx_req_put_wlan_response( - void *priv, enum upnp_wps_wlanevent_type ev_type, - const u8 *mac_addr, const struct wpabuf *msg, - enum wps_msg_type msg_type) -{ - struct hostapd_data *hapd = priv; - struct sta_info *sta; - struct upnp_pending_message *p; - - wpa_printf(MSG_DEBUG, "WPS UPnP: PutWLANResponse ev_type=%d mac_addr=" - MACSTR, ev_type, MAC2STR(mac_addr)); - wpa_hexdump(MSG_MSGDUMP, "WPS UPnP: PutWLANResponse NewMessage", - wpabuf_head(msg), wpabuf_len(msg)); - if (ev_type != UPNP_WPS_WLANEVENT_TYPE_EAP) { - wpa_printf(MSG_DEBUG, "WPS UPnP: Ignored unexpected " - "PutWLANResponse WLANEventType %d", ev_type); - return -1; - } - - /* - * EAP response to ongoing to WPS Registration. Send it to EAP-WSC - * server implementation for delivery to the peer. - */ - - sta = ap_get_sta(hapd, mac_addr); -#ifndef CONFIG_WPS_STRICT - if (!sta) { - /* - * Workaround - Intel wsccmd uses bogus NewWLANEventMAC: - * Pick STA that is in an ongoing WPS registration without - * checking the MAC address. - */ - wpa_printf(MSG_DEBUG, "WPS UPnP: No matching STA found based " - "on NewWLANEventMAC; try wildcard match"); - for (sta = hapd->sta_list; sta; sta = sta->next) { - if (sta->eapol_sm && (sta->flags & WLAN_STA_WPS)) - break; - } - } -#endif /* CONFIG_WPS_STRICT */ - - if (!sta) { - wpa_printf(MSG_DEBUG, "WPS UPnP: No matching STA found"); - return 0; - } - - p = os_zalloc(sizeof(*p)); - if (p == NULL) - return -1; - os_memcpy(p->addr, sta->addr, ETH_ALEN); - p->msg = wpabuf_dup(msg); - p->type = msg_type; - p->next = hapd->wps->upnp_msgs; - hapd->wps->upnp_msgs = p; - - return eapol_auth_eap_pending_cb(sta->eapol_sm, sta->eapol_sm->eap); -} - - -static int hostapd_wps_upnp_init(struct hostapd_data *hapd, - struct wps_context *wps) -{ - struct upnp_wps_device_ctx *ctx; - - if (!hapd->conf->upnp_iface) - return 0; - ctx = os_zalloc(sizeof(*ctx)); - if (ctx == NULL) - return -1; - - ctx->rx_req_put_wlan_response = hostapd_rx_req_put_wlan_response; - if (hapd->conf->ap_pin) - ctx->ap_pin = os_strdup(hapd->conf->ap_pin); - - hapd->wps_upnp = upnp_wps_device_init(ctx, wps, hapd, - hapd->conf->upnp_iface); - if (hapd->wps_upnp == NULL) - return -1; - wps->wps_upnp = hapd->wps_upnp; - - return 0; -} - - -static void hostapd_wps_upnp_deinit(struct hostapd_data *hapd) -{ - upnp_wps_device_deinit(hapd->wps_upnp, hapd); -} - -#endif /* CONFIG_WPS_UPNP */ - - -int hostapd_wps_get_mib_sta(struct hostapd_data *hapd, const u8 *addr, - char *buf, size_t buflen) -{ - if (hapd->wps == NULL) - return 0; - return wps_registrar_get_info(hapd->wps->registrar, addr, buf, buflen); -} - - -static void hostapd_wps_ap_pin_timeout(void *eloop_data, void *user_ctx) -{ - struct hostapd_data *hapd = eloop_data; - wpa_printf(MSG_DEBUG, "WPS: AP PIN timed out"); - hostapd_wps_ap_pin_disable(hapd); -} - - -static void hostapd_wps_ap_pin_enable(struct hostapd_data *hapd, int timeout) -{ - wpa_printf(MSG_DEBUG, "WPS: Enabling AP PIN (timeout=%d)", timeout); - hapd->ap_pin_failures = 0; - hapd->conf->ap_setup_locked = 0; - if (hapd->wps->ap_setup_locked) { - wpa_msg(hapd->msg_ctx, MSG_INFO, WPS_EVENT_AP_SETUP_UNLOCKED); - hapd->wps->ap_setup_locked = 0; - wps_registrar_update_ie(hapd->wps->registrar); - } - eloop_cancel_timeout(hostapd_wps_ap_pin_timeout, hapd, NULL); - if (timeout > 0) - eloop_register_timeout(timeout, 0, - hostapd_wps_ap_pin_timeout, hapd, NULL); -} - - -static int wps_ap_pin_disable(struct hostapd_data *hapd, void *ctx) -{ - os_free(hapd->conf->ap_pin); - hapd->conf->ap_pin = NULL; -#ifdef CONFIG_WPS_UPNP - upnp_wps_set_ap_pin(hapd->wps_upnp, NULL); -#endif /* CONFIG_WPS_UPNP */ - eloop_cancel_timeout(hostapd_wps_ap_pin_timeout, hapd, NULL); - return 0; -} - - -void hostapd_wps_ap_pin_disable(struct hostapd_data *hapd) -{ - wpa_printf(MSG_DEBUG, "WPS: Disabling AP PIN"); - hostapd_wps_for_each(hapd, wps_ap_pin_disable, NULL); -} - - -struct wps_ap_pin_data { - char pin_txt[9]; - int timeout; -}; - - -static int wps_ap_pin_set(struct hostapd_data *hapd, void *ctx) -{ - struct wps_ap_pin_data *data = ctx; - os_free(hapd->conf->ap_pin); - hapd->conf->ap_pin = os_strdup(data->pin_txt); -#ifdef CONFIG_WPS_UPNP - upnp_wps_set_ap_pin(hapd->wps_upnp, data->pin_txt); -#endif /* CONFIG_WPS_UPNP */ - hostapd_wps_ap_pin_enable(hapd, data->timeout); - return 0; -} - - -const char * hostapd_wps_ap_pin_random(struct hostapd_data *hapd, int timeout) -{ - unsigned int pin; - struct wps_ap_pin_data data; - - pin = wps_generate_pin(); - os_snprintf(data.pin_txt, sizeof(data.pin_txt), "%u", pin); - data.timeout = timeout; - hostapd_wps_for_each(hapd, wps_ap_pin_set, &data); - return hapd->conf->ap_pin; -} - - -const char * hostapd_wps_ap_pin_get(struct hostapd_data *hapd) -{ - return hapd->conf->ap_pin; -} - - -int hostapd_wps_ap_pin_set(struct hostapd_data *hapd, const char *pin, - int timeout) -{ - struct wps_ap_pin_data data; - int ret; - - ret = os_snprintf(data.pin_txt, sizeof(data.pin_txt), "%s", pin); - if (ret < 0 || ret >= (int) sizeof(data.pin_txt)) - return -1; - data.timeout = timeout; - return hostapd_wps_for_each(hapd, wps_ap_pin_set, &data); -} - - -static int wps_update_ie(struct hostapd_data *hapd, void *ctx) -{ - if (hapd->wps) - wps_registrar_update_ie(hapd->wps->registrar); - return 0; -} - - -void hostapd_wps_update_ie(struct hostapd_data *hapd) -{ - hostapd_wps_for_each(hapd, wps_update_ie, NULL); -} - - -int hostapd_wps_config_ap(struct hostapd_data *hapd, const char *ssid, - const char *auth, const char *encr, const char *key) -{ - struct wps_credential cred; - size_t len; - - os_memset(&cred, 0, sizeof(cred)); - - len = os_strlen(ssid); - if ((len & 1) || len > 2 * sizeof(cred.ssid) || - hexstr2bin(ssid, cred.ssid, len / 2)) - return -1; - cred.ssid_len = len / 2; - - if (os_strncmp(auth, "OPEN", 4) == 0) - cred.auth_type = WPS_AUTH_OPEN; - else if (os_strncmp(auth, "WPAPSK", 6) == 0) - cred.auth_type = WPS_AUTH_WPAPSK; - else if (os_strncmp(auth, "WPA2PSK", 7) == 0) - cred.auth_type = WPS_AUTH_WPA2PSK; - else - return -1; - - if (encr) { - if (os_strncmp(encr, "NONE", 4) == 0) - cred.encr_type = WPS_ENCR_NONE; - else if (os_strncmp(encr, "WEP", 3) == 0) - cred.encr_type = WPS_ENCR_WEP; - else if (os_strncmp(encr, "TKIP", 4) == 0) - cred.encr_type = WPS_ENCR_TKIP; - else if (os_strncmp(encr, "CCMP", 4) == 0) - cred.encr_type = WPS_ENCR_AES; - else - return -1; - } else - cred.encr_type = WPS_ENCR_NONE; - - if (key) { - len = os_strlen(key); - if ((len & 1) || len > 2 * sizeof(cred.key) || - hexstr2bin(key, cred.key, len / 2)) - return -1; - cred.key_len = len / 2; - } - - return wps_registrar_config_ap(hapd->wps->registrar, &cred); -} diff --git a/hostapd-0.8/src/ap/wps_hostapd.h b/hostapd-0.8/src/ap/wps_hostapd.h deleted file mode 100644 index 338a220..0000000 --- a/hostapd-0.8/src/ap/wps_hostapd.h +++ /dev/null @@ -1,72 +0,0 @@ -/* - * hostapd / WPS integration - * Copyright (c) 2008-2010, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#ifndef WPS_HOSTAPD_H -#define WPS_HOSTAPD_H - -#ifdef CONFIG_WPS - -int hostapd_init_wps(struct hostapd_data *hapd, - struct hostapd_bss_config *conf); -void hostapd_deinit_wps(struct hostapd_data *hapd); -void hostapd_update_wps(struct hostapd_data *hapd); -int hostapd_wps_add_pin(struct hostapd_data *hapd, const u8 *addr, - const char *uuid, const char *pin, int timeout); -int hostapd_wps_button_pushed(struct hostapd_data *hapd, - const u8 *p2p_dev_addr); -int hostapd_wps_start_oob(struct hostapd_data *hapd, char *device_type, - char *path, char *method, char *name); -int hostapd_wps_get_mib_sta(struct hostapd_data *hapd, const u8 *addr, - char *buf, size_t buflen); -void hostapd_wps_ap_pin_disable(struct hostapd_data *hapd); -const char * hostapd_wps_ap_pin_random(struct hostapd_data *hapd, int timeout); -const char * hostapd_wps_ap_pin_get(struct hostapd_data *hapd); -int hostapd_wps_ap_pin_set(struct hostapd_data *hapd, const char *pin, - int timeout); -void hostapd_wps_update_ie(struct hostapd_data *hapd); -int hostapd_wps_config_ap(struct hostapd_data *hapd, const char *ssid, - const char *auth, const char *encr, const char *key); - -#else /* CONFIG_WPS */ - -static inline int hostapd_init_wps(struct hostapd_data *hapd, - struct hostapd_bss_config *conf) -{ - return 0; -} - -static inline void hostapd_deinit_wps(struct hostapd_data *hapd) -{ -} - -static inline void hostapd_update_wps(struct hostapd_data *hapd) -{ -} - -static inline int hostapd_wps_get_mib_sta(struct hostapd_data *hapd, - const u8 *addr, - char *buf, size_t buflen) -{ - return 0; -} - -static inline int hostapd_wps_button_pushed(struct hostapd_data *hapd, - const u8 *p2p_dev_addr) -{ - return 0; -} - -#endif /* CONFIG_WPS */ - -#endif /* WPS_HOSTAPD_H */ diff --git a/hostapd-0.8/src/common/Makefile b/hostapd-0.8/src/common/Makefile deleted file mode 100644 index 9c41962..0000000 --- a/hostapd-0.8/src/common/Makefile +++ /dev/null @@ -1,8 +0,0 @@ -all: - @echo Nothing to be made. - -clean: - rm -f *~ *.o *.d - -install: - @echo Nothing to be made. diff --git a/hostapd-0.8/src/common/defs.h b/hostapd-0.8/src/common/defs.h deleted file mode 100644 index 8abec07..0000000 --- a/hostapd-0.8/src/common/defs.h +++ /dev/null @@ -1,270 +0,0 @@ -/* - * WPA Supplicant - Common definitions - * Copyright (c) 2004-2008, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#ifndef DEFS_H -#define DEFS_H - -#ifdef FALSE -#undef FALSE -#endif -#ifdef TRUE -#undef TRUE -#endif -typedef enum { FALSE = 0, TRUE = 1 } Boolean; - - -#define WPA_CIPHER_NONE BIT(0) -#define WPA_CIPHER_WEP40 BIT(1) -#define WPA_CIPHER_WEP104 BIT(2) -#define WPA_CIPHER_TKIP BIT(3) -#define WPA_CIPHER_CCMP BIT(4) -#ifdef CONFIG_IEEE80211W -#define WPA_CIPHER_AES_128_CMAC BIT(5) -#endif /* CONFIG_IEEE80211W */ - -#define WPA_KEY_MGMT_IEEE8021X BIT(0) -#define WPA_KEY_MGMT_PSK BIT(1) -#define WPA_KEY_MGMT_NONE BIT(2) -#define WPA_KEY_MGMT_IEEE8021X_NO_WPA BIT(3) -#define WPA_KEY_MGMT_WPA_NONE BIT(4) -#define WPA_KEY_MGMT_FT_IEEE8021X BIT(5) -#define WPA_KEY_MGMT_FT_PSK BIT(6) -#define WPA_KEY_MGMT_IEEE8021X_SHA256 BIT(7) -#define WPA_KEY_MGMT_PSK_SHA256 BIT(8) -#define WPA_KEY_MGMT_WPS BIT(9) - -static inline int wpa_key_mgmt_wpa_ieee8021x(int akm) -{ - return !!(akm & (WPA_KEY_MGMT_IEEE8021X | - WPA_KEY_MGMT_FT_IEEE8021X | - WPA_KEY_MGMT_IEEE8021X_SHA256)); -} - -static inline int wpa_key_mgmt_wpa_psk(int akm) -{ - return !!(akm & (WPA_KEY_MGMT_PSK | - WPA_KEY_MGMT_FT_PSK | - WPA_KEY_MGMT_PSK_SHA256)); -} - -static inline int wpa_key_mgmt_ft(int akm) -{ - return !!(akm & (WPA_KEY_MGMT_FT_PSK | - WPA_KEY_MGMT_FT_IEEE8021X)); -} - -static inline int wpa_key_mgmt_sha256(int akm) -{ - return !!(akm & (WPA_KEY_MGMT_PSK_SHA256 | - WPA_KEY_MGMT_IEEE8021X_SHA256)); -} - -static inline int wpa_key_mgmt_wpa(int akm) -{ - return wpa_key_mgmt_wpa_ieee8021x(akm) || - wpa_key_mgmt_wpa_psk(akm); -} - - -#define WPA_PROTO_WPA BIT(0) -#define WPA_PROTO_RSN BIT(1) - -#define WPA_AUTH_ALG_OPEN BIT(0) -#define WPA_AUTH_ALG_SHARED BIT(1) -#define WPA_AUTH_ALG_LEAP BIT(2) -#define WPA_AUTH_ALG_FT BIT(3) - - -enum wpa_alg { - WPA_ALG_NONE, - WPA_ALG_WEP, - WPA_ALG_TKIP, - WPA_ALG_CCMP, - WPA_ALG_IGTK, - WPA_ALG_PMK -}; - -/** - * enum wpa_cipher - Cipher suites - */ -enum wpa_cipher { - CIPHER_NONE, - CIPHER_WEP40, - CIPHER_TKIP, - CIPHER_CCMP, - CIPHER_WEP104 -}; - -/** - * enum wpa_key_mgmt - Key management suites - */ -enum wpa_key_mgmt { - KEY_MGMT_802_1X, - KEY_MGMT_PSK, - KEY_MGMT_NONE, - KEY_MGMT_802_1X_NO_WPA, - KEY_MGMT_WPA_NONE, - KEY_MGMT_FT_802_1X, - KEY_MGMT_FT_PSK, - KEY_MGMT_802_1X_SHA256, - KEY_MGMT_PSK_SHA256, - KEY_MGMT_WPS -}; - -/** - * enum wpa_states - wpa_supplicant state - * - * These enumeration values are used to indicate the current wpa_supplicant - * state (wpa_s->wpa_state). The current state can be retrieved with - * wpa_supplicant_get_state() function and the state can be changed by calling - * wpa_supplicant_set_state(). In WPA state machine (wpa.c and preauth.c), the - * wrapper functions wpa_sm_get_state() and wpa_sm_set_state() should be used - * to access the state variable. - */ -enum wpa_states { - /** - * WPA_DISCONNECTED - Disconnected state - * - * This state indicates that client is not associated, but is likely to - * start looking for an access point. This state is entered when a - * connection is lost. - */ - WPA_DISCONNECTED, - - /** - * WPA_INTERFACE_DISABLED - Interface disabled - * - * This stat eis entered if the network interface is disabled, e.g., - * due to rfkill. wpa_supplicant refuses any new operations that would - * use the radio until the interface has been enabled. - */ - WPA_INTERFACE_DISABLED, - - /** - * WPA_INACTIVE - Inactive state (wpa_supplicant disabled) - * - * This state is entered if there are no enabled networks in the - * configuration. wpa_supplicant is not trying to associate with a new - * network and external interaction (e.g., ctrl_iface call to add or - * enable a network) is needed to start association. - */ - WPA_INACTIVE, - - /** - * WPA_SCANNING - Scanning for a network - * - * This state is entered when wpa_supplicant starts scanning for a - * network. - */ - WPA_SCANNING, - - /** - * WPA_AUTHENTICATING - Trying to authenticate with a BSS/SSID - * - * This state is entered when wpa_supplicant has found a suitable BSS - * to authenticate with and the driver is configured to try to - * authenticate with this BSS. This state is used only with drivers - * that use wpa_supplicant as the SME. - */ - WPA_AUTHENTICATING, - - /** - * WPA_ASSOCIATING - Trying to associate with a BSS/SSID - * - * This state is entered when wpa_supplicant has found a suitable BSS - * to associate with and the driver is configured to try to associate - * with this BSS in ap_scan=1 mode. When using ap_scan=2 mode, this - * state is entered when the driver is configured to try to associate - * with a network using the configured SSID and security policy. - */ - WPA_ASSOCIATING, - - /** - * WPA_ASSOCIATED - Association completed - * - * This state is entered when the driver reports that association has - * been successfully completed with an AP. If IEEE 802.1X is used - * (with or without WPA/WPA2), wpa_supplicant remains in this state - * until the IEEE 802.1X/EAPOL authentication has been completed. - */ - WPA_ASSOCIATED, - - /** - * WPA_4WAY_HANDSHAKE - WPA 4-Way Key Handshake in progress - * - * This state is entered when WPA/WPA2 4-Way Handshake is started. In - * case of WPA-PSK, this happens when receiving the first EAPOL-Key - * frame after association. In case of WPA-EAP, this state is entered - * when the IEEE 802.1X/EAPOL authentication has been completed. - */ - WPA_4WAY_HANDSHAKE, - - /** - * WPA_GROUP_HANDSHAKE - WPA Group Key Handshake in progress - * - * This state is entered when 4-Way Key Handshake has been completed - * (i.e., when the supplicant sends out message 4/4) and when Group - * Key rekeying is started by the AP (i.e., when supplicant receives - * message 1/2). - */ - WPA_GROUP_HANDSHAKE, - - /** - * WPA_COMPLETED - All authentication completed - * - * This state is entered when the full authentication process is - * completed. In case of WPA2, this happens when the 4-Way Handshake is - * successfully completed. With WPA, this state is entered after the - * Group Key Handshake; with IEEE 802.1X (non-WPA) connection is - * completed after dynamic keys are received (or if not used, after - * the EAP authentication has been completed). With static WEP keys and - * plaintext connections, this state is entered when an association - * has been completed. - * - * This state indicates that the supplicant has completed its - * processing for the association phase and that data connection is - * fully configured. - */ - WPA_COMPLETED -}; - -#define MLME_SETPROTECTION_PROTECT_TYPE_NONE 0 -#define MLME_SETPROTECTION_PROTECT_TYPE_RX 1 -#define MLME_SETPROTECTION_PROTECT_TYPE_TX 2 -#define MLME_SETPROTECTION_PROTECT_TYPE_RX_TX 3 - -#define MLME_SETPROTECTION_KEY_TYPE_GROUP 0 -#define MLME_SETPROTECTION_KEY_TYPE_PAIRWISE 1 - - -/** - * enum mfp_options - Management frame protection (IEEE 802.11w) options - */ -enum mfp_options { - NO_MGMT_FRAME_PROTECTION = 0, - MGMT_FRAME_PROTECTION_OPTIONAL = 1, - MGMT_FRAME_PROTECTION_REQUIRED = 2 -}; - -/** - * enum hostapd_hw_mode - Hardware mode - */ -enum hostapd_hw_mode { - HOSTAPD_MODE_IEEE80211B, - HOSTAPD_MODE_IEEE80211G, - HOSTAPD_MODE_IEEE80211A, - NUM_HOSTAPD_MODES -}; - -#endif /* DEFS_H */ diff --git a/hostapd-0.8/src/common/eapol_common.h b/hostapd-0.8/src/common/eapol_common.h deleted file mode 100644 index d70e62d..0000000 --- a/hostapd-0.8/src/common/eapol_common.h +++ /dev/null @@ -1,47 +0,0 @@ -/* - * EAPOL definitions shared between hostapd and wpa_supplicant - * Copyright (c) 2002-2007, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#ifndef EAPOL_COMMON_H -#define EAPOL_COMMON_H - -/* IEEE Std 802.1X-2004 */ - -#ifdef _MSC_VER -#pragma pack(push, 1) -#endif /* _MSC_VER */ - -struct ieee802_1x_hdr { - u8 version; - u8 type; - be16 length; - /* followed by length octets of data */ -} STRUCT_PACKED; - -#ifdef _MSC_VER -#pragma pack(pop) -#endif /* _MSC_VER */ - -#define EAPOL_VERSION 2 - -enum { IEEE802_1X_TYPE_EAP_PACKET = 0, - IEEE802_1X_TYPE_EAPOL_START = 1, - IEEE802_1X_TYPE_EAPOL_LOGOFF = 2, - IEEE802_1X_TYPE_EAPOL_KEY = 3, - IEEE802_1X_TYPE_EAPOL_ENCAPSULATED_ASF_ALERT = 4 -}; - -enum { EAPOL_KEY_TYPE_RC4 = 1, EAPOL_KEY_TYPE_RSN = 2, - EAPOL_KEY_TYPE_WPA = 254 }; - -#endif /* EAPOL_COMMON_H */ diff --git a/hostapd-0.8/src/common/ieee802_11_common.c b/hostapd-0.8/src/common/ieee802_11_common.c deleted file mode 100644 index ee41b3a..0000000 --- a/hostapd-0.8/src/common/ieee802_11_common.c +++ /dev/null @@ -1,347 +0,0 @@ -/* - * IEEE 802.11 Common routines - * Copyright (c) 2002-2009, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#include "includes.h" - -#include "common.h" -#include "ieee802_11_defs.h" -#include "ieee802_11_common.h" - - -static int ieee802_11_parse_vendor_specific(const u8 *pos, size_t elen, - struct ieee802_11_elems *elems, - int show_errors) -{ - unsigned int oui; - - /* first 3 bytes in vendor specific information element are the IEEE - * OUI of the vendor. The following byte is used a vendor specific - * sub-type. */ - if (elen < 4) { - if (show_errors) { - wpa_printf(MSG_MSGDUMP, "short vendor specific " - "information element ignored (len=%lu)", - (unsigned long) elen); - } - return -1; - } - - oui = WPA_GET_BE24(pos); - switch (oui) { - case OUI_MICROSOFT: - /* Microsoft/Wi-Fi information elements are further typed and - * subtyped */ - switch (pos[3]) { - case 1: - /* Microsoft OUI (00:50:F2) with OUI Type 1: - * real WPA information element */ - elems->wpa_ie = pos; - elems->wpa_ie_len = elen; - break; - case WMM_OUI_TYPE: - /* WMM information element */ - if (elen < 5) { - wpa_printf(MSG_MSGDUMP, "short WMM " - "information element ignored " - "(len=%lu)", - (unsigned long) elen); - return -1; - } - switch (pos[4]) { - case WMM_OUI_SUBTYPE_INFORMATION_ELEMENT: - case WMM_OUI_SUBTYPE_PARAMETER_ELEMENT: - /* - * Share same pointer since only one of these - * is used and they start with same data. - * Length field can be used to distinguish the - * IEs. - */ - elems->wmm = pos; - elems->wmm_len = elen; - break; - case WMM_OUI_SUBTYPE_TSPEC_ELEMENT: - elems->wmm_tspec = pos; - elems->wmm_tspec_len = elen; - break; - default: - wpa_printf(MSG_EXCESSIVE, "unknown WMM " - "information element ignored " - "(subtype=%d len=%lu)", - pos[4], (unsigned long) elen); - return -1; - } - break; - case 4: - /* Wi-Fi Protected Setup (WPS) IE */ - elems->wps_ie = pos; - elems->wps_ie_len = elen; - break; - default: - wpa_printf(MSG_EXCESSIVE, "Unknown Microsoft " - "information element ignored " - "(type=%d len=%lu)", - pos[3], (unsigned long) elen); - return -1; - } - break; - - case OUI_WFA: - switch (pos[3]) { - case P2P_OUI_TYPE: - /* Wi-Fi Alliance - P2P IE */ - elems->p2p = pos; - elems->p2p_len = elen; - break; - default: - wpa_printf(MSG_MSGDUMP, "Unknown WFA " - "information element ignored " - "(type=%d len=%lu)\n", - pos[3], (unsigned long) elen); - return -1; - } - break; - - case OUI_BROADCOM: - switch (pos[3]) { - case VENDOR_HT_CAPAB_OUI_TYPE: - elems->vendor_ht_cap = pos; - elems->vendor_ht_cap_len = elen; - break; - default: - wpa_printf(MSG_EXCESSIVE, "Unknown Broadcom " - "information element ignored " - "(type=%d len=%lu)", - pos[3], (unsigned long) elen); - return -1; - } - break; - - default: - wpa_printf(MSG_EXCESSIVE, "unknown vendor specific " - "information element ignored (vendor OUI " - "%02x:%02x:%02x len=%lu)", - pos[0], pos[1], pos[2], (unsigned long) elen); - return -1; - } - - return 0; -} - - -/** - * ieee802_11_parse_elems - Parse information elements in management frames - * @start: Pointer to the start of IEs - * @len: Length of IE buffer in octets - * @elems: Data structure for parsed elements - * @show_errors: Whether to show parsing errors in debug log - * Returns: Parsing result - */ -ParseRes ieee802_11_parse_elems(const u8 *start, size_t len, - struct ieee802_11_elems *elems, - int show_errors) -{ - size_t left = len; - const u8 *pos = start; - int unknown = 0; - - os_memset(elems, 0, sizeof(*elems)); - - while (left >= 2) { - u8 id, elen; - - id = *pos++; - elen = *pos++; - left -= 2; - - if (elen > left) { - if (show_errors) { - wpa_printf(MSG_DEBUG, "IEEE 802.11 element " - "parse failed (id=%d elen=%d " - "left=%lu)", - id, elen, (unsigned long) left); - wpa_hexdump(MSG_MSGDUMP, "IEs", start, len); - } - return ParseFailed; - } - - switch (id) { - case WLAN_EID_SSID: - elems->ssid = pos; - elems->ssid_len = elen; - break; - case WLAN_EID_SUPP_RATES: - elems->supp_rates = pos; - elems->supp_rates_len = elen; - break; - case WLAN_EID_FH_PARAMS: - elems->fh_params = pos; - elems->fh_params_len = elen; - break; - case WLAN_EID_DS_PARAMS: - elems->ds_params = pos; - elems->ds_params_len = elen; - break; - case WLAN_EID_CF_PARAMS: - elems->cf_params = pos; - elems->cf_params_len = elen; - break; - case WLAN_EID_TIM: - elems->tim = pos; - elems->tim_len = elen; - break; - case WLAN_EID_IBSS_PARAMS: - elems->ibss_params = pos; - elems->ibss_params_len = elen; - break; - case WLAN_EID_CHALLENGE: - elems->challenge = pos; - elems->challenge_len = elen; - break; - case WLAN_EID_ERP_INFO: - elems->erp_info = pos; - elems->erp_info_len = elen; - break; - case WLAN_EID_EXT_SUPP_RATES: - elems->ext_supp_rates = pos; - elems->ext_supp_rates_len = elen; - break; - case WLAN_EID_VENDOR_SPECIFIC: - if (ieee802_11_parse_vendor_specific(pos, elen, - elems, - show_errors)) - unknown++; - break; - case WLAN_EID_RSN: - elems->rsn_ie = pos; - elems->rsn_ie_len = elen; - break; - case WLAN_EID_PWR_CAPABILITY: - elems->power_cap = pos; - elems->power_cap_len = elen; - break; - case WLAN_EID_SUPPORTED_CHANNELS: - elems->supp_channels = pos; - elems->supp_channels_len = elen; - break; - case WLAN_EID_MOBILITY_DOMAIN: - elems->mdie = pos; - elems->mdie_len = elen; - break; - case WLAN_EID_FAST_BSS_TRANSITION: - elems->ftie = pos; - elems->ftie_len = elen; - break; - case WLAN_EID_TIMEOUT_INTERVAL: - elems->timeout_int = pos; - elems->timeout_int_len = elen; - break; - case WLAN_EID_HT_CAP: - elems->ht_capabilities = pos; - elems->ht_capabilities_len = elen; - break; - case WLAN_EID_HT_OPERATION: - elems->ht_operation = pos; - elems->ht_operation_len = elen; - break; - case WLAN_EID_LINK_ID: - if (elen < 18) - break; - elems->link_id = pos; - break; - default: - unknown++; - if (!show_errors) - break; - wpa_printf(MSG_MSGDUMP, "IEEE 802.11 element parse " - "ignored unknown element (id=%d elen=%d)", - id, elen); - break; - } - - left -= elen; - pos += elen; - } - - if (left) - return ParseFailed; - - return unknown ? ParseUnknown : ParseOK; -} - - -int ieee802_11_ie_count(const u8 *ies, size_t ies_len) -{ - int count = 0; - const u8 *pos, *end; - - if (ies == NULL) - return 0; - - pos = ies; - end = ies + ies_len; - - while (pos + 2 <= end) { - if (pos + 2 + pos[1] > end) - break; - count++; - pos += 2 + pos[1]; - } - - return count; -} - - -struct wpabuf * ieee802_11_vendor_ie_concat(const u8 *ies, size_t ies_len, - u32 oui_type) -{ - struct wpabuf *buf; - const u8 *end, *pos, *ie; - - pos = ies; - end = ies + ies_len; - ie = NULL; - - while (pos + 1 < end) { - if (pos + 2 + pos[1] > end) - return NULL; - if (pos[0] == WLAN_EID_VENDOR_SPECIFIC && pos[1] >= 4 && - WPA_GET_BE32(&pos[2]) == oui_type) { - ie = pos; - break; - } - pos += 2 + pos[1]; - } - - if (ie == NULL) - return NULL; /* No specified vendor IE found */ - - buf = wpabuf_alloc(ies_len); - if (buf == NULL) - return NULL; - - /* - * There may be multiple vendor IEs in the message, so need to - * concatenate their data fields. - */ - while (pos + 1 < end) { - if (pos + 2 + pos[1] > end) - break; - if (pos[0] == WLAN_EID_VENDOR_SPECIFIC && pos[1] >= 4 && - WPA_GET_BE32(&pos[2]) == oui_type) - wpabuf_put_data(buf, pos + 6, pos[1] - 4); - pos += 2 + pos[1]; - } - - return buf; -} diff --git a/hostapd-0.8/src/common/ieee802_11_common.h b/hostapd-0.8/src/common/ieee802_11_common.h deleted file mode 100644 index 0c90fa4..0000000 --- a/hostapd-0.8/src/common/ieee802_11_common.h +++ /dev/null @@ -1,81 +0,0 @@ -/* - * IEEE 802.11 Common routines - * Copyright (c) 2002-2009, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#ifndef IEEE802_11_COMMON_H -#define IEEE802_11_COMMON_H - -/* Parsed Information Elements */ -struct ieee802_11_elems { - const u8 *ssid; - const u8 *supp_rates; - const u8 *fh_params; - const u8 *ds_params; - const u8 *cf_params; - const u8 *tim; - const u8 *ibss_params; - const u8 *challenge; - const u8 *erp_info; - const u8 *ext_supp_rates; - const u8 *wpa_ie; - const u8 *rsn_ie; - const u8 *wmm; /* WMM Information or Parameter Element */ - const u8 *wmm_tspec; - const u8 *wps_ie; - const u8 *power_cap; - const u8 *supp_channels; - const u8 *mdie; - const u8 *ftie; - const u8 *timeout_int; - const u8 *ht_capabilities; - const u8 *ht_operation; - const u8 *vendor_ht_cap; - const u8 *p2p; - const u8 *link_id; - - u8 ssid_len; - u8 supp_rates_len; - u8 fh_params_len; - u8 ds_params_len; - u8 cf_params_len; - u8 tim_len; - u8 ibss_params_len; - u8 challenge_len; - u8 erp_info_len; - u8 ext_supp_rates_len; - u8 wpa_ie_len; - u8 rsn_ie_len; - u8 wmm_len; /* 7 = WMM Information; 24 = WMM Parameter */ - u8 wmm_tspec_len; - u8 wps_ie_len; - u8 power_cap_len; - u8 supp_channels_len; - u8 mdie_len; - u8 ftie_len; - u8 timeout_int_len; - u8 ht_capabilities_len; - u8 ht_operation_len; - u8 vendor_ht_cap_len; - u8 p2p_len; -}; - -typedef enum { ParseOK = 0, ParseUnknown = 1, ParseFailed = -1 } ParseRes; - -ParseRes ieee802_11_parse_elems(const u8 *start, size_t len, - struct ieee802_11_elems *elems, - int show_errors); -int ieee802_11_ie_count(const u8 *ies, size_t ies_len); -struct wpabuf * ieee802_11_vendor_ie_concat(const u8 *ies, size_t ies_len, - u32 oui_type); - -#endif /* IEEE802_11_COMMON_H */ diff --git a/hostapd-0.8/src/common/ieee802_11_defs.h b/hostapd-0.8/src/common/ieee802_11_defs.h deleted file mode 100644 index 86868c0..0000000 --- a/hostapd-0.8/src/common/ieee802_11_defs.h +++ /dev/null @@ -1,800 +0,0 @@ -/* - * IEEE 802.11 Frame type definitions - * Copyright (c) 2002-2009, Jouni Malinen - * Copyright (c) 2007-2008 Intel Corporation - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#ifndef IEEE802_11_DEFS_H -#define IEEE802_11_DEFS_H - -/* IEEE 802.11 defines */ - -#define WLAN_FC_PVER 0x0003 -#define WLAN_FC_TODS 0x0100 -#define WLAN_FC_FROMDS 0x0200 -#define WLAN_FC_MOREFRAG 0x0400 -#define WLAN_FC_RETRY 0x0800 -#define WLAN_FC_PWRMGT 0x1000 -#define WLAN_FC_MOREDATA 0x2000 -#define WLAN_FC_ISWEP 0x4000 -#define WLAN_FC_ORDER 0x8000 - -#define WLAN_FC_GET_TYPE(fc) (((fc) & 0x000c) >> 2) -#define WLAN_FC_GET_STYPE(fc) (((fc) & 0x00f0) >> 4) - -#define WLAN_GET_SEQ_FRAG(seq) ((seq) & (BIT(3) | BIT(2) | BIT(1) | BIT(0))) -#define WLAN_GET_SEQ_SEQ(seq) \ - (((seq) & (~(BIT(3) | BIT(2) | BIT(1) | BIT(0)))) >> 4) - -#define WLAN_FC_TYPE_MGMT 0 -#define WLAN_FC_TYPE_CTRL 1 -#define WLAN_FC_TYPE_DATA 2 - -/* management */ -#define WLAN_FC_STYPE_ASSOC_REQ 0 -#define WLAN_FC_STYPE_ASSOC_RESP 1 -#define WLAN_FC_STYPE_REASSOC_REQ 2 -#define WLAN_FC_STYPE_REASSOC_RESP 3 -#define WLAN_FC_STYPE_PROBE_REQ 4 -#define WLAN_FC_STYPE_PROBE_RESP 5 -#define WLAN_FC_STYPE_BEACON 8 -#define WLAN_FC_STYPE_ATIM 9 -#define WLAN_FC_STYPE_DISASSOC 10 -#define WLAN_FC_STYPE_AUTH 11 -#define WLAN_FC_STYPE_DEAUTH 12 -#define WLAN_FC_STYPE_ACTION 13 - -/* control */ -#define WLAN_FC_STYPE_PSPOLL 10 -#define WLAN_FC_STYPE_RTS 11 -#define WLAN_FC_STYPE_CTS 12 -#define WLAN_FC_STYPE_ACK 13 -#define WLAN_FC_STYPE_CFEND 14 -#define WLAN_FC_STYPE_CFENDACK 15 - -/* data */ -#define WLAN_FC_STYPE_DATA 0 -#define WLAN_FC_STYPE_DATA_CFACK 1 -#define WLAN_FC_STYPE_DATA_CFPOLL 2 -#define WLAN_FC_STYPE_DATA_CFACKPOLL 3 -#define WLAN_FC_STYPE_NULLFUNC 4 -#define WLAN_FC_STYPE_CFACK 5 -#define WLAN_FC_STYPE_CFPOLL 6 -#define WLAN_FC_STYPE_CFACKPOLL 7 -#define WLAN_FC_STYPE_QOS_DATA 8 -#define WLAN_FC_STYPE_QOS_DATA_CFACK 9 -#define WLAN_FC_STYPE_QOS_DATA_CFPOLL 10 -#define WLAN_FC_STYPE_QOS_DATA_CFACKPOLL 11 -#define WLAN_FC_STYPE_QOS_NULL 12 -#define WLAN_FC_STYPE_QOS_CFPOLL 14 -#define WLAN_FC_STYPE_QOS_CFACKPOLL 15 - -/* Authentication algorithms */ -#define WLAN_AUTH_OPEN 0 -#define WLAN_AUTH_SHARED_KEY 1 -#define WLAN_AUTH_FT 2 -#define WLAN_AUTH_LEAP 128 - -#define WLAN_AUTH_CHALLENGE_LEN 128 - -#define WLAN_CAPABILITY_ESS BIT(0) -#define WLAN_CAPABILITY_IBSS BIT(1) -#define WLAN_CAPABILITY_CF_POLLABLE BIT(2) -#define WLAN_CAPABILITY_CF_POLL_REQUEST BIT(3) -#define WLAN_CAPABILITY_PRIVACY BIT(4) -#define WLAN_CAPABILITY_SHORT_PREAMBLE BIT(5) -#define WLAN_CAPABILITY_PBCC BIT(6) -#define WLAN_CAPABILITY_CHANNEL_AGILITY BIT(7) -#define WLAN_CAPABILITY_SPECTRUM_MGMT BIT(8) -#define WLAN_CAPABILITY_SHORT_SLOT_TIME BIT(10) -#define WLAN_CAPABILITY_DSSS_OFDM BIT(13) - -/* Status codes (IEEE 802.11-2007, 7.3.1.9, Table 7-23) */ -#define WLAN_STATUS_SUCCESS 0 -#define WLAN_STATUS_UNSPECIFIED_FAILURE 1 -#define WLAN_STATUS_TDLS_WAKEUP_ALTERNATE 2 -#define WLAN_STATUS_TDLS_WAKEUP_REJECT 3 -#define WLAN_STATUS_SECURITY_DISABLED 5 -#define WLAN_STATUS_UNACCEPTABLE_LIFETIME 6 -#define WLAN_STATUS_NOT_IN_SAME_BSS 7 -#define WLAN_STATUS_CAPS_UNSUPPORTED 10 -#define WLAN_STATUS_REASSOC_NO_ASSOC 11 -#define WLAN_STATUS_ASSOC_DENIED_UNSPEC 12 -#define WLAN_STATUS_NOT_SUPPORTED_AUTH_ALG 13 -#define WLAN_STATUS_UNKNOWN_AUTH_TRANSACTION 14 -#define WLAN_STATUS_CHALLENGE_FAIL 15 -#define WLAN_STATUS_AUTH_TIMEOUT 16 -#define WLAN_STATUS_AP_UNABLE_TO_HANDLE_NEW_STA 17 -#define WLAN_STATUS_ASSOC_DENIED_RATES 18 -/* IEEE 802.11b */ -#define WLAN_STATUS_ASSOC_DENIED_NOSHORT 19 -#define WLAN_STATUS_ASSOC_DENIED_NOPBCC 20 -#define WLAN_STATUS_ASSOC_DENIED_NOAGILITY 21 -/* IEEE 802.11h */ -#define WLAN_STATUS_SPEC_MGMT_REQUIRED 22 -#define WLAN_STATUS_PWR_CAPABILITY_NOT_VALID 23 -#define WLAN_STATUS_SUPPORTED_CHANNEL_NOT_VALID 24 -/* IEEE 802.11g */ -#define WLAN_STATUS_ASSOC_DENIED_NO_SHORT_SLOT_TIME 25 -#define WLAN_STATUS_ASSOC_DENIED_NO_DSSS_OFDM 26 -#define WLAN_STATUS_ASSOC_DENIED_NO_HT 27 -#define WLAN_STATUS_R0KH_UNREACHABLE 28 -#define WLAN_STATUS_ASSOC_DENIED_NO_PCO 29 -/* IEEE 802.11w */ -#define WLAN_STATUS_ASSOC_REJECTED_TEMPORARILY 30 -#define WLAN_STATUS_ROBUST_MGMT_FRAME_POLICY_VIOLATION 31 -#define WLAN_STATUS_UNSPECIFIED_QOS_FAILURE 32 -#define WLAN_STATUS_REQUEST_DECLINED 37 -#define WLAN_STATUS_INVALID_PARAMETERS 38 -/* IEEE 802.11i */ -#define WLAN_STATUS_INVALID_IE 40 -#define WLAN_STATUS_GROUP_CIPHER_NOT_VALID 41 -#define WLAN_STATUS_PAIRWISE_CIPHER_NOT_VALID 42 -#define WLAN_STATUS_AKMP_NOT_VALID 43 -#define WLAN_STATUS_UNSUPPORTED_RSN_IE_VERSION 44 -#define WLAN_STATUS_INVALID_RSN_IE_CAPAB 45 -#define WLAN_STATUS_CIPHER_REJECTED_PER_POLICY 46 -#define WLAN_STATUS_TS_NOT_CREATED 47 -#define WLAN_STATUS_DIRECT_LINK_NOT_ALLOWED 48 -#define WLAN_STATUS_DEST_STA_NOT_PRESENT 49 -#define WLAN_STATUS_DEST_STA_NOT_QOS_STA 50 -#define WLAN_STATUS_ASSOC_DENIED_LISTEN_INT_TOO_LARGE 51 -/* IEEE 802.11r */ -#define WLAN_STATUS_INVALID_FT_ACTION_FRAME_COUNT 52 -#define WLAN_STATUS_INVALID_PMKID 53 -#define WLAN_STATUS_INVALID_MDIE 54 -#define WLAN_STATUS_INVALID_FTIE 55 -#define WLAN_STATUS_INVALID_RSNIE 72 - -/* Reason codes (IEEE 802.11-2007, 7.3.1.7, Table 7-22) */ -#define WLAN_REASON_UNSPECIFIED 1 -#define WLAN_REASON_PREV_AUTH_NOT_VALID 2 -#define WLAN_REASON_DEAUTH_LEAVING 3 -#define WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY 4 -#define WLAN_REASON_DISASSOC_AP_BUSY 5 -#define WLAN_REASON_CLASS2_FRAME_FROM_NONAUTH_STA 6 -#define WLAN_REASON_CLASS3_FRAME_FROM_NONASSOC_STA 7 -#define WLAN_REASON_DISASSOC_STA_HAS_LEFT 8 -#define WLAN_REASON_STA_REQ_ASSOC_WITHOUT_AUTH 9 -/* IEEE 802.11h */ -#define WLAN_REASON_PWR_CAPABILITY_NOT_VALID 10 -#define WLAN_REASON_SUPPORTED_CHANNEL_NOT_VALID 11 -/* IEEE 802.11i */ -#define WLAN_REASON_INVALID_IE 13 -#define WLAN_REASON_MICHAEL_MIC_FAILURE 14 -#define WLAN_REASON_4WAY_HANDSHAKE_TIMEOUT 15 -#define WLAN_REASON_GROUP_KEY_UPDATE_TIMEOUT 16 -#define WLAN_REASON_IE_IN_4WAY_DIFFERS 17 -#define WLAN_REASON_GROUP_CIPHER_NOT_VALID 18 -#define WLAN_REASON_PAIRWISE_CIPHER_NOT_VALID 19 -#define WLAN_REASON_AKMP_NOT_VALID 20 -#define WLAN_REASON_UNSUPPORTED_RSN_IE_VERSION 21 -#define WLAN_REASON_INVALID_RSN_IE_CAPAB 22 -#define WLAN_REASON_IEEE_802_1X_AUTH_FAILED 23 -#define WLAN_REASON_CIPHER_SUITE_REJECTED 24 -#define WLAN_REASON_TDLS_TEARDOWN_UNREACHABLE 25 -#define WLAN_REASON_TDLS_TEARDOWN_UNSPECIFIED 26 -/* IEEE 802.11e */ -#define WLAN_REASON_DISASSOC_LOW_ACK 34 - - -/* Information Element IDs */ -#define WLAN_EID_SSID 0 -#define WLAN_EID_SUPP_RATES 1 -#define WLAN_EID_FH_PARAMS 2 -#define WLAN_EID_DS_PARAMS 3 -#define WLAN_EID_CF_PARAMS 4 -#define WLAN_EID_TIM 5 -#define WLAN_EID_IBSS_PARAMS 6 -#define WLAN_EID_COUNTRY 7 -#define WLAN_EID_CHALLENGE 16 -/* EIDs defined by IEEE 802.11h - START */ -#define WLAN_EID_PWR_CONSTRAINT 32 -#define WLAN_EID_PWR_CAPABILITY 33 -#define WLAN_EID_TPC_REQUEST 34 -#define WLAN_EID_TPC_REPORT 35 -#define WLAN_EID_SUPPORTED_CHANNELS 36 -#define WLAN_EID_CHANNEL_SWITCH 37 -#define WLAN_EID_MEASURE_REQUEST 38 -#define WLAN_EID_MEASURE_REPORT 39 -#define WLAN_EID_QUITE 40 -#define WLAN_EID_IBSS_DFS 41 -/* EIDs defined by IEEE 802.11h - END */ -#define WLAN_EID_ERP_INFO 42 -#define WLAN_EID_HT_CAP 45 -#define WLAN_EID_RSN 48 -#define WLAN_EID_EXT_SUPP_RATES 50 -#define WLAN_EID_MOBILITY_DOMAIN 54 -#define WLAN_EID_FAST_BSS_TRANSITION 55 -#define WLAN_EID_TIMEOUT_INTERVAL 56 -#define WLAN_EID_RIC_DATA 57 -#define WLAN_EID_HT_OPERATION 61 -#define WLAN_EID_SECONDARY_CHANNEL_OFFSET 62 -#define WLAN_EID_20_40_BSS_COEXISTENCE 72 -#define WLAN_EID_20_40_BSS_INTOLERANT 73 -#define WLAN_EID_OVERLAPPING_BSS_SCAN_PARAMS 74 -#define WLAN_EID_MMIE 76 -#define WLAN_EID_LINK_ID 101 -#define WLAN_EID_ADV_PROTO 108 -#define WLAN_EID_EXT_CAPAB 127 -#define WLAN_EID_VENDOR_SPECIFIC 221 - - -/* Action frame categories (IEEE 802.11-2007, 7.3.1.11, Table 7-24) */ -#define WLAN_ACTION_SPECTRUM_MGMT 0 -#define WLAN_ACTION_QOS 1 -#define WLAN_ACTION_DLS 2 -#define WLAN_ACTION_BLOCK_ACK 3 -#define WLAN_ACTION_PUBLIC 4 -#define WLAN_ACTION_RADIO_MEASUREMENT 5 -#define WLAN_ACTION_FT 6 -#define WLAN_ACTION_HT 7 -#define WLAN_ACTION_SA_QUERY 8 -#define WLAN_ACTION_TDLS 12 -#define WLAN_ACTION_WMM 17 /* WMM Specification 1.1 */ -#define WLAN_ACTION_VENDOR_SPECIFIC 127 - -/* Public action codes */ -#define WLAN_PA_VENDOR_SPECIFIC 9 -#define WLAN_PA_GAS_INITIAL_REQ 10 -#define WLAN_PA_GAS_INITIAL_RESP 11 -#define WLAN_PA_GAS_COMEBACK_REQ 12 -#define WLAN_PA_GAS_COMEBACK_RESP 13 - -/* SA Query Action frame (IEEE 802.11w/D8.0, 7.4.9) */ -#define WLAN_SA_QUERY_REQUEST 0 -#define WLAN_SA_QUERY_RESPONSE 1 - -#define WLAN_SA_QUERY_TR_ID_LEN 2 - -/* TDLS action codes */ -#define WLAN_TDLS_SETUP_REQUEST 0 -#define WLAN_TDLS_SETUP_RESPONSE 1 -#define WLAN_TDLS_SETUP_CONFIRM 2 -#define WLAN_TDLS_TEARDOWN 3 -#define WLAN_TDLS_PEER_TRAFFIC_INDICATION 4 -#define WLAN_TDLS_CHANNEL_SWITCH_REQUEST 5 -#define WLAN_TDLS_CHANNEL_SWITCH_RESPONSE 6 -#define WLAN_TDLS_PEER_PSM_REQUEST 7 -#define WLAN_TDLS_PEER_PSM_RESPONSE 8 -#define WLAN_TDLS_PEER_TRAFFIC_RESPONSE 9 -#define WLAN_TDLS_DISCOVERY_REQUEST 10 - -/* Timeout Interval Type */ -#define WLAN_TIMEOUT_REASSOC_DEADLINE 1 -#define WLAN_TIMEOUT_KEY_LIFETIME 2 -#define WLAN_TIMEOUT_ASSOC_COMEBACK 3 - -/* Advertisement Protocol ID definitions (IEEE 802.11u) */ -enum adv_proto_id { - NATIVE_QUERY_PROTOCOL = 0, - MIH_INFO_SERVICE = 1, - MIH_CMD_AND_EVENT_DISCOVERY = 2, - EMERGENCY_ALERT_SYSTEM = 3, - LOCATION_TO_SERVICE = 4, - ADV_PROTO_VENDOR_SPECIFIC = 221 -}; - -/* Native Query Protocol info ID definitions (IEEE 802.11u) */ -enum nqp_info_id { - NQP_CAPABILITY_LIST = 256, - NQP_VENUE_NAME = 257, - NQP_EMERGENCY_CALL_NUMBER = 258, - NQP_NETWORK_AUTH_TYPE = 259, - NQP_ROAMING_CONSORTIUM = 260, - NQP_IP_ADDR_TYPE_AVAILABILITY = 261, - NQP_NAI_REALM = 262, - NQP_3GPP_CELLULAR_NETWORK = 263, - NQP_AP_GEOSPATIAL_LOCATION = 264, - NQP_AP_CIVIC_LOCATION = 265, - NQP_DOMAIN_NAME = 266, - NQP_EMERGENCY_ALERT_URI = 267, - NQP_VENDOR_SPECIFIC = 56797 -}; - - -#ifdef _MSC_VER -#pragma pack(push, 1) -#endif /* _MSC_VER */ - -struct ieee80211_hdr { - le16 frame_control; - le16 duration_id; - u8 addr1[6]; - u8 addr2[6]; - u8 addr3[6]; - le16 seq_ctrl; - /* followed by 'u8 addr4[6];' if ToDS and FromDS is set in data frame - */ -} STRUCT_PACKED; - -#define IEEE80211_DA_FROMDS addr1 -#define IEEE80211_BSSID_FROMDS addr2 -#define IEEE80211_SA_FROMDS addr3 - -#define IEEE80211_HDRLEN (sizeof(struct ieee80211_hdr)) - -#define IEEE80211_FC(type, stype) host_to_le16((type << 2) | (stype << 4)) - -struct ieee80211_mgmt { - le16 frame_control; - le16 duration; - u8 da[6]; - u8 sa[6]; - u8 bssid[6]; - le16 seq_ctrl; - union { - struct { - le16 auth_alg; - le16 auth_transaction; - le16 status_code; - /* possibly followed by Challenge text */ - u8 variable[0]; - } STRUCT_PACKED auth; - struct { - le16 reason_code; - u8 variable[0]; - } STRUCT_PACKED deauth; - struct { - le16 capab_info; - le16 listen_interval; - /* followed by SSID and Supported rates */ - u8 variable[0]; - } STRUCT_PACKED assoc_req; - struct { - le16 capab_info; - le16 status_code; - le16 aid; - /* followed by Supported rates */ - u8 variable[0]; - } STRUCT_PACKED assoc_resp, reassoc_resp; - struct { - le16 capab_info; - le16 listen_interval; - u8 current_ap[6]; - /* followed by SSID and Supported rates */ - u8 variable[0]; - } STRUCT_PACKED reassoc_req; - struct { - le16 reason_code; - u8 variable[0]; - } STRUCT_PACKED disassoc; - struct { - u8 timestamp[8]; - le16 beacon_int; - le16 capab_info; - /* followed by some of SSID, Supported rates, - * FH Params, DS Params, CF Params, IBSS Params, TIM */ - u8 variable[0]; - } STRUCT_PACKED beacon; - struct { - /* only variable items: SSID, Supported rates */ - u8 variable[0]; - } STRUCT_PACKED probe_req; - struct { - u8 timestamp[8]; - le16 beacon_int; - le16 capab_info; - /* followed by some of SSID, Supported rates, - * FH Params, DS Params, CF Params, IBSS Params */ - u8 variable[0]; - } STRUCT_PACKED probe_resp; - struct { - u8 category; - union { - struct { - u8 action_code; - u8 dialog_token; - u8 status_code; - u8 variable[0]; - } STRUCT_PACKED wmm_action; - struct{ - u8 action_code; - u8 element_id; - u8 length; - u8 switch_mode; - u8 new_chan; - u8 switch_count; - } STRUCT_PACKED chan_switch; - struct { - u8 action; - u8 sta_addr[ETH_ALEN]; - u8 target_ap_addr[ETH_ALEN]; - u8 variable[0]; /* FT Request */ - } STRUCT_PACKED ft_action_req; - struct { - u8 action; - u8 sta_addr[ETH_ALEN]; - u8 target_ap_addr[ETH_ALEN]; - le16 status_code; - u8 variable[0]; /* FT Request */ - } STRUCT_PACKED ft_action_resp; - struct { - u8 action; - u8 trans_id[WLAN_SA_QUERY_TR_ID_LEN]; - } STRUCT_PACKED sa_query_req; - struct { - u8 action; /* */ - u8 trans_id[WLAN_SA_QUERY_TR_ID_LEN]; - } STRUCT_PACKED sa_query_resp; - struct { - u8 action; - u8 variable[0]; - } STRUCT_PACKED public_action; - struct { - u8 action; /* 9 */ - u8 oui[3]; - /* Vendor-specific content */ - u8 variable[0]; - } STRUCT_PACKED vs_public_action; - } u; - } STRUCT_PACKED action; - } u; -} STRUCT_PACKED; - - -struct ieee80211_ht_capabilities { - le16 ht_capabilities_info; - u8 a_mpdu_params; - u8 supported_mcs_set[16]; - le16 ht_extended_capabilities; - le32 tx_bf_capability_info; - u8 asel_capabilities; -} STRUCT_PACKED; - - -struct ieee80211_ht_operation { - u8 control_chan; - u8 ht_param; - le16 operation_mode; - le16 stbc_param; - u8 basic_set[16]; -} STRUCT_PACKED; - -#ifdef _MSC_VER -#pragma pack(pop) -#endif /* _MSC_VER */ - -#define ERP_INFO_NON_ERP_PRESENT BIT(0) -#define ERP_INFO_USE_PROTECTION BIT(1) -#define ERP_INFO_BARKER_PREAMBLE_MODE BIT(2) - - -#define HT_CAP_INFO_LDPC_CODING_CAP ((u16) BIT(0)) -#define HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET ((u16) BIT(1)) -#define HT_CAP_INFO_SMPS_MASK ((u16) (BIT(2) | BIT(3))) -#define HT_CAP_INFO_SMPS_STATIC ((u16) 0) -#define HT_CAP_INFO_SMPS_DYNAMIC ((u16) BIT(2)) -#define HT_CAP_INFO_SMPS_DISABLED ((u16) (BIT(2) | BIT(3))) -#define HT_CAP_INFO_GREEN_FIELD ((u16) BIT(4)) -#define HT_CAP_INFO_SHORT_GI20MHZ ((u16) BIT(5)) -#define HT_CAP_INFO_SHORT_GI40MHZ ((u16) BIT(6)) -#define HT_CAP_INFO_TX_STBC ((u16) BIT(7)) -#define HT_CAP_INFO_RX_STBC_MASK ((u16) (BIT(8) | BIT(9))) -#define HT_CAP_INFO_RX_STBC_1 ((u16) BIT(8)) -#define HT_CAP_INFO_RX_STBC_12 ((u16) BIT(9)) -#define HT_CAP_INFO_RX_STBC_123 ((u16) (BIT(8) | BIT(9))) -#define HT_CAP_INFO_DELAYED_BA ((u16) BIT(10)) -#define HT_CAP_INFO_MAX_AMSDU_SIZE ((u16) BIT(11)) -#define HT_CAP_INFO_DSSS_CCK40MHZ ((u16) BIT(12)) -#define HT_CAP_INFO_PSMP_SUPP ((u16) BIT(13)) -#define HT_CAP_INFO_40MHZ_INTOLERANT ((u16) BIT(14)) -#define HT_CAP_INFO_LSIG_TXOP_PROTECT_SUPPORT ((u16) BIT(15)) - - -#define EXT_HT_CAP_INFO_PCO ((u16) BIT(0)) -#define EXT_HT_CAP_INFO_TRANS_TIME_OFFSET 1 -#define EXT_HT_CAP_INFO_MCS_FEEDBACK_OFFSET 8 -#define EXT_HT_CAP_INFO_HTC_SUPPORTED ((u16) BIT(10)) -#define EXT_HT_CAP_INFO_RD_RESPONDER ((u16) BIT(11)) - - -#define TX_BEAMFORM_CAP_TXBF_CAP ((u32) BIT(0)) -#define TX_BEAMFORM_CAP_RX_STAGGERED_SOUNDING_CAP ((u32) BIT(1)) -#define TX_BEAMFORM_CAP_TX_STAGGERED_SOUNDING_CAP ((u32) BIT(2)) -#define TX_BEAMFORM_CAP_RX_ZLF_CAP ((u32) BIT(3)) -#define TX_BEAMFORM_CAP_TX_ZLF_CAP ((u32) BIT(4)) -#define TX_BEAMFORM_CAP_IMPLICIT_ZLF_CAP ((u32) BIT(5)) -#define TX_BEAMFORM_CAP_CALIB_OFFSET 6 -#define TX_BEAMFORM_CAP_EXPLICIT_CSI_TXBF_CAP ((u32) BIT(8)) -#define TX_BEAMFORM_CAP_EXPLICIT_UNCOMPR_STEERING_MATRIX_CAP ((u32) BIT(9)) -#define TX_BEAMFORM_CAP_EXPLICIT_BF_CSI_FEEDBACK_CAP ((u32) BIT(10)) -#define TX_BEAMFORM_CAP_EXPLICIT_BF_CSI_FEEDBACK_OFFSET 11 -#define TX_BEAMFORM_CAP_EXPLICIT_UNCOMPR_STEERING_MATRIX_FEEDBACK_OFFSET 13 -#define TX_BEAMFORM_CAP_EXPLICIT_COMPRESSED_STEERING_MATRIX_FEEDBACK_OFFSET 15 -#define TX_BEAMFORM_CAP_MINIMAL_GROUPING_OFFSET 17 -#define TX_BEAMFORM_CAP_CSI_NUM_BEAMFORMER_ANT_OFFSET 19 -#define TX_BEAMFORM_CAP_UNCOMPRESSED_STEERING_MATRIX_BEAMFORMER_ANT_OFFSET 21 -#define TX_BEAMFORM_CAP_COMPRESSED_STEERING_MATRIX_BEAMFORMER_ANT_OFFSET 23 -#define TX_BEAMFORM_CAP_SCI_MAX_OF_ROWS_BEANFORMER_SUPPORTED_OFFSET 25 - - -#define ASEL_CAPABILITY_ASEL_CAPABLE ((u8) BIT(0)) -#define ASEL_CAPABILITY_EXPLICIT_CSI_FEEDBACK_BASED_TX_AS_CAP ((u8) BIT(1)) -#define ASEL_CAPABILITY_ANT_INDICES_FEEDBACK_BASED_TX_AS_CAP ((u8) BIT(2)) -#define ASEL_CAPABILITY_EXPLICIT_CSI_FEEDBACK_CAP ((u8) BIT(3)) -#define ASEL_CAPABILITY_ANT_INDICES_FEEDBACK_CAP ((u8) BIT(4)) -#define ASEL_CAPABILITY_RX_AS_CAP ((u8) BIT(5)) -#define ASEL_CAPABILITY_TX_SOUND_PPDUS_CAP ((u8) BIT(6)) - -#define HT_INFO_HT_PARAM_SECONDARY_CHNL_OFF_MASK ((u8) BIT(0) | BIT(1)) -#define HT_INFO_HT_PARAM_SECONDARY_CHNL_ABOVE ((u8) BIT(0)) -#define HT_INFO_HT_PARAM_SECONDARY_CHNL_BELOW ((u8) BIT(0) | BIT(1)) -#define HT_INFO_HT_PARAM_REC_TRANS_CHNL_WIDTH ((u8) BIT(2)) -#define HT_INFO_HT_PARAM_RIFS_MODE ((u8) BIT(3)) -#define HT_INFO_HT_PARAM_CTRL_ACCESS_ONLY ((u8) BIT(4)) -#define HT_INFO_HT_PARAM_SRV_INTERVAL_GRANULARITY ((u8) BIT(5)) - - -#define OP_MODE_PURE 0 -#define OP_MODE_MAY_BE_LEGACY_STAS 1 -#define OP_MODE_20MHZ_HT_STA_ASSOCED 2 -#define OP_MODE_MIXED 3 - -#define HT_INFO_OPERATION_MODE_OP_MODE_MASK \ - ((le16) (0x0001 | 0x0002)) -#define HT_INFO_OPERATION_MODE_OP_MODE_OFFSET 0 -#define HT_INFO_OPERATION_MODE_NON_GF_DEVS_PRESENT ((u8) BIT(2)) -#define HT_INFO_OPERATION_MODE_TRANSMIT_BURST_LIMIT ((u8) BIT(3)) -#define HT_INFO_OPERATION_MODE_NON_HT_STA_PRESENT ((u8) BIT(4)) - -#define HT_INFO_STBC_PARAM_DUAL_BEACON ((u16) BIT(6)) -#define HT_INFO_STBC_PARAM_DUAL_STBC_PROTECT ((u16) BIT(7)) -#define HT_INFO_STBC_PARAM_SECONDARY_BCN ((u16) BIT(8)) -#define HT_INFO_STBC_PARAM_LSIG_TXOP_PROTECT_ALLOWED ((u16) BIT(9)) -#define HT_INFO_STBC_PARAM_PCO_ACTIVE ((u16) BIT(10)) -#define HT_INFO_STBC_PARAM_PCO_PHASE ((u16) BIT(11)) - -#define BSS_MEMBERSHIP_SELECTOR_HT_PHY 127 - -#define OUI_MICROSOFT 0x0050f2 /* Microsoft (also used in Wi-Fi specs) - * 00:50:F2 */ -#define WPA_IE_VENDOR_TYPE 0x0050f201 -#define WPS_IE_VENDOR_TYPE 0x0050f204 -#define OUI_WFA 0x506f9a -#define P2P_IE_VENDOR_TYPE 0x506f9a09 - -#define WMM_OUI_TYPE 2 -#define WMM_OUI_SUBTYPE_INFORMATION_ELEMENT 0 -#define WMM_OUI_SUBTYPE_PARAMETER_ELEMENT 1 -#define WMM_OUI_SUBTYPE_TSPEC_ELEMENT 2 -#define WMM_VERSION 1 - -#define WMM_ACTION_CODE_ADDTS_REQ 0 -#define WMM_ACTION_CODE_ADDTS_RESP 1 -#define WMM_ACTION_CODE_DELTS 2 - -#define WMM_ADDTS_STATUS_ADMISSION_ACCEPTED 0 -#define WMM_ADDTS_STATUS_INVALID_PARAMETERS 1 -/* 2 - Reserved */ -#define WMM_ADDTS_STATUS_REFUSED 3 -/* 4-255 - Reserved */ - -/* WMM TSPEC Direction Field Values */ -#define WMM_TSPEC_DIRECTION_UPLINK 0 -#define WMM_TSPEC_DIRECTION_DOWNLINK 1 -/* 2 - Reserved */ -#define WMM_TSPEC_DIRECTION_BI_DIRECTIONAL 3 - -/* - * WMM Information Element (used in (Re)Association Request frames; may also be - * used in Beacon frames) - */ -struct wmm_information_element { - /* Element ID: 221 (0xdd); Length: 7 */ - /* required fields for WMM version 1 */ - u8 oui[3]; /* 00:50:f2 */ - u8 oui_type; /* 2 */ - u8 oui_subtype; /* 0 */ - u8 version; /* 1 for WMM version 1.0 */ - u8 qos_info; /* AP/STA specific QoS info */ - -} STRUCT_PACKED; - -#define WMM_AC_AIFSN_MASK 0x0f -#define WMM_AC_AIFNS_SHIFT 0 -#define WMM_AC_ACM 0x10 -#define WMM_AC_ACI_MASK 0x60 -#define WMM_AC_ACI_SHIFT 5 - -#define WMM_AC_ECWMIN_MASK 0x0f -#define WMM_AC_ECWMIN_SHIFT 0 -#define WMM_AC_ECWMAX_MASK 0xf0 -#define WMM_AC_ECWMAX_SHIFT 4 - -struct wmm_ac_parameter { - u8 aci_aifsn; /* AIFSN, ACM, ACI */ - u8 cw; /* ECWmin, ECWmax (CW = 2^ECW - 1) */ - le16 txop_limit; -} STRUCT_PACKED; - -/* - * WMM Parameter Element (used in Beacon, Probe Response, and (Re)Association - * Response frmaes) - */ -struct wmm_parameter_element { - /* Element ID: 221 (0xdd); Length: 24 */ - /* required fields for WMM version 1 */ - u8 oui[3]; /* 00:50:f2 */ - u8 oui_type; /* 2 */ - u8 oui_subtype; /* 1 */ - u8 version; /* 1 for WMM version 1.0 */ - u8 qos_info; /* AP/STA specif QoS info */ - u8 reserved; /* 0 */ - struct wmm_ac_parameter ac[4]; /* AC_BE, AC_BK, AC_VI, AC_VO */ - -} STRUCT_PACKED; - -/* WMM TSPEC Element */ -struct wmm_tspec_element { - u8 eid; /* 221 = 0xdd */ - u8 length; /* 6 + 55 = 61 */ - u8 oui[3]; /* 00:50:f2 */ - u8 oui_type; /* 2 */ - u8 oui_subtype; /* 2 */ - u8 version; /* 1 */ - /* WMM TSPEC body (55 octets): */ - u8 ts_info[3]; - le16 nominal_msdu_size; - le16 maximum_msdu_size; - le32 minimum_service_interval; - le32 maximum_service_interval; - le32 inactivity_interval; - le32 suspension_interval; - le32 service_start_time; - le32 minimum_data_rate; - le32 mean_data_rate; - le32 peak_data_rate; - le32 maximum_burst_size; - le32 delay_bound; - le32 minimum_phy_rate; - le16 surplus_bandwidth_allowance; - le16 medium_time; -} STRUCT_PACKED; - - -/* Access Categories / ACI to AC coding */ -enum { - WMM_AC_BE = 0 /* Best Effort */, - WMM_AC_BK = 1 /* Background */, - WMM_AC_VI = 2 /* Video */, - WMM_AC_VO = 3 /* Voice */ -}; - - -/* Wi-Fi Direct (P2P) */ - -#define P2P_OUI_TYPE 9 - -enum p2p_attr_id { - P2P_ATTR_STATUS = 0, - P2P_ATTR_MINOR_REASON_CODE = 1, - P2P_ATTR_CAPABILITY = 2, - P2P_ATTR_DEVICE_ID = 3, - P2P_ATTR_GROUP_OWNER_INTENT = 4, - P2P_ATTR_CONFIGURATION_TIMEOUT = 5, - P2P_ATTR_LISTEN_CHANNEL = 6, - P2P_ATTR_GROUP_BSSID = 7, - P2P_ATTR_EXT_LISTEN_TIMING = 8, - P2P_ATTR_INTENDED_INTERFACE_ADDR = 9, - P2P_ATTR_MANAGEABILITY = 10, - P2P_ATTR_CHANNEL_LIST = 11, - P2P_ATTR_NOTICE_OF_ABSENCE = 12, - P2P_ATTR_DEVICE_INFO = 13, - P2P_ATTR_GROUP_INFO = 14, - P2P_ATTR_GROUP_ID = 15, - P2P_ATTR_INTERFACE = 16, - P2P_ATTR_OPERATING_CHANNEL = 17, - P2P_ATTR_INVITATION_FLAGS = 18, - P2P_ATTR_VENDOR_SPECIFIC = 221 -}; - -#define P2P_MAX_GO_INTENT 15 - -/* P2P Capability - Device Capability bitmap */ -#define P2P_DEV_CAPAB_SERVICE_DISCOVERY BIT(0) -#define P2P_DEV_CAPAB_CLIENT_DISCOVERABILITY BIT(1) -#define P2P_DEV_CAPAB_CONCURRENT_OPER BIT(2) -#define P2P_DEV_CAPAB_INFRA_MANAGED BIT(3) -#define P2P_DEV_CAPAB_DEVICE_LIMIT BIT(4) -#define P2P_DEV_CAPAB_INVITATION_PROCEDURE BIT(5) - -/* P2P Capability - Group Capability bitmap */ -#define P2P_GROUP_CAPAB_GROUP_OWNER BIT(0) -#define P2P_GROUP_CAPAB_PERSISTENT_GROUP BIT(1) -#define P2P_GROUP_CAPAB_GROUP_LIMIT BIT(2) -#define P2P_GROUP_CAPAB_INTRA_BSS_DIST BIT(3) -#define P2P_GROUP_CAPAB_CROSS_CONN BIT(4) -#define P2P_GROUP_CAPAB_PERSISTENT_RECONN BIT(5) -#define P2P_GROUP_CAPAB_GROUP_FORMATION BIT(6) - -/* Invitation Flags */ -#define P2P_INVITATION_FLAGS_TYPE BIT(0) - -/* P2P Manageability */ -#define P2P_MAN_DEVICE_MANAGEMENT BIT(0) -#define P2P_MAN_CROSS_CONNECTION_PERMITTED BIT(1) -#define P2P_MAN_COEXISTENCE_OPTIONAL BIT(2) - -enum p2p_status_code { - P2P_SC_SUCCESS = 0, - P2P_SC_FAIL_INFO_CURRENTLY_UNAVAILABLE = 1, - P2P_SC_FAIL_INCOMPATIBLE_PARAMS = 2, - P2P_SC_FAIL_LIMIT_REACHED = 3, - P2P_SC_FAIL_INVALID_PARAMS = 4, - P2P_SC_FAIL_UNABLE_TO_ACCOMMODATE = 5, - P2P_SC_FAIL_PREV_PROTOCOL_ERROR = 6, - P2P_SC_FAIL_NO_COMMON_CHANNELS = 7, - P2P_SC_FAIL_UNKNOWN_GROUP = 8, - P2P_SC_FAIL_BOTH_GO_INTENT_15 = 9, - P2P_SC_FAIL_INCOMPATIBLE_PROV_METHOD = 10, - P2P_SC_FAIL_REJECTED_BY_USER = 11, -}; - -#define P2P_WILDCARD_SSID "DIRECT-" -#define P2P_WILDCARD_SSID_LEN 7 - -/* P2P action frames */ -enum p2p_act_frame_type { - P2P_NOA = 0, - P2P_PRESENCE_REQ = 1, - P2P_PRESENCE_RESP = 2, - P2P_GO_DISC_REQ = 3 -}; - -/* P2P public action frames */ -enum p2p_action_frame_type { - P2P_GO_NEG_REQ = 0, - P2P_GO_NEG_RESP = 1, - P2P_GO_NEG_CONF = 2, - P2P_INVITATION_REQ = 3, - P2P_INVITATION_RESP = 4, - P2P_DEV_DISC_REQ = 5, - P2P_DEV_DISC_RESP = 6, - P2P_PROV_DISC_REQ = 7, - P2P_PROV_DISC_RESP = 8 -}; - -enum p2p_service_protocol_type { - P2P_SERV_ALL_SERVICES = 0, - P2P_SERV_BONJOUR = 1, - P2P_SERV_UPNP = 2, - P2P_SERV_WS_DISCOVERY = 3, - P2P_SERV_VENDOR_SPECIFIC = 255 -}; - -enum p2p_sd_status { - P2P_SD_SUCCESS = 0, - P2P_SD_PROTO_NOT_AVAILABLE = 1, - P2P_SD_REQUESTED_INFO_NOT_AVAILABLE = 2, - P2P_SD_BAD_REQUEST = 3 -}; - - -#define OUI_BROADCOM 0x00904c /* Broadcom (Epigram) */ - -#define VENDOR_HT_CAPAB_OUI_TYPE 0x33 /* 00-90-4c:0x33 */ - -/* cipher suite selectors */ -#define WLAN_CIPHER_SUITE_USE_GROUP 0x000FAC00 -#define WLAN_CIPHER_SUITE_WEP40 0x000FAC01 -#define WLAN_CIPHER_SUITE_TKIP 0x000FAC02 -/* reserved: 0x000FAC03 */ -#define WLAN_CIPHER_SUITE_CCMP 0x000FAC04 -#define WLAN_CIPHER_SUITE_WEP104 0x000FAC05 -#define WLAN_CIPHER_SUITE_AES_CMAC 0x000FAC06 - -/* AKM suite selectors */ -#define WLAN_AKM_SUITE_8021X 0x000FAC01 -#define WLAN_AKM_SUITE_PSK 0x000FAC02 - -#endif /* IEEE802_11_DEFS_H */ diff --git a/hostapd-0.8/src/common/privsep_commands.h b/hostapd-0.8/src/common/privsep_commands.h deleted file mode 100644 index cc900be..0000000 --- a/hostapd-0.8/src/common/privsep_commands.h +++ /dev/null @@ -1,75 +0,0 @@ -/* - * WPA Supplicant - privilege separation commands - * Copyright (c) 2007-2009, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#ifndef PRIVSEP_COMMANDS_H -#define PRIVSEP_COMMANDS_H - -enum privsep_cmd { - PRIVSEP_CMD_REGISTER, - PRIVSEP_CMD_UNREGISTER, - PRIVSEP_CMD_SCAN, - PRIVSEP_CMD_GET_SCAN_RESULTS, - PRIVSEP_CMD_ASSOCIATE, - PRIVSEP_CMD_GET_BSSID, - PRIVSEP_CMD_GET_SSID, - PRIVSEP_CMD_SET_KEY, - PRIVSEP_CMD_GET_CAPA, - PRIVSEP_CMD_L2_REGISTER, - PRIVSEP_CMD_L2_UNREGISTER, - PRIVSEP_CMD_L2_NOTIFY_AUTH_START, - PRIVSEP_CMD_L2_SEND, - PRIVSEP_CMD_SET_COUNTRY, -}; - -struct privsep_cmd_associate -{ - u8 bssid[ETH_ALEN]; - u8 ssid[32]; - size_t ssid_len; - int freq; - int pairwise_suite; - int group_suite; - int key_mgmt_suite; - int auth_alg; - int mode; - size_t wpa_ie_len; - /* followed by wpa_ie_len bytes of wpa_ie */ -}; - -struct privsep_cmd_set_key -{ - int alg; - u8 addr[ETH_ALEN]; - int key_idx; - int set_tx; - u8 seq[8]; - size_t seq_len; - u8 key[32]; - size_t key_len; -}; - -enum privsep_event { - PRIVSEP_EVENT_SCAN_RESULTS, - PRIVSEP_EVENT_ASSOC, - PRIVSEP_EVENT_DISASSOC, - PRIVSEP_EVENT_ASSOCINFO, - PRIVSEP_EVENT_MICHAEL_MIC_FAILURE, - PRIVSEP_EVENT_INTERFACE_STATUS, - PRIVSEP_EVENT_PMKID_CANDIDATE, - PRIVSEP_EVENT_STKSTART, - PRIVSEP_EVENT_FT_RESPONSE, - PRIVSEP_EVENT_RX_EAPOL, -}; - -#endif /* PRIVSEP_COMMANDS_H */ diff --git a/hostapd-0.8/src/common/version.h b/hostapd-0.8/src/common/version.h deleted file mode 100644 index ba2d2c0..0000000 --- a/hostapd-0.8/src/common/version.h +++ /dev/null @@ -1,10 +0,0 @@ -#ifndef VERSION_H -#define VERSION_H - -#ifndef VERSION_STR_POSTFIX -#define VERSION_STR_POSTFIX "" -#endif /* VERSION_STR_POSTFIX */ - -#define VERSION_STR "0.8.x" VERSION_STR_POSTFIX - -#endif /* VERSION_H */ diff --git a/hostapd-0.8/src/common/wpa_common.c b/hostapd-0.8/src/common/wpa_common.c deleted file mode 100644 index eb2745e..0000000 --- a/hostapd-0.8/src/common/wpa_common.c +++ /dev/null @@ -1,927 +0,0 @@ -/* - * WPA/RSN - Shared functions for supplicant and authenticator - * Copyright (c) 2002-2008, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#include "includes.h" - -#include "common.h" -#include "crypto/md5.h" -#include "crypto/sha1.h" -#include "crypto/sha256.h" -#include "crypto/aes_wrap.h" -#include "crypto/crypto.h" -#include "ieee802_11_defs.h" -#include "defs.h" -#include "wpa_common.h" - - -/** - * wpa_eapol_key_mic - Calculate EAPOL-Key MIC - * @key: EAPOL-Key Key Confirmation Key (KCK) - * @ver: Key descriptor version (WPA_KEY_INFO_TYPE_*) - * @buf: Pointer to the beginning of the EAPOL header (version field) - * @len: Length of the EAPOL frame (from EAPOL header to the end of the frame) - * @mic: Pointer to the buffer to which the EAPOL-Key MIC is written - * Returns: 0 on success, -1 on failure - * - * Calculate EAPOL-Key MIC for an EAPOL-Key packet. The EAPOL-Key MIC field has - * to be cleared (all zeroes) when calling this function. - * - * Note: 'IEEE Std 802.11i-2004 - 8.5.2 EAPOL-Key frames' has an error in the - * description of the Key MIC calculation. It includes packet data from the - * beginning of the EAPOL-Key header, not EAPOL header. This incorrect change - * happened during final editing of the standard and the correct behavior is - * defined in the last draft (IEEE 802.11i/D10). - */ -int wpa_eapol_key_mic(const u8 *key, int ver, const u8 *buf, size_t len, - u8 *mic) -{ - u8 hash[SHA1_MAC_LEN]; - - switch (ver) { - case WPA_KEY_INFO_TYPE_HMAC_MD5_RC4: - return hmac_md5(key, 16, buf, len, mic); - case WPA_KEY_INFO_TYPE_HMAC_SHA1_AES: - if (hmac_sha1(key, 16, buf, len, hash)) - return -1; - os_memcpy(mic, hash, MD5_MAC_LEN); - break; -#if defined(CONFIG_IEEE80211R) || defined(CONFIG_IEEE80211W) - case WPA_KEY_INFO_TYPE_AES_128_CMAC: - return omac1_aes_128(key, buf, len, mic); -#endif /* CONFIG_IEEE80211R || CONFIG_IEEE80211W */ - default: - return -1; - } - - return 0; -} - - -/** - * wpa_pmk_to_ptk - Calculate PTK from PMK, addresses, and nonces - * @pmk: Pairwise master key - * @pmk_len: Length of PMK - * @label: Label to use in derivation - * @addr1: AA or SA - * @addr2: SA or AA - * @nonce1: ANonce or SNonce - * @nonce2: SNonce or ANonce - * @ptk: Buffer for pairwise transient key - * @ptk_len: Length of PTK - * @use_sha256: Whether to use SHA256-based KDF - * - * IEEE Std 802.11i-2004 - 8.5.1.2 Pairwise key hierarchy - * PTK = PRF-X(PMK, "Pairwise key expansion", - * Min(AA, SA) || Max(AA, SA) || - * Min(ANonce, SNonce) || Max(ANonce, SNonce)) - * - * STK = PRF-X(SMK, "Peer key expansion", - * Min(MAC_I, MAC_P) || Max(MAC_I, MAC_P) || - * Min(INonce, PNonce) || Max(INonce, PNonce)) - */ -void wpa_pmk_to_ptk(const u8 *pmk, size_t pmk_len, const char *label, - const u8 *addr1, const u8 *addr2, - const u8 *nonce1, const u8 *nonce2, - u8 *ptk, size_t ptk_len, int use_sha256) -{ - u8 data[2 * ETH_ALEN + 2 * WPA_NONCE_LEN]; - - if (os_memcmp(addr1, addr2, ETH_ALEN) < 0) { - os_memcpy(data, addr1, ETH_ALEN); - os_memcpy(data + ETH_ALEN, addr2, ETH_ALEN); - } else { - os_memcpy(data, addr2, ETH_ALEN); - os_memcpy(data + ETH_ALEN, addr1, ETH_ALEN); - } - - if (os_memcmp(nonce1, nonce2, WPA_NONCE_LEN) < 0) { - os_memcpy(data + 2 * ETH_ALEN, nonce1, WPA_NONCE_LEN); - os_memcpy(data + 2 * ETH_ALEN + WPA_NONCE_LEN, nonce2, - WPA_NONCE_LEN); - } else { - os_memcpy(data + 2 * ETH_ALEN, nonce2, WPA_NONCE_LEN); - os_memcpy(data + 2 * ETH_ALEN + WPA_NONCE_LEN, nonce1, - WPA_NONCE_LEN); - } - -#ifdef CONFIG_IEEE80211W - if (use_sha256) - sha256_prf(pmk, pmk_len, label, data, sizeof(data), - ptk, ptk_len); - else -#endif /* CONFIG_IEEE80211W */ - sha1_prf(pmk, pmk_len, label, data, sizeof(data), ptk, - ptk_len); - - wpa_printf(MSG_DEBUG, "WPA: PTK derivation - A1=" MACSTR " A2=" MACSTR, - MAC2STR(addr1), MAC2STR(addr2)); - wpa_hexdump(MSG_DEBUG, "WPA: Nonce1", nonce1, WPA_NONCE_LEN); - wpa_hexdump(MSG_DEBUG, "WPA: Nonce2", nonce2, WPA_NONCE_LEN); - wpa_hexdump_key(MSG_DEBUG, "WPA: PMK", pmk, pmk_len); - wpa_hexdump_key(MSG_DEBUG, "WPA: PTK", ptk, ptk_len); -} - - -#ifdef CONFIG_IEEE80211R -int wpa_ft_mic(const u8 *kck, const u8 *sta_addr, const u8 *ap_addr, - u8 transaction_seqnum, const u8 *mdie, size_t mdie_len, - const u8 *ftie, size_t ftie_len, - const u8 *rsnie, size_t rsnie_len, - const u8 *ric, size_t ric_len, u8 *mic) -{ - u8 *buf, *pos; - size_t buf_len; - - buf_len = 2 * ETH_ALEN + 1 + mdie_len + ftie_len + rsnie_len + ric_len; - buf = os_malloc(buf_len); - if (buf == NULL) - return -1; - - pos = buf; - os_memcpy(pos, sta_addr, ETH_ALEN); - pos += ETH_ALEN; - os_memcpy(pos, ap_addr, ETH_ALEN); - pos += ETH_ALEN; - *pos++ = transaction_seqnum; - if (rsnie) { - os_memcpy(pos, rsnie, rsnie_len); - pos += rsnie_len; - } - if (mdie) { - os_memcpy(pos, mdie, mdie_len); - pos += mdie_len; - } - if (ftie) { - struct rsn_ftie *_ftie; - os_memcpy(pos, ftie, ftie_len); - if (ftie_len < 2 + sizeof(*_ftie)) { - os_free(buf); - return -1; - } - _ftie = (struct rsn_ftie *) (pos + 2); - os_memset(_ftie->mic, 0, sizeof(_ftie->mic)); - pos += ftie_len; - } - if (ric) { - os_memcpy(pos, ric, ric_len); - pos += ric_len; - } - - wpa_hexdump(MSG_MSGDUMP, "FT: MIC data", buf, pos - buf); - if (omac1_aes_128(kck, buf, pos - buf, mic)) { - os_free(buf); - return -1; - } - - os_free(buf); - - return 0; -} -#endif /* CONFIG_IEEE80211R */ - - -#ifndef CONFIG_NO_WPA2 -static int rsn_selector_to_bitfield(const u8 *s) -{ - if (RSN_SELECTOR_GET(s) == RSN_CIPHER_SUITE_NONE) - return WPA_CIPHER_NONE; - if (RSN_SELECTOR_GET(s) == RSN_CIPHER_SUITE_WEP40) - return WPA_CIPHER_WEP40; - if (RSN_SELECTOR_GET(s) == RSN_CIPHER_SUITE_TKIP) - return WPA_CIPHER_TKIP; - if (RSN_SELECTOR_GET(s) == RSN_CIPHER_SUITE_CCMP) - return WPA_CIPHER_CCMP; - if (RSN_SELECTOR_GET(s) == RSN_CIPHER_SUITE_WEP104) - return WPA_CIPHER_WEP104; -#ifdef CONFIG_IEEE80211W - if (RSN_SELECTOR_GET(s) == RSN_CIPHER_SUITE_AES_128_CMAC) - return WPA_CIPHER_AES_128_CMAC; -#endif /* CONFIG_IEEE80211W */ - return 0; -} - - -static int rsn_key_mgmt_to_bitfield(const u8 *s) -{ - if (RSN_SELECTOR_GET(s) == RSN_AUTH_KEY_MGMT_UNSPEC_802_1X) - return WPA_KEY_MGMT_IEEE8021X; - if (RSN_SELECTOR_GET(s) == RSN_AUTH_KEY_MGMT_PSK_OVER_802_1X) - return WPA_KEY_MGMT_PSK; -#ifdef CONFIG_IEEE80211R - if (RSN_SELECTOR_GET(s) == RSN_AUTH_KEY_MGMT_FT_802_1X) - return WPA_KEY_MGMT_FT_IEEE8021X; - if (RSN_SELECTOR_GET(s) == RSN_AUTH_KEY_MGMT_FT_PSK) - return WPA_KEY_MGMT_FT_PSK; -#endif /* CONFIG_IEEE80211R */ -#ifdef CONFIG_IEEE80211W - if (RSN_SELECTOR_GET(s) == RSN_AUTH_KEY_MGMT_802_1X_SHA256) - return WPA_KEY_MGMT_IEEE8021X_SHA256; - if (RSN_SELECTOR_GET(s) == RSN_AUTH_KEY_MGMT_PSK_SHA256) - return WPA_KEY_MGMT_PSK_SHA256; -#endif /* CONFIG_IEEE80211W */ - return 0; -} -#endif /* CONFIG_NO_WPA2 */ - - -/** - * wpa_parse_wpa_ie_rsn - Parse RSN IE - * @rsn_ie: Buffer containing RSN IE - * @rsn_ie_len: RSN IE buffer length (including IE number and length octets) - * @data: Pointer to structure that will be filled in with parsed data - * Returns: 0 on success, <0 on failure - */ -int wpa_parse_wpa_ie_rsn(const u8 *rsn_ie, size_t rsn_ie_len, - struct wpa_ie_data *data) -{ -#ifndef CONFIG_NO_WPA2 - const struct rsn_ie_hdr *hdr; - const u8 *pos; - int left; - int i, count; - - os_memset(data, 0, sizeof(*data)); - data->proto = WPA_PROTO_RSN; - data->pairwise_cipher = WPA_CIPHER_CCMP; - data->group_cipher = WPA_CIPHER_CCMP; - data->key_mgmt = WPA_KEY_MGMT_IEEE8021X; - data->capabilities = 0; - data->pmkid = NULL; - data->num_pmkid = 0; -#ifdef CONFIG_IEEE80211W - data->mgmt_group_cipher = WPA_CIPHER_AES_128_CMAC; -#else /* CONFIG_IEEE80211W */ - data->mgmt_group_cipher = 0; -#endif /* CONFIG_IEEE80211W */ - - if (rsn_ie_len == 0) { - /* No RSN IE - fail silently */ - return -1; - } - - if (rsn_ie_len < sizeof(struct rsn_ie_hdr)) { - wpa_printf(MSG_DEBUG, "%s: ie len too short %lu", - __func__, (unsigned long) rsn_ie_len); - return -1; - } - - hdr = (const struct rsn_ie_hdr *) rsn_ie; - - if (hdr->elem_id != WLAN_EID_RSN || - hdr->len != rsn_ie_len - 2 || - WPA_GET_LE16(hdr->version) != RSN_VERSION) { - wpa_printf(MSG_DEBUG, "%s: malformed ie or unknown version", - __func__); - return -2; - } - - pos = (const u8 *) (hdr + 1); - left = rsn_ie_len - sizeof(*hdr); - - if (left >= RSN_SELECTOR_LEN) { - data->group_cipher = rsn_selector_to_bitfield(pos); -#ifdef CONFIG_IEEE80211W - if (data->group_cipher == WPA_CIPHER_AES_128_CMAC) { - wpa_printf(MSG_DEBUG, "%s: AES-128-CMAC used as group " - "cipher", __func__); - return -1; - } -#endif /* CONFIG_IEEE80211W */ - pos += RSN_SELECTOR_LEN; - left -= RSN_SELECTOR_LEN; - } else if (left > 0) { - wpa_printf(MSG_DEBUG, "%s: ie length mismatch, %u too much", - __func__, left); - return -3; - } - - if (left >= 2) { - data->pairwise_cipher = 0; - count = WPA_GET_LE16(pos); - pos += 2; - left -= 2; - if (count == 0 || left < count * RSN_SELECTOR_LEN) { - wpa_printf(MSG_DEBUG, "%s: ie count botch (pairwise), " - "count %u left %u", __func__, count, left); - return -4; - } - for (i = 0; i < count; i++) { - data->pairwise_cipher |= rsn_selector_to_bitfield(pos); - pos += RSN_SELECTOR_LEN; - left -= RSN_SELECTOR_LEN; - } -#ifdef CONFIG_IEEE80211W - if (data->pairwise_cipher & WPA_CIPHER_AES_128_CMAC) { - wpa_printf(MSG_DEBUG, "%s: AES-128-CMAC used as " - "pairwise cipher", __func__); - return -1; - } -#endif /* CONFIG_IEEE80211W */ - } else if (left == 1) { - wpa_printf(MSG_DEBUG, "%s: ie too short (for key mgmt)", - __func__); - return -5; - } - - if (left >= 2) { - data->key_mgmt = 0; - count = WPA_GET_LE16(pos); - pos += 2; - left -= 2; - if (count == 0 || left < count * RSN_SELECTOR_LEN) { - wpa_printf(MSG_DEBUG, "%s: ie count botch (key mgmt), " - "count %u left %u", __func__, count, left); - return -6; - } - for (i = 0; i < count; i++) { - data->key_mgmt |= rsn_key_mgmt_to_bitfield(pos); - pos += RSN_SELECTOR_LEN; - left -= RSN_SELECTOR_LEN; - } - } else if (left == 1) { - wpa_printf(MSG_DEBUG, "%s: ie too short (for capabilities)", - __func__); - return -7; - } - - if (left >= 2) { - data->capabilities = WPA_GET_LE16(pos); - pos += 2; - left -= 2; - } - - if (left >= 2) { - data->num_pmkid = WPA_GET_LE16(pos); - pos += 2; - left -= 2; - if (left < (int) data->num_pmkid * PMKID_LEN) { - wpa_printf(MSG_DEBUG, "%s: PMKID underflow " - "(num_pmkid=%lu left=%d)", - __func__, (unsigned long) data->num_pmkid, - left); - data->num_pmkid = 0; - return -9; - } else { - data->pmkid = pos; - pos += data->num_pmkid * PMKID_LEN; - left -= data->num_pmkid * PMKID_LEN; - } - } - -#ifdef CONFIG_IEEE80211W - if (left >= 4) { - data->mgmt_group_cipher = rsn_selector_to_bitfield(pos); - if (data->mgmt_group_cipher != WPA_CIPHER_AES_128_CMAC) { - wpa_printf(MSG_DEBUG, "%s: Unsupported management " - "group cipher 0x%x", __func__, - data->mgmt_group_cipher); - return -10; - } - pos += RSN_SELECTOR_LEN; - left -= RSN_SELECTOR_LEN; - } -#endif /* CONFIG_IEEE80211W */ - - if (left > 0) { - wpa_printf(MSG_DEBUG, "%s: ie has %u trailing bytes - ignored", - __func__, left); - } - - return 0; -#else /* CONFIG_NO_WPA2 */ - return -1; -#endif /* CONFIG_NO_WPA2 */ -} - - -static int wpa_selector_to_bitfield(const u8 *s) -{ - if (RSN_SELECTOR_GET(s) == WPA_CIPHER_SUITE_NONE) - return WPA_CIPHER_NONE; - if (RSN_SELECTOR_GET(s) == WPA_CIPHER_SUITE_WEP40) - return WPA_CIPHER_WEP40; - if (RSN_SELECTOR_GET(s) == WPA_CIPHER_SUITE_TKIP) - return WPA_CIPHER_TKIP; - if (RSN_SELECTOR_GET(s) == WPA_CIPHER_SUITE_CCMP) - return WPA_CIPHER_CCMP; - if (RSN_SELECTOR_GET(s) == WPA_CIPHER_SUITE_WEP104) - return WPA_CIPHER_WEP104; - return 0; -} - - -static int wpa_key_mgmt_to_bitfield(const u8 *s) -{ - if (RSN_SELECTOR_GET(s) == WPA_AUTH_KEY_MGMT_UNSPEC_802_1X) - return WPA_KEY_MGMT_IEEE8021X; - if (RSN_SELECTOR_GET(s) == WPA_AUTH_KEY_MGMT_PSK_OVER_802_1X) - return WPA_KEY_MGMT_PSK; - if (RSN_SELECTOR_GET(s) == WPA_AUTH_KEY_MGMT_NONE) - return WPA_KEY_MGMT_WPA_NONE; - return 0; -} - - -int wpa_parse_wpa_ie_wpa(const u8 *wpa_ie, size_t wpa_ie_len, - struct wpa_ie_data *data) -{ - const struct wpa_ie_hdr *hdr; - const u8 *pos; - int left; - int i, count; - - os_memset(data, 0, sizeof(*data)); - data->proto = WPA_PROTO_WPA; - data->pairwise_cipher = WPA_CIPHER_TKIP; - data->group_cipher = WPA_CIPHER_TKIP; - data->key_mgmt = WPA_KEY_MGMT_IEEE8021X; - data->capabilities = 0; - data->pmkid = NULL; - data->num_pmkid = 0; - data->mgmt_group_cipher = 0; - - if (wpa_ie_len == 0) { - /* No WPA IE - fail silently */ - return -1; - } - - if (wpa_ie_len < sizeof(struct wpa_ie_hdr)) { - wpa_printf(MSG_DEBUG, "%s: ie len too short %lu", - __func__, (unsigned long) wpa_ie_len); - return -1; - } - - hdr = (const struct wpa_ie_hdr *) wpa_ie; - - if (hdr->elem_id != WLAN_EID_VENDOR_SPECIFIC || - hdr->len != wpa_ie_len - 2 || - RSN_SELECTOR_GET(hdr->oui) != WPA_OUI_TYPE || - WPA_GET_LE16(hdr->version) != WPA_VERSION) { - wpa_printf(MSG_DEBUG, "%s: malformed ie or unknown version", - __func__); - return -2; - } - - pos = (const u8 *) (hdr + 1); - left = wpa_ie_len - sizeof(*hdr); - - if (left >= WPA_SELECTOR_LEN) { - data->group_cipher = wpa_selector_to_bitfield(pos); - pos += WPA_SELECTOR_LEN; - left -= WPA_SELECTOR_LEN; - } else if (left > 0) { - wpa_printf(MSG_DEBUG, "%s: ie length mismatch, %u too much", - __func__, left); - return -3; - } - - if (left >= 2) { - data->pairwise_cipher = 0; - count = WPA_GET_LE16(pos); - pos += 2; - left -= 2; - if (count == 0 || left < count * WPA_SELECTOR_LEN) { - wpa_printf(MSG_DEBUG, "%s: ie count botch (pairwise), " - "count %u left %u", __func__, count, left); - return -4; - } - for (i = 0; i < count; i++) { - data->pairwise_cipher |= wpa_selector_to_bitfield(pos); - pos += WPA_SELECTOR_LEN; - left -= WPA_SELECTOR_LEN; - } - } else if (left == 1) { - wpa_printf(MSG_DEBUG, "%s: ie too short (for key mgmt)", - __func__); - return -5; - } - - if (left >= 2) { - data->key_mgmt = 0; - count = WPA_GET_LE16(pos); - pos += 2; - left -= 2; - if (count == 0 || left < count * WPA_SELECTOR_LEN) { - wpa_printf(MSG_DEBUG, "%s: ie count botch (key mgmt), " - "count %u left %u", __func__, count, left); - return -6; - } - for (i = 0; i < count; i++) { - data->key_mgmt |= wpa_key_mgmt_to_bitfield(pos); - pos += WPA_SELECTOR_LEN; - left -= WPA_SELECTOR_LEN; - } - } else if (left == 1) { - wpa_printf(MSG_DEBUG, "%s: ie too short (for capabilities)", - __func__); - return -7; - } - - if (left >= 2) { - data->capabilities = WPA_GET_LE16(pos); - pos += 2; - left -= 2; - } - - if (left > 0) { - wpa_printf(MSG_DEBUG, "%s: ie has %u trailing bytes - ignored", - __func__, left); - } - - return 0; -} - - -#ifdef CONFIG_IEEE80211R - -/** - * wpa_derive_pmk_r0 - Derive PMK-R0 and PMKR0Name - * - * IEEE Std 802.11r-2008 - 8.5.1.5.3 - */ -void wpa_derive_pmk_r0(const u8 *xxkey, size_t xxkey_len, - const u8 *ssid, size_t ssid_len, - const u8 *mdid, const u8 *r0kh_id, size_t r0kh_id_len, - const u8 *s0kh_id, u8 *pmk_r0, u8 *pmk_r0_name) -{ - u8 buf[1 + WPA_MAX_SSID_LEN + MOBILITY_DOMAIN_ID_LEN + 1 + - FT_R0KH_ID_MAX_LEN + ETH_ALEN]; - u8 *pos, r0_key_data[48], hash[32]; - const u8 *addr[2]; - size_t len[2]; - - /* - * R0-Key-Data = KDF-384(XXKey, "FT-R0", - * SSIDlength || SSID || MDID || R0KHlength || - * R0KH-ID || S0KH-ID) - * XXKey is either the second 256 bits of MSK or PSK. - * PMK-R0 = L(R0-Key-Data, 0, 256) - * PMK-R0Name-Salt = L(R0-Key-Data, 256, 128) - */ - if (ssid_len > WPA_MAX_SSID_LEN || r0kh_id_len > FT_R0KH_ID_MAX_LEN) - return; - pos = buf; - *pos++ = ssid_len; - os_memcpy(pos, ssid, ssid_len); - pos += ssid_len; - os_memcpy(pos, mdid, MOBILITY_DOMAIN_ID_LEN); - pos += MOBILITY_DOMAIN_ID_LEN; - *pos++ = r0kh_id_len; - os_memcpy(pos, r0kh_id, r0kh_id_len); - pos += r0kh_id_len; - os_memcpy(pos, s0kh_id, ETH_ALEN); - pos += ETH_ALEN; - - sha256_prf(xxkey, xxkey_len, "FT-R0", buf, pos - buf, - r0_key_data, sizeof(r0_key_data)); - os_memcpy(pmk_r0, r0_key_data, PMK_LEN); - - /* - * PMKR0Name = Truncate-128(SHA-256("FT-R0N" || PMK-R0Name-Salt) - */ - addr[0] = (const u8 *) "FT-R0N"; - len[0] = 6; - addr[1] = r0_key_data + PMK_LEN; - len[1] = 16; - - sha256_vector(2, addr, len, hash); - os_memcpy(pmk_r0_name, hash, WPA_PMK_NAME_LEN); -} - - -/** - * wpa_derive_pmk_r1_name - Derive PMKR1Name - * - * IEEE Std 802.11r-2008 - 8.5.1.5.4 - */ -void wpa_derive_pmk_r1_name(const u8 *pmk_r0_name, const u8 *r1kh_id, - const u8 *s1kh_id, u8 *pmk_r1_name) -{ - u8 hash[32]; - const u8 *addr[4]; - size_t len[4]; - - /* - * PMKR1Name = Truncate-128(SHA-256("FT-R1N" || PMKR0Name || - * R1KH-ID || S1KH-ID)) - */ - addr[0] = (const u8 *) "FT-R1N"; - len[0] = 6; - addr[1] = pmk_r0_name; - len[1] = WPA_PMK_NAME_LEN; - addr[2] = r1kh_id; - len[2] = FT_R1KH_ID_LEN; - addr[3] = s1kh_id; - len[3] = ETH_ALEN; - - sha256_vector(4, addr, len, hash); - os_memcpy(pmk_r1_name, hash, WPA_PMK_NAME_LEN); -} - - -/** - * wpa_derive_pmk_r1 - Derive PMK-R1 and PMKR1Name from PMK-R0 - * - * IEEE Std 802.11r-2008 - 8.5.1.5.4 - */ -void wpa_derive_pmk_r1(const u8 *pmk_r0, const u8 *pmk_r0_name, - const u8 *r1kh_id, const u8 *s1kh_id, - u8 *pmk_r1, u8 *pmk_r1_name) -{ - u8 buf[FT_R1KH_ID_LEN + ETH_ALEN]; - u8 *pos; - - /* PMK-R1 = KDF-256(PMK-R0, "FT-R1", R1KH-ID || S1KH-ID) */ - pos = buf; - os_memcpy(pos, r1kh_id, FT_R1KH_ID_LEN); - pos += FT_R1KH_ID_LEN; - os_memcpy(pos, s1kh_id, ETH_ALEN); - pos += ETH_ALEN; - - sha256_prf(pmk_r0, PMK_LEN, "FT-R1", buf, pos - buf, pmk_r1, PMK_LEN); - - wpa_derive_pmk_r1_name(pmk_r0_name, r1kh_id, s1kh_id, pmk_r1_name); -} - - -/** - * wpa_pmk_r1_to_ptk - Derive PTK and PTKName from PMK-R1 - * - * IEEE Std 802.11r-2008 - 8.5.1.5.5 - */ -void wpa_pmk_r1_to_ptk(const u8 *pmk_r1, const u8 *snonce, const u8 *anonce, - const u8 *sta_addr, const u8 *bssid, - const u8 *pmk_r1_name, - u8 *ptk, size_t ptk_len, u8 *ptk_name) -{ - u8 buf[2 * WPA_NONCE_LEN + 2 * ETH_ALEN]; - u8 *pos, hash[32]; - const u8 *addr[6]; - size_t len[6]; - - /* - * PTK = KDF-PTKLen(PMK-R1, "FT-PTK", SNonce || ANonce || - * BSSID || STA-ADDR) - */ - pos = buf; - os_memcpy(pos, snonce, WPA_NONCE_LEN); - pos += WPA_NONCE_LEN; - os_memcpy(pos, anonce, WPA_NONCE_LEN); - pos += WPA_NONCE_LEN; - os_memcpy(pos, bssid, ETH_ALEN); - pos += ETH_ALEN; - os_memcpy(pos, sta_addr, ETH_ALEN); - pos += ETH_ALEN; - - sha256_prf(pmk_r1, PMK_LEN, "FT-PTK", buf, pos - buf, ptk, ptk_len); - - /* - * PTKName = Truncate-128(SHA-256(PMKR1Name || "FT-PTKN" || SNonce || - * ANonce || BSSID || STA-ADDR)) - */ - addr[0] = pmk_r1_name; - len[0] = WPA_PMK_NAME_LEN; - addr[1] = (const u8 *) "FT-PTKN"; - len[1] = 7; - addr[2] = snonce; - len[2] = WPA_NONCE_LEN; - addr[3] = anonce; - len[3] = WPA_NONCE_LEN; - addr[4] = bssid; - len[4] = ETH_ALEN; - addr[5] = sta_addr; - len[5] = ETH_ALEN; - - sha256_vector(6, addr, len, hash); - os_memcpy(ptk_name, hash, WPA_PMK_NAME_LEN); -} - -#endif /* CONFIG_IEEE80211R */ - - -/** - * rsn_pmkid - Calculate PMK identifier - * @pmk: Pairwise master key - * @pmk_len: Length of pmk in bytes - * @aa: Authenticator address - * @spa: Supplicant address - * @pmkid: Buffer for PMKID - * @use_sha256: Whether to use SHA256-based KDF - * - * IEEE Std 802.11i-2004 - 8.5.1.2 Pairwise key hierarchy - * PMKID = HMAC-SHA1-128(PMK, "PMK Name" || AA || SPA) - */ -void rsn_pmkid(const u8 *pmk, size_t pmk_len, const u8 *aa, const u8 *spa, - u8 *pmkid, int use_sha256) -{ - char *title = "PMK Name"; - const u8 *addr[3]; - const size_t len[3] = { 8, ETH_ALEN, ETH_ALEN }; - unsigned char hash[SHA256_MAC_LEN]; - - addr[0] = (u8 *) title; - addr[1] = aa; - addr[2] = spa; - -#ifdef CONFIG_IEEE80211W - if (use_sha256) - hmac_sha256_vector(pmk, pmk_len, 3, addr, len, hash); - else -#endif /* CONFIG_IEEE80211W */ - hmac_sha1_vector(pmk, pmk_len, 3, addr, len, hash); - os_memcpy(pmkid, hash, PMKID_LEN); -} - - -/** - * wpa_cipher_txt - Convert cipher suite to a text string - * @cipher: Cipher suite (WPA_CIPHER_* enum) - * Returns: Pointer to a text string of the cipher suite name - */ -const char * wpa_cipher_txt(int cipher) -{ - switch (cipher) { - case WPA_CIPHER_NONE: - return "NONE"; - case WPA_CIPHER_WEP40: - return "WEP-40"; - case WPA_CIPHER_WEP104: - return "WEP-104"; - case WPA_CIPHER_TKIP: - return "TKIP"; - case WPA_CIPHER_CCMP: - return "CCMP"; - case WPA_CIPHER_CCMP | WPA_CIPHER_TKIP: - return "CCMP+TKIP"; - default: - return "UNKNOWN"; - } -} - - -/** - * wpa_key_mgmt_txt - Convert key management suite to a text string - * @key_mgmt: Key management suite (WPA_KEY_MGMT_* enum) - * @proto: WPA/WPA2 version (WPA_PROTO_*) - * Returns: Pointer to a text string of the key management suite name - */ -const char * wpa_key_mgmt_txt(int key_mgmt, int proto) -{ - switch (key_mgmt) { - case WPA_KEY_MGMT_IEEE8021X: - if (proto == (WPA_PROTO_RSN | WPA_PROTO_WPA)) - return "WPA2+WPA/IEEE 802.1X/EAP"; - return proto == WPA_PROTO_RSN ? - "WPA2/IEEE 802.1X/EAP" : "WPA/IEEE 802.1X/EAP"; - case WPA_KEY_MGMT_PSK: - if (proto == (WPA_PROTO_RSN | WPA_PROTO_WPA)) - return "WPA2-PSK+WPA-PSK"; - return proto == WPA_PROTO_RSN ? - "WPA2-PSK" : "WPA-PSK"; - case WPA_KEY_MGMT_NONE: - return "NONE"; - case WPA_KEY_MGMT_IEEE8021X_NO_WPA: - return "IEEE 802.1X (no WPA)"; -#ifdef CONFIG_IEEE80211R - case WPA_KEY_MGMT_FT_IEEE8021X: - return "FT-EAP"; - case WPA_KEY_MGMT_FT_PSK: - return "FT-PSK"; -#endif /* CONFIG_IEEE80211R */ -#ifdef CONFIG_IEEE80211W - case WPA_KEY_MGMT_IEEE8021X_SHA256: - return "WPA2-EAP-SHA256"; - case WPA_KEY_MGMT_PSK_SHA256: - return "WPA2-PSK-SHA256"; -#endif /* CONFIG_IEEE80211W */ - default: - return "UNKNOWN"; - } -} - - -int wpa_compare_rsn_ie(int ft_initial_assoc, - const u8 *ie1, size_t ie1len, - const u8 *ie2, size_t ie2len) -{ - if (ie1 == NULL || ie2 == NULL) - return -1; - - if (ie1len == ie2len && os_memcmp(ie1, ie2, ie1len) == 0) - return 0; /* identical IEs */ - -#ifdef CONFIG_IEEE80211R - if (ft_initial_assoc) { - struct wpa_ie_data ie1d, ie2d; - /* - * The PMKID-List in RSN IE is different between Beacon/Probe - * Response/(Re)Association Request frames and EAPOL-Key - * messages in FT initial mobility domain association. Allow - * for this, but verify that other parts of the RSN IEs are - * identical. - */ - if (wpa_parse_wpa_ie_rsn(ie1, ie1len, &ie1d) < 0 || - wpa_parse_wpa_ie_rsn(ie2, ie2len, &ie2d) < 0) - return -1; - if (ie1d.proto == ie2d.proto && - ie1d.pairwise_cipher == ie2d.pairwise_cipher && - ie1d.group_cipher == ie2d.group_cipher && - ie1d.key_mgmt == ie2d.key_mgmt && - ie1d.capabilities == ie2d.capabilities && - ie1d.mgmt_group_cipher == ie2d.mgmt_group_cipher) - return 0; - } -#endif /* CONFIG_IEEE80211R */ - - return -1; -} - - -#ifdef CONFIG_IEEE80211R -int wpa_insert_pmkid(u8 *ies, size_t ies_len, const u8 *pmkid) -{ - u8 *start, *end, *rpos, *rend; - int added = 0; - - start = ies; - end = ies + ies_len; - - while (start < end) { - if (*start == WLAN_EID_RSN) - break; - start += 2 + start[1]; - } - if (start >= end) { - wpa_printf(MSG_ERROR, "FT: Could not find RSN IE in " - "IEs data"); - return -1; - } - wpa_hexdump(MSG_DEBUG, "FT: RSN IE before modification", - start, 2 + start[1]); - - /* Find start of PMKID-Count */ - rpos = start + 2; - rend = rpos + start[1]; - - /* Skip Version and Group Data Cipher Suite */ - rpos += 2 + 4; - /* Skip Pairwise Cipher Suite Count and List */ - rpos += 2 + WPA_GET_LE16(rpos) * RSN_SELECTOR_LEN; - /* Skip AKM Suite Count and List */ - rpos += 2 + WPA_GET_LE16(rpos) * RSN_SELECTOR_LEN; - - if (rpos == rend) { - /* Add RSN Capabilities */ - os_memmove(rpos + 2, rpos, end - rpos); - *rpos++ = 0; - *rpos++ = 0; - } else { - /* Skip RSN Capabilities */ - rpos += 2; - if (rpos > rend) { - wpa_printf(MSG_ERROR, "FT: Could not parse RSN IE in " - "IEs data"); - return -1; - } - } - - if (rpos == rend) { - /* No PMKID-Count field included; add it */ - os_memmove(rpos + 2 + PMKID_LEN, rpos, end - rpos); - WPA_PUT_LE16(rpos, 1); - rpos += 2; - os_memcpy(rpos, pmkid, PMKID_LEN); - added += 2 + PMKID_LEN; - start[1] += 2 + PMKID_LEN; - } else { - /* PMKID-Count was included; use it */ - if (WPA_GET_LE16(rpos) != 0) { - wpa_printf(MSG_ERROR, "FT: Unexpected PMKID " - "in RSN IE in EAPOL-Key data"); - return -1; - } - WPA_PUT_LE16(rpos, 1); - rpos += 2; - os_memmove(rpos + PMKID_LEN, rpos, end - rpos); - os_memcpy(rpos, pmkid, PMKID_LEN); - added += PMKID_LEN; - start[1] += PMKID_LEN; - } - - wpa_hexdump(MSG_DEBUG, "FT: RSN IE after modification " - "(PMKID inserted)", start, 2 + start[1]); - - return added; -} -#endif /* CONFIG_IEEE80211R */ diff --git a/hostapd-0.8/src/common/wpa_common.h b/hostapd-0.8/src/common/wpa_common.h deleted file mode 100644 index fe79cee..0000000 --- a/hostapd-0.8/src/common/wpa_common.h +++ /dev/null @@ -1,361 +0,0 @@ -/* - * WPA definitions shared between hostapd and wpa_supplicant - * Copyright (c) 2002-2008, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#ifndef WPA_COMMON_H -#define WPA_COMMON_H - -#define WPA_MAX_SSID_LEN 32 - -/* IEEE 802.11i */ -#define PMKID_LEN 16 -#define PMK_LEN 32 -#define WPA_REPLAY_COUNTER_LEN 8 -#define WPA_NONCE_LEN 32 -#define WPA_KEY_RSC_LEN 8 -#define WPA_GMK_LEN 32 -#define WPA_GTK_MAX_LEN 32 - -#define WPA_SELECTOR_LEN 4 -#define WPA_VERSION 1 -#define RSN_SELECTOR_LEN 4 -#define RSN_VERSION 1 - -#define RSN_SELECTOR(a, b, c, d) \ - ((((u32) (a)) << 24) | (((u32) (b)) << 16) | (((u32) (c)) << 8) | \ - (u32) (d)) - -#define WPA_AUTH_KEY_MGMT_NONE RSN_SELECTOR(0x00, 0x50, 0xf2, 0) -#define WPA_AUTH_KEY_MGMT_UNSPEC_802_1X RSN_SELECTOR(0x00, 0x50, 0xf2, 1) -#define WPA_AUTH_KEY_MGMT_PSK_OVER_802_1X RSN_SELECTOR(0x00, 0x50, 0xf2, 2) -#define WPA_CIPHER_SUITE_NONE RSN_SELECTOR(0x00, 0x50, 0xf2, 0) -#define WPA_CIPHER_SUITE_WEP40 RSN_SELECTOR(0x00, 0x50, 0xf2, 1) -#define WPA_CIPHER_SUITE_TKIP RSN_SELECTOR(0x00, 0x50, 0xf2, 2) -#if 0 -#define WPA_CIPHER_SUITE_WRAP RSN_SELECTOR(0x00, 0x50, 0xf2, 3) -#endif -#define WPA_CIPHER_SUITE_CCMP RSN_SELECTOR(0x00, 0x50, 0xf2, 4) -#define WPA_CIPHER_SUITE_WEP104 RSN_SELECTOR(0x00, 0x50, 0xf2, 5) - - -#define RSN_AUTH_KEY_MGMT_UNSPEC_802_1X RSN_SELECTOR(0x00, 0x0f, 0xac, 1) -#define RSN_AUTH_KEY_MGMT_PSK_OVER_802_1X RSN_SELECTOR(0x00, 0x0f, 0xac, 2) -#ifdef CONFIG_IEEE80211R -#define RSN_AUTH_KEY_MGMT_FT_802_1X RSN_SELECTOR(0x00, 0x0f, 0xac, 3) -#define RSN_AUTH_KEY_MGMT_FT_PSK RSN_SELECTOR(0x00, 0x0f, 0xac, 4) -#endif /* CONFIG_IEEE80211R */ -#define RSN_AUTH_KEY_MGMT_802_1X_SHA256 RSN_SELECTOR(0x00, 0x0f, 0xac, 5) -#define RSN_AUTH_KEY_MGMT_PSK_SHA256 RSN_SELECTOR(0x00, 0x0f, 0xac, 6) -#define RSN_AUTH_KEY_MGMT_TPK_HANDSHAKE RSN_SELECTOR(0x00, 0x0f, 0xac, 7) - -#define RSN_CIPHER_SUITE_NONE RSN_SELECTOR(0x00, 0x0f, 0xac, 0) -#define RSN_CIPHER_SUITE_WEP40 RSN_SELECTOR(0x00, 0x0f, 0xac, 1) -#define RSN_CIPHER_SUITE_TKIP RSN_SELECTOR(0x00, 0x0f, 0xac, 2) -#if 0 -#define RSN_CIPHER_SUITE_WRAP RSN_SELECTOR(0x00, 0x0f, 0xac, 3) -#endif -#define RSN_CIPHER_SUITE_CCMP RSN_SELECTOR(0x00, 0x0f, 0xac, 4) -#define RSN_CIPHER_SUITE_WEP104 RSN_SELECTOR(0x00, 0x0f, 0xac, 5) -#ifdef CONFIG_IEEE80211W -#define RSN_CIPHER_SUITE_AES_128_CMAC RSN_SELECTOR(0x00, 0x0f, 0xac, 6) -#endif /* CONFIG_IEEE80211W */ -#define RSN_CIPHER_SUITE_NO_GROUP_ADDRESSED RSN_SELECTOR(0x00, 0x0f, 0xac, 7) - -/* EAPOL-Key Key Data Encapsulation - * GroupKey and PeerKey require encryption, otherwise, encryption is optional. - */ -#define RSN_KEY_DATA_GROUPKEY RSN_SELECTOR(0x00, 0x0f, 0xac, 1) -#if 0 -#define RSN_KEY_DATA_STAKEY RSN_SELECTOR(0x00, 0x0f, 0xac, 2) -#endif -#define RSN_KEY_DATA_MAC_ADDR RSN_SELECTOR(0x00, 0x0f, 0xac, 3) -#define RSN_KEY_DATA_PMKID RSN_SELECTOR(0x00, 0x0f, 0xac, 4) -#ifdef CONFIG_PEERKEY -#define RSN_KEY_DATA_SMK RSN_SELECTOR(0x00, 0x0f, 0xac, 5) -#define RSN_KEY_DATA_NONCE RSN_SELECTOR(0x00, 0x0f, 0xac, 6) -#define RSN_KEY_DATA_LIFETIME RSN_SELECTOR(0x00, 0x0f, 0xac, 7) -#define RSN_KEY_DATA_ERROR RSN_SELECTOR(0x00, 0x0f, 0xac, 8) -#endif /* CONFIG_PEERKEY */ -#ifdef CONFIG_IEEE80211W -#define RSN_KEY_DATA_IGTK RSN_SELECTOR(0x00, 0x0f, 0xac, 9) -#endif /* CONFIG_IEEE80211W */ - -#define WPA_OUI_TYPE RSN_SELECTOR(0x00, 0x50, 0xf2, 1) - -#define RSN_SELECTOR_PUT(a, val) WPA_PUT_BE32((u8 *) (a), (val)) -#define RSN_SELECTOR_GET(a) WPA_GET_BE32((const u8 *) (a)) - -#define RSN_NUM_REPLAY_COUNTERS_1 0 -#define RSN_NUM_REPLAY_COUNTERS_2 1 -#define RSN_NUM_REPLAY_COUNTERS_4 2 -#define RSN_NUM_REPLAY_COUNTERS_16 3 - - -#ifdef _MSC_VER -#pragma pack(push, 1) -#endif /* _MSC_VER */ - -#ifdef CONFIG_IEEE80211W -#define WPA_IGTK_LEN 16 -#endif /* CONFIG_IEEE80211W */ - - -/* IEEE 802.11, 7.3.2.25.3 RSN Capabilities */ -#define WPA_CAPABILITY_PREAUTH BIT(0) -#define WPA_CAPABILITY_NO_PAIRWISE BIT(1) -/* B2-B3: PTKSA Replay Counter */ -/* B4-B5: GTKSA Replay Counter */ -#define WPA_CAPABILITY_MFPR BIT(6) -#define WPA_CAPABILITY_MFPC BIT(7) -/* B8: Reserved */ -#define WPA_CAPABILITY_PEERKEY_ENABLED BIT(9) -#define WPA_CAPABILITY_SPP_A_MSDU_CAPABLE BIT(10) -#define WPA_CAPABILITY_SPP_A_MSDU_REQUIRED BIT(11) -#define WPA_CAPABILITY_PBAC BIT(12) -#define WPA_CAPABILITY_EXT_KEY_ID_FOR_UNICAST BIT(13) -/* B14-B15: Reserved */ - - -/* IEEE 802.11r */ -#define MOBILITY_DOMAIN_ID_LEN 2 -#define FT_R0KH_ID_MAX_LEN 48 -#define FT_R1KH_ID_LEN 6 -#define WPA_PMK_NAME_LEN 16 - - -/* IEEE 802.11, 8.5.2 EAPOL-Key frames */ -#define WPA_KEY_INFO_TYPE_MASK ((u16) (BIT(0) | BIT(1) | BIT(2))) -#define WPA_KEY_INFO_TYPE_HMAC_MD5_RC4 BIT(0) -#define WPA_KEY_INFO_TYPE_HMAC_SHA1_AES BIT(1) -#define WPA_KEY_INFO_TYPE_AES_128_CMAC 3 -#define WPA_KEY_INFO_KEY_TYPE BIT(3) /* 1 = Pairwise, 0 = Group key */ -/* bit4..5 is used in WPA, but is reserved in IEEE 802.11i/RSN */ -#define WPA_KEY_INFO_KEY_INDEX_MASK (BIT(4) | BIT(5)) -#define WPA_KEY_INFO_KEY_INDEX_SHIFT 4 -#define WPA_KEY_INFO_INSTALL BIT(6) /* pairwise */ -#define WPA_KEY_INFO_TXRX BIT(6) /* group */ -#define WPA_KEY_INFO_ACK BIT(7) -#define WPA_KEY_INFO_MIC BIT(8) -#define WPA_KEY_INFO_SECURE BIT(9) -#define WPA_KEY_INFO_ERROR BIT(10) -#define WPA_KEY_INFO_REQUEST BIT(11) -#define WPA_KEY_INFO_ENCR_KEY_DATA BIT(12) /* IEEE 802.11i/RSN only */ -#define WPA_KEY_INFO_SMK_MESSAGE BIT(13) - - -struct wpa_eapol_key { - u8 type; - /* Note: key_info, key_length, and key_data_length are unaligned */ - u8 key_info[2]; /* big endian */ - u8 key_length[2]; /* big endian */ - u8 replay_counter[WPA_REPLAY_COUNTER_LEN]; - u8 key_nonce[WPA_NONCE_LEN]; - u8 key_iv[16]; - u8 key_rsc[WPA_KEY_RSC_LEN]; - u8 key_id[8]; /* Reserved in IEEE 802.11i/RSN */ - u8 key_mic[16]; - u8 key_data_length[2]; /* big endian */ - /* followed by key_data_length bytes of key_data */ -} STRUCT_PACKED; - -/** - * struct wpa_ptk - WPA Pairwise Transient Key - * IEEE Std 802.11i-2004 - 8.5.1.2 Pairwise key hierarchy - */ -struct wpa_ptk { - u8 kck[16]; /* EAPOL-Key Key Confirmation Key (KCK) */ - u8 kek[16]; /* EAPOL-Key Key Encryption Key (KEK) */ - u8 tk1[16]; /* Temporal Key 1 (TK1) */ - union { - u8 tk2[16]; /* Temporal Key 2 (TK2) */ - struct { - u8 tx_mic_key[8]; - u8 rx_mic_key[8]; - } auth; - } u; -} STRUCT_PACKED; - - -/* WPA IE version 1 - * 00-50-f2:1 (OUI:OUI type) - * 0x01 0x00 (version; little endian) - * (all following fields are optional:) - * Group Suite Selector (4 octets) (default: TKIP) - * Pairwise Suite Count (2 octets, little endian) (default: 1) - * Pairwise Suite List (4 * n octets) (default: TKIP) - * Authenticated Key Management Suite Count (2 octets, little endian) - * (default: 1) - * Authenticated Key Management Suite List (4 * n octets) - * (default: unspec 802.1X) - * WPA Capabilities (2 octets, little endian) (default: 0) - */ - -struct wpa_ie_hdr { - u8 elem_id; - u8 len; - u8 oui[4]; /* 24-bit OUI followed by 8-bit OUI type */ - u8 version[2]; /* little endian */ -} STRUCT_PACKED; - - -/* 1/4: PMKID - * 2/4: RSN IE - * 3/4: one or two RSN IEs + GTK IE (encrypted) - * 4/4: empty - * 1/2: GTK IE (encrypted) - * 2/2: empty - */ - -/* RSN IE version 1 - * 0x01 0x00 (version; little endian) - * (all following fields are optional:) - * Group Suite Selector (4 octets) (default: CCMP) - * Pairwise Suite Count (2 octets, little endian) (default: 1) - * Pairwise Suite List (4 * n octets) (default: CCMP) - * Authenticated Key Management Suite Count (2 octets, little endian) - * (default: 1) - * Authenticated Key Management Suite List (4 * n octets) - * (default: unspec 802.1X) - * RSN Capabilities (2 octets, little endian) (default: 0) - * PMKID Count (2 octets) (default: 0) - * PMKID List (16 * n octets) - * Management Group Cipher Suite (4 octets) (default: AES-128-CMAC) - */ - -struct rsn_ie_hdr { - u8 elem_id; /* WLAN_EID_RSN */ - u8 len; - u8 version[2]; /* little endian */ -} STRUCT_PACKED; - - -#ifdef CONFIG_PEERKEY -enum { - STK_MUI_4WAY_STA_AP = 1, - STK_MUI_4WAY_STAT_STA = 2, - STK_MUI_GTK = 3, - STK_MUI_SMK = 4 -}; - -enum { - STK_ERR_STA_NR = 1, - STK_ERR_STA_NRSN = 2, - STK_ERR_CPHR_NS = 3, - STK_ERR_NO_STSL = 4 -}; -#endif /* CONFIG_PEERKEY */ - -struct rsn_error_kde { - be16 mui; - be16 error_type; -} STRUCT_PACKED; - -#ifdef CONFIG_IEEE80211W -struct wpa_igtk_kde { - u8 keyid[2]; - u8 pn[6]; - u8 igtk[WPA_IGTK_LEN]; -} STRUCT_PACKED; -#endif /* CONFIG_IEEE80211W */ - -#ifdef CONFIG_IEEE80211R -struct rsn_mdie { - u8 mobility_domain[MOBILITY_DOMAIN_ID_LEN]; - u8 ft_capab; -} STRUCT_PACKED; - -#define RSN_FT_CAPAB_FT_OVER_DS BIT(0) -#define RSN_FT_CAPAB_FT_RESOURCE_REQ_SUPP BIT(1) - -struct rsn_ftie { - u8 mic_control[2]; - u8 mic[16]; - u8 anonce[WPA_NONCE_LEN]; - u8 snonce[WPA_NONCE_LEN]; - /* followed by optional parameters */ -} STRUCT_PACKED; - -#define FTIE_SUBELEM_R1KH_ID 1 -#define FTIE_SUBELEM_GTK 2 -#define FTIE_SUBELEM_R0KH_ID 3 -#define FTIE_SUBELEM_IGTK 4 - -struct rsn_rdie { - u8 id; - u8 descr_count; - le16 status_code; -} STRUCT_PACKED; - -#endif /* CONFIG_IEEE80211R */ - -#ifdef _MSC_VER -#pragma pack(pop) -#endif /* _MSC_VER */ - - -int wpa_eapol_key_mic(const u8 *key, int ver, const u8 *buf, size_t len, - u8 *mic); -void wpa_pmk_to_ptk(const u8 *pmk, size_t pmk_len, const char *label, - const u8 *addr1, const u8 *addr2, - const u8 *nonce1, const u8 *nonce2, - u8 *ptk, size_t ptk_len, int use_sha256); - -#ifdef CONFIG_IEEE80211R -int wpa_ft_mic(const u8 *kck, const u8 *sta_addr, const u8 *ap_addr, - u8 transaction_seqnum, const u8 *mdie, size_t mdie_len, - const u8 *ftie, size_t ftie_len, - const u8 *rsnie, size_t rsnie_len, - const u8 *ric, size_t ric_len, u8 *mic); -void wpa_derive_pmk_r0(const u8 *xxkey, size_t xxkey_len, - const u8 *ssid, size_t ssid_len, - const u8 *mdid, const u8 *r0kh_id, size_t r0kh_id_len, - const u8 *s0kh_id, u8 *pmk_r0, u8 *pmk_r0_name); -void wpa_derive_pmk_r1_name(const u8 *pmk_r0_name, const u8 *r1kh_id, - const u8 *s1kh_id, u8 *pmk_r1_name); -void wpa_derive_pmk_r1(const u8 *pmk_r0, const u8 *pmk_r0_name, - const u8 *r1kh_id, const u8 *s1kh_id, - u8 *pmk_r1, u8 *pmk_r1_name); -void wpa_pmk_r1_to_ptk(const u8 *pmk_r1, const u8 *snonce, const u8 *anonce, - const u8 *sta_addr, const u8 *bssid, - const u8 *pmk_r1_name, - u8 *ptk, size_t ptk_len, u8 *ptk_name); -#endif /* CONFIG_IEEE80211R */ - -struct wpa_ie_data { - int proto; - int pairwise_cipher; - int group_cipher; - int key_mgmt; - int capabilities; - size_t num_pmkid; - const u8 *pmkid; - int mgmt_group_cipher; -}; - - -int wpa_parse_wpa_ie_rsn(const u8 *rsn_ie, size_t rsn_ie_len, - struct wpa_ie_data *data); -int wpa_parse_wpa_ie_wpa(const u8 *wpa_ie, size_t wpa_ie_len, - struct wpa_ie_data *data); - -void rsn_pmkid(const u8 *pmk, size_t pmk_len, const u8 *aa, const u8 *spa, - u8 *pmkid, int use_sha256); - -const char * wpa_cipher_txt(int cipher); -const char * wpa_key_mgmt_txt(int key_mgmt, int proto); -int wpa_compare_rsn_ie(int ft_initial_assoc, - const u8 *ie1, size_t ie1len, - const u8 *ie2, size_t ie2len); -int wpa_insert_pmkid(u8 *ies, size_t ies_len, const u8 *pmkid); - -#endif /* WPA_COMMON_H */ diff --git a/hostapd-0.8/src/common/wpa_ctrl.c b/hostapd-0.8/src/common/wpa_ctrl.c deleted file mode 100644 index 88d3a02..0000000 --- a/hostapd-0.8/src/common/wpa_ctrl.c +++ /dev/null @@ -1,500 +0,0 @@ -/* - * wpa_supplicant/hostapd control interface library - * Copyright (c) 2004-2007, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#include "includes.h" - -#ifdef CONFIG_CTRL_IFACE - -#ifdef CONFIG_CTRL_IFACE_UNIX -#include -#endif /* CONFIG_CTRL_IFACE_UNIX */ - -#ifdef ANDROID -#include -#include "private/android_filesystem_config.h" -#endif /* ANDROID */ - -#include "wpa_ctrl.h" -#include "common.h" - - -#if defined(CONFIG_CTRL_IFACE_UNIX) || defined(CONFIG_CTRL_IFACE_UDP) -#define CTRL_IFACE_SOCKET -#endif /* CONFIG_CTRL_IFACE_UNIX || CONFIG_CTRL_IFACE_UDP */ - - -/** - * struct wpa_ctrl - Internal structure for control interface library - * - * This structure is used by the wpa_supplicant/hostapd control interface - * library to store internal data. Programs using the library should not touch - * this data directly. They can only use the pointer to the data structure as - * an identifier for the control interface connection and use this as one of - * the arguments for most of the control interface library functions. - */ -struct wpa_ctrl { -#ifdef CONFIG_CTRL_IFACE_UDP - int s; - struct sockaddr_in local; - struct sockaddr_in dest; - char *cookie; -#endif /* CONFIG_CTRL_IFACE_UDP */ -#ifdef CONFIG_CTRL_IFACE_UNIX - int s; - struct sockaddr_un local; - struct sockaddr_un dest; -#endif /* CONFIG_CTRL_IFACE_UNIX */ -#ifdef CONFIG_CTRL_IFACE_NAMED_PIPE - HANDLE pipe; -#endif /* CONFIG_CTRL_IFACE_NAMED_PIPE */ -}; - - -#ifdef CONFIG_CTRL_IFACE_UNIX - -#ifndef CONFIG_CTRL_IFACE_CLIENT_DIR -#define CONFIG_CTRL_IFACE_CLIENT_DIR "/tmp" -#endif /* CONFIG_CTRL_IFACE_CLIENT_DIR */ -#ifndef CONFIG_CTRL_IFACE_CLIENT_PREFIX -#define CONFIG_CTRL_IFACE_CLIENT_PREFIX "wpa_ctrl_" -#endif /* CONFIG_CTRL_IFACE_CLIENT_PREFIX */ - - -struct wpa_ctrl * wpa_ctrl_open(const char *ctrl_path) -{ - struct wpa_ctrl *ctrl; - static int counter = 0; - int ret; - size_t res; - int tries = 0; - - ctrl = os_malloc(sizeof(*ctrl)); - if (ctrl == NULL) - return NULL; - os_memset(ctrl, 0, sizeof(*ctrl)); - - ctrl->s = socket(PF_UNIX, SOCK_DGRAM, 0); - if (ctrl->s < 0) { - os_free(ctrl); - return NULL; - } - - ctrl->local.sun_family = AF_UNIX; - counter++; -try_again: - ret = os_snprintf(ctrl->local.sun_path, sizeof(ctrl->local.sun_path), - CONFIG_CTRL_IFACE_CLIENT_DIR "/" - CONFIG_CTRL_IFACE_CLIENT_PREFIX "%d-%d", - (int) getpid(), counter); - if (ret < 0 || (size_t) ret >= sizeof(ctrl->local.sun_path)) { - close(ctrl->s); - os_free(ctrl); - return NULL; - } - tries++; - if (bind(ctrl->s, (struct sockaddr *) &ctrl->local, - sizeof(ctrl->local)) < 0) { - if (errno == EADDRINUSE && tries < 2) { - /* - * getpid() returns unique identifier for this instance - * of wpa_ctrl, so the existing socket file must have - * been left by unclean termination of an earlier run. - * Remove the file and try again. - */ - unlink(ctrl->local.sun_path); - goto try_again; - } - close(ctrl->s); - os_free(ctrl); - return NULL; - } - -#ifdef ANDROID - chmod(ctrl->local.sun_path, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP); - chown(ctrl->local.sun_path, AID_SYSTEM, AID_WIFI); - /* - * If the ctrl_path isn't an absolute pathname, assume that - * it's the name of a socket in the Android reserved namespace. - * Otherwise, it's a normal UNIX domain socket appearing in the - * filesystem. - */ - if (ctrl_path != NULL && *ctrl_path != '/') { - char buf[21]; - os_snprintf(buf, sizeof(buf), "wpa_%s", ctrl_path); - if (socket_local_client_connect( - ctrl->s, buf, - ANDROID_SOCKET_NAMESPACE_RESERVED, - SOCK_DGRAM) < 0) { - close(ctrl->s); - unlink(ctrl->local.sun_path); - os_free(ctrl); - return NULL; - } - return ctrl; - } -#endif /* ANDROID */ - - ctrl->dest.sun_family = AF_UNIX; - res = os_strlcpy(ctrl->dest.sun_path, ctrl_path, - sizeof(ctrl->dest.sun_path)); - if (res >= sizeof(ctrl->dest.sun_path)) { - close(ctrl->s); - os_free(ctrl); - return NULL; - } - if (connect(ctrl->s, (struct sockaddr *) &ctrl->dest, - sizeof(ctrl->dest)) < 0) { - close(ctrl->s); - unlink(ctrl->local.sun_path); - os_free(ctrl); - return NULL; - } - - return ctrl; -} - - -void wpa_ctrl_close(struct wpa_ctrl *ctrl) -{ - if (ctrl == NULL) - return; - unlink(ctrl->local.sun_path); - if (ctrl->s >= 0) - close(ctrl->s); - os_free(ctrl); -} - -#endif /* CONFIG_CTRL_IFACE_UNIX */ - - -#ifdef CONFIG_CTRL_IFACE_UDP - -struct wpa_ctrl * wpa_ctrl_open(const char *ctrl_path) -{ - struct wpa_ctrl *ctrl; - char buf[128]; - size_t len; - - ctrl = os_malloc(sizeof(*ctrl)); - if (ctrl == NULL) - return NULL; - os_memset(ctrl, 0, sizeof(*ctrl)); - - ctrl->s = socket(PF_INET, SOCK_DGRAM, 0); - if (ctrl->s < 0) { - perror("socket"); - os_free(ctrl); - return NULL; - } - - ctrl->local.sin_family = AF_INET; - ctrl->local.sin_addr.s_addr = htonl((127 << 24) | 1); - if (bind(ctrl->s, (struct sockaddr *) &ctrl->local, - sizeof(ctrl->local)) < 0) { - close(ctrl->s); - os_free(ctrl); - return NULL; - } - - ctrl->dest.sin_family = AF_INET; - ctrl->dest.sin_addr.s_addr = htonl((127 << 24) | 1); - ctrl->dest.sin_port = htons(WPA_CTRL_IFACE_PORT); - if (connect(ctrl->s, (struct sockaddr *) &ctrl->dest, - sizeof(ctrl->dest)) < 0) { - perror("connect"); - close(ctrl->s); - os_free(ctrl); - return NULL; - } - - len = sizeof(buf) - 1; - if (wpa_ctrl_request(ctrl, "GET_COOKIE", 10, buf, &len, NULL) == 0) { - buf[len] = '\0'; - ctrl->cookie = os_strdup(buf); - } - - return ctrl; -} - - -void wpa_ctrl_close(struct wpa_ctrl *ctrl) -{ - close(ctrl->s); - os_free(ctrl->cookie); - os_free(ctrl); -} - -#endif /* CONFIG_CTRL_IFACE_UDP */ - - -#ifdef CTRL_IFACE_SOCKET -int wpa_ctrl_request(struct wpa_ctrl *ctrl, const char *cmd, size_t cmd_len, - char *reply, size_t *reply_len, - void (*msg_cb)(char *msg, size_t len)) -{ - struct timeval tv; - int res; - fd_set rfds; - const char *_cmd; - char *cmd_buf = NULL; - size_t _cmd_len; - -#ifdef CONFIG_CTRL_IFACE_UDP - if (ctrl->cookie) { - char *pos; - _cmd_len = os_strlen(ctrl->cookie) + 1 + cmd_len; - cmd_buf = os_malloc(_cmd_len); - if (cmd_buf == NULL) - return -1; - _cmd = cmd_buf; - pos = cmd_buf; - os_strlcpy(pos, ctrl->cookie, _cmd_len); - pos += os_strlen(ctrl->cookie); - *pos++ = ' '; - os_memcpy(pos, cmd, cmd_len); - } else -#endif /* CONFIG_CTRL_IFACE_UDP */ - { - _cmd = cmd; - _cmd_len = cmd_len; - } - - if (send(ctrl->s, _cmd, _cmd_len, 0) < 0) { - os_free(cmd_buf); - return -1; - } - os_free(cmd_buf); - - for (;;) { - tv.tv_sec = 10; - tv.tv_usec = 0; - FD_ZERO(&rfds); - FD_SET(ctrl->s, &rfds); - res = select(ctrl->s + 1, &rfds, NULL, NULL, &tv); - if (res < 0) - return res; - if (FD_ISSET(ctrl->s, &rfds)) { - res = recv(ctrl->s, reply, *reply_len, 0); - if (res < 0) - return res; - if (res > 0 && reply[0] == '<') { - /* This is an unsolicited message from - * wpa_supplicant, not the reply to the - * request. Use msg_cb to report this to the - * caller. */ - if (msg_cb) { - /* Make sure the message is nul - * terminated. */ - if ((size_t) res == *reply_len) - res = (*reply_len) - 1; - reply[res] = '\0'; - msg_cb(reply, res); - } - continue; - } - *reply_len = res; - break; - } else { - return -2; - } - } - return 0; -} -#endif /* CTRL_IFACE_SOCKET */ - - -static int wpa_ctrl_attach_helper(struct wpa_ctrl *ctrl, int attach) -{ - char buf[10]; - int ret; - size_t len = 10; - - ret = wpa_ctrl_request(ctrl, attach ? "ATTACH" : "DETACH", 6, - buf, &len, NULL); - if (ret < 0) - return ret; - if (len == 3 && os_memcmp(buf, "OK\n", 3) == 0) - return 0; - return -1; -} - - -int wpa_ctrl_attach(struct wpa_ctrl *ctrl) -{ - return wpa_ctrl_attach_helper(ctrl, 1); -} - - -int wpa_ctrl_detach(struct wpa_ctrl *ctrl) -{ - return wpa_ctrl_attach_helper(ctrl, 0); -} - - -#ifdef CTRL_IFACE_SOCKET - -int wpa_ctrl_recv(struct wpa_ctrl *ctrl, char *reply, size_t *reply_len) -{ - int res; - - res = recv(ctrl->s, reply, *reply_len, 0); - if (res < 0) - return res; - *reply_len = res; - return 0; -} - - -int wpa_ctrl_pending(struct wpa_ctrl *ctrl) -{ - struct timeval tv; - fd_set rfds; - tv.tv_sec = 0; - tv.tv_usec = 0; - FD_ZERO(&rfds); - FD_SET(ctrl->s, &rfds); - select(ctrl->s + 1, &rfds, NULL, NULL, &tv); - return FD_ISSET(ctrl->s, &rfds); -} - - -int wpa_ctrl_get_fd(struct wpa_ctrl *ctrl) -{ - return ctrl->s; -} - -#endif /* CTRL_IFACE_SOCKET */ - - -#ifdef CONFIG_CTRL_IFACE_NAMED_PIPE - -#ifndef WPA_SUPPLICANT_NAMED_PIPE -#define WPA_SUPPLICANT_NAMED_PIPE "WpaSupplicant" -#endif -#define NAMED_PIPE_PREFIX TEXT("\\\\.\\pipe\\") TEXT(WPA_SUPPLICANT_NAMED_PIPE) - -struct wpa_ctrl * wpa_ctrl_open(const char *ctrl_path) -{ - struct wpa_ctrl *ctrl; - DWORD mode; - TCHAR name[256]; - int i, ret; - - ctrl = os_malloc(sizeof(*ctrl)); - if (ctrl == NULL) - return NULL; - os_memset(ctrl, 0, sizeof(*ctrl)); - -#ifdef UNICODE - if (ctrl_path == NULL) - ret = _snwprintf(name, 256, NAMED_PIPE_PREFIX); - else - ret = _snwprintf(name, 256, NAMED_PIPE_PREFIX TEXT("-%S"), - ctrl_path); -#else /* UNICODE */ - if (ctrl_path == NULL) - ret = os_snprintf(name, 256, NAMED_PIPE_PREFIX); - else - ret = os_snprintf(name, 256, NAMED_PIPE_PREFIX "-%s", - ctrl_path); -#endif /* UNICODE */ - if (ret < 0 || ret >= 256) { - os_free(ctrl); - return NULL; - } - - for (i = 0; i < 10; i++) { - ctrl->pipe = CreateFile(name, GENERIC_READ | GENERIC_WRITE, 0, - NULL, OPEN_EXISTING, 0, NULL); - /* - * Current named pipe server side in wpa_supplicant is - * re-opening the pipe for new clients only after the previous - * one is taken into use. This leaves a small window for race - * conditions when two connections are being opened at almost - * the same time. Retry if that was the case. - */ - if (ctrl->pipe != INVALID_HANDLE_VALUE || - GetLastError() != ERROR_PIPE_BUSY) - break; - WaitNamedPipe(name, 1000); - } - if (ctrl->pipe == INVALID_HANDLE_VALUE) { - os_free(ctrl); - return NULL; - } - - mode = PIPE_READMODE_MESSAGE; - if (!SetNamedPipeHandleState(ctrl->pipe, &mode, NULL, NULL)) { - CloseHandle(ctrl->pipe); - os_free(ctrl); - return NULL; - } - - return ctrl; -} - - -void wpa_ctrl_close(struct wpa_ctrl *ctrl) -{ - CloseHandle(ctrl->pipe); - os_free(ctrl); -} - - -int wpa_ctrl_request(struct wpa_ctrl *ctrl, const char *cmd, size_t cmd_len, - char *reply, size_t *reply_len, - void (*msg_cb)(char *msg, size_t len)) -{ - DWORD written; - DWORD readlen = *reply_len; - - if (!WriteFile(ctrl->pipe, cmd, cmd_len, &written, NULL)) - return -1; - - if (!ReadFile(ctrl->pipe, reply, *reply_len, &readlen, NULL)) - return -1; - *reply_len = readlen; - - return 0; -} - - -int wpa_ctrl_recv(struct wpa_ctrl *ctrl, char *reply, size_t *reply_len) -{ - DWORD len = *reply_len; - if (!ReadFile(ctrl->pipe, reply, *reply_len, &len, NULL)) - return -1; - *reply_len = len; - return 0; -} - - -int wpa_ctrl_pending(struct wpa_ctrl *ctrl) -{ - DWORD left; - - if (!PeekNamedPipe(ctrl->pipe, NULL, 0, NULL, &left, NULL)) - return -1; - return left ? 1 : 0; -} - - -int wpa_ctrl_get_fd(struct wpa_ctrl *ctrl) -{ - return -1; -} - -#endif /* CONFIG_CTRL_IFACE_NAMED_PIPE */ - -#endif /* CONFIG_CTRL_IFACE */ diff --git a/hostapd-0.8/src/common/wpa_ctrl.h b/hostapd-0.8/src/common/wpa_ctrl.h deleted file mode 100644 index 528cc16..0000000 --- a/hostapd-0.8/src/common/wpa_ctrl.h +++ /dev/null @@ -1,274 +0,0 @@ -/* - * wpa_supplicant/hostapd control interface library - * Copyright (c) 2004-2006, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#ifndef WPA_CTRL_H -#define WPA_CTRL_H - -#ifdef __cplusplus -extern "C" { -#endif - -/* wpa_supplicant control interface - fixed message prefixes */ - -/** Interactive request for identity/password/pin */ -#define WPA_CTRL_REQ "CTRL-REQ-" - -/** Response to identity/password/pin request */ -#define WPA_CTRL_RSP "CTRL-RSP-" - -/* Event messages with fixed prefix */ -/** Authentication completed successfully and data connection enabled */ -#define WPA_EVENT_CONNECTED "CTRL-EVENT-CONNECTED " -/** Disconnected, data connection is not available */ -#define WPA_EVENT_DISCONNECTED "CTRL-EVENT-DISCONNECTED " -/** Association rejected during connection attempt */ -#define WPA_EVENT_ASSOC_REJECT "CTRL-EVENT-ASSOC-REJECT " -/** wpa_supplicant is exiting */ -#define WPA_EVENT_TERMINATING "CTRL-EVENT-TERMINATING " -/** Password change was completed successfully */ -#define WPA_EVENT_PASSWORD_CHANGED "CTRL-EVENT-PASSWORD-CHANGED " -/** EAP-Request/Notification received */ -#define WPA_EVENT_EAP_NOTIFICATION "CTRL-EVENT-EAP-NOTIFICATION " -/** EAP authentication started (EAP-Request/Identity received) */ -#define WPA_EVENT_EAP_STARTED "CTRL-EVENT-EAP-STARTED " -/** EAP method proposed by the server */ -#define WPA_EVENT_EAP_PROPOSED_METHOD "CTRL-EVENT-EAP-PROPOSED-METHOD " -/** EAP method selected */ -#define WPA_EVENT_EAP_METHOD "CTRL-EVENT-EAP-METHOD " -/** EAP peer certificate from TLS */ -#define WPA_EVENT_EAP_PEER_CERT "CTRL-EVENT-EAP-PEER-CERT " -/** EAP TLS certificate chain validation error */ -#define WPA_EVENT_EAP_TLS_CERT_ERROR "CTRL-EVENT-EAP-TLS-CERT-ERROR " -/** EAP authentication completed successfully */ -#define WPA_EVENT_EAP_SUCCESS "CTRL-EVENT-EAP-SUCCESS " -/** EAP authentication failed (EAP-Failure received) */ -#define WPA_EVENT_EAP_FAILURE "CTRL-EVENT-EAP-FAILURE " -/** New scan results available */ -#define WPA_EVENT_SCAN_RESULTS "CTRL-EVENT-SCAN-RESULTS " -/** wpa_supplicant state change */ -#define WPA_EVENT_STATE_CHANGE "CTRL-EVENT-STATE-CHANGE " -/** A new BSS entry was added (followed by BSS entry id and BSSID) */ -#define WPA_EVENT_BSS_ADDED "CTRL-EVENT-BSS-ADDED " -/** A BSS entry was removed (followed by BSS entry id and BSSID) */ -#define WPA_EVENT_BSS_REMOVED "CTRL-EVENT-BSS-REMOVED " - -/** WPS overlap detected in PBC mode */ -#define WPS_EVENT_OVERLAP "WPS-OVERLAP-DETECTED " -/** Available WPS AP with active PBC found in scan results */ -#define WPS_EVENT_AP_AVAILABLE_PBC "WPS-AP-AVAILABLE-PBC " -/** Available WPS AP with our address as authorized in scan results */ -#define WPS_EVENT_AP_AVAILABLE_AUTH "WPS-AP-AVAILABLE-AUTH " -/** Available WPS AP with recently selected PIN registrar found in scan results - */ -#define WPS_EVENT_AP_AVAILABLE_PIN "WPS-AP-AVAILABLE-PIN " -/** Available WPS AP found in scan results */ -#define WPS_EVENT_AP_AVAILABLE "WPS-AP-AVAILABLE " -/** A new credential received */ -#define WPS_EVENT_CRED_RECEIVED "WPS-CRED-RECEIVED " -/** M2D received */ -#define WPS_EVENT_M2D "WPS-M2D " -/** WPS registration failed after M2/M2D */ -#define WPS_EVENT_FAIL "WPS-FAIL " -/** WPS registration completed successfully */ -#define WPS_EVENT_SUCCESS "WPS-SUCCESS " -/** WPS enrollment attempt timed out and was terminated */ -#define WPS_EVENT_TIMEOUT "WPS-TIMEOUT " - -#define WPS_EVENT_ENROLLEE_SEEN "WPS-ENROLLEE-SEEN " - -#define WPS_EVENT_OPEN_NETWORK "WPS-OPEN-NETWORK " - -/* WPS ER events */ -#define WPS_EVENT_ER_AP_ADD "WPS-ER-AP-ADD " -#define WPS_EVENT_ER_AP_REMOVE "WPS-ER-AP-REMOVE " -#define WPS_EVENT_ER_ENROLLEE_ADD "WPS-ER-ENROLLEE-ADD " -#define WPS_EVENT_ER_ENROLLEE_REMOVE "WPS-ER-ENROLLEE-REMOVE " -#define WPS_EVENT_ER_AP_SETTINGS "WPS-ER-AP-SETTINGS " -#define WPS_EVENT_ER_SET_SEL_REG "WPS-ER-AP-SET-SEL-REG " - -/** P2P device found */ -#define P2P_EVENT_DEVICE_FOUND "P2P-DEVICE-FOUND " -/** A P2P device requested GO negotiation, but we were not ready to start the - * negotiation */ -#define P2P_EVENT_GO_NEG_REQUEST "P2P-GO-NEG-REQUEST " -#define P2P_EVENT_GO_NEG_SUCCESS "P2P-GO-NEG-SUCCESS " -#define P2P_EVENT_GO_NEG_FAILURE "P2P-GO-NEG-FAILURE " -#define P2P_EVENT_GROUP_FORMATION_SUCCESS "P2P-GROUP-FORMATION-SUCCESS " -#define P2P_EVENT_GROUP_FORMATION_FAILURE "P2P-GROUP-FORMATION-FAILURE " -#define P2P_EVENT_GROUP_STARTED "P2P-GROUP-STARTED " -#define P2P_EVENT_GROUP_REMOVED "P2P-GROUP-REMOVED " -#define P2P_EVENT_CROSS_CONNECT_ENABLE "P2P-CROSS-CONNECT-ENABLE " -#define P2P_EVENT_CROSS_CONNECT_DISABLE "P2P-CROSS-CONNECT-DISABLE " -/* parameters: */ -#define P2P_EVENT_PROV_DISC_SHOW_PIN "P2P-PROV-DISC-SHOW-PIN " -/* parameters: */ -#define P2P_EVENT_PROV_DISC_ENTER_PIN "P2P-PROV-DISC-ENTER-PIN " -/* parameters: */ -#define P2P_EVENT_PROV_DISC_PBC_REQ "P2P-PROV-DISC-PBC-REQ " -/* parameters: */ -#define P2P_EVENT_PROV_DISC_PBC_RESP "P2P-PROV-DISC-PBC-RESP " -/* parameters: */ -#define P2P_EVENT_SERV_DISC_REQ "P2P-SERV-DISC-REQ " -/* parameters: */ -#define P2P_EVENT_SERV_DISC_RESP "P2P-SERV-DISC-RESP " -#define P2P_EVENT_INVITATION_RECEIVED "P2P-INVITATION-RECEIVED " -#define P2P_EVENT_INVITATION_RESULT "P2P-INVITATION-RESULT " - -/* hostapd control interface - fixed message prefixes */ -#define WPS_EVENT_PIN_NEEDED "WPS-PIN-NEEDED " -#define WPS_EVENT_NEW_AP_SETTINGS "WPS-NEW-AP-SETTINGS " -#define WPS_EVENT_REG_SUCCESS "WPS-REG-SUCCESS " -#define WPS_EVENT_AP_SETUP_LOCKED "WPS-AP-SETUP-LOCKED " -#define WPS_EVENT_AP_SETUP_UNLOCKED "WPS-AP-SETUP-UNLOCKED " -#define WPS_EVENT_AP_PIN_ENABLED "WPS-AP-PIN-ENABLED " -#define WPS_EVENT_AP_PIN_DISABLED "WPS-AP-PIN-DISABLED " -#define AP_STA_CONNECTED "AP-STA-CONNECTED " -#define AP_STA_DISCONNECTED "AP-STA-DISCONNECTED " - - -/* wpa_supplicant/hostapd control interface access */ - -/** - * wpa_ctrl_open - Open a control interface to wpa_supplicant/hostapd - * @ctrl_path: Path for UNIX domain sockets; ignored if UDP sockets are used. - * Returns: Pointer to abstract control interface data or %NULL on failure - * - * This function is used to open a control interface to wpa_supplicant/hostapd. - * ctrl_path is usually /var/run/wpa_supplicant or /var/run/hostapd. This path - * is configured in wpa_supplicant/hostapd and other programs using the control - * interface need to use matching path configuration. - */ -struct wpa_ctrl * wpa_ctrl_open(const char *ctrl_path); - - -/** - * wpa_ctrl_close - Close a control interface to wpa_supplicant/hostapd - * @ctrl: Control interface data from wpa_ctrl_open() - * - * This function is used to close a control interface. - */ -void wpa_ctrl_close(struct wpa_ctrl *ctrl); - - -/** - * wpa_ctrl_request - Send a command to wpa_supplicant/hostapd - * @ctrl: Control interface data from wpa_ctrl_open() - * @cmd: Command; usually, ASCII text, e.g., "PING" - * @cmd_len: Length of the cmd in bytes - * @reply: Buffer for the response - * @reply_len: Reply buffer length - * @msg_cb: Callback function for unsolicited messages or %NULL if not used - * Returns: 0 on success, -1 on error (send or receive failed), -2 on timeout - * - * This function is used to send commands to wpa_supplicant/hostapd. Received - * response will be written to reply and reply_len is set to the actual length - * of the reply. This function will block for up to two seconds while waiting - * for the reply. If unsolicited messages are received, the blocking time may - * be longer. - * - * msg_cb can be used to register a callback function that will be called for - * unsolicited messages received while waiting for the command response. These - * messages may be received if wpa_ctrl_request() is called at the same time as - * wpa_supplicant/hostapd is sending such a message. This can happen only if - * the program has used wpa_ctrl_attach() to register itself as a monitor for - * event messages. Alternatively to msg_cb, programs can register two control - * interface connections and use one of them for commands and the other one for - * receiving event messages, in other words, call wpa_ctrl_attach() only for - * the control interface connection that will be used for event messages. - */ -int wpa_ctrl_request(struct wpa_ctrl *ctrl, const char *cmd, size_t cmd_len, - char *reply, size_t *reply_len, - void (*msg_cb)(char *msg, size_t len)); - - -/** - * wpa_ctrl_attach - Register as an event monitor for the control interface - * @ctrl: Control interface data from wpa_ctrl_open() - * Returns: 0 on success, -1 on failure, -2 on timeout - * - * This function registers the control interface connection as a monitor for - * wpa_supplicant/hostapd events. After a success wpa_ctrl_attach() call, the - * control interface connection starts receiving event messages that can be - * read with wpa_ctrl_recv(). - */ -int wpa_ctrl_attach(struct wpa_ctrl *ctrl); - - -/** - * wpa_ctrl_detach - Unregister event monitor from the control interface - * @ctrl: Control interface data from wpa_ctrl_open() - * Returns: 0 on success, -1 on failure, -2 on timeout - * - * This function unregisters the control interface connection as a monitor for - * wpa_supplicant/hostapd events, i.e., cancels the registration done with - * wpa_ctrl_attach(). - */ -int wpa_ctrl_detach(struct wpa_ctrl *ctrl); - - -/** - * wpa_ctrl_recv - Receive a pending control interface message - * @ctrl: Control interface data from wpa_ctrl_open() - * @reply: Buffer for the message data - * @reply_len: Length of the reply buffer - * Returns: 0 on success, -1 on failure - * - * This function will receive a pending control interface message. This - * function will block if no messages are available. The received response will - * be written to reply and reply_len is set to the actual length of the reply. - * wpa_ctrl_recv() is only used for event messages, i.e., wpa_ctrl_attach() - * must have been used to register the control interface as an event monitor. - */ -int wpa_ctrl_recv(struct wpa_ctrl *ctrl, char *reply, size_t *reply_len); - - -/** - * wpa_ctrl_pending - Check whether there are pending event messages - * @ctrl: Control interface data from wpa_ctrl_open() - * Returns: 1 if there are pending messages, 0 if no, or -1 on error - * - * This function will check whether there are any pending control interface - * message available to be received with wpa_ctrl_recv(). wpa_ctrl_pending() is - * only used for event messages, i.e., wpa_ctrl_attach() must have been used to - * register the control interface as an event monitor. - */ -int wpa_ctrl_pending(struct wpa_ctrl *ctrl); - - -/** - * wpa_ctrl_get_fd - Get file descriptor used by the control interface - * @ctrl: Control interface data from wpa_ctrl_open() - * Returns: File descriptor used for the connection - * - * This function can be used to get the file descriptor that is used for the - * control interface connection. The returned value can be used, e.g., with - * select() while waiting for multiple events. - * - * The returned file descriptor must not be used directly for sending or - * receiving packets; instead, the library functions wpa_ctrl_request() and - * wpa_ctrl_recv() must be used for this. - */ -int wpa_ctrl_get_fd(struct wpa_ctrl *ctrl); - -#ifdef CONFIG_CTRL_IFACE_UDP -#define WPA_CTRL_IFACE_PORT 9877 -#define WPA_GLOBAL_CTRL_IFACE_PORT 9878 -#endif /* CONFIG_CTRL_IFACE_UDP */ - - -#ifdef __cplusplus -} -#endif - -#endif /* WPA_CTRL_H */ diff --git a/hostapd-0.8/src/crypto/.gitignore b/hostapd-0.8/src/crypto/.gitignore deleted file mode 100644 index ee60604..0000000 --- a/hostapd-0.8/src/crypto/.gitignore +++ /dev/null @@ -1 +0,0 @@ -libcrypto.a diff --git a/hostapd-0.8/src/crypto/Makefile b/hostapd-0.8/src/crypto/Makefile deleted file mode 100644 index 69aa16a..0000000 --- a/hostapd-0.8/src/crypto/Makefile +++ /dev/null @@ -1,56 +0,0 @@ -all: libcrypto.a - -clean: - rm -f *~ *.o *.d libcrypto.a - -install: - @echo Nothing to be made. - - -include ../lib.rules - -CFLAGS += -DCONFIG_TLS_INTERNAL_CLIENT -CFLAGS += -DCONFIG_TLS_INTERNAL_SERVER -#CFLAGS += -DALL_DH_GROUPS - -LIB_OBJS= \ - aes-cbc.o \ - aes-ctr.o \ - aes-eax.o \ - aes-encblock.o \ - aes-internal.o \ - aes-internal-dec.o \ - aes-internal-enc.o \ - aes-omac1.o \ - aes-unwrap.o \ - aes-wrap.o \ - des-internal.o \ - dh_group5.o \ - dh_groups.o \ - md4-internal.o \ - md5.o \ - md5-internal.o \ - md5-non-fips.o \ - milenage.o \ - ms_funcs.o \ - rc4.o \ - sha1.o \ - sha1-internal.o \ - sha1-pbkdf2.o \ - sha1-tlsprf.o \ - sha1-tprf.o \ - sha256.o \ - sha256-internal.o - -LIB_OBJS += crypto_internal.o -LIB_OBJS += crypto_internal-cipher.o -LIB_OBJS += crypto_internal-modexp.o -LIB_OBJS += crypto_internal-rsa.o -LIB_OBJS += tls_internal.o -LIB_OBJS += fips_prf_internal.o - - -libcrypto.a: $(LIB_OBJS) - $(AR) crT $@ $? - --include $(OBJS:%.o=%.d) diff --git a/hostapd-0.8/src/crypto/aes-cbc.c b/hostapd-0.8/src/crypto/aes-cbc.c deleted file mode 100644 index bd74769..0000000 --- a/hostapd-0.8/src/crypto/aes-cbc.c +++ /dev/null @@ -1,86 +0,0 @@ -/* - * AES-128 CBC - * - * Copyright (c) 2003-2007, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#include "includes.h" - -#include "common.h" -#include "aes.h" -#include "aes_wrap.h" - -/** - * aes_128_cbc_encrypt - AES-128 CBC encryption - * @key: Encryption key - * @iv: Encryption IV for CBC mode (16 bytes) - * @data: Data to encrypt in-place - * @data_len: Length of data in bytes (must be divisible by 16) - * Returns: 0 on success, -1 on failure - */ -int aes_128_cbc_encrypt(const u8 *key, const u8 *iv, u8 *data, size_t data_len) -{ - void *ctx; - u8 cbc[AES_BLOCK_SIZE]; - u8 *pos = data; - int i, j, blocks; - - ctx = aes_encrypt_init(key, 16); - if (ctx == NULL) - return -1; - os_memcpy(cbc, iv, AES_BLOCK_SIZE); - - blocks = data_len / AES_BLOCK_SIZE; - for (i = 0; i < blocks; i++) { - for (j = 0; j < AES_BLOCK_SIZE; j++) - cbc[j] ^= pos[j]; - aes_encrypt(ctx, cbc, cbc); - os_memcpy(pos, cbc, AES_BLOCK_SIZE); - pos += AES_BLOCK_SIZE; - } - aes_encrypt_deinit(ctx); - return 0; -} - - -/** - * aes_128_cbc_decrypt - AES-128 CBC decryption - * @key: Decryption key - * @iv: Decryption IV for CBC mode (16 bytes) - * @data: Data to decrypt in-place - * @data_len: Length of data in bytes (must be divisible by 16) - * Returns: 0 on success, -1 on failure - */ -int aes_128_cbc_decrypt(const u8 *key, const u8 *iv, u8 *data, size_t data_len) -{ - void *ctx; - u8 cbc[AES_BLOCK_SIZE], tmp[AES_BLOCK_SIZE]; - u8 *pos = data; - int i, j, blocks; - - ctx = aes_decrypt_init(key, 16); - if (ctx == NULL) - return -1; - os_memcpy(cbc, iv, AES_BLOCK_SIZE); - - blocks = data_len / AES_BLOCK_SIZE; - for (i = 0; i < blocks; i++) { - os_memcpy(tmp, pos, AES_BLOCK_SIZE); - aes_decrypt(ctx, pos, pos); - for (j = 0; j < AES_BLOCK_SIZE; j++) - pos[j] ^= cbc[j]; - os_memcpy(cbc, tmp, AES_BLOCK_SIZE); - pos += AES_BLOCK_SIZE; - } - aes_decrypt_deinit(ctx); - return 0; -} diff --git a/hostapd-0.8/src/crypto/aes-ctr.c b/hostapd-0.8/src/crypto/aes-ctr.c deleted file mode 100644 index 468f877..0000000 --- a/hostapd-0.8/src/crypto/aes-ctr.c +++ /dev/null @@ -1,61 +0,0 @@ -/* - * AES-128 CTR - * - * Copyright (c) 2003-2007, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#include "includes.h" - -#include "common.h" -#include "aes.h" -#include "aes_wrap.h" - -/** - * aes_128_ctr_encrypt - AES-128 CTR mode encryption - * @key: Key for encryption (16 bytes) - * @nonce: Nonce for counter mode (16 bytes) - * @data: Data to encrypt in-place - * @data_len: Length of data in bytes - * Returns: 0 on success, -1 on failure - */ -int aes_128_ctr_encrypt(const u8 *key, const u8 *nonce, - u8 *data, size_t data_len) -{ - void *ctx; - size_t j, len, left = data_len; - int i; - u8 *pos = data; - u8 counter[AES_BLOCK_SIZE], buf[AES_BLOCK_SIZE]; - - ctx = aes_encrypt_init(key, 16); - if (ctx == NULL) - return -1; - os_memcpy(counter, nonce, AES_BLOCK_SIZE); - - while (left > 0) { - aes_encrypt(ctx, counter, buf); - - len = (left < AES_BLOCK_SIZE) ? left : AES_BLOCK_SIZE; - for (j = 0; j < len; j++) - pos[j] ^= buf[j]; - pos += len; - left -= len; - - for (i = AES_BLOCK_SIZE - 1; i >= 0; i--) { - counter[i]++; - if (counter[i]) - break; - } - } - aes_encrypt_deinit(ctx); - return 0; -} diff --git a/hostapd-0.8/src/crypto/aes-eax.c b/hostapd-0.8/src/crypto/aes-eax.c deleted file mode 100644 index d5c3971..0000000 --- a/hostapd-0.8/src/crypto/aes-eax.c +++ /dev/null @@ -1,151 +0,0 @@ -/* - * AES-128 EAX - * - * Copyright (c) 2003-2007, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#include "includes.h" - -#include "common.h" -#include "aes.h" -#include "aes_wrap.h" - -/** - * aes_128_eax_encrypt - AES-128 EAX mode encryption - * @key: Key for encryption (16 bytes) - * @nonce: Nonce for counter mode - * @nonce_len: Nonce length in bytes - * @hdr: Header data to be authenticity protected - * @hdr_len: Length of the header data bytes - * @data: Data to encrypt in-place - * @data_len: Length of data in bytes - * @tag: 16-byte tag value - * Returns: 0 on success, -1 on failure - */ -int aes_128_eax_encrypt(const u8 *key, const u8 *nonce, size_t nonce_len, - const u8 *hdr, size_t hdr_len, - u8 *data, size_t data_len, u8 *tag) -{ - u8 *buf; - size_t buf_len; - u8 nonce_mac[AES_BLOCK_SIZE], hdr_mac[AES_BLOCK_SIZE], - data_mac[AES_BLOCK_SIZE]; - int i, ret = -1; - - if (nonce_len > data_len) - buf_len = nonce_len; - else - buf_len = data_len; - if (hdr_len > buf_len) - buf_len = hdr_len; - buf_len += 16; - - buf = os_malloc(buf_len); - if (buf == NULL) - return -1; - - os_memset(buf, 0, 15); - - buf[15] = 0; - os_memcpy(buf + 16, nonce, nonce_len); - if (omac1_aes_128(key, buf, 16 + nonce_len, nonce_mac)) - goto fail; - - buf[15] = 1; - os_memcpy(buf + 16, hdr, hdr_len); - if (omac1_aes_128(key, buf, 16 + hdr_len, hdr_mac)) - goto fail; - - if (aes_128_ctr_encrypt(key, nonce_mac, data, data_len)) - goto fail; - buf[15] = 2; - os_memcpy(buf + 16, data, data_len); - if (omac1_aes_128(key, buf, 16 + data_len, data_mac)) - goto fail; - - for (i = 0; i < AES_BLOCK_SIZE; i++) - tag[i] = nonce_mac[i] ^ data_mac[i] ^ hdr_mac[i]; - - ret = 0; -fail: - os_free(buf); - - return ret; -} - - -/** - * aes_128_eax_decrypt - AES-128 EAX mode decryption - * @key: Key for decryption (16 bytes) - * @nonce: Nonce for counter mode - * @nonce_len: Nonce length in bytes - * @hdr: Header data to be authenticity protected - * @hdr_len: Length of the header data bytes - * @data: Data to encrypt in-place - * @data_len: Length of data in bytes - * @tag: 16-byte tag value - * Returns: 0 on success, -1 on failure, -2 if tag does not match - */ -int aes_128_eax_decrypt(const u8 *key, const u8 *nonce, size_t nonce_len, - const u8 *hdr, size_t hdr_len, - u8 *data, size_t data_len, const u8 *tag) -{ - u8 *buf; - size_t buf_len; - u8 nonce_mac[AES_BLOCK_SIZE], hdr_mac[AES_BLOCK_SIZE], - data_mac[AES_BLOCK_SIZE]; - int i; - - if (nonce_len > data_len) - buf_len = nonce_len; - else - buf_len = data_len; - if (hdr_len > buf_len) - buf_len = hdr_len; - buf_len += 16; - - buf = os_malloc(buf_len); - if (buf == NULL) - return -1; - - os_memset(buf, 0, 15); - - buf[15] = 0; - os_memcpy(buf + 16, nonce, nonce_len); - if (omac1_aes_128(key, buf, 16 + nonce_len, nonce_mac)) { - os_free(buf); - return -1; - } - - buf[15] = 1; - os_memcpy(buf + 16, hdr, hdr_len); - if (omac1_aes_128(key, buf, 16 + hdr_len, hdr_mac)) { - os_free(buf); - return -1; - } - - buf[15] = 2; - os_memcpy(buf + 16, data, data_len); - if (omac1_aes_128(key, buf, 16 + data_len, data_mac)) { - os_free(buf); - return -1; - } - - os_free(buf); - - for (i = 0; i < AES_BLOCK_SIZE; i++) { - if (tag[i] != (nonce_mac[i] ^ data_mac[i] ^ hdr_mac[i])) - return -2; - } - - return aes_128_ctr_encrypt(key, nonce_mac, data, data_len); -} diff --git a/hostapd-0.8/src/crypto/aes-encblock.c b/hostapd-0.8/src/crypto/aes-encblock.c deleted file mode 100644 index 8f35caa..0000000 --- a/hostapd-0.8/src/crypto/aes-encblock.c +++ /dev/null @@ -1,38 +0,0 @@ -/* - * AES encrypt_block - * - * Copyright (c) 2003-2007, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#include "includes.h" - -#include "common.h" -#include "aes.h" -#include "aes_wrap.h" - -/** - * aes_128_encrypt_block - Perform one AES 128-bit block operation - * @key: Key for AES - * @in: Input data (16 bytes) - * @out: Output of the AES block operation (16 bytes) - * Returns: 0 on success, -1 on failure - */ -int aes_128_encrypt_block(const u8 *key, const u8 *in, u8 *out) -{ - void *ctx; - ctx = aes_encrypt_init(key, 16); - if (ctx == NULL) - return -1; - aes_encrypt(ctx, in, out); - aes_encrypt_deinit(ctx); - return 0; -} diff --git a/hostapd-0.8/src/crypto/aes-internal-dec.c b/hostapd-0.8/src/crypto/aes-internal-dec.c deleted file mode 100644 index 2d32c03..0000000 --- a/hostapd-0.8/src/crypto/aes-internal-dec.c +++ /dev/null @@ -1,151 +0,0 @@ -/* - * AES (Rijndael) cipher - decrypt - * - * Modifications to public domain implementation: - * - support only 128-bit keys - * - cleanup - * - use C pre-processor to make it easier to change S table access - * - added option (AES_SMALL_TABLES) for reducing code size by about 8 kB at - * cost of reduced throughput (quite small difference on Pentium 4, - * 10-25% when using -O1 or -O2 optimization) - * - * Copyright (c) 2003-2005, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#include "includes.h" - -#include "common.h" -#include "crypto.h" -#include "aes_i.h" - -/** - * Expand the cipher key into the decryption key schedule. - * - * @return the number of rounds for the given cipher key size. - */ -void rijndaelKeySetupDec(u32 rk[/*44*/], const u8 cipherKey[]) -{ - int Nr = 10, i, j; - u32 temp; - - /* expand the cipher key: */ - rijndaelKeySetupEnc(rk, cipherKey); - /* invert the order of the round keys: */ - for (i = 0, j = 4*Nr; i < j; i += 4, j -= 4) { - temp = rk[i ]; rk[i ] = rk[j ]; rk[j ] = temp; - temp = rk[i + 1]; rk[i + 1] = rk[j + 1]; rk[j + 1] = temp; - temp = rk[i + 2]; rk[i + 2] = rk[j + 2]; rk[j + 2] = temp; - temp = rk[i + 3]; rk[i + 3] = rk[j + 3]; rk[j + 3] = temp; - } - /* apply the inverse MixColumn transform to all round keys but the - * first and the last: */ - for (i = 1; i < Nr; i++) { - rk += 4; - for (j = 0; j < 4; j++) { - rk[j] = TD0_(TE4((rk[j] >> 24) )) ^ - TD1_(TE4((rk[j] >> 16) & 0xff)) ^ - TD2_(TE4((rk[j] >> 8) & 0xff)) ^ - TD3_(TE4((rk[j] ) & 0xff)); - } - } -} - -void * aes_decrypt_init(const u8 *key, size_t len) -{ - u32 *rk; - if (len != 16) - return NULL; - rk = os_malloc(AES_PRIV_SIZE); - if (rk == NULL) - return NULL; - rijndaelKeySetupDec(rk, key); - return rk; -} - -static void rijndaelDecrypt(const u32 rk[/*44*/], const u8 ct[16], u8 pt[16]) -{ - u32 s0, s1, s2, s3, t0, t1, t2, t3; - const int Nr = 10; -#ifndef FULL_UNROLL - int r; -#endif /* ?FULL_UNROLL */ - - /* - * map byte array block to cipher state - * and add initial round key: - */ - s0 = GETU32(ct ) ^ rk[0]; - s1 = GETU32(ct + 4) ^ rk[1]; - s2 = GETU32(ct + 8) ^ rk[2]; - s3 = GETU32(ct + 12) ^ rk[3]; - -#define ROUND(i,d,s) \ -d##0 = TD0(s##0) ^ TD1(s##3) ^ TD2(s##2) ^ TD3(s##1) ^ rk[4 * i]; \ -d##1 = TD0(s##1) ^ TD1(s##0) ^ TD2(s##3) ^ TD3(s##2) ^ rk[4 * i + 1]; \ -d##2 = TD0(s##2) ^ TD1(s##1) ^ TD2(s##0) ^ TD3(s##3) ^ rk[4 * i + 2]; \ -d##3 = TD0(s##3) ^ TD1(s##2) ^ TD2(s##1) ^ TD3(s##0) ^ rk[4 * i + 3] - -#ifdef FULL_UNROLL - - ROUND(1,t,s); - ROUND(2,s,t); - ROUND(3,t,s); - ROUND(4,s,t); - ROUND(5,t,s); - ROUND(6,s,t); - ROUND(7,t,s); - ROUND(8,s,t); - ROUND(9,t,s); - - rk += Nr << 2; - -#else /* !FULL_UNROLL */ - - /* Nr - 1 full rounds: */ - r = Nr >> 1; - for (;;) { - ROUND(1,t,s); - rk += 8; - if (--r == 0) - break; - ROUND(0,s,t); - } - -#endif /* ?FULL_UNROLL */ - -#undef ROUND - - /* - * apply last round and - * map cipher state to byte array block: - */ - s0 = TD41(t0) ^ TD42(t3) ^ TD43(t2) ^ TD44(t1) ^ rk[0]; - PUTU32(pt , s0); - s1 = TD41(t1) ^ TD42(t0) ^ TD43(t3) ^ TD44(t2) ^ rk[1]; - PUTU32(pt + 4, s1); - s2 = TD41(t2) ^ TD42(t1) ^ TD43(t0) ^ TD44(t3) ^ rk[2]; - PUTU32(pt + 8, s2); - s3 = TD41(t3) ^ TD42(t2) ^ TD43(t1) ^ TD44(t0) ^ rk[3]; - PUTU32(pt + 12, s3); -} - -void aes_decrypt(void *ctx, const u8 *crypt, u8 *plain) -{ - rijndaelDecrypt(ctx, crypt, plain); -} - - -void aes_decrypt_deinit(void *ctx) -{ - os_memset(ctx, 0, AES_PRIV_SIZE); - os_free(ctx); -} diff --git a/hostapd-0.8/src/crypto/aes-internal-enc.c b/hostapd-0.8/src/crypto/aes-internal-enc.c deleted file mode 100644 index 2f19826..0000000 --- a/hostapd-0.8/src/crypto/aes-internal-enc.c +++ /dev/null @@ -1,121 +0,0 @@ -/* - * AES (Rijndael) cipher - encrypt - * - * Modifications to public domain implementation: - * - support only 128-bit keys - * - cleanup - * - use C pre-processor to make it easier to change S table access - * - added option (AES_SMALL_TABLES) for reducing code size by about 8 kB at - * cost of reduced throughput (quite small difference on Pentium 4, - * 10-25% when using -O1 or -O2 optimization) - * - * Copyright (c) 2003-2005, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#include "includes.h" - -#include "common.h" -#include "crypto.h" -#include "aes_i.h" - -void rijndaelEncrypt(const u32 rk[/*44*/], const u8 pt[16], u8 ct[16]) -{ - u32 s0, s1, s2, s3, t0, t1, t2, t3; - const int Nr = 10; -#ifndef FULL_UNROLL - int r; -#endif /* ?FULL_UNROLL */ - - /* - * map byte array block to cipher state - * and add initial round key: - */ - s0 = GETU32(pt ) ^ rk[0]; - s1 = GETU32(pt + 4) ^ rk[1]; - s2 = GETU32(pt + 8) ^ rk[2]; - s3 = GETU32(pt + 12) ^ rk[3]; - -#define ROUND(i,d,s) \ -d##0 = TE0(s##0) ^ TE1(s##1) ^ TE2(s##2) ^ TE3(s##3) ^ rk[4 * i]; \ -d##1 = TE0(s##1) ^ TE1(s##2) ^ TE2(s##3) ^ TE3(s##0) ^ rk[4 * i + 1]; \ -d##2 = TE0(s##2) ^ TE1(s##3) ^ TE2(s##0) ^ TE3(s##1) ^ rk[4 * i + 2]; \ -d##3 = TE0(s##3) ^ TE1(s##0) ^ TE2(s##1) ^ TE3(s##2) ^ rk[4 * i + 3] - -#ifdef FULL_UNROLL - - ROUND(1,t,s); - ROUND(2,s,t); - ROUND(3,t,s); - ROUND(4,s,t); - ROUND(5,t,s); - ROUND(6,s,t); - ROUND(7,t,s); - ROUND(8,s,t); - ROUND(9,t,s); - - rk += Nr << 2; - -#else /* !FULL_UNROLL */ - - /* Nr - 1 full rounds: */ - r = Nr >> 1; - for (;;) { - ROUND(1,t,s); - rk += 8; - if (--r == 0) - break; - ROUND(0,s,t); - } - -#endif /* ?FULL_UNROLL */ - -#undef ROUND - - /* - * apply last round and - * map cipher state to byte array block: - */ - s0 = TE41(t0) ^ TE42(t1) ^ TE43(t2) ^ TE44(t3) ^ rk[0]; - PUTU32(ct , s0); - s1 = TE41(t1) ^ TE42(t2) ^ TE43(t3) ^ TE44(t0) ^ rk[1]; - PUTU32(ct + 4, s1); - s2 = TE41(t2) ^ TE42(t3) ^ TE43(t0) ^ TE44(t1) ^ rk[2]; - PUTU32(ct + 8, s2); - s3 = TE41(t3) ^ TE42(t0) ^ TE43(t1) ^ TE44(t2) ^ rk[3]; - PUTU32(ct + 12, s3); -} - - -void * aes_encrypt_init(const u8 *key, size_t len) -{ - u32 *rk; - if (len != 16) - return NULL; - rk = os_malloc(AES_PRIV_SIZE); - if (rk == NULL) - return NULL; - rijndaelKeySetupEnc(rk, key); - return rk; -} - - -void aes_encrypt(void *ctx, const u8 *plain, u8 *crypt) -{ - rijndaelEncrypt(ctx, plain, crypt); -} - - -void aes_encrypt_deinit(void *ctx) -{ - os_memset(ctx, 0, AES_PRIV_SIZE); - os_free(ctx); -} diff --git a/hostapd-0.8/src/crypto/aes-internal.c b/hostapd-0.8/src/crypto/aes-internal.c deleted file mode 100644 index 4161220..0000000 --- a/hostapd-0.8/src/crypto/aes-internal.c +++ /dev/null @@ -1,805 +0,0 @@ -/* - * AES (Rijndael) cipher - * - * Modifications to public domain implementation: - * - support only 128-bit keys - * - cleanup - * - use C pre-processor to make it easier to change S table access - * - added option (AES_SMALL_TABLES) for reducing code size by about 8 kB at - * cost of reduced throughput (quite small difference on Pentium 4, - * 10-25% when using -O1 or -O2 optimization) - * - * Copyright (c) 2003-2005, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#include "includes.h" - -#include "common.h" -#include "crypto.h" -#include "aes_i.h" - -/* - * rijndael-alg-fst.c - * - * @version 3.0 (December 2000) - * - * Optimised ANSI C code for the Rijndael cipher (now AES) - * - * @author Vincent Rijmen - * @author Antoon Bosselaers - * @author Paulo Barreto - * - * This code is hereby placed in the public domain. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ''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 AUTHORS 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. - */ - - -/* -Te0[x] = S [x].[02, 01, 01, 03]; -Te1[x] = S [x].[03, 02, 01, 01]; -Te2[x] = S [x].[01, 03, 02, 01]; -Te3[x] = S [x].[01, 01, 03, 02]; -Te4[x] = S [x].[01, 01, 01, 01]; - -Td0[x] = Si[x].[0e, 09, 0d, 0b]; -Td1[x] = Si[x].[0b, 0e, 09, 0d]; -Td2[x] = Si[x].[0d, 0b, 0e, 09]; -Td3[x] = Si[x].[09, 0d, 0b, 0e]; -Td4[x] = Si[x].[01, 01, 01, 01]; -*/ - -const u32 Te0[256] = { - 0xc66363a5U, 0xf87c7c84U, 0xee777799U, 0xf67b7b8dU, - 0xfff2f20dU, 0xd66b6bbdU, 0xde6f6fb1U, 0x91c5c554U, - 0x60303050U, 0x02010103U, 0xce6767a9U, 0x562b2b7dU, - 0xe7fefe19U, 0xb5d7d762U, 0x4dababe6U, 0xec76769aU, - 0x8fcaca45U, 0x1f82829dU, 0x89c9c940U, 0xfa7d7d87U, - 0xeffafa15U, 0xb25959ebU, 0x8e4747c9U, 0xfbf0f00bU, - 0x41adadecU, 0xb3d4d467U, 0x5fa2a2fdU, 0x45afafeaU, - 0x239c9cbfU, 0x53a4a4f7U, 0xe4727296U, 0x9bc0c05bU, - 0x75b7b7c2U, 0xe1fdfd1cU, 0x3d9393aeU, 0x4c26266aU, - 0x6c36365aU, 0x7e3f3f41U, 0xf5f7f702U, 0x83cccc4fU, - 0x6834345cU, 0x51a5a5f4U, 0xd1e5e534U, 0xf9f1f108U, - 0xe2717193U, 0xabd8d873U, 0x62313153U, 0x2a15153fU, - 0x0804040cU, 0x95c7c752U, 0x46232365U, 0x9dc3c35eU, - 0x30181828U, 0x379696a1U, 0x0a05050fU, 0x2f9a9ab5U, - 0x0e070709U, 0x24121236U, 0x1b80809bU, 0xdfe2e23dU, - 0xcdebeb26U, 0x4e272769U, 0x7fb2b2cdU, 0xea75759fU, - 0x1209091bU, 0x1d83839eU, 0x582c2c74U, 0x341a1a2eU, - 0x361b1b2dU, 0xdc6e6eb2U, 0xb45a5aeeU, 0x5ba0a0fbU, - 0xa45252f6U, 0x763b3b4dU, 0xb7d6d661U, 0x7db3b3ceU, - 0x5229297bU, 0xdde3e33eU, 0x5e2f2f71U, 0x13848497U, - 0xa65353f5U, 0xb9d1d168U, 0x00000000U, 0xc1eded2cU, - 0x40202060U, 0xe3fcfc1fU, 0x79b1b1c8U, 0xb65b5bedU, - 0xd46a6abeU, 0x8dcbcb46U, 0x67bebed9U, 0x7239394bU, - 0x944a4adeU, 0x984c4cd4U, 0xb05858e8U, 0x85cfcf4aU, - 0xbbd0d06bU, 0xc5efef2aU, 0x4faaaae5U, 0xedfbfb16U, - 0x864343c5U, 0x9a4d4dd7U, 0x66333355U, 0x11858594U, - 0x8a4545cfU, 0xe9f9f910U, 0x04020206U, 0xfe7f7f81U, - 0xa05050f0U, 0x783c3c44U, 0x259f9fbaU, 0x4ba8a8e3U, - 0xa25151f3U, 0x5da3a3feU, 0x804040c0U, 0x058f8f8aU, - 0x3f9292adU, 0x219d9dbcU, 0x70383848U, 0xf1f5f504U, - 0x63bcbcdfU, 0x77b6b6c1U, 0xafdada75U, 0x42212163U, - 0x20101030U, 0xe5ffff1aU, 0xfdf3f30eU, 0xbfd2d26dU, - 0x81cdcd4cU, 0x180c0c14U, 0x26131335U, 0xc3ecec2fU, - 0xbe5f5fe1U, 0x359797a2U, 0x884444ccU, 0x2e171739U, - 0x93c4c457U, 0x55a7a7f2U, 0xfc7e7e82U, 0x7a3d3d47U, - 0xc86464acU, 0xba5d5de7U, 0x3219192bU, 0xe6737395U, - 0xc06060a0U, 0x19818198U, 0x9e4f4fd1U, 0xa3dcdc7fU, - 0x44222266U, 0x542a2a7eU, 0x3b9090abU, 0x0b888883U, - 0x8c4646caU, 0xc7eeee29U, 0x6bb8b8d3U, 0x2814143cU, - 0xa7dede79U, 0xbc5e5ee2U, 0x160b0b1dU, 0xaddbdb76U, - 0xdbe0e03bU, 0x64323256U, 0x743a3a4eU, 0x140a0a1eU, - 0x924949dbU, 0x0c06060aU, 0x4824246cU, 0xb85c5ce4U, - 0x9fc2c25dU, 0xbdd3d36eU, 0x43acacefU, 0xc46262a6U, - 0x399191a8U, 0x319595a4U, 0xd3e4e437U, 0xf279798bU, - 0xd5e7e732U, 0x8bc8c843U, 0x6e373759U, 0xda6d6db7U, - 0x018d8d8cU, 0xb1d5d564U, 0x9c4e4ed2U, 0x49a9a9e0U, - 0xd86c6cb4U, 0xac5656faU, 0xf3f4f407U, 0xcfeaea25U, - 0xca6565afU, 0xf47a7a8eU, 0x47aeaee9U, 0x10080818U, - 0x6fbabad5U, 0xf0787888U, 0x4a25256fU, 0x5c2e2e72U, - 0x381c1c24U, 0x57a6a6f1U, 0x73b4b4c7U, 0x97c6c651U, - 0xcbe8e823U, 0xa1dddd7cU, 0xe874749cU, 0x3e1f1f21U, - 0x964b4bddU, 0x61bdbddcU, 0x0d8b8b86U, 0x0f8a8a85U, - 0xe0707090U, 0x7c3e3e42U, 0x71b5b5c4U, 0xcc6666aaU, - 0x904848d8U, 0x06030305U, 0xf7f6f601U, 0x1c0e0e12U, - 0xc26161a3U, 0x6a35355fU, 0xae5757f9U, 0x69b9b9d0U, - 0x17868691U, 0x99c1c158U, 0x3a1d1d27U, 0x279e9eb9U, - 0xd9e1e138U, 0xebf8f813U, 0x2b9898b3U, 0x22111133U, - 0xd26969bbU, 0xa9d9d970U, 0x078e8e89U, 0x339494a7U, - 0x2d9b9bb6U, 0x3c1e1e22U, 0x15878792U, 0xc9e9e920U, - 0x87cece49U, 0xaa5555ffU, 0x50282878U, 0xa5dfdf7aU, - 0x038c8c8fU, 0x59a1a1f8U, 0x09898980U, 0x1a0d0d17U, - 0x65bfbfdaU, 0xd7e6e631U, 0x844242c6U, 0xd06868b8U, - 0x824141c3U, 0x299999b0U, 0x5a2d2d77U, 0x1e0f0f11U, - 0x7bb0b0cbU, 0xa85454fcU, 0x6dbbbbd6U, 0x2c16163aU, -}; -#ifndef AES_SMALL_TABLES -const u32 Te1[256] = { - 0xa5c66363U, 0x84f87c7cU, 0x99ee7777U, 0x8df67b7bU, - 0x0dfff2f2U, 0xbdd66b6bU, 0xb1de6f6fU, 0x5491c5c5U, - 0x50603030U, 0x03020101U, 0xa9ce6767U, 0x7d562b2bU, - 0x19e7fefeU, 0x62b5d7d7U, 0xe64dababU, 0x9aec7676U, - 0x458fcacaU, 0x9d1f8282U, 0x4089c9c9U, 0x87fa7d7dU, - 0x15effafaU, 0xebb25959U, 0xc98e4747U, 0x0bfbf0f0U, - 0xec41adadU, 0x67b3d4d4U, 0xfd5fa2a2U, 0xea45afafU, - 0xbf239c9cU, 0xf753a4a4U, 0x96e47272U, 0x5b9bc0c0U, - 0xc275b7b7U, 0x1ce1fdfdU, 0xae3d9393U, 0x6a4c2626U, - 0x5a6c3636U, 0x417e3f3fU, 0x02f5f7f7U, 0x4f83ccccU, - 0x5c683434U, 0xf451a5a5U, 0x34d1e5e5U, 0x08f9f1f1U, - 0x93e27171U, 0x73abd8d8U, 0x53623131U, 0x3f2a1515U, - 0x0c080404U, 0x5295c7c7U, 0x65462323U, 0x5e9dc3c3U, - 0x28301818U, 0xa1379696U, 0x0f0a0505U, 0xb52f9a9aU, - 0x090e0707U, 0x36241212U, 0x9b1b8080U, 0x3ddfe2e2U, - 0x26cdebebU, 0x694e2727U, 0xcd7fb2b2U, 0x9fea7575U, - 0x1b120909U, 0x9e1d8383U, 0x74582c2cU, 0x2e341a1aU, - 0x2d361b1bU, 0xb2dc6e6eU, 0xeeb45a5aU, 0xfb5ba0a0U, - 0xf6a45252U, 0x4d763b3bU, 0x61b7d6d6U, 0xce7db3b3U, - 0x7b522929U, 0x3edde3e3U, 0x715e2f2fU, 0x97138484U, - 0xf5a65353U, 0x68b9d1d1U, 0x00000000U, 0x2cc1ededU, - 0x60402020U, 0x1fe3fcfcU, 0xc879b1b1U, 0xedb65b5bU, - 0xbed46a6aU, 0x468dcbcbU, 0xd967bebeU, 0x4b723939U, - 0xde944a4aU, 0xd4984c4cU, 0xe8b05858U, 0x4a85cfcfU, - 0x6bbbd0d0U, 0x2ac5efefU, 0xe54faaaaU, 0x16edfbfbU, - 0xc5864343U, 0xd79a4d4dU, 0x55663333U, 0x94118585U, - 0xcf8a4545U, 0x10e9f9f9U, 0x06040202U, 0x81fe7f7fU, - 0xf0a05050U, 0x44783c3cU, 0xba259f9fU, 0xe34ba8a8U, - 0xf3a25151U, 0xfe5da3a3U, 0xc0804040U, 0x8a058f8fU, - 0xad3f9292U, 0xbc219d9dU, 0x48703838U, 0x04f1f5f5U, - 0xdf63bcbcU, 0xc177b6b6U, 0x75afdadaU, 0x63422121U, - 0x30201010U, 0x1ae5ffffU, 0x0efdf3f3U, 0x6dbfd2d2U, - 0x4c81cdcdU, 0x14180c0cU, 0x35261313U, 0x2fc3ececU, - 0xe1be5f5fU, 0xa2359797U, 0xcc884444U, 0x392e1717U, - 0x5793c4c4U, 0xf255a7a7U, 0x82fc7e7eU, 0x477a3d3dU, - 0xacc86464U, 0xe7ba5d5dU, 0x2b321919U, 0x95e67373U, - 0xa0c06060U, 0x98198181U, 0xd19e4f4fU, 0x7fa3dcdcU, - 0x66442222U, 0x7e542a2aU, 0xab3b9090U, 0x830b8888U, - 0xca8c4646U, 0x29c7eeeeU, 0xd36bb8b8U, 0x3c281414U, - 0x79a7dedeU, 0xe2bc5e5eU, 0x1d160b0bU, 0x76addbdbU, - 0x3bdbe0e0U, 0x56643232U, 0x4e743a3aU, 0x1e140a0aU, - 0xdb924949U, 0x0a0c0606U, 0x6c482424U, 0xe4b85c5cU, - 0x5d9fc2c2U, 0x6ebdd3d3U, 0xef43acacU, 0xa6c46262U, - 0xa8399191U, 0xa4319595U, 0x37d3e4e4U, 0x8bf27979U, - 0x32d5e7e7U, 0x438bc8c8U, 0x596e3737U, 0xb7da6d6dU, - 0x8c018d8dU, 0x64b1d5d5U, 0xd29c4e4eU, 0xe049a9a9U, - 0xb4d86c6cU, 0xfaac5656U, 0x07f3f4f4U, 0x25cfeaeaU, - 0xafca6565U, 0x8ef47a7aU, 0xe947aeaeU, 0x18100808U, - 0xd56fbabaU, 0x88f07878U, 0x6f4a2525U, 0x725c2e2eU, - 0x24381c1cU, 0xf157a6a6U, 0xc773b4b4U, 0x5197c6c6U, - 0x23cbe8e8U, 0x7ca1ddddU, 0x9ce87474U, 0x213e1f1fU, - 0xdd964b4bU, 0xdc61bdbdU, 0x860d8b8bU, 0x850f8a8aU, - 0x90e07070U, 0x427c3e3eU, 0xc471b5b5U, 0xaacc6666U, - 0xd8904848U, 0x05060303U, 0x01f7f6f6U, 0x121c0e0eU, - 0xa3c26161U, 0x5f6a3535U, 0xf9ae5757U, 0xd069b9b9U, - 0x91178686U, 0x5899c1c1U, 0x273a1d1dU, 0xb9279e9eU, - 0x38d9e1e1U, 0x13ebf8f8U, 0xb32b9898U, 0x33221111U, - 0xbbd26969U, 0x70a9d9d9U, 0x89078e8eU, 0xa7339494U, - 0xb62d9b9bU, 0x223c1e1eU, 0x92158787U, 0x20c9e9e9U, - 0x4987ceceU, 0xffaa5555U, 0x78502828U, 0x7aa5dfdfU, - 0x8f038c8cU, 0xf859a1a1U, 0x80098989U, 0x171a0d0dU, - 0xda65bfbfU, 0x31d7e6e6U, 0xc6844242U, 0xb8d06868U, - 0xc3824141U, 0xb0299999U, 0x775a2d2dU, 0x111e0f0fU, - 0xcb7bb0b0U, 0xfca85454U, 0xd66dbbbbU, 0x3a2c1616U, -}; -const u32 Te2[256] = { - 0x63a5c663U, 0x7c84f87cU, 0x7799ee77U, 0x7b8df67bU, - 0xf20dfff2U, 0x6bbdd66bU, 0x6fb1de6fU, 0xc55491c5U, - 0x30506030U, 0x01030201U, 0x67a9ce67U, 0x2b7d562bU, - 0xfe19e7feU, 0xd762b5d7U, 0xabe64dabU, 0x769aec76U, - 0xca458fcaU, 0x829d1f82U, 0xc94089c9U, 0x7d87fa7dU, - 0xfa15effaU, 0x59ebb259U, 0x47c98e47U, 0xf00bfbf0U, - 0xadec41adU, 0xd467b3d4U, 0xa2fd5fa2U, 0xafea45afU, - 0x9cbf239cU, 0xa4f753a4U, 0x7296e472U, 0xc05b9bc0U, - 0xb7c275b7U, 0xfd1ce1fdU, 0x93ae3d93U, 0x266a4c26U, - 0x365a6c36U, 0x3f417e3fU, 0xf702f5f7U, 0xcc4f83ccU, - 0x345c6834U, 0xa5f451a5U, 0xe534d1e5U, 0xf108f9f1U, - 0x7193e271U, 0xd873abd8U, 0x31536231U, 0x153f2a15U, - 0x040c0804U, 0xc75295c7U, 0x23654623U, 0xc35e9dc3U, - 0x18283018U, 0x96a13796U, 0x050f0a05U, 0x9ab52f9aU, - 0x07090e07U, 0x12362412U, 0x809b1b80U, 0xe23ddfe2U, - 0xeb26cdebU, 0x27694e27U, 0xb2cd7fb2U, 0x759fea75U, - 0x091b1209U, 0x839e1d83U, 0x2c74582cU, 0x1a2e341aU, - 0x1b2d361bU, 0x6eb2dc6eU, 0x5aeeb45aU, 0xa0fb5ba0U, - 0x52f6a452U, 0x3b4d763bU, 0xd661b7d6U, 0xb3ce7db3U, - 0x297b5229U, 0xe33edde3U, 0x2f715e2fU, 0x84971384U, - 0x53f5a653U, 0xd168b9d1U, 0x00000000U, 0xed2cc1edU, - 0x20604020U, 0xfc1fe3fcU, 0xb1c879b1U, 0x5bedb65bU, - 0x6abed46aU, 0xcb468dcbU, 0xbed967beU, 0x394b7239U, - 0x4ade944aU, 0x4cd4984cU, 0x58e8b058U, 0xcf4a85cfU, - 0xd06bbbd0U, 0xef2ac5efU, 0xaae54faaU, 0xfb16edfbU, - 0x43c58643U, 0x4dd79a4dU, 0x33556633U, 0x85941185U, - 0x45cf8a45U, 0xf910e9f9U, 0x02060402U, 0x7f81fe7fU, - 0x50f0a050U, 0x3c44783cU, 0x9fba259fU, 0xa8e34ba8U, - 0x51f3a251U, 0xa3fe5da3U, 0x40c08040U, 0x8f8a058fU, - 0x92ad3f92U, 0x9dbc219dU, 0x38487038U, 0xf504f1f5U, - 0xbcdf63bcU, 0xb6c177b6U, 0xda75afdaU, 0x21634221U, - 0x10302010U, 0xff1ae5ffU, 0xf30efdf3U, 0xd26dbfd2U, - 0xcd4c81cdU, 0x0c14180cU, 0x13352613U, 0xec2fc3ecU, - 0x5fe1be5fU, 0x97a23597U, 0x44cc8844U, 0x17392e17U, - 0xc45793c4U, 0xa7f255a7U, 0x7e82fc7eU, 0x3d477a3dU, - 0x64acc864U, 0x5de7ba5dU, 0x192b3219U, 0x7395e673U, - 0x60a0c060U, 0x81981981U, 0x4fd19e4fU, 0xdc7fa3dcU, - 0x22664422U, 0x2a7e542aU, 0x90ab3b90U, 0x88830b88U, - 0x46ca8c46U, 0xee29c7eeU, 0xb8d36bb8U, 0x143c2814U, - 0xde79a7deU, 0x5ee2bc5eU, 0x0b1d160bU, 0xdb76addbU, - 0xe03bdbe0U, 0x32566432U, 0x3a4e743aU, 0x0a1e140aU, - 0x49db9249U, 0x060a0c06U, 0x246c4824U, 0x5ce4b85cU, - 0xc25d9fc2U, 0xd36ebdd3U, 0xacef43acU, 0x62a6c462U, - 0x91a83991U, 0x95a43195U, 0xe437d3e4U, 0x798bf279U, - 0xe732d5e7U, 0xc8438bc8U, 0x37596e37U, 0x6db7da6dU, - 0x8d8c018dU, 0xd564b1d5U, 0x4ed29c4eU, 0xa9e049a9U, - 0x6cb4d86cU, 0x56faac56U, 0xf407f3f4U, 0xea25cfeaU, - 0x65afca65U, 0x7a8ef47aU, 0xaee947aeU, 0x08181008U, - 0xbad56fbaU, 0x7888f078U, 0x256f4a25U, 0x2e725c2eU, - 0x1c24381cU, 0xa6f157a6U, 0xb4c773b4U, 0xc65197c6U, - 0xe823cbe8U, 0xdd7ca1ddU, 0x749ce874U, 0x1f213e1fU, - 0x4bdd964bU, 0xbddc61bdU, 0x8b860d8bU, 0x8a850f8aU, - 0x7090e070U, 0x3e427c3eU, 0xb5c471b5U, 0x66aacc66U, - 0x48d89048U, 0x03050603U, 0xf601f7f6U, 0x0e121c0eU, - 0x61a3c261U, 0x355f6a35U, 0x57f9ae57U, 0xb9d069b9U, - 0x86911786U, 0xc15899c1U, 0x1d273a1dU, 0x9eb9279eU, - 0xe138d9e1U, 0xf813ebf8U, 0x98b32b98U, 0x11332211U, - 0x69bbd269U, 0xd970a9d9U, 0x8e89078eU, 0x94a73394U, - 0x9bb62d9bU, 0x1e223c1eU, 0x87921587U, 0xe920c9e9U, - 0xce4987ceU, 0x55ffaa55U, 0x28785028U, 0xdf7aa5dfU, - 0x8c8f038cU, 0xa1f859a1U, 0x89800989U, 0x0d171a0dU, - 0xbfda65bfU, 0xe631d7e6U, 0x42c68442U, 0x68b8d068U, - 0x41c38241U, 0x99b02999U, 0x2d775a2dU, 0x0f111e0fU, - 0xb0cb7bb0U, 0x54fca854U, 0xbbd66dbbU, 0x163a2c16U, -}; -const u32 Te3[256] = { - - 0x6363a5c6U, 0x7c7c84f8U, 0x777799eeU, 0x7b7b8df6U, - 0xf2f20dffU, 0x6b6bbdd6U, 0x6f6fb1deU, 0xc5c55491U, - 0x30305060U, 0x01010302U, 0x6767a9ceU, 0x2b2b7d56U, - 0xfefe19e7U, 0xd7d762b5U, 0xababe64dU, 0x76769aecU, - 0xcaca458fU, 0x82829d1fU, 0xc9c94089U, 0x7d7d87faU, - 0xfafa15efU, 0x5959ebb2U, 0x4747c98eU, 0xf0f00bfbU, - 0xadadec41U, 0xd4d467b3U, 0xa2a2fd5fU, 0xafafea45U, - 0x9c9cbf23U, 0xa4a4f753U, 0x727296e4U, 0xc0c05b9bU, - 0xb7b7c275U, 0xfdfd1ce1U, 0x9393ae3dU, 0x26266a4cU, - 0x36365a6cU, 0x3f3f417eU, 0xf7f702f5U, 0xcccc4f83U, - 0x34345c68U, 0xa5a5f451U, 0xe5e534d1U, 0xf1f108f9U, - 0x717193e2U, 0xd8d873abU, 0x31315362U, 0x15153f2aU, - 0x04040c08U, 0xc7c75295U, 0x23236546U, 0xc3c35e9dU, - 0x18182830U, 0x9696a137U, 0x05050f0aU, 0x9a9ab52fU, - 0x0707090eU, 0x12123624U, 0x80809b1bU, 0xe2e23ddfU, - 0xebeb26cdU, 0x2727694eU, 0xb2b2cd7fU, 0x75759feaU, - 0x09091b12U, 0x83839e1dU, 0x2c2c7458U, 0x1a1a2e34U, - 0x1b1b2d36U, 0x6e6eb2dcU, 0x5a5aeeb4U, 0xa0a0fb5bU, - 0x5252f6a4U, 0x3b3b4d76U, 0xd6d661b7U, 0xb3b3ce7dU, - 0x29297b52U, 0xe3e33eddU, 0x2f2f715eU, 0x84849713U, - 0x5353f5a6U, 0xd1d168b9U, 0x00000000U, 0xeded2cc1U, - 0x20206040U, 0xfcfc1fe3U, 0xb1b1c879U, 0x5b5bedb6U, - 0x6a6abed4U, 0xcbcb468dU, 0xbebed967U, 0x39394b72U, - 0x4a4ade94U, 0x4c4cd498U, 0x5858e8b0U, 0xcfcf4a85U, - 0xd0d06bbbU, 0xefef2ac5U, 0xaaaae54fU, 0xfbfb16edU, - 0x4343c586U, 0x4d4dd79aU, 0x33335566U, 0x85859411U, - 0x4545cf8aU, 0xf9f910e9U, 0x02020604U, 0x7f7f81feU, - 0x5050f0a0U, 0x3c3c4478U, 0x9f9fba25U, 0xa8a8e34bU, - 0x5151f3a2U, 0xa3a3fe5dU, 0x4040c080U, 0x8f8f8a05U, - 0x9292ad3fU, 0x9d9dbc21U, 0x38384870U, 0xf5f504f1U, - 0xbcbcdf63U, 0xb6b6c177U, 0xdada75afU, 0x21216342U, - 0x10103020U, 0xffff1ae5U, 0xf3f30efdU, 0xd2d26dbfU, - 0xcdcd4c81U, 0x0c0c1418U, 0x13133526U, 0xecec2fc3U, - 0x5f5fe1beU, 0x9797a235U, 0x4444cc88U, 0x1717392eU, - 0xc4c45793U, 0xa7a7f255U, 0x7e7e82fcU, 0x3d3d477aU, - 0x6464acc8U, 0x5d5de7baU, 0x19192b32U, 0x737395e6U, - 0x6060a0c0U, 0x81819819U, 0x4f4fd19eU, 0xdcdc7fa3U, - 0x22226644U, 0x2a2a7e54U, 0x9090ab3bU, 0x8888830bU, - 0x4646ca8cU, 0xeeee29c7U, 0xb8b8d36bU, 0x14143c28U, - 0xdede79a7U, 0x5e5ee2bcU, 0x0b0b1d16U, 0xdbdb76adU, - 0xe0e03bdbU, 0x32325664U, 0x3a3a4e74U, 0x0a0a1e14U, - 0x4949db92U, 0x06060a0cU, 0x24246c48U, 0x5c5ce4b8U, - 0xc2c25d9fU, 0xd3d36ebdU, 0xacacef43U, 0x6262a6c4U, - 0x9191a839U, 0x9595a431U, 0xe4e437d3U, 0x79798bf2U, - 0xe7e732d5U, 0xc8c8438bU, 0x3737596eU, 0x6d6db7daU, - 0x8d8d8c01U, 0xd5d564b1U, 0x4e4ed29cU, 0xa9a9e049U, - 0x6c6cb4d8U, 0x5656faacU, 0xf4f407f3U, 0xeaea25cfU, - 0x6565afcaU, 0x7a7a8ef4U, 0xaeaee947U, 0x08081810U, - 0xbabad56fU, 0x787888f0U, 0x25256f4aU, 0x2e2e725cU, - 0x1c1c2438U, 0xa6a6f157U, 0xb4b4c773U, 0xc6c65197U, - 0xe8e823cbU, 0xdddd7ca1U, 0x74749ce8U, 0x1f1f213eU, - 0x4b4bdd96U, 0xbdbddc61U, 0x8b8b860dU, 0x8a8a850fU, - 0x707090e0U, 0x3e3e427cU, 0xb5b5c471U, 0x6666aaccU, - 0x4848d890U, 0x03030506U, 0xf6f601f7U, 0x0e0e121cU, - 0x6161a3c2U, 0x35355f6aU, 0x5757f9aeU, 0xb9b9d069U, - 0x86869117U, 0xc1c15899U, 0x1d1d273aU, 0x9e9eb927U, - 0xe1e138d9U, 0xf8f813ebU, 0x9898b32bU, 0x11113322U, - 0x6969bbd2U, 0xd9d970a9U, 0x8e8e8907U, 0x9494a733U, - 0x9b9bb62dU, 0x1e1e223cU, 0x87879215U, 0xe9e920c9U, - 0xcece4987U, 0x5555ffaaU, 0x28287850U, 0xdfdf7aa5U, - 0x8c8c8f03U, 0xa1a1f859U, 0x89898009U, 0x0d0d171aU, - 0xbfbfda65U, 0xe6e631d7U, 0x4242c684U, 0x6868b8d0U, - 0x4141c382U, 0x9999b029U, 0x2d2d775aU, 0x0f0f111eU, - 0xb0b0cb7bU, 0x5454fca8U, 0xbbbbd66dU, 0x16163a2cU, -}; -const u32 Te4[256] = { - 0x63636363U, 0x7c7c7c7cU, 0x77777777U, 0x7b7b7b7bU, - 0xf2f2f2f2U, 0x6b6b6b6bU, 0x6f6f6f6fU, 0xc5c5c5c5U, - 0x30303030U, 0x01010101U, 0x67676767U, 0x2b2b2b2bU, - 0xfefefefeU, 0xd7d7d7d7U, 0xababababU, 0x76767676U, - 0xcacacacaU, 0x82828282U, 0xc9c9c9c9U, 0x7d7d7d7dU, - 0xfafafafaU, 0x59595959U, 0x47474747U, 0xf0f0f0f0U, - 0xadadadadU, 0xd4d4d4d4U, 0xa2a2a2a2U, 0xafafafafU, - 0x9c9c9c9cU, 0xa4a4a4a4U, 0x72727272U, 0xc0c0c0c0U, - 0xb7b7b7b7U, 0xfdfdfdfdU, 0x93939393U, 0x26262626U, - 0x36363636U, 0x3f3f3f3fU, 0xf7f7f7f7U, 0xccccccccU, - 0x34343434U, 0xa5a5a5a5U, 0xe5e5e5e5U, 0xf1f1f1f1U, - 0x71717171U, 0xd8d8d8d8U, 0x31313131U, 0x15151515U, - 0x04040404U, 0xc7c7c7c7U, 0x23232323U, 0xc3c3c3c3U, - 0x18181818U, 0x96969696U, 0x05050505U, 0x9a9a9a9aU, - 0x07070707U, 0x12121212U, 0x80808080U, 0xe2e2e2e2U, - 0xebebebebU, 0x27272727U, 0xb2b2b2b2U, 0x75757575U, - 0x09090909U, 0x83838383U, 0x2c2c2c2cU, 0x1a1a1a1aU, - 0x1b1b1b1bU, 0x6e6e6e6eU, 0x5a5a5a5aU, 0xa0a0a0a0U, - 0x52525252U, 0x3b3b3b3bU, 0xd6d6d6d6U, 0xb3b3b3b3U, - 0x29292929U, 0xe3e3e3e3U, 0x2f2f2f2fU, 0x84848484U, - 0x53535353U, 0xd1d1d1d1U, 0x00000000U, 0xededededU, - 0x20202020U, 0xfcfcfcfcU, 0xb1b1b1b1U, 0x5b5b5b5bU, - 0x6a6a6a6aU, 0xcbcbcbcbU, 0xbebebebeU, 0x39393939U, - 0x4a4a4a4aU, 0x4c4c4c4cU, 0x58585858U, 0xcfcfcfcfU, - 0xd0d0d0d0U, 0xefefefefU, 0xaaaaaaaaU, 0xfbfbfbfbU, - 0x43434343U, 0x4d4d4d4dU, 0x33333333U, 0x85858585U, - 0x45454545U, 0xf9f9f9f9U, 0x02020202U, 0x7f7f7f7fU, - 0x50505050U, 0x3c3c3c3cU, 0x9f9f9f9fU, 0xa8a8a8a8U, - 0x51515151U, 0xa3a3a3a3U, 0x40404040U, 0x8f8f8f8fU, - 0x92929292U, 0x9d9d9d9dU, 0x38383838U, 0xf5f5f5f5U, - 0xbcbcbcbcU, 0xb6b6b6b6U, 0xdadadadaU, 0x21212121U, - 0x10101010U, 0xffffffffU, 0xf3f3f3f3U, 0xd2d2d2d2U, - 0xcdcdcdcdU, 0x0c0c0c0cU, 0x13131313U, 0xececececU, - 0x5f5f5f5fU, 0x97979797U, 0x44444444U, 0x17171717U, - 0xc4c4c4c4U, 0xa7a7a7a7U, 0x7e7e7e7eU, 0x3d3d3d3dU, - 0x64646464U, 0x5d5d5d5dU, 0x19191919U, 0x73737373U, - 0x60606060U, 0x81818181U, 0x4f4f4f4fU, 0xdcdcdcdcU, - 0x22222222U, 0x2a2a2a2aU, 0x90909090U, 0x88888888U, - 0x46464646U, 0xeeeeeeeeU, 0xb8b8b8b8U, 0x14141414U, - 0xdedededeU, 0x5e5e5e5eU, 0x0b0b0b0bU, 0xdbdbdbdbU, - 0xe0e0e0e0U, 0x32323232U, 0x3a3a3a3aU, 0x0a0a0a0aU, - 0x49494949U, 0x06060606U, 0x24242424U, 0x5c5c5c5cU, - 0xc2c2c2c2U, 0xd3d3d3d3U, 0xacacacacU, 0x62626262U, - 0x91919191U, 0x95959595U, 0xe4e4e4e4U, 0x79797979U, - 0xe7e7e7e7U, 0xc8c8c8c8U, 0x37373737U, 0x6d6d6d6dU, - 0x8d8d8d8dU, 0xd5d5d5d5U, 0x4e4e4e4eU, 0xa9a9a9a9U, - 0x6c6c6c6cU, 0x56565656U, 0xf4f4f4f4U, 0xeaeaeaeaU, - 0x65656565U, 0x7a7a7a7aU, 0xaeaeaeaeU, 0x08080808U, - 0xbabababaU, 0x78787878U, 0x25252525U, 0x2e2e2e2eU, - 0x1c1c1c1cU, 0xa6a6a6a6U, 0xb4b4b4b4U, 0xc6c6c6c6U, - 0xe8e8e8e8U, 0xddddddddU, 0x74747474U, 0x1f1f1f1fU, - 0x4b4b4b4bU, 0xbdbdbdbdU, 0x8b8b8b8bU, 0x8a8a8a8aU, - 0x70707070U, 0x3e3e3e3eU, 0xb5b5b5b5U, 0x66666666U, - 0x48484848U, 0x03030303U, 0xf6f6f6f6U, 0x0e0e0e0eU, - 0x61616161U, 0x35353535U, 0x57575757U, 0xb9b9b9b9U, - 0x86868686U, 0xc1c1c1c1U, 0x1d1d1d1dU, 0x9e9e9e9eU, - 0xe1e1e1e1U, 0xf8f8f8f8U, 0x98989898U, 0x11111111U, - 0x69696969U, 0xd9d9d9d9U, 0x8e8e8e8eU, 0x94949494U, - 0x9b9b9b9bU, 0x1e1e1e1eU, 0x87878787U, 0xe9e9e9e9U, - 0xcecececeU, 0x55555555U, 0x28282828U, 0xdfdfdfdfU, - 0x8c8c8c8cU, 0xa1a1a1a1U, 0x89898989U, 0x0d0d0d0dU, - 0xbfbfbfbfU, 0xe6e6e6e6U, 0x42424242U, 0x68686868U, - 0x41414141U, 0x99999999U, 0x2d2d2d2dU, 0x0f0f0f0fU, - 0xb0b0b0b0U, 0x54545454U, 0xbbbbbbbbU, 0x16161616U, -}; -#endif /* AES_SMALL_TABLES */ -const u32 Td0[256] = { - 0x51f4a750U, 0x7e416553U, 0x1a17a4c3U, 0x3a275e96U, - 0x3bab6bcbU, 0x1f9d45f1U, 0xacfa58abU, 0x4be30393U, - 0x2030fa55U, 0xad766df6U, 0x88cc7691U, 0xf5024c25U, - 0x4fe5d7fcU, 0xc52acbd7U, 0x26354480U, 0xb562a38fU, - 0xdeb15a49U, 0x25ba1b67U, 0x45ea0e98U, 0x5dfec0e1U, - 0xc32f7502U, 0x814cf012U, 0x8d4697a3U, 0x6bd3f9c6U, - 0x038f5fe7U, 0x15929c95U, 0xbf6d7aebU, 0x955259daU, - 0xd4be832dU, 0x587421d3U, 0x49e06929U, 0x8ec9c844U, - 0x75c2896aU, 0xf48e7978U, 0x99583e6bU, 0x27b971ddU, - 0xbee14fb6U, 0xf088ad17U, 0xc920ac66U, 0x7dce3ab4U, - 0x63df4a18U, 0xe51a3182U, 0x97513360U, 0x62537f45U, - 0xb16477e0U, 0xbb6bae84U, 0xfe81a01cU, 0xf9082b94U, - 0x70486858U, 0x8f45fd19U, 0x94de6c87U, 0x527bf8b7U, - 0xab73d323U, 0x724b02e2U, 0xe31f8f57U, 0x6655ab2aU, - 0xb2eb2807U, 0x2fb5c203U, 0x86c57b9aU, 0xd33708a5U, - 0x302887f2U, 0x23bfa5b2U, 0x02036abaU, 0xed16825cU, - 0x8acf1c2bU, 0xa779b492U, 0xf307f2f0U, 0x4e69e2a1U, - 0x65daf4cdU, 0x0605bed5U, 0xd134621fU, 0xc4a6fe8aU, - 0x342e539dU, 0xa2f355a0U, 0x058ae132U, 0xa4f6eb75U, - 0x0b83ec39U, 0x4060efaaU, 0x5e719f06U, 0xbd6e1051U, - 0x3e218af9U, 0x96dd063dU, 0xdd3e05aeU, 0x4de6bd46U, - 0x91548db5U, 0x71c45d05U, 0x0406d46fU, 0x605015ffU, - 0x1998fb24U, 0xd6bde997U, 0x894043ccU, 0x67d99e77U, - 0xb0e842bdU, 0x07898b88U, 0xe7195b38U, 0x79c8eedbU, - 0xa17c0a47U, 0x7c420fe9U, 0xf8841ec9U, 0x00000000U, - 0x09808683U, 0x322bed48U, 0x1e1170acU, 0x6c5a724eU, - 0xfd0efffbU, 0x0f853856U, 0x3daed51eU, 0x362d3927U, - 0x0a0fd964U, 0x685ca621U, 0x9b5b54d1U, 0x24362e3aU, - 0x0c0a67b1U, 0x9357e70fU, 0xb4ee96d2U, 0x1b9b919eU, - 0x80c0c54fU, 0x61dc20a2U, 0x5a774b69U, 0x1c121a16U, - 0xe293ba0aU, 0xc0a02ae5U, 0x3c22e043U, 0x121b171dU, - 0x0e090d0bU, 0xf28bc7adU, 0x2db6a8b9U, 0x141ea9c8U, - 0x57f11985U, 0xaf75074cU, 0xee99ddbbU, 0xa37f60fdU, - 0xf701269fU, 0x5c72f5bcU, 0x44663bc5U, 0x5bfb7e34U, - 0x8b432976U, 0xcb23c6dcU, 0xb6edfc68U, 0xb8e4f163U, - 0xd731dccaU, 0x42638510U, 0x13972240U, 0x84c61120U, - 0x854a247dU, 0xd2bb3df8U, 0xaef93211U, 0xc729a16dU, - 0x1d9e2f4bU, 0xdcb230f3U, 0x0d8652ecU, 0x77c1e3d0U, - 0x2bb3166cU, 0xa970b999U, 0x119448faU, 0x47e96422U, - 0xa8fc8cc4U, 0xa0f03f1aU, 0x567d2cd8U, 0x223390efU, - 0x87494ec7U, 0xd938d1c1U, 0x8ccaa2feU, 0x98d40b36U, - 0xa6f581cfU, 0xa57ade28U, 0xdab78e26U, 0x3fadbfa4U, - 0x2c3a9de4U, 0x5078920dU, 0x6a5fcc9bU, 0x547e4662U, - 0xf68d13c2U, 0x90d8b8e8U, 0x2e39f75eU, 0x82c3aff5U, - 0x9f5d80beU, 0x69d0937cU, 0x6fd52da9U, 0xcf2512b3U, - 0xc8ac993bU, 0x10187da7U, 0xe89c636eU, 0xdb3bbb7bU, - 0xcd267809U, 0x6e5918f4U, 0xec9ab701U, 0x834f9aa8U, - 0xe6956e65U, 0xaaffe67eU, 0x21bccf08U, 0xef15e8e6U, - 0xbae79bd9U, 0x4a6f36ceU, 0xea9f09d4U, 0x29b07cd6U, - 0x31a4b2afU, 0x2a3f2331U, 0xc6a59430U, 0x35a266c0U, - 0x744ebc37U, 0xfc82caa6U, 0xe090d0b0U, 0x33a7d815U, - 0xf104984aU, 0x41ecdaf7U, 0x7fcd500eU, 0x1791f62fU, - 0x764dd68dU, 0x43efb04dU, 0xccaa4d54U, 0xe49604dfU, - 0x9ed1b5e3U, 0x4c6a881bU, 0xc12c1fb8U, 0x4665517fU, - 0x9d5eea04U, 0x018c355dU, 0xfa877473U, 0xfb0b412eU, - 0xb3671d5aU, 0x92dbd252U, 0xe9105633U, 0x6dd64713U, - 0x9ad7618cU, 0x37a10c7aU, 0x59f8148eU, 0xeb133c89U, - 0xcea927eeU, 0xb761c935U, 0xe11ce5edU, 0x7a47b13cU, - 0x9cd2df59U, 0x55f2733fU, 0x1814ce79U, 0x73c737bfU, - 0x53f7cdeaU, 0x5ffdaa5bU, 0xdf3d6f14U, 0x7844db86U, - 0xcaaff381U, 0xb968c43eU, 0x3824342cU, 0xc2a3405fU, - 0x161dc372U, 0xbce2250cU, 0x283c498bU, 0xff0d9541U, - 0x39a80171U, 0x080cb3deU, 0xd8b4e49cU, 0x6456c190U, - 0x7bcb8461U, 0xd532b670U, 0x486c5c74U, 0xd0b85742U, -}; -#ifndef AES_SMALL_TABLES -const u32 Td1[256] = { - 0x5051f4a7U, 0x537e4165U, 0xc31a17a4U, 0x963a275eU, - 0xcb3bab6bU, 0xf11f9d45U, 0xabacfa58U, 0x934be303U, - 0x552030faU, 0xf6ad766dU, 0x9188cc76U, 0x25f5024cU, - 0xfc4fe5d7U, 0xd7c52acbU, 0x80263544U, 0x8fb562a3U, - 0x49deb15aU, 0x6725ba1bU, 0x9845ea0eU, 0xe15dfec0U, - 0x02c32f75U, 0x12814cf0U, 0xa38d4697U, 0xc66bd3f9U, - 0xe7038f5fU, 0x9515929cU, 0xebbf6d7aU, 0xda955259U, - 0x2dd4be83U, 0xd3587421U, 0x2949e069U, 0x448ec9c8U, - 0x6a75c289U, 0x78f48e79U, 0x6b99583eU, 0xdd27b971U, - 0xb6bee14fU, 0x17f088adU, 0x66c920acU, 0xb47dce3aU, - 0x1863df4aU, 0x82e51a31U, 0x60975133U, 0x4562537fU, - 0xe0b16477U, 0x84bb6baeU, 0x1cfe81a0U, 0x94f9082bU, - 0x58704868U, 0x198f45fdU, 0x8794de6cU, 0xb7527bf8U, - 0x23ab73d3U, 0xe2724b02U, 0x57e31f8fU, 0x2a6655abU, - 0x07b2eb28U, 0x032fb5c2U, 0x9a86c57bU, 0xa5d33708U, - 0xf2302887U, 0xb223bfa5U, 0xba02036aU, 0x5ced1682U, - 0x2b8acf1cU, 0x92a779b4U, 0xf0f307f2U, 0xa14e69e2U, - 0xcd65daf4U, 0xd50605beU, 0x1fd13462U, 0x8ac4a6feU, - 0x9d342e53U, 0xa0a2f355U, 0x32058ae1U, 0x75a4f6ebU, - 0x390b83ecU, 0xaa4060efU, 0x065e719fU, 0x51bd6e10U, - 0xf93e218aU, 0x3d96dd06U, 0xaedd3e05U, 0x464de6bdU, - 0xb591548dU, 0x0571c45dU, 0x6f0406d4U, 0xff605015U, - 0x241998fbU, 0x97d6bde9U, 0xcc894043U, 0x7767d99eU, - 0xbdb0e842U, 0x8807898bU, 0x38e7195bU, 0xdb79c8eeU, - 0x47a17c0aU, 0xe97c420fU, 0xc9f8841eU, 0x00000000U, - 0x83098086U, 0x48322bedU, 0xac1e1170U, 0x4e6c5a72U, - 0xfbfd0effU, 0x560f8538U, 0x1e3daed5U, 0x27362d39U, - 0x640a0fd9U, 0x21685ca6U, 0xd19b5b54U, 0x3a24362eU, - 0xb10c0a67U, 0x0f9357e7U, 0xd2b4ee96U, 0x9e1b9b91U, - 0x4f80c0c5U, 0xa261dc20U, 0x695a774bU, 0x161c121aU, - 0x0ae293baU, 0xe5c0a02aU, 0x433c22e0U, 0x1d121b17U, - 0x0b0e090dU, 0xadf28bc7U, 0xb92db6a8U, 0xc8141ea9U, - 0x8557f119U, 0x4caf7507U, 0xbbee99ddU, 0xfda37f60U, - 0x9ff70126U, 0xbc5c72f5U, 0xc544663bU, 0x345bfb7eU, - 0x768b4329U, 0xdccb23c6U, 0x68b6edfcU, 0x63b8e4f1U, - 0xcad731dcU, 0x10426385U, 0x40139722U, 0x2084c611U, - 0x7d854a24U, 0xf8d2bb3dU, 0x11aef932U, 0x6dc729a1U, - 0x4b1d9e2fU, 0xf3dcb230U, 0xec0d8652U, 0xd077c1e3U, - 0x6c2bb316U, 0x99a970b9U, 0xfa119448U, 0x2247e964U, - 0xc4a8fc8cU, 0x1aa0f03fU, 0xd8567d2cU, 0xef223390U, - 0xc787494eU, 0xc1d938d1U, 0xfe8ccaa2U, 0x3698d40bU, - 0xcfa6f581U, 0x28a57adeU, 0x26dab78eU, 0xa43fadbfU, - 0xe42c3a9dU, 0x0d507892U, 0x9b6a5fccU, 0x62547e46U, - 0xc2f68d13U, 0xe890d8b8U, 0x5e2e39f7U, 0xf582c3afU, - 0xbe9f5d80U, 0x7c69d093U, 0xa96fd52dU, 0xb3cf2512U, - 0x3bc8ac99U, 0xa710187dU, 0x6ee89c63U, 0x7bdb3bbbU, - 0x09cd2678U, 0xf46e5918U, 0x01ec9ab7U, 0xa8834f9aU, - 0x65e6956eU, 0x7eaaffe6U, 0x0821bccfU, 0xe6ef15e8U, - 0xd9bae79bU, 0xce4a6f36U, 0xd4ea9f09U, 0xd629b07cU, - 0xaf31a4b2U, 0x312a3f23U, 0x30c6a594U, 0xc035a266U, - 0x37744ebcU, 0xa6fc82caU, 0xb0e090d0U, 0x1533a7d8U, - 0x4af10498U, 0xf741ecdaU, 0x0e7fcd50U, 0x2f1791f6U, - 0x8d764dd6U, 0x4d43efb0U, 0x54ccaa4dU, 0xdfe49604U, - 0xe39ed1b5U, 0x1b4c6a88U, 0xb8c12c1fU, 0x7f466551U, - 0x049d5eeaU, 0x5d018c35U, 0x73fa8774U, 0x2efb0b41U, - 0x5ab3671dU, 0x5292dbd2U, 0x33e91056U, 0x136dd647U, - 0x8c9ad761U, 0x7a37a10cU, 0x8e59f814U, 0x89eb133cU, - 0xeecea927U, 0x35b761c9U, 0xede11ce5U, 0x3c7a47b1U, - 0x599cd2dfU, 0x3f55f273U, 0x791814ceU, 0xbf73c737U, - 0xea53f7cdU, 0x5b5ffdaaU, 0x14df3d6fU, 0x867844dbU, - 0x81caaff3U, 0x3eb968c4U, 0x2c382434U, 0x5fc2a340U, - 0x72161dc3U, 0x0cbce225U, 0x8b283c49U, 0x41ff0d95U, - 0x7139a801U, 0xde080cb3U, 0x9cd8b4e4U, 0x906456c1U, - 0x617bcb84U, 0x70d532b6U, 0x74486c5cU, 0x42d0b857U, -}; -const u32 Td2[256] = { - 0xa75051f4U, 0x65537e41U, 0xa4c31a17U, 0x5e963a27U, - 0x6bcb3babU, 0x45f11f9dU, 0x58abacfaU, 0x03934be3U, - 0xfa552030U, 0x6df6ad76U, 0x769188ccU, 0x4c25f502U, - 0xd7fc4fe5U, 0xcbd7c52aU, 0x44802635U, 0xa38fb562U, - 0x5a49deb1U, 0x1b6725baU, 0x0e9845eaU, 0xc0e15dfeU, - 0x7502c32fU, 0xf012814cU, 0x97a38d46U, 0xf9c66bd3U, - 0x5fe7038fU, 0x9c951592U, 0x7aebbf6dU, 0x59da9552U, - 0x832dd4beU, 0x21d35874U, 0x692949e0U, 0xc8448ec9U, - 0x896a75c2U, 0x7978f48eU, 0x3e6b9958U, 0x71dd27b9U, - 0x4fb6bee1U, 0xad17f088U, 0xac66c920U, 0x3ab47dceU, - 0x4a1863dfU, 0x3182e51aU, 0x33609751U, 0x7f456253U, - 0x77e0b164U, 0xae84bb6bU, 0xa01cfe81U, 0x2b94f908U, - 0x68587048U, 0xfd198f45U, 0x6c8794deU, 0xf8b7527bU, - 0xd323ab73U, 0x02e2724bU, 0x8f57e31fU, 0xab2a6655U, - 0x2807b2ebU, 0xc2032fb5U, 0x7b9a86c5U, 0x08a5d337U, - 0x87f23028U, 0xa5b223bfU, 0x6aba0203U, 0x825ced16U, - 0x1c2b8acfU, 0xb492a779U, 0xf2f0f307U, 0xe2a14e69U, - 0xf4cd65daU, 0xbed50605U, 0x621fd134U, 0xfe8ac4a6U, - 0x539d342eU, 0x55a0a2f3U, 0xe132058aU, 0xeb75a4f6U, - 0xec390b83U, 0xefaa4060U, 0x9f065e71U, 0x1051bd6eU, - - 0x8af93e21U, 0x063d96ddU, 0x05aedd3eU, 0xbd464de6U, - 0x8db59154U, 0x5d0571c4U, 0xd46f0406U, 0x15ff6050U, - 0xfb241998U, 0xe997d6bdU, 0x43cc8940U, 0x9e7767d9U, - 0x42bdb0e8U, 0x8b880789U, 0x5b38e719U, 0xeedb79c8U, - 0x0a47a17cU, 0x0fe97c42U, 0x1ec9f884U, 0x00000000U, - 0x86830980U, 0xed48322bU, 0x70ac1e11U, 0x724e6c5aU, - 0xfffbfd0eU, 0x38560f85U, 0xd51e3daeU, 0x3927362dU, - 0xd9640a0fU, 0xa621685cU, 0x54d19b5bU, 0x2e3a2436U, - 0x67b10c0aU, 0xe70f9357U, 0x96d2b4eeU, 0x919e1b9bU, - 0xc54f80c0U, 0x20a261dcU, 0x4b695a77U, 0x1a161c12U, - 0xba0ae293U, 0x2ae5c0a0U, 0xe0433c22U, 0x171d121bU, - 0x0d0b0e09U, 0xc7adf28bU, 0xa8b92db6U, 0xa9c8141eU, - 0x198557f1U, 0x074caf75U, 0xddbbee99U, 0x60fda37fU, - 0x269ff701U, 0xf5bc5c72U, 0x3bc54466U, 0x7e345bfbU, - 0x29768b43U, 0xc6dccb23U, 0xfc68b6edU, 0xf163b8e4U, - 0xdccad731U, 0x85104263U, 0x22401397U, 0x112084c6U, - 0x247d854aU, 0x3df8d2bbU, 0x3211aef9U, 0xa16dc729U, - 0x2f4b1d9eU, 0x30f3dcb2U, 0x52ec0d86U, 0xe3d077c1U, - 0x166c2bb3U, 0xb999a970U, 0x48fa1194U, 0x642247e9U, - 0x8cc4a8fcU, 0x3f1aa0f0U, 0x2cd8567dU, 0x90ef2233U, - 0x4ec78749U, 0xd1c1d938U, 0xa2fe8ccaU, 0x0b3698d4U, - 0x81cfa6f5U, 0xde28a57aU, 0x8e26dab7U, 0xbfa43fadU, - 0x9de42c3aU, 0x920d5078U, 0xcc9b6a5fU, 0x4662547eU, - 0x13c2f68dU, 0xb8e890d8U, 0xf75e2e39U, 0xaff582c3U, - 0x80be9f5dU, 0x937c69d0U, 0x2da96fd5U, 0x12b3cf25U, - 0x993bc8acU, 0x7da71018U, 0x636ee89cU, 0xbb7bdb3bU, - 0x7809cd26U, 0x18f46e59U, 0xb701ec9aU, 0x9aa8834fU, - 0x6e65e695U, 0xe67eaaffU, 0xcf0821bcU, 0xe8e6ef15U, - 0x9bd9bae7U, 0x36ce4a6fU, 0x09d4ea9fU, 0x7cd629b0U, - 0xb2af31a4U, 0x23312a3fU, 0x9430c6a5U, 0x66c035a2U, - 0xbc37744eU, 0xcaa6fc82U, 0xd0b0e090U, 0xd81533a7U, - 0x984af104U, 0xdaf741ecU, 0x500e7fcdU, 0xf62f1791U, - 0xd68d764dU, 0xb04d43efU, 0x4d54ccaaU, 0x04dfe496U, - 0xb5e39ed1U, 0x881b4c6aU, 0x1fb8c12cU, 0x517f4665U, - 0xea049d5eU, 0x355d018cU, 0x7473fa87U, 0x412efb0bU, - 0x1d5ab367U, 0xd25292dbU, 0x5633e910U, 0x47136dd6U, - 0x618c9ad7U, 0x0c7a37a1U, 0x148e59f8U, 0x3c89eb13U, - 0x27eecea9U, 0xc935b761U, 0xe5ede11cU, 0xb13c7a47U, - 0xdf599cd2U, 0x733f55f2U, 0xce791814U, 0x37bf73c7U, - 0xcdea53f7U, 0xaa5b5ffdU, 0x6f14df3dU, 0xdb867844U, - 0xf381caafU, 0xc43eb968U, 0x342c3824U, 0x405fc2a3U, - 0xc372161dU, 0x250cbce2U, 0x498b283cU, 0x9541ff0dU, - 0x017139a8U, 0xb3de080cU, 0xe49cd8b4U, 0xc1906456U, - 0x84617bcbU, 0xb670d532U, 0x5c74486cU, 0x5742d0b8U, -}; -const u32 Td3[256] = { - 0xf4a75051U, 0x4165537eU, 0x17a4c31aU, 0x275e963aU, - 0xab6bcb3bU, 0x9d45f11fU, 0xfa58abacU, 0xe303934bU, - 0x30fa5520U, 0x766df6adU, 0xcc769188U, 0x024c25f5U, - 0xe5d7fc4fU, 0x2acbd7c5U, 0x35448026U, 0x62a38fb5U, - 0xb15a49deU, 0xba1b6725U, 0xea0e9845U, 0xfec0e15dU, - 0x2f7502c3U, 0x4cf01281U, 0x4697a38dU, 0xd3f9c66bU, - 0x8f5fe703U, 0x929c9515U, 0x6d7aebbfU, 0x5259da95U, - 0xbe832dd4U, 0x7421d358U, 0xe0692949U, 0xc9c8448eU, - 0xc2896a75U, 0x8e7978f4U, 0x583e6b99U, 0xb971dd27U, - 0xe14fb6beU, 0x88ad17f0U, 0x20ac66c9U, 0xce3ab47dU, - 0xdf4a1863U, 0x1a3182e5U, 0x51336097U, 0x537f4562U, - 0x6477e0b1U, 0x6bae84bbU, 0x81a01cfeU, 0x082b94f9U, - 0x48685870U, 0x45fd198fU, 0xde6c8794U, 0x7bf8b752U, - 0x73d323abU, 0x4b02e272U, 0x1f8f57e3U, 0x55ab2a66U, - 0xeb2807b2U, 0xb5c2032fU, 0xc57b9a86U, 0x3708a5d3U, - 0x2887f230U, 0xbfa5b223U, 0x036aba02U, 0x16825cedU, - 0xcf1c2b8aU, 0x79b492a7U, 0x07f2f0f3U, 0x69e2a14eU, - 0xdaf4cd65U, 0x05bed506U, 0x34621fd1U, 0xa6fe8ac4U, - 0x2e539d34U, 0xf355a0a2U, 0x8ae13205U, 0xf6eb75a4U, - 0x83ec390bU, 0x60efaa40U, 0x719f065eU, 0x6e1051bdU, - 0x218af93eU, 0xdd063d96U, 0x3e05aeddU, 0xe6bd464dU, - 0x548db591U, 0xc45d0571U, 0x06d46f04U, 0x5015ff60U, - 0x98fb2419U, 0xbde997d6U, 0x4043cc89U, 0xd99e7767U, - 0xe842bdb0U, 0x898b8807U, 0x195b38e7U, 0xc8eedb79U, - 0x7c0a47a1U, 0x420fe97cU, 0x841ec9f8U, 0x00000000U, - 0x80868309U, 0x2bed4832U, 0x1170ac1eU, 0x5a724e6cU, - 0x0efffbfdU, 0x8538560fU, 0xaed51e3dU, 0x2d392736U, - 0x0fd9640aU, 0x5ca62168U, 0x5b54d19bU, 0x362e3a24U, - 0x0a67b10cU, 0x57e70f93U, 0xee96d2b4U, 0x9b919e1bU, - 0xc0c54f80U, 0xdc20a261U, 0x774b695aU, 0x121a161cU, - 0x93ba0ae2U, 0xa02ae5c0U, 0x22e0433cU, 0x1b171d12U, - 0x090d0b0eU, 0x8bc7adf2U, 0xb6a8b92dU, 0x1ea9c814U, - 0xf1198557U, 0x75074cafU, 0x99ddbbeeU, 0x7f60fda3U, - 0x01269ff7U, 0x72f5bc5cU, 0x663bc544U, 0xfb7e345bU, - 0x4329768bU, 0x23c6dccbU, 0xedfc68b6U, 0xe4f163b8U, - 0x31dccad7U, 0x63851042U, 0x97224013U, 0xc6112084U, - 0x4a247d85U, 0xbb3df8d2U, 0xf93211aeU, 0x29a16dc7U, - 0x9e2f4b1dU, 0xb230f3dcU, 0x8652ec0dU, 0xc1e3d077U, - 0xb3166c2bU, 0x70b999a9U, 0x9448fa11U, 0xe9642247U, - 0xfc8cc4a8U, 0xf03f1aa0U, 0x7d2cd856U, 0x3390ef22U, - 0x494ec787U, 0x38d1c1d9U, 0xcaa2fe8cU, 0xd40b3698U, - 0xf581cfa6U, 0x7ade28a5U, 0xb78e26daU, 0xadbfa43fU, - 0x3a9de42cU, 0x78920d50U, 0x5fcc9b6aU, 0x7e466254U, - 0x8d13c2f6U, 0xd8b8e890U, 0x39f75e2eU, 0xc3aff582U, - 0x5d80be9fU, 0xd0937c69U, 0xd52da96fU, 0x2512b3cfU, - 0xac993bc8U, 0x187da710U, 0x9c636ee8U, 0x3bbb7bdbU, - 0x267809cdU, 0x5918f46eU, 0x9ab701ecU, 0x4f9aa883U, - 0x956e65e6U, 0xffe67eaaU, 0xbccf0821U, 0x15e8e6efU, - 0xe79bd9baU, 0x6f36ce4aU, 0x9f09d4eaU, 0xb07cd629U, - 0xa4b2af31U, 0x3f23312aU, 0xa59430c6U, 0xa266c035U, - 0x4ebc3774U, 0x82caa6fcU, 0x90d0b0e0U, 0xa7d81533U, - 0x04984af1U, 0xecdaf741U, 0xcd500e7fU, 0x91f62f17U, - 0x4dd68d76U, 0xefb04d43U, 0xaa4d54ccU, 0x9604dfe4U, - 0xd1b5e39eU, 0x6a881b4cU, 0x2c1fb8c1U, 0x65517f46U, - 0x5eea049dU, 0x8c355d01U, 0x877473faU, 0x0b412efbU, - 0x671d5ab3U, 0xdbd25292U, 0x105633e9U, 0xd647136dU, - 0xd7618c9aU, 0xa10c7a37U, 0xf8148e59U, 0x133c89ebU, - 0xa927eeceU, 0x61c935b7U, 0x1ce5ede1U, 0x47b13c7aU, - 0xd2df599cU, 0xf2733f55U, 0x14ce7918U, 0xc737bf73U, - 0xf7cdea53U, 0xfdaa5b5fU, 0x3d6f14dfU, 0x44db8678U, - 0xaff381caU, 0x68c43eb9U, 0x24342c38U, 0xa3405fc2U, - 0x1dc37216U, 0xe2250cbcU, 0x3c498b28U, 0x0d9541ffU, - 0xa8017139U, 0x0cb3de08U, 0xb4e49cd8U, 0x56c19064U, - 0xcb84617bU, 0x32b670d5U, 0x6c5c7448U, 0xb85742d0U, -}; -const u32 Td4[256] = { - 0x52525252U, 0x09090909U, 0x6a6a6a6aU, 0xd5d5d5d5U, - 0x30303030U, 0x36363636U, 0xa5a5a5a5U, 0x38383838U, - 0xbfbfbfbfU, 0x40404040U, 0xa3a3a3a3U, 0x9e9e9e9eU, - 0x81818181U, 0xf3f3f3f3U, 0xd7d7d7d7U, 0xfbfbfbfbU, - 0x7c7c7c7cU, 0xe3e3e3e3U, 0x39393939U, 0x82828282U, - 0x9b9b9b9bU, 0x2f2f2f2fU, 0xffffffffU, 0x87878787U, - 0x34343434U, 0x8e8e8e8eU, 0x43434343U, 0x44444444U, - 0xc4c4c4c4U, 0xdedededeU, 0xe9e9e9e9U, 0xcbcbcbcbU, - 0x54545454U, 0x7b7b7b7bU, 0x94949494U, 0x32323232U, - 0xa6a6a6a6U, 0xc2c2c2c2U, 0x23232323U, 0x3d3d3d3dU, - 0xeeeeeeeeU, 0x4c4c4c4cU, 0x95959595U, 0x0b0b0b0bU, - 0x42424242U, 0xfafafafaU, 0xc3c3c3c3U, 0x4e4e4e4eU, - 0x08080808U, 0x2e2e2e2eU, 0xa1a1a1a1U, 0x66666666U, - 0x28282828U, 0xd9d9d9d9U, 0x24242424U, 0xb2b2b2b2U, - 0x76767676U, 0x5b5b5b5bU, 0xa2a2a2a2U, 0x49494949U, - 0x6d6d6d6dU, 0x8b8b8b8bU, 0xd1d1d1d1U, 0x25252525U, - 0x72727272U, 0xf8f8f8f8U, 0xf6f6f6f6U, 0x64646464U, - 0x86868686U, 0x68686868U, 0x98989898U, 0x16161616U, - 0xd4d4d4d4U, 0xa4a4a4a4U, 0x5c5c5c5cU, 0xccccccccU, - 0x5d5d5d5dU, 0x65656565U, 0xb6b6b6b6U, 0x92929292U, - 0x6c6c6c6cU, 0x70707070U, 0x48484848U, 0x50505050U, - 0xfdfdfdfdU, 0xededededU, 0xb9b9b9b9U, 0xdadadadaU, - 0x5e5e5e5eU, 0x15151515U, 0x46464646U, 0x57575757U, - 0xa7a7a7a7U, 0x8d8d8d8dU, 0x9d9d9d9dU, 0x84848484U, - 0x90909090U, 0xd8d8d8d8U, 0xababababU, 0x00000000U, - 0x8c8c8c8cU, 0xbcbcbcbcU, 0xd3d3d3d3U, 0x0a0a0a0aU, - 0xf7f7f7f7U, 0xe4e4e4e4U, 0x58585858U, 0x05050505U, - 0xb8b8b8b8U, 0xb3b3b3b3U, 0x45454545U, 0x06060606U, - 0xd0d0d0d0U, 0x2c2c2c2cU, 0x1e1e1e1eU, 0x8f8f8f8fU, - 0xcacacacaU, 0x3f3f3f3fU, 0x0f0f0f0fU, 0x02020202U, - 0xc1c1c1c1U, 0xafafafafU, 0xbdbdbdbdU, 0x03030303U, - 0x01010101U, 0x13131313U, 0x8a8a8a8aU, 0x6b6b6b6bU, - 0x3a3a3a3aU, 0x91919191U, 0x11111111U, 0x41414141U, - 0x4f4f4f4fU, 0x67676767U, 0xdcdcdcdcU, 0xeaeaeaeaU, - 0x97979797U, 0xf2f2f2f2U, 0xcfcfcfcfU, 0xcecececeU, - 0xf0f0f0f0U, 0xb4b4b4b4U, 0xe6e6e6e6U, 0x73737373U, - 0x96969696U, 0xacacacacU, 0x74747474U, 0x22222222U, - 0xe7e7e7e7U, 0xadadadadU, 0x35353535U, 0x85858585U, - 0xe2e2e2e2U, 0xf9f9f9f9U, 0x37373737U, 0xe8e8e8e8U, - 0x1c1c1c1cU, 0x75757575U, 0xdfdfdfdfU, 0x6e6e6e6eU, - 0x47474747U, 0xf1f1f1f1U, 0x1a1a1a1aU, 0x71717171U, - 0x1d1d1d1dU, 0x29292929U, 0xc5c5c5c5U, 0x89898989U, - 0x6f6f6f6fU, 0xb7b7b7b7U, 0x62626262U, 0x0e0e0e0eU, - 0xaaaaaaaaU, 0x18181818U, 0xbebebebeU, 0x1b1b1b1bU, - 0xfcfcfcfcU, 0x56565656U, 0x3e3e3e3eU, 0x4b4b4b4bU, - 0xc6c6c6c6U, 0xd2d2d2d2U, 0x79797979U, 0x20202020U, - 0x9a9a9a9aU, 0xdbdbdbdbU, 0xc0c0c0c0U, 0xfefefefeU, - 0x78787878U, 0xcdcdcdcdU, 0x5a5a5a5aU, 0xf4f4f4f4U, - 0x1f1f1f1fU, 0xddddddddU, 0xa8a8a8a8U, 0x33333333U, - 0x88888888U, 0x07070707U, 0xc7c7c7c7U, 0x31313131U, - 0xb1b1b1b1U, 0x12121212U, 0x10101010U, 0x59595959U, - 0x27272727U, 0x80808080U, 0xececececU, 0x5f5f5f5fU, - 0x60606060U, 0x51515151U, 0x7f7f7f7fU, 0xa9a9a9a9U, - 0x19191919U, 0xb5b5b5b5U, 0x4a4a4a4aU, 0x0d0d0d0dU, - 0x2d2d2d2dU, 0xe5e5e5e5U, 0x7a7a7a7aU, 0x9f9f9f9fU, - 0x93939393U, 0xc9c9c9c9U, 0x9c9c9c9cU, 0xefefefefU, - 0xa0a0a0a0U, 0xe0e0e0e0U, 0x3b3b3b3bU, 0x4d4d4d4dU, - 0xaeaeaeaeU, 0x2a2a2a2aU, 0xf5f5f5f5U, 0xb0b0b0b0U, - 0xc8c8c8c8U, 0xebebebebU, 0xbbbbbbbbU, 0x3c3c3c3cU, - 0x83838383U, 0x53535353U, 0x99999999U, 0x61616161U, - 0x17171717U, 0x2b2b2b2bU, 0x04040404U, 0x7e7e7e7eU, - 0xbabababaU, 0x77777777U, 0xd6d6d6d6U, 0x26262626U, - 0xe1e1e1e1U, 0x69696969U, 0x14141414U, 0x63636363U, - 0x55555555U, 0x21212121U, 0x0c0c0c0cU, 0x7d7d7d7dU, -}; -const u32 rcon[] = { - 0x01000000, 0x02000000, 0x04000000, 0x08000000, - 0x10000000, 0x20000000, 0x40000000, 0x80000000, - 0x1B000000, 0x36000000, /* for 128-bit blocks, Rijndael never uses more than 10 rcon values */ -}; -#else /* AES_SMALL_TABLES */ -const u8 Td4s[256] = { - 0x52U, 0x09U, 0x6aU, 0xd5U, 0x30U, 0x36U, 0xa5U, 0x38U, - 0xbfU, 0x40U, 0xa3U, 0x9eU, 0x81U, 0xf3U, 0xd7U, 0xfbU, - 0x7cU, 0xe3U, 0x39U, 0x82U, 0x9bU, 0x2fU, 0xffU, 0x87U, - 0x34U, 0x8eU, 0x43U, 0x44U, 0xc4U, 0xdeU, 0xe9U, 0xcbU, - 0x54U, 0x7bU, 0x94U, 0x32U, 0xa6U, 0xc2U, 0x23U, 0x3dU, - 0xeeU, 0x4cU, 0x95U, 0x0bU, 0x42U, 0xfaU, 0xc3U, 0x4eU, - 0x08U, 0x2eU, 0xa1U, 0x66U, 0x28U, 0xd9U, 0x24U, 0xb2U, - 0x76U, 0x5bU, 0xa2U, 0x49U, 0x6dU, 0x8bU, 0xd1U, 0x25U, - 0x72U, 0xf8U, 0xf6U, 0x64U, 0x86U, 0x68U, 0x98U, 0x16U, - 0xd4U, 0xa4U, 0x5cU, 0xccU, 0x5dU, 0x65U, 0xb6U, 0x92U, - 0x6cU, 0x70U, 0x48U, 0x50U, 0xfdU, 0xedU, 0xb9U, 0xdaU, - 0x5eU, 0x15U, 0x46U, 0x57U, 0xa7U, 0x8dU, 0x9dU, 0x84U, - 0x90U, 0xd8U, 0xabU, 0x00U, 0x8cU, 0xbcU, 0xd3U, 0x0aU, - 0xf7U, 0xe4U, 0x58U, 0x05U, 0xb8U, 0xb3U, 0x45U, 0x06U, - 0xd0U, 0x2cU, 0x1eU, 0x8fU, 0xcaU, 0x3fU, 0x0fU, 0x02U, - 0xc1U, 0xafU, 0xbdU, 0x03U, 0x01U, 0x13U, 0x8aU, 0x6bU, - 0x3aU, 0x91U, 0x11U, 0x41U, 0x4fU, 0x67U, 0xdcU, 0xeaU, - 0x97U, 0xf2U, 0xcfU, 0xceU, 0xf0U, 0xb4U, 0xe6U, 0x73U, - 0x96U, 0xacU, 0x74U, 0x22U, 0xe7U, 0xadU, 0x35U, 0x85U, - 0xe2U, 0xf9U, 0x37U, 0xe8U, 0x1cU, 0x75U, 0xdfU, 0x6eU, - 0x47U, 0xf1U, 0x1aU, 0x71U, 0x1dU, 0x29U, 0xc5U, 0x89U, - 0x6fU, 0xb7U, 0x62U, 0x0eU, 0xaaU, 0x18U, 0xbeU, 0x1bU, - 0xfcU, 0x56U, 0x3eU, 0x4bU, 0xc6U, 0xd2U, 0x79U, 0x20U, - 0x9aU, 0xdbU, 0xc0U, 0xfeU, 0x78U, 0xcdU, 0x5aU, 0xf4U, - 0x1fU, 0xddU, 0xa8U, 0x33U, 0x88U, 0x07U, 0xc7U, 0x31U, - 0xb1U, 0x12U, 0x10U, 0x59U, 0x27U, 0x80U, 0xecU, 0x5fU, - 0x60U, 0x51U, 0x7fU, 0xa9U, 0x19U, 0xb5U, 0x4aU, 0x0dU, - 0x2dU, 0xe5U, 0x7aU, 0x9fU, 0x93U, 0xc9U, 0x9cU, 0xefU, - 0xa0U, 0xe0U, 0x3bU, 0x4dU, 0xaeU, 0x2aU, 0xf5U, 0xb0U, - 0xc8U, 0xebU, 0xbbU, 0x3cU, 0x83U, 0x53U, 0x99U, 0x61U, - 0x17U, 0x2bU, 0x04U, 0x7eU, 0xbaU, 0x77U, 0xd6U, 0x26U, - 0xe1U, 0x69U, 0x14U, 0x63U, 0x55U, 0x21U, 0x0cU, 0x7dU, -}; -const u8 rcons[] = { - 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1B, 0x36 - /* for 128-bit blocks, Rijndael never uses more than 10 rcon values */ -}; -#endif /* AES_SMALL_TABLES */ -/** - * Expand the cipher key into the encryption key schedule. - * - * @return the number of rounds for the given cipher key size. - */ -void rijndaelKeySetupEnc(u32 rk[/*44*/], const u8 cipherKey[]) -{ - int i; - u32 temp; - - rk[0] = GETU32(cipherKey ); - rk[1] = GETU32(cipherKey + 4); - rk[2] = GETU32(cipherKey + 8); - rk[3] = GETU32(cipherKey + 12); - for (i = 0; i < 10; i++) { - temp = rk[3]; - rk[4] = rk[0] ^ - TE421(temp) ^ TE432(temp) ^ TE443(temp) ^ TE414(temp) ^ - RCON(i); - rk[5] = rk[1] ^ rk[4]; - rk[6] = rk[2] ^ rk[5]; - rk[7] = rk[3] ^ rk[6]; - rk += 4; - } -} diff --git a/hostapd-0.8/src/crypto/aes-omac1.c b/hostapd-0.8/src/crypto/aes-omac1.c deleted file mode 100644 index f775296..0000000 --- a/hostapd-0.8/src/crypto/aes-omac1.c +++ /dev/null @@ -1,124 +0,0 @@ -/* - * One-key CBC MAC (OMAC1) hash with AES-128 - * - * Copyright (c) 2003-2007, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#include "includes.h" - -#include "common.h" -#include "aes.h" -#include "aes_wrap.h" - -static void gf_mulx(u8 *pad) -{ - int i, carry; - - carry = pad[0] & 0x80; - for (i = 0; i < AES_BLOCK_SIZE - 1; i++) - pad[i] = (pad[i] << 1) | (pad[i + 1] >> 7); - pad[AES_BLOCK_SIZE - 1] <<= 1; - if (carry) - pad[AES_BLOCK_SIZE - 1] ^= 0x87; -} - - -/** - * omac1_aes_128_vector - One-Key CBC MAC (OMAC1) hash with AES-128 - * @key: 128-bit key for the hash operation - * @num_elem: Number of elements in the data vector - * @addr: Pointers to the data areas - * @len: Lengths of the data blocks - * @mac: Buffer for MAC (128 bits, i.e., 16 bytes) - * Returns: 0 on success, -1 on failure - * - * This is a mode for using block cipher (AES in this case) for authentication. - * OMAC1 was standardized with the name CMAC by NIST in a Special Publication - * (SP) 800-38B. - */ -int omac1_aes_128_vector(const u8 *key, size_t num_elem, - const u8 *addr[], const size_t *len, u8 *mac) -{ - void *ctx; - u8 cbc[AES_BLOCK_SIZE], pad[AES_BLOCK_SIZE]; - const u8 *pos, *end; - size_t i, e, left, total_len; - - ctx = aes_encrypt_init(key, 16); - if (ctx == NULL) - return -1; - os_memset(cbc, 0, AES_BLOCK_SIZE); - - total_len = 0; - for (e = 0; e < num_elem; e++) - total_len += len[e]; - left = total_len; - - e = 0; - pos = addr[0]; - end = pos + len[0]; - - while (left >= AES_BLOCK_SIZE) { - for (i = 0; i < AES_BLOCK_SIZE; i++) { - cbc[i] ^= *pos++; - if (pos >= end) { - e++; - pos = addr[e]; - end = pos + len[e]; - } - } - if (left > AES_BLOCK_SIZE) - aes_encrypt(ctx, cbc, cbc); - left -= AES_BLOCK_SIZE; - } - - os_memset(pad, 0, AES_BLOCK_SIZE); - aes_encrypt(ctx, pad, pad); - gf_mulx(pad); - - if (left || total_len == 0) { - for (i = 0; i < left; i++) { - cbc[i] ^= *pos++; - if (pos >= end) { - e++; - pos = addr[e]; - end = pos + len[e]; - } - } - cbc[left] ^= 0x80; - gf_mulx(pad); - } - - for (i = 0; i < AES_BLOCK_SIZE; i++) - pad[i] ^= cbc[i]; - aes_encrypt(ctx, pad, mac); - aes_encrypt_deinit(ctx); - return 0; -} - - -/** - * omac1_aes_128 - One-Key CBC MAC (OMAC1) hash with AES-128 (aka AES-CMAC) - * @key: 128-bit key for the hash operation - * @data: Data buffer for which a MAC is determined - * @data_len: Length of data buffer in bytes - * @mac: Buffer for MAC (128 bits, i.e., 16 bytes) - * Returns: 0 on success, -1 on failure - * - * This is a mode for using block cipher (AES in this case) for authentication. - * OMAC1 was standardized with the name CMAC by NIST in a Special Publication - * (SP) 800-38B. - */ -int omac1_aes_128(const u8 *key, const u8 *data, size_t data_len, u8 *mac) -{ - return omac1_aes_128_vector(key, 1, &data, &data_len, mac); -} diff --git a/hostapd-0.8/src/crypto/aes-unwrap.c b/hostapd-0.8/src/crypto/aes-unwrap.c deleted file mode 100644 index f233ffa..0000000 --- a/hostapd-0.8/src/crypto/aes-unwrap.c +++ /dev/null @@ -1,79 +0,0 @@ -/* - * AES key unwrap (128-bit KEK, RFC3394) - * - * Copyright (c) 2003-2007, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#include "includes.h" - -#include "common.h" -#include "aes.h" -#include "aes_wrap.h" - -/** - * aes_unwrap - Unwrap key with AES Key Wrap Algorithm (128-bit KEK) (RFC3394) - * @kek: Key encryption key (KEK) - * @n: Length of the plaintext key in 64-bit units; e.g., 2 = 128-bit = 16 - * bytes - * @cipher: Wrapped key to be unwrapped, (n + 1) * 64 bits - * @plain: Plaintext key, n * 64 bits - * Returns: 0 on success, -1 on failure (e.g., integrity verification failed) - */ -int aes_unwrap(const u8 *kek, int n, const u8 *cipher, u8 *plain) -{ - u8 a[8], *r, b[16]; - int i, j; - void *ctx; - - /* 1) Initialize variables. */ - os_memcpy(a, cipher, 8); - r = plain; - os_memcpy(r, cipher + 8, 8 * n); - - ctx = aes_decrypt_init(kek, 16); - if (ctx == NULL) - return -1; - - /* 2) Compute intermediate values. - * For j = 5 to 0 - * For i = n to 1 - * B = AES-1(K, (A ^ t) | R[i]) where t = n*j+i - * A = MSB(64, B) - * R[i] = LSB(64, B) - */ - for (j = 5; j >= 0; j--) { - r = plain + (n - 1) * 8; - for (i = n; i >= 1; i--) { - os_memcpy(b, a, 8); - b[7] ^= n * j + i; - - os_memcpy(b + 8, r, 8); - aes_decrypt(ctx, b, b); - os_memcpy(a, b, 8); - os_memcpy(r, b + 8, 8); - r -= 8; - } - } - aes_decrypt_deinit(ctx); - - /* 3) Output results. - * - * These are already in @plain due to the location of temporary - * variables. Just verify that the IV matches with the expected value. - */ - for (i = 0; i < 8; i++) { - if (a[i] != 0xa6) - return -1; - } - - return 0; -} diff --git a/hostapd-0.8/src/crypto/aes-wrap.c b/hostapd-0.8/src/crypto/aes-wrap.c deleted file mode 100644 index 28d0c89..0000000 --- a/hostapd-0.8/src/crypto/aes-wrap.c +++ /dev/null @@ -1,76 +0,0 @@ -/* - * AES Key Wrap Algorithm (128-bit KEK) (RFC3394) - * - * Copyright (c) 2003-2007, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#include "includes.h" - -#include "common.h" -#include "aes.h" -#include "aes_wrap.h" - -/** - * aes_wrap - Wrap keys with AES Key Wrap Algorithm (128-bit KEK) (RFC3394) - * @kek: 16-octet Key encryption key (KEK) - * @n: Length of the plaintext key in 64-bit units; e.g., 2 = 128-bit = 16 - * bytes - * @plain: Plaintext key to be wrapped, n * 64 bits - * @cipher: Wrapped key, (n + 1) * 64 bits - * Returns: 0 on success, -1 on failure - */ -int aes_wrap(const u8 *kek, int n, const u8 *plain, u8 *cipher) -{ - u8 *a, *r, b[16]; - int i, j; - void *ctx; - - a = cipher; - r = cipher + 8; - - /* 1) Initialize variables. */ - os_memset(a, 0xa6, 8); - os_memcpy(r, plain, 8 * n); - - ctx = aes_encrypt_init(kek, 16); - if (ctx == NULL) - return -1; - - /* 2) Calculate intermediate values. - * For j = 0 to 5 - * For i=1 to n - * B = AES(K, A | R[i]) - * A = MSB(64, B) ^ t where t = (n*j)+i - * R[i] = LSB(64, B) - */ - for (j = 0; j <= 5; j++) { - r = cipher + 8; - for (i = 1; i <= n; i++) { - os_memcpy(b, a, 8); - os_memcpy(b + 8, r, 8); - aes_encrypt(ctx, b, b); - os_memcpy(a, b, 8); - a[7] ^= n * j + i; - os_memcpy(r, b + 8, 8); - r += 8; - } - } - aes_encrypt_deinit(ctx); - - /* 3) Output the results. - * - * These are already in @cipher due to the location of temporary - * variables. - */ - - return 0; -} diff --git a/hostapd-0.8/src/crypto/aes.h b/hostapd-0.8/src/crypto/aes.h deleted file mode 100644 index ba384a9..0000000 --- a/hostapd-0.8/src/crypto/aes.h +++ /dev/null @@ -1,27 +0,0 @@ -/* - * AES functions - * Copyright (c) 2003-2006, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#ifndef AES_H -#define AES_H - -#define AES_BLOCK_SIZE 16 - -void * aes_encrypt_init(const u8 *key, size_t len); -void aes_encrypt(void *ctx, const u8 *plain, u8 *crypt); -void aes_encrypt_deinit(void *ctx); -void * aes_decrypt_init(const u8 *key, size_t len); -void aes_decrypt(void *ctx, const u8 *crypt, u8 *plain); -void aes_decrypt_deinit(void *ctx); - -#endif /* AES_H */ diff --git a/hostapd-0.8/src/crypto/aes_i.h b/hostapd-0.8/src/crypto/aes_i.h deleted file mode 100644 index 6b40bc7..0000000 --- a/hostapd-0.8/src/crypto/aes_i.h +++ /dev/null @@ -1,122 +0,0 @@ -/* - * AES (Rijndael) cipher - * Copyright (c) 2003-2005, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#ifndef AES_I_H -#define AES_I_H - -#include "aes.h" - -/* #define FULL_UNROLL */ -#define AES_SMALL_TABLES - -extern const u32 Te0[256]; -extern const u32 Te1[256]; -extern const u32 Te2[256]; -extern const u32 Te3[256]; -extern const u32 Te4[256]; -extern const u32 Td0[256]; -extern const u32 Td1[256]; -extern const u32 Td2[256]; -extern const u32 Td3[256]; -extern const u32 Td4[256]; -extern const u32 rcon[10]; -extern const u8 Td4s[256]; -extern const u8 rcons[10]; - -#ifndef AES_SMALL_TABLES - -#define RCON(i) rcon[(i)] - -#define TE0(i) Te0[((i) >> 24) & 0xff] -#define TE1(i) Te1[((i) >> 16) & 0xff] -#define TE2(i) Te2[((i) >> 8) & 0xff] -#define TE3(i) Te3[(i) & 0xff] -#define TE41(i) (Te4[((i) >> 24) & 0xff] & 0xff000000) -#define TE42(i) (Te4[((i) >> 16) & 0xff] & 0x00ff0000) -#define TE43(i) (Te4[((i) >> 8) & 0xff] & 0x0000ff00) -#define TE44(i) (Te4[(i) & 0xff] & 0x000000ff) -#define TE421(i) (Te4[((i) >> 16) & 0xff] & 0xff000000) -#define TE432(i) (Te4[((i) >> 8) & 0xff] & 0x00ff0000) -#define TE443(i) (Te4[(i) & 0xff] & 0x0000ff00) -#define TE414(i) (Te4[((i) >> 24) & 0xff] & 0x000000ff) -#define TE4(i) (Te4[(i)] & 0x000000ff) - -#define TD0(i) Td0[((i) >> 24) & 0xff] -#define TD1(i) Td1[((i) >> 16) & 0xff] -#define TD2(i) Td2[((i) >> 8) & 0xff] -#define TD3(i) Td3[(i) & 0xff] -#define TD41(i) (Td4[((i) >> 24) & 0xff] & 0xff000000) -#define TD42(i) (Td4[((i) >> 16) & 0xff] & 0x00ff0000) -#define TD43(i) (Td4[((i) >> 8) & 0xff] & 0x0000ff00) -#define TD44(i) (Td4[(i) & 0xff] & 0x000000ff) -#define TD0_(i) Td0[(i) & 0xff] -#define TD1_(i) Td1[(i) & 0xff] -#define TD2_(i) Td2[(i) & 0xff] -#define TD3_(i) Td3[(i) & 0xff] - -#else /* AES_SMALL_TABLES */ - -#define RCON(i) (rcons[(i)] << 24) - -static inline u32 rotr(u32 val, int bits) -{ - return (val >> bits) | (val << (32 - bits)); -} - -#define TE0(i) Te0[((i) >> 24) & 0xff] -#define TE1(i) rotr(Te0[((i) >> 16) & 0xff], 8) -#define TE2(i) rotr(Te0[((i) >> 8) & 0xff], 16) -#define TE3(i) rotr(Te0[(i) & 0xff], 24) -#define TE41(i) ((Te0[((i) >> 24) & 0xff] << 8) & 0xff000000) -#define TE42(i) (Te0[((i) >> 16) & 0xff] & 0x00ff0000) -#define TE43(i) (Te0[((i) >> 8) & 0xff] & 0x0000ff00) -#define TE44(i) ((Te0[(i) & 0xff] >> 8) & 0x000000ff) -#define TE421(i) ((Te0[((i) >> 16) & 0xff] << 8) & 0xff000000) -#define TE432(i) (Te0[((i) >> 8) & 0xff] & 0x00ff0000) -#define TE443(i) (Te0[(i) & 0xff] & 0x0000ff00) -#define TE414(i) ((Te0[((i) >> 24) & 0xff] >> 8) & 0x000000ff) -#define TE4(i) ((Te0[(i)] >> 8) & 0x000000ff) - -#define TD0(i) Td0[((i) >> 24) & 0xff] -#define TD1(i) rotr(Td0[((i) >> 16) & 0xff], 8) -#define TD2(i) rotr(Td0[((i) >> 8) & 0xff], 16) -#define TD3(i) rotr(Td0[(i) & 0xff], 24) -#define TD41(i) (Td4s[((i) >> 24) & 0xff] << 24) -#define TD42(i) (Td4s[((i) >> 16) & 0xff] << 16) -#define TD43(i) (Td4s[((i) >> 8) & 0xff] << 8) -#define TD44(i) (Td4s[(i) & 0xff]) -#define TD0_(i) Td0[(i) & 0xff] -#define TD1_(i) rotr(Td0[(i) & 0xff], 8) -#define TD2_(i) rotr(Td0[(i) & 0xff], 16) -#define TD3_(i) rotr(Td0[(i) & 0xff], 24) - -#endif /* AES_SMALL_TABLES */ - -#ifdef _MSC_VER -#define SWAP(x) (_lrotl(x, 8) & 0x00ff00ff | _lrotr(x, 8) & 0xff00ff00) -#define GETU32(p) SWAP(*((u32 *)(p))) -#define PUTU32(ct, st) { *((u32 *)(ct)) = SWAP((st)); } -#else -#define GETU32(pt) (((u32)(pt)[0] << 24) ^ ((u32)(pt)[1] << 16) ^ \ -((u32)(pt)[2] << 8) ^ ((u32)(pt)[3])) -#define PUTU32(ct, st) { \ -(ct)[0] = (u8)((st) >> 24); (ct)[1] = (u8)((st) >> 16); \ -(ct)[2] = (u8)((st) >> 8); (ct)[3] = (u8)(st); } -#endif - -#define AES_PRIV_SIZE (4 * 44) - -void rijndaelKeySetupEnc(u32 rk[/*44*/], const u8 cipherKey[]); - -#endif /* AES_I_H */ diff --git a/hostapd-0.8/src/crypto/aes_wrap.h b/hostapd-0.8/src/crypto/aes_wrap.h deleted file mode 100644 index 4b1c7b0..0000000 --- a/hostapd-0.8/src/crypto/aes_wrap.h +++ /dev/null @@ -1,48 +0,0 @@ -/* - * AES-based functions - * - * - AES Key Wrap Algorithm (128-bit KEK) (RFC3394) - * - One-Key CBC MAC (OMAC1) hash with AES-128 - * - AES-128 CTR mode encryption - * - AES-128 EAX mode encryption/decryption - * - AES-128 CBC - * - * Copyright (c) 2003-2007, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#ifndef AES_WRAP_H -#define AES_WRAP_H - -int __must_check aes_wrap(const u8 *kek, int n, const u8 *plain, u8 *cipher); -int __must_check aes_unwrap(const u8 *kek, int n, const u8 *cipher, u8 *plain); -int __must_check omac1_aes_128_vector(const u8 *key, size_t num_elem, - const u8 *addr[], const size_t *len, - u8 *mac); -int __must_check omac1_aes_128(const u8 *key, const u8 *data, size_t data_len, - u8 *mac); -int __must_check aes_128_encrypt_block(const u8 *key, const u8 *in, u8 *out); -int __must_check aes_128_ctr_encrypt(const u8 *key, const u8 *nonce, - u8 *data, size_t data_len); -int __must_check aes_128_eax_encrypt(const u8 *key, - const u8 *nonce, size_t nonce_len, - const u8 *hdr, size_t hdr_len, - u8 *data, size_t data_len, u8 *tag); -int __must_check aes_128_eax_decrypt(const u8 *key, - const u8 *nonce, size_t nonce_len, - const u8 *hdr, size_t hdr_len, - u8 *data, size_t data_len, const u8 *tag); -int __must_check aes_128_cbc_encrypt(const u8 *key, const u8 *iv, u8 *data, - size_t data_len); -int __must_check aes_128_cbc_decrypt(const u8 *key, const u8 *iv, u8 *data, - size_t data_len); - -#endif /* AES_WRAP_H */ diff --git a/hostapd-0.8/src/crypto/crypto.h b/hostapd-0.8/src/crypto/crypto.h deleted file mode 100644 index 587b5a9..0000000 --- a/hostapd-0.8/src/crypto/crypto.h +++ /dev/null @@ -1,469 +0,0 @@ -/* - * WPA Supplicant / wrapper functions for crypto libraries - * Copyright (c) 2004-2009, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - * - * This file defines the cryptographic functions that need to be implemented - * for wpa_supplicant and hostapd. When TLS is not used, internal - * implementation of MD5, SHA1, and AES is used and no external libraries are - * required. When TLS is enabled (e.g., by enabling EAP-TLS or EAP-PEAP), the - * crypto library used by the TLS implementation is expected to be used for - * non-TLS needs, too, in order to save space by not implementing these - * functions twice. - * - * Wrapper code for using each crypto library is in its own file (crypto*.c) - * and one of these files is build and linked in to provide the functions - * defined here. - */ - -#ifndef CRYPTO_H -#define CRYPTO_H - -/** - * md4_vector - MD4 hash for data vector - * @num_elem: Number of elements in the data vector - * @addr: Pointers to the data areas - * @len: Lengths of the data blocks - * @mac: Buffer for the hash - * Returns: 0 on success, -1 on failure - */ -int md4_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac); - -/** - * md5_vector - MD5 hash for data vector - * @num_elem: Number of elements in the data vector - * @addr: Pointers to the data areas - * @len: Lengths of the data blocks - * @mac: Buffer for the hash - * Returns: 0 on success, -1 on failure - */ -int md5_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac); - -#ifdef CONFIG_FIPS -/** - * md5_vector_non_fips_allow - MD5 hash for data vector (non-FIPS use allowed) - * @num_elem: Number of elements in the data vector - * @addr: Pointers to the data areas - * @len: Lengths of the data blocks - * @mac: Buffer for the hash - * Returns: 0 on success, -1 on failure - */ -int md5_vector_non_fips_allow(size_t num_elem, const u8 *addr[], - const size_t *len, u8 *mac); -#else /* CONFIG_FIPS */ -#define md5_vector_non_fips_allow md5_vector -#endif /* CONFIG_FIPS */ - - -/** - * sha1_vector - SHA-1 hash for data vector - * @num_elem: Number of elements in the data vector - * @addr: Pointers to the data areas - * @len: Lengths of the data blocks - * @mac: Buffer for the hash - * Returns: 0 on success, -1 on failure - */ -int sha1_vector(size_t num_elem, const u8 *addr[], const size_t *len, - u8 *mac); - -/** - * fips186_2-prf - NIST FIPS Publication 186-2 change notice 1 PRF - * @seed: Seed/key for the PRF - * @seed_len: Seed length in bytes - * @x: Buffer for PRF output - * @xlen: Output length in bytes - * Returns: 0 on success, -1 on failure - * - * This function implements random number generation specified in NIST FIPS - * Publication 186-2 for EAP-SIM. This PRF uses a function that is similar to - * SHA-1, but has different message padding. - */ -int __must_check fips186_2_prf(const u8 *seed, size_t seed_len, u8 *x, - size_t xlen); - -/** - * sha256_vector - SHA256 hash for data vector - * @num_elem: Number of elements in the data vector - * @addr: Pointers to the data areas - * @len: Lengths of the data blocks - * @mac: Buffer for the hash - * Returns: 0 on success, -1 on failure - */ -int sha256_vector(size_t num_elem, const u8 *addr[], const size_t *len, - u8 *mac); - -/** - * des_encrypt - Encrypt one block with DES - * @clear: 8 octets (in) - * @key: 7 octets (in) (no parity bits included) - * @cypher: 8 octets (out) - */ -void des_encrypt(const u8 *clear, const u8 *key, u8 *cypher); - -/** - * aes_encrypt_init - Initialize AES for encryption - * @key: Encryption key - * @len: Key length in bytes (usually 16, i.e., 128 bits) - * Returns: Pointer to context data or %NULL on failure - */ -void * aes_encrypt_init(const u8 *key, size_t len); - -/** - * aes_encrypt - Encrypt one AES block - * @ctx: Context pointer from aes_encrypt_init() - * @plain: Plaintext data to be encrypted (16 bytes) - * @crypt: Buffer for the encrypted data (16 bytes) - */ -void aes_encrypt(void *ctx, const u8 *plain, u8 *crypt); - -/** - * aes_encrypt_deinit - Deinitialize AES encryption - * @ctx: Context pointer from aes_encrypt_init() - */ -void aes_encrypt_deinit(void *ctx); - -/** - * aes_decrypt_init - Initialize AES for decryption - * @key: Decryption key - * @len: Key length in bytes (usually 16, i.e., 128 bits) - * Returns: Pointer to context data or %NULL on failure - */ -void * aes_decrypt_init(const u8 *key, size_t len); - -/** - * aes_decrypt - Decrypt one AES block - * @ctx: Context pointer from aes_encrypt_init() - * @crypt: Encrypted data (16 bytes) - * @plain: Buffer for the decrypted data (16 bytes) - */ -void aes_decrypt(void *ctx, const u8 *crypt, u8 *plain); - -/** - * aes_decrypt_deinit - Deinitialize AES decryption - * @ctx: Context pointer from aes_encrypt_init() - */ -void aes_decrypt_deinit(void *ctx); - - -enum crypto_hash_alg { - CRYPTO_HASH_ALG_MD5, CRYPTO_HASH_ALG_SHA1, - CRYPTO_HASH_ALG_HMAC_MD5, CRYPTO_HASH_ALG_HMAC_SHA1 -}; - -struct crypto_hash; - -/** - * crypto_hash_init - Initialize hash/HMAC function - * @alg: Hash algorithm - * @key: Key for keyed hash (e.g., HMAC) or %NULL if not needed - * @key_len: Length of the key in bytes - * Returns: Pointer to hash context to use with other hash functions or %NULL - * on failure - * - * This function is only used with internal TLSv1 implementation - * (CONFIG_TLS=internal). If that is not used, the crypto wrapper does not need - * to implement this. - */ -struct crypto_hash * crypto_hash_init(enum crypto_hash_alg alg, const u8 *key, - size_t key_len); - -/** - * crypto_hash_update - Add data to hash calculation - * @ctx: Context pointer from crypto_hash_init() - * @data: Data buffer to add - * @len: Length of the buffer - * - * This function is only used with internal TLSv1 implementation - * (CONFIG_TLS=internal). If that is not used, the crypto wrapper does not need - * to implement this. - */ -void crypto_hash_update(struct crypto_hash *ctx, const u8 *data, size_t len); - -/** - * crypto_hash_finish - Complete hash calculation - * @ctx: Context pointer from crypto_hash_init() - * @hash: Buffer for hash value or %NULL if caller is just freeing the hash - * context - * @len: Pointer to length of the buffer or %NULL if caller is just freeing the - * hash context; on return, this is set to the actual length of the hash value - * Returns: 0 on success, -1 if buffer is too small (len set to needed length), - * or -2 on other failures (including failed crypto_hash_update() operations) - * - * This function calculates the hash value and frees the context buffer that - * was used for hash calculation. - * - * This function is only used with internal TLSv1 implementation - * (CONFIG_TLS=internal). If that is not used, the crypto wrapper does not need - * to implement this. - */ -int crypto_hash_finish(struct crypto_hash *ctx, u8 *hash, size_t *len); - - -enum crypto_cipher_alg { - CRYPTO_CIPHER_NULL = 0, CRYPTO_CIPHER_ALG_AES, CRYPTO_CIPHER_ALG_3DES, - CRYPTO_CIPHER_ALG_DES, CRYPTO_CIPHER_ALG_RC2, CRYPTO_CIPHER_ALG_RC4 -}; - -struct crypto_cipher; - -/** - * crypto_cipher_init - Initialize block/stream cipher function - * @alg: Cipher algorithm - * @iv: Initialization vector for block ciphers or %NULL for stream ciphers - * @key: Cipher key - * @key_len: Length of key in bytes - * Returns: Pointer to cipher context to use with other cipher functions or - * %NULL on failure - * - * This function is only used with internal TLSv1 implementation - * (CONFIG_TLS=internal). If that is not used, the crypto wrapper does not need - * to implement this. - */ -struct crypto_cipher * crypto_cipher_init(enum crypto_cipher_alg alg, - const u8 *iv, const u8 *key, - size_t key_len); - -/** - * crypto_cipher_encrypt - Cipher encrypt - * @ctx: Context pointer from crypto_cipher_init() - * @plain: Plaintext to cipher - * @crypt: Resulting ciphertext - * @len: Length of the plaintext - * Returns: 0 on success, -1 on failure - * - * This function is only used with internal TLSv1 implementation - * (CONFIG_TLS=internal). If that is not used, the crypto wrapper does not need - * to implement this. - */ -int __must_check crypto_cipher_encrypt(struct crypto_cipher *ctx, - const u8 *plain, u8 *crypt, size_t len); - -/** - * crypto_cipher_decrypt - Cipher decrypt - * @ctx: Context pointer from crypto_cipher_init() - * @crypt: Ciphertext to decrypt - * @plain: Resulting plaintext - * @len: Length of the cipher text - * Returns: 0 on success, -1 on failure - * - * This function is only used with internal TLSv1 implementation - * (CONFIG_TLS=internal). If that is not used, the crypto wrapper does not need - * to implement this. - */ -int __must_check crypto_cipher_decrypt(struct crypto_cipher *ctx, - const u8 *crypt, u8 *plain, size_t len); - -/** - * crypto_cipher_decrypt - Free cipher context - * @ctx: Context pointer from crypto_cipher_init() - * - * This function is only used with internal TLSv1 implementation - * (CONFIG_TLS=internal). If that is not used, the crypto wrapper does not need - * to implement this. - */ -void crypto_cipher_deinit(struct crypto_cipher *ctx); - - -struct crypto_public_key; -struct crypto_private_key; - -/** - * crypto_public_key_import - Import an RSA public key - * @key: Key buffer (DER encoded RSA public key) - * @len: Key buffer length in bytes - * Returns: Pointer to the public key or %NULL on failure - * - * This function can just return %NULL if the crypto library supports X.509 - * parsing. In that case, crypto_public_key_from_cert() is used to import the - * public key from a certificate. - * - * This function is only used with internal TLSv1 implementation - * (CONFIG_TLS=internal). If that is not used, the crypto wrapper does not need - * to implement this. - */ -struct crypto_public_key * crypto_public_key_import(const u8 *key, size_t len); - -/** - * crypto_private_key_import - Import an RSA private key - * @key: Key buffer (DER encoded RSA private key) - * @len: Key buffer length in bytes - * @passwd: Key encryption password or %NULL if key is not encrypted - * Returns: Pointer to the private key or %NULL on failure - * - * This function is only used with internal TLSv1 implementation - * (CONFIG_TLS=internal). If that is not used, the crypto wrapper does not need - * to implement this. - */ -struct crypto_private_key * crypto_private_key_import(const u8 *key, - size_t len, - const char *passwd); - -/** - * crypto_public_key_from_cert - Import an RSA public key from a certificate - * @buf: DER encoded X.509 certificate - * @len: Certificate buffer length in bytes - * Returns: Pointer to public key or %NULL on failure - * - * This function can just return %NULL if the crypto library does not support - * X.509 parsing. In that case, internal code will be used to parse the - * certificate and public key is imported using crypto_public_key_import(). - * - * This function is only used with internal TLSv1 implementation - * (CONFIG_TLS=internal). If that is not used, the crypto wrapper does not need - * to implement this. - */ -struct crypto_public_key * crypto_public_key_from_cert(const u8 *buf, - size_t len); - -/** - * crypto_public_key_encrypt_pkcs1_v15 - Public key encryption (PKCS #1 v1.5) - * @key: Public key - * @in: Plaintext buffer - * @inlen: Length of plaintext buffer in bytes - * @out: Output buffer for encrypted data - * @outlen: Length of output buffer in bytes; set to used length on success - * Returns: 0 on success, -1 on failure - * - * This function is only used with internal TLSv1 implementation - * (CONFIG_TLS=internal). If that is not used, the crypto wrapper does not need - * to implement this. - */ -int __must_check crypto_public_key_encrypt_pkcs1_v15( - struct crypto_public_key *key, const u8 *in, size_t inlen, - u8 *out, size_t *outlen); - -/** - * crypto_private_key_decrypt_pkcs1_v15 - Private key decryption (PKCS #1 v1.5) - * @key: Private key - * @in: Encrypted buffer - * @inlen: Length of encrypted buffer in bytes - * @out: Output buffer for encrypted data - * @outlen: Length of output buffer in bytes; set to used length on success - * Returns: 0 on success, -1 on failure - * - * This function is only used with internal TLSv1 implementation - * (CONFIG_TLS=internal). If that is not used, the crypto wrapper does not need - * to implement this. - */ -int __must_check crypto_private_key_decrypt_pkcs1_v15( - struct crypto_private_key *key, const u8 *in, size_t inlen, - u8 *out, size_t *outlen); - -/** - * crypto_private_key_sign_pkcs1 - Sign with private key (PKCS #1) - * @key: Private key from crypto_private_key_import() - * @in: Plaintext buffer - * @inlen: Length of plaintext buffer in bytes - * @out: Output buffer for encrypted (signed) data - * @outlen: Length of output buffer in bytes; set to used length on success - * Returns: 0 on success, -1 on failure - * - * This function is only used with internal TLSv1 implementation - * (CONFIG_TLS=internal). If that is not used, the crypto wrapper does not need - * to implement this. - */ -int __must_check crypto_private_key_sign_pkcs1(struct crypto_private_key *key, - const u8 *in, size_t inlen, - u8 *out, size_t *outlen); - -/** - * crypto_public_key_free - Free public key - * @key: Public key - * - * This function is only used with internal TLSv1 implementation - * (CONFIG_TLS=internal). If that is not used, the crypto wrapper does not need - * to implement this. - */ -void crypto_public_key_free(struct crypto_public_key *key); - -/** - * crypto_private_key_free - Free private key - * @key: Private key from crypto_private_key_import() - * - * This function is only used with internal TLSv1 implementation - * (CONFIG_TLS=internal). If that is not used, the crypto wrapper does not need - * to implement this. - */ -void crypto_private_key_free(struct crypto_private_key *key); - -/** - * crypto_public_key_decrypt_pkcs1 - Decrypt PKCS #1 signature - * @key: Public key - * @crypt: Encrypted signature data (using the private key) - * @crypt_len: Encrypted signature data length - * @plain: Buffer for plaintext (at least crypt_len bytes) - * @plain_len: Plaintext length (max buffer size on input, real len on output); - * Returns: 0 on success, -1 on failure - */ -int __must_check crypto_public_key_decrypt_pkcs1( - struct crypto_public_key *key, const u8 *crypt, size_t crypt_len, - u8 *plain, size_t *plain_len); - -/** - * crypto_global_init - Initialize crypto wrapper - * - * This function is only used with internal TLSv1 implementation - * (CONFIG_TLS=internal). If that is not used, the crypto wrapper does not need - * to implement this. - */ -int __must_check crypto_global_init(void); - -/** - * crypto_global_deinit - Deinitialize crypto wrapper - * - * This function is only used with internal TLSv1 implementation - * (CONFIG_TLS=internal). If that is not used, the crypto wrapper does not need - * to implement this. - */ -void crypto_global_deinit(void); - -/** - * crypto_mod_exp - Modular exponentiation of large integers - * @base: Base integer (big endian byte array) - * @base_len: Length of base integer in bytes - * @power: Power integer (big endian byte array) - * @power_len: Length of power integer in bytes - * @modulus: Modulus integer (big endian byte array) - * @modulus_len: Length of modulus integer in bytes - * @result: Buffer for the result - * @result_len: Result length (max buffer size on input, real len on output) - * Returns: 0 on success, -1 on failure - * - * This function calculates result = base ^ power mod modulus. modules_len is - * used as the maximum size of modulus buffer. It is set to the used size on - * success. - * - * This function is only used with internal TLSv1 implementation - * (CONFIG_TLS=internal). If that is not used, the crypto wrapper does not need - * to implement this. - */ -int __must_check crypto_mod_exp(const u8 *base, size_t base_len, - const u8 *power, size_t power_len, - const u8 *modulus, size_t modulus_len, - u8 *result, size_t *result_len); - -/** - * rc4_skip - XOR RC4 stream to given data with skip-stream-start - * @key: RC4 key - * @keylen: RC4 key length - * @skip: number of bytes to skip from the beginning of the RC4 stream - * @data: data to be XOR'ed with RC4 stream - * @data_len: buf length - * Returns: 0 on success, -1 on failure - * - * Generate RC4 pseudo random stream for the given key, skip beginning of the - * stream, and XOR the end result with the data buffer to perform RC4 - * encryption/decryption. - */ -int rc4_skip(const u8 *key, size_t keylen, size_t skip, - u8 *data, size_t data_len); - -#endif /* CRYPTO_H */ diff --git a/hostapd-0.8/src/crypto/crypto_cryptoapi.c b/hostapd-0.8/src/crypto/crypto_cryptoapi.c deleted file mode 100644 index 2a8d200..0000000 --- a/hostapd-0.8/src/crypto/crypto_cryptoapi.c +++ /dev/null @@ -1,789 +0,0 @@ -/* - * Crypto wrapper for Microsoft CryptoAPI - * Copyright (c) 2005-2009, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#include "includes.h" -#include -#include - -#include "common.h" -#include "crypto.h" - -#ifndef MS_ENH_RSA_AES_PROV -#ifdef UNICODE -#define MS_ENH_RSA_AES_PROV \ -L"Microsoft Enhanced RSA and AES Cryptographic Provider (Prototype)" -#else -#define MS_ENH_RSA_AES_PROV \ -"Microsoft Enhanced RSA and AES Cryptographic Provider (Prototype)" -#endif -#endif /* MS_ENH_RSA_AES_PROV */ - -#ifndef CALG_HMAC -#define CALG_HMAC (ALG_CLASS_HASH | ALG_TYPE_ANY | ALG_SID_HMAC) -#endif - -#ifdef __MINGW32_VERSION -/* - * MinGW does not yet include all the needed definitions for CryptoAPI, so - * define here whatever extra is needed. - */ - -static BOOL WINAPI -(*CryptImportPublicKeyInfo)(HCRYPTPROV hCryptProv, DWORD dwCertEncodingType, - PCERT_PUBLIC_KEY_INFO pInfo, HCRYPTKEY *phKey) -= NULL; /* to be loaded from crypt32.dll */ - - -static int mingw_load_crypto_func(void) -{ - HINSTANCE dll; - - /* MinGW does not yet have full CryptoAPI support, so load the needed - * function here. */ - - if (CryptImportPublicKeyInfo) - return 0; - - dll = LoadLibrary("crypt32"); - if (dll == NULL) { - wpa_printf(MSG_DEBUG, "CryptoAPI: Could not load crypt32 " - "library"); - return -1; - } - - CryptImportPublicKeyInfo = GetProcAddress( - dll, "CryptImportPublicKeyInfo"); - if (CryptImportPublicKeyInfo == NULL) { - wpa_printf(MSG_DEBUG, "CryptoAPI: Could not get " - "CryptImportPublicKeyInfo() address from " - "crypt32 library"); - return -1; - } - - return 0; -} - -#else /* __MINGW32_VERSION */ - -static int mingw_load_crypto_func(void) -{ - return 0; -} - -#endif /* __MINGW32_VERSION */ - - -static void cryptoapi_report_error(const char *msg) -{ - char *s, *pos; - DWORD err = GetLastError(); - - if (FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | - FORMAT_MESSAGE_FROM_SYSTEM, - NULL, err, 0, (LPTSTR) &s, 0, NULL) == 0) { - wpa_printf(MSG_DEBUG, "CryptoAPI: %s: %d", msg, (int) err); - } - - pos = s; - while (*pos) { - if (*pos == '\n' || *pos == '\r') { - *pos = '\0'; - break; - } - pos++; - } - - wpa_printf(MSG_DEBUG, "CryptoAPI: %s: %d: (%s)", msg, (int) err, s); - LocalFree(s); -} - - -int cryptoapi_hash_vector(ALG_ID alg, size_t hash_len, size_t num_elem, - const u8 *addr[], const size_t *len, u8 *mac) -{ - HCRYPTPROV prov; - HCRYPTHASH hash; - size_t i; - DWORD hlen; - int ret = 0; - - if (!CryptAcquireContext(&prov, NULL, NULL, PROV_RSA_FULL, 0)) { - cryptoapi_report_error("CryptAcquireContext"); - return -1; - } - - if (!CryptCreateHash(prov, alg, 0, 0, &hash)) { - cryptoapi_report_error("CryptCreateHash"); - CryptReleaseContext(prov, 0); - return -1; - } - - for (i = 0; i < num_elem; i++) { - if (!CryptHashData(hash, (BYTE *) addr[i], len[i], 0)) { - cryptoapi_report_error("CryptHashData"); - CryptDestroyHash(hash); - CryptReleaseContext(prov, 0); - } - } - - hlen = hash_len; - if (!CryptGetHashParam(hash, HP_HASHVAL, mac, &hlen, 0)) { - cryptoapi_report_error("CryptGetHashParam"); - ret = -1; - } - - CryptDestroyHash(hash); - CryptReleaseContext(prov, 0); - - return ret; -} - - -int md4_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac) -{ - return cryptoapi_hash_vector(CALG_MD4, 16, num_elem, addr, len, mac); -} - - -void des_encrypt(const u8 *clear, const u8 *key, u8 *cypher) -{ - u8 next, tmp; - int i; - HCRYPTPROV prov; - HCRYPTKEY ckey; - DWORD dlen; - struct { - BLOBHEADER hdr; - DWORD len; - BYTE key[8]; - } key_blob; - DWORD mode = CRYPT_MODE_ECB; - - key_blob.hdr.bType = PLAINTEXTKEYBLOB; - key_blob.hdr.bVersion = CUR_BLOB_VERSION; - key_blob.hdr.reserved = 0; - key_blob.hdr.aiKeyAlg = CALG_DES; - key_blob.len = 8; - - /* Add parity bits to the key */ - next = 0; - for (i = 0; i < 7; i++) { - tmp = key[i]; - key_blob.key[i] = (tmp >> i) | next | 1; - next = tmp << (7 - i); - } - key_blob.key[i] = next | 1; - - if (!CryptAcquireContext(&prov, NULL, MS_ENHANCED_PROV, PROV_RSA_FULL, - CRYPT_VERIFYCONTEXT)) { - wpa_printf(MSG_DEBUG, "CryptoAPI: CryptAcquireContext failed: " - "%d", (int) GetLastError()); - return; - } - - if (!CryptImportKey(prov, (BYTE *) &key_blob, sizeof(key_blob), 0, 0, - &ckey)) { - wpa_printf(MSG_DEBUG, "CryptoAPI: CryptImportKey failed: %d", - (int) GetLastError()); - CryptReleaseContext(prov, 0); - return; - } - - if (!CryptSetKeyParam(ckey, KP_MODE, (BYTE *) &mode, 0)) { - wpa_printf(MSG_DEBUG, "CryptoAPI: CryptSetKeyParam(KP_MODE) " - "failed: %d", (int) GetLastError()); - CryptDestroyKey(ckey); - CryptReleaseContext(prov, 0); - return; - } - - os_memcpy(cypher, clear, 8); - dlen = 8; - if (!CryptEncrypt(ckey, 0, FALSE, 0, cypher, &dlen, 8)) { - wpa_printf(MSG_DEBUG, "CryptoAPI: CryptEncrypt failed: %d", - (int) GetLastError()); - os_memset(cypher, 0, 8); - } - - CryptDestroyKey(ckey); - CryptReleaseContext(prov, 0); -} - - -int md5_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac) -{ - return cryptoapi_hash_vector(CALG_MD5, 16, num_elem, addr, len, mac); -} - - -int sha1_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac) -{ - return cryptoapi_hash_vector(CALG_SHA, 20, num_elem, addr, len, mac); -} - - -struct aes_context { - HCRYPTPROV prov; - HCRYPTKEY ckey; -}; - - -void * aes_encrypt_init(const u8 *key, size_t len) -{ - struct aes_context *akey; - struct { - BLOBHEADER hdr; - DWORD len; - BYTE key[16]; - } key_blob; - DWORD mode = CRYPT_MODE_ECB; - - if (len != 16) - return NULL; - - key_blob.hdr.bType = PLAINTEXTKEYBLOB; - key_blob.hdr.bVersion = CUR_BLOB_VERSION; - key_blob.hdr.reserved = 0; - key_blob.hdr.aiKeyAlg = CALG_AES_128; - key_blob.len = len; - os_memcpy(key_blob.key, key, len); - - akey = os_zalloc(sizeof(*akey)); - if (akey == NULL) - return NULL; - - if (!CryptAcquireContext(&akey->prov, NULL, - MS_ENH_RSA_AES_PROV, PROV_RSA_AES, - CRYPT_VERIFYCONTEXT)) { - wpa_printf(MSG_DEBUG, "CryptoAPI: CryptAcquireContext failed: " - "%d", (int) GetLastError()); - os_free(akey); - return NULL; - } - - if (!CryptImportKey(akey->prov, (BYTE *) &key_blob, sizeof(key_blob), - 0, 0, &akey->ckey)) { - wpa_printf(MSG_DEBUG, "CryptoAPI: CryptImportKey failed: %d", - (int) GetLastError()); - CryptReleaseContext(akey->prov, 0); - os_free(akey); - return NULL; - } - - if (!CryptSetKeyParam(akey->ckey, KP_MODE, (BYTE *) &mode, 0)) { - wpa_printf(MSG_DEBUG, "CryptoAPI: CryptSetKeyParam(KP_MODE) " - "failed: %d", (int) GetLastError()); - CryptDestroyKey(akey->ckey); - CryptReleaseContext(akey->prov, 0); - os_free(akey); - return NULL; - } - - return akey; -} - - -void aes_encrypt(void *ctx, const u8 *plain, u8 *crypt) -{ - struct aes_context *akey = ctx; - DWORD dlen; - - os_memcpy(crypt, plain, 16); - dlen = 16; - if (!CryptEncrypt(akey->ckey, 0, FALSE, 0, crypt, &dlen, 16)) { - wpa_printf(MSG_DEBUG, "CryptoAPI: CryptEncrypt failed: %d", - (int) GetLastError()); - os_memset(crypt, 0, 16); - } -} - - -void aes_encrypt_deinit(void *ctx) -{ - struct aes_context *akey = ctx; - if (akey) { - CryptDestroyKey(akey->ckey); - CryptReleaseContext(akey->prov, 0); - os_free(akey); - } -} - - -void * aes_decrypt_init(const u8 *key, size_t len) -{ - return aes_encrypt_init(key, len); -} - - -void aes_decrypt(void *ctx, const u8 *crypt, u8 *plain) -{ - struct aes_context *akey = ctx; - DWORD dlen; - - os_memcpy(plain, crypt, 16); - dlen = 16; - - if (!CryptDecrypt(akey->ckey, 0, FALSE, 0, plain, &dlen)) { - wpa_printf(MSG_DEBUG, "CryptoAPI: CryptDecrypt failed: %d", - (int) GetLastError()); - } -} - - -void aes_decrypt_deinit(void *ctx) -{ - aes_encrypt_deinit(ctx); -} - - -struct crypto_hash { - enum crypto_hash_alg alg; - int error; - HCRYPTPROV prov; - HCRYPTHASH hash; - HCRYPTKEY key; -}; - -struct crypto_hash * crypto_hash_init(enum crypto_hash_alg alg, const u8 *key, - size_t key_len) -{ - struct crypto_hash *ctx; - ALG_ID calg; - struct { - BLOBHEADER hdr; - DWORD len; - BYTE key[32]; - } key_blob; - - os_memset(&key_blob, 0, sizeof(key_blob)); - switch (alg) { - case CRYPTO_HASH_ALG_MD5: - calg = CALG_MD5; - break; - case CRYPTO_HASH_ALG_SHA1: - calg = CALG_SHA; - break; - case CRYPTO_HASH_ALG_HMAC_MD5: - case CRYPTO_HASH_ALG_HMAC_SHA1: - calg = CALG_HMAC; - key_blob.hdr.bType = PLAINTEXTKEYBLOB; - key_blob.hdr.bVersion = CUR_BLOB_VERSION; - key_blob.hdr.reserved = 0; - /* - * Note: RC2 is not really used, but that can be used to - * import HMAC keys of up to 16 byte long. - * CRYPT_IPSEC_HMAC_KEY flag for CryptImportKey() is needed to - * be able to import longer keys (HMAC-SHA1 uses 20-byte key). - */ - key_blob.hdr.aiKeyAlg = CALG_RC2; - key_blob.len = key_len; - if (key_len > sizeof(key_blob.key)) - return NULL; - os_memcpy(key_blob.key, key, key_len); - break; - default: - return NULL; - } - - ctx = os_zalloc(sizeof(*ctx)); - if (ctx == NULL) - return NULL; - - ctx->alg = alg; - - if (!CryptAcquireContext(&ctx->prov, NULL, NULL, PROV_RSA_FULL, 0)) { - cryptoapi_report_error("CryptAcquireContext"); - os_free(ctx); - return NULL; - } - - if (calg == CALG_HMAC) { -#ifndef CRYPT_IPSEC_HMAC_KEY -#define CRYPT_IPSEC_HMAC_KEY 0x00000100 -#endif - if (!CryptImportKey(ctx->prov, (BYTE *) &key_blob, - sizeof(key_blob), 0, CRYPT_IPSEC_HMAC_KEY, - &ctx->key)) { - cryptoapi_report_error("CryptImportKey"); - CryptReleaseContext(ctx->prov, 0); - os_free(ctx); - return NULL; - } - } - - if (!CryptCreateHash(ctx->prov, calg, ctx->key, 0, &ctx->hash)) { - cryptoapi_report_error("CryptCreateHash"); - CryptReleaseContext(ctx->prov, 0); - os_free(ctx); - return NULL; - } - - if (calg == CALG_HMAC) { - HMAC_INFO info; - os_memset(&info, 0, sizeof(info)); - switch (alg) { - case CRYPTO_HASH_ALG_HMAC_MD5: - info.HashAlgid = CALG_MD5; - break; - case CRYPTO_HASH_ALG_HMAC_SHA1: - info.HashAlgid = CALG_SHA; - break; - default: - /* unreachable */ - break; - } - - if (!CryptSetHashParam(ctx->hash, HP_HMAC_INFO, (BYTE *) &info, - 0)) { - cryptoapi_report_error("CryptSetHashParam"); - CryptDestroyHash(ctx->hash); - CryptReleaseContext(ctx->prov, 0); - os_free(ctx); - return NULL; - } - } - - return ctx; -} - - -void crypto_hash_update(struct crypto_hash *ctx, const u8 *data, size_t len) -{ - if (ctx == NULL || ctx->error) - return; - - if (!CryptHashData(ctx->hash, (BYTE *) data, len, 0)) { - cryptoapi_report_error("CryptHashData"); - ctx->error = 1; - } -} - - -int crypto_hash_finish(struct crypto_hash *ctx, u8 *mac, size_t *len) -{ - int ret = 0; - DWORD hlen; - - if (ctx == NULL) - return -2; - - if (mac == NULL || len == NULL) - goto done; - - if (ctx->error) { - ret = -2; - goto done; - } - - hlen = *len; - if (!CryptGetHashParam(ctx->hash, HP_HASHVAL, mac, &hlen, 0)) { - cryptoapi_report_error("CryptGetHashParam"); - ret = -2; - } - *len = hlen; - -done: - if (ctx->alg == CRYPTO_HASH_ALG_HMAC_SHA1 || - ctx->alg == CRYPTO_HASH_ALG_HMAC_MD5) - CryptDestroyKey(ctx->key); - - os_free(ctx); - - return ret; -} - - -struct crypto_cipher { - HCRYPTPROV prov; - HCRYPTKEY key; -}; - - -struct crypto_cipher * crypto_cipher_init(enum crypto_cipher_alg alg, - const u8 *iv, const u8 *key, - size_t key_len) -{ - struct crypto_cipher *ctx; - struct { - BLOBHEADER hdr; - DWORD len; - BYTE key[32]; - } key_blob; - DWORD mode = CRYPT_MODE_CBC; - - key_blob.hdr.bType = PLAINTEXTKEYBLOB; - key_blob.hdr.bVersion = CUR_BLOB_VERSION; - key_blob.hdr.reserved = 0; - key_blob.len = key_len; - if (key_len > sizeof(key_blob.key)) - return NULL; - os_memcpy(key_blob.key, key, key_len); - - switch (alg) { - case CRYPTO_CIPHER_ALG_AES: - if (key_len == 32) - key_blob.hdr.aiKeyAlg = CALG_AES_256; - else if (key_len == 24) - key_blob.hdr.aiKeyAlg = CALG_AES_192; - else - key_blob.hdr.aiKeyAlg = CALG_AES_128; - break; - case CRYPTO_CIPHER_ALG_3DES: - key_blob.hdr.aiKeyAlg = CALG_3DES; - break; - case CRYPTO_CIPHER_ALG_DES: - key_blob.hdr.aiKeyAlg = CALG_DES; - break; - case CRYPTO_CIPHER_ALG_RC2: - key_blob.hdr.aiKeyAlg = CALG_RC2; - break; - case CRYPTO_CIPHER_ALG_RC4: - key_blob.hdr.aiKeyAlg = CALG_RC4; - break; - default: - return NULL; - } - - ctx = os_zalloc(sizeof(*ctx)); - if (ctx == NULL) - return NULL; - - if (!CryptAcquireContext(&ctx->prov, NULL, MS_ENH_RSA_AES_PROV, - PROV_RSA_AES, CRYPT_VERIFYCONTEXT)) { - cryptoapi_report_error("CryptAcquireContext"); - goto fail1; - } - - if (!CryptImportKey(ctx->prov, (BYTE *) &key_blob, - sizeof(key_blob), 0, 0, &ctx->key)) { - cryptoapi_report_error("CryptImportKey"); - goto fail2; - } - - if (!CryptSetKeyParam(ctx->key, KP_MODE, (BYTE *) &mode, 0)) { - cryptoapi_report_error("CryptSetKeyParam(KP_MODE)"); - goto fail3; - } - - if (iv && !CryptSetKeyParam(ctx->key, KP_IV, (BYTE *) iv, 0)) { - cryptoapi_report_error("CryptSetKeyParam(KP_IV)"); - goto fail3; - } - - return ctx; - -fail3: - CryptDestroyKey(ctx->key); -fail2: - CryptReleaseContext(ctx->prov, 0); -fail1: - os_free(ctx); - return NULL; -} - - -int crypto_cipher_encrypt(struct crypto_cipher *ctx, const u8 *plain, - u8 *crypt, size_t len) -{ - DWORD dlen; - - os_memcpy(crypt, plain, len); - dlen = len; - if (!CryptEncrypt(ctx->key, 0, FALSE, 0, crypt, &dlen, len)) { - cryptoapi_report_error("CryptEncrypt"); - os_memset(crypt, 0, len); - return -1; - } - - return 0; -} - - -int crypto_cipher_decrypt(struct crypto_cipher *ctx, const u8 *crypt, - u8 *plain, size_t len) -{ - DWORD dlen; - - os_memcpy(plain, crypt, len); - dlen = len; - if (!CryptDecrypt(ctx->key, 0, FALSE, 0, plain, &dlen)) { - cryptoapi_report_error("CryptDecrypt"); - return -1; - } - - return 0; -} - - -void crypto_cipher_deinit(struct crypto_cipher *ctx) -{ - CryptDestroyKey(ctx->key); - CryptReleaseContext(ctx->prov, 0); - os_free(ctx); -} - - -struct crypto_public_key { - HCRYPTPROV prov; - HCRYPTKEY rsa; -}; - -struct crypto_private_key { - HCRYPTPROV prov; - HCRYPTKEY rsa; -}; - - -struct crypto_public_key * crypto_public_key_import(const u8 *key, size_t len) -{ - /* Use crypto_public_key_from_cert() instead. */ - return NULL; -} - - -struct crypto_private_key * crypto_private_key_import(const u8 *key, - size_t len, - const char *passwd) -{ - /* TODO */ - return NULL; -} - - -struct crypto_public_key * crypto_public_key_from_cert(const u8 *buf, - size_t len) -{ - struct crypto_public_key *pk; - PCCERT_CONTEXT cc; - - pk = os_zalloc(sizeof(*pk)); - if (pk == NULL) - return NULL; - - cc = CertCreateCertificateContext(X509_ASN_ENCODING | - PKCS_7_ASN_ENCODING, buf, len); - if (!cc) { - cryptoapi_report_error("CryptCreateCertificateContext"); - os_free(pk); - return NULL; - } - - if (!CryptAcquireContext(&pk->prov, NULL, MS_DEF_PROV, PROV_RSA_FULL, - 0)) { - cryptoapi_report_error("CryptAcquireContext"); - os_free(pk); - CertFreeCertificateContext(cc); - return NULL; - } - - if (!CryptImportPublicKeyInfo(pk->prov, X509_ASN_ENCODING | - PKCS_7_ASN_ENCODING, - &cc->pCertInfo->SubjectPublicKeyInfo, - &pk->rsa)) { - cryptoapi_report_error("CryptImportPublicKeyInfo"); - CryptReleaseContext(pk->prov, 0); - os_free(pk); - CertFreeCertificateContext(cc); - return NULL; - } - - CertFreeCertificateContext(cc); - - return pk; -} - - -int crypto_public_key_encrypt_pkcs1_v15(struct crypto_public_key *key, - const u8 *in, size_t inlen, - u8 *out, size_t *outlen) -{ - DWORD clen; - u8 *tmp; - size_t i; - - if (*outlen < inlen) - return -1; - tmp = malloc(*outlen); - if (tmp == NULL) - return -1; - - os_memcpy(tmp, in, inlen); - clen = inlen; - if (!CryptEncrypt(key->rsa, 0, TRUE, 0, tmp, &clen, *outlen)) { - wpa_printf(MSG_DEBUG, "CryptoAPI: Failed to encrypt using " - "public key: %d", (int) GetLastError()); - os_free(tmp); - return -1; - } - - *outlen = clen; - - /* Reverse the output */ - for (i = 0; i < *outlen; i++) - out[i] = tmp[*outlen - 1 - i]; - - os_free(tmp); - - return 0; -} - - -int crypto_private_key_sign_pkcs1(struct crypto_private_key *key, - const u8 *in, size_t inlen, - u8 *out, size_t *outlen) -{ - /* TODO */ - return -1; -} - - -void crypto_public_key_free(struct crypto_public_key *key) -{ - if (key) { - CryptDestroyKey(key->rsa); - CryptReleaseContext(key->prov, 0); - os_free(key); - } -} - - -void crypto_private_key_free(struct crypto_private_key *key) -{ - if (key) { - CryptDestroyKey(key->rsa); - CryptReleaseContext(key->prov, 0); - os_free(key); - } -} - - -int crypto_global_init(void) -{ - return mingw_load_crypto_func(); -} - - -void crypto_global_deinit(void) -{ -} - - -int crypto_mod_exp(const u8 *base, size_t base_len, - const u8 *power, size_t power_len, - const u8 *modulus, size_t modulus_len, - u8 *result, size_t *result_len) -{ - /* TODO */ - return -1; -} diff --git a/hostapd-0.8/src/crypto/crypto_gnutls.c b/hostapd-0.8/src/crypto/crypto_gnutls.c deleted file mode 100644 index 0998cca..0000000 --- a/hostapd-0.8/src/crypto/crypto_gnutls.c +++ /dev/null @@ -1,305 +0,0 @@ -/* - * WPA Supplicant / wrapper functions for libgcrypt - * Copyright (c) 2004-2009, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#include "includes.h" -#include - -#include "common.h" -#include "crypto.h" - -int md4_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac) -{ - gcry_md_hd_t hd; - unsigned char *p; - size_t i; - - if (gcry_md_open(&hd, GCRY_MD_MD4, 0) != GPG_ERR_NO_ERROR) - return -1; - for (i = 0; i < num_elem; i++) - gcry_md_write(hd, addr[i], len[i]); - p = gcry_md_read(hd, GCRY_MD_MD4); - if (p) - memcpy(mac, p, gcry_md_get_algo_dlen(GCRY_MD_MD4)); - gcry_md_close(hd); - return 0; -} - - -void des_encrypt(const u8 *clear, const u8 *key, u8 *cypher) -{ - gcry_cipher_hd_t hd; - u8 pkey[8], next, tmp; - int i; - - /* Add parity bits to the key */ - next = 0; - for (i = 0; i < 7; i++) { - tmp = key[i]; - pkey[i] = (tmp >> i) | next | 1; - next = tmp << (7 - i); - } - pkey[i] = next | 1; - - gcry_cipher_open(&hd, GCRY_CIPHER_DES, GCRY_CIPHER_MODE_ECB, 0); - gcry_err_code(gcry_cipher_setkey(hd, pkey, 8)); - gcry_cipher_encrypt(hd, cypher, 8, clear, 8); - gcry_cipher_close(hd); -} - - -int md5_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac) -{ - gcry_md_hd_t hd; - unsigned char *p; - size_t i; - - if (gcry_md_open(&hd, GCRY_MD_MD5, 0) != GPG_ERR_NO_ERROR) - return -1; - for (i = 0; i < num_elem; i++) - gcry_md_write(hd, addr[i], len[i]); - p = gcry_md_read(hd, GCRY_MD_MD5); - if (p) - memcpy(mac, p, gcry_md_get_algo_dlen(GCRY_MD_MD5)); - gcry_md_close(hd); - return 0; -} - - -int sha1_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac) -{ - gcry_md_hd_t hd; - unsigned char *p; - size_t i; - - if (gcry_md_open(&hd, GCRY_MD_SHA1, 0) != GPG_ERR_NO_ERROR) - return -1; - for (i = 0; i < num_elem; i++) - gcry_md_write(hd, addr[i], len[i]); - p = gcry_md_read(hd, GCRY_MD_SHA1); - if (p) - memcpy(mac, p, gcry_md_get_algo_dlen(GCRY_MD_SHA1)); - gcry_md_close(hd); - return 0; -} - - -void * aes_encrypt_init(const u8 *key, size_t len) -{ - gcry_cipher_hd_t hd; - - if (gcry_cipher_open(&hd, GCRY_CIPHER_AES, GCRY_CIPHER_MODE_ECB, 0) != - GPG_ERR_NO_ERROR) { - printf("cipher open failed\n"); - return NULL; - } - if (gcry_cipher_setkey(hd, key, len) != GPG_ERR_NO_ERROR) { - printf("setkey failed\n"); - gcry_cipher_close(hd); - return NULL; - } - - return hd; -} - - -void aes_encrypt(void *ctx, const u8 *plain, u8 *crypt) -{ - gcry_cipher_hd_t hd = ctx; - gcry_cipher_encrypt(hd, crypt, 16, plain, 16); -} - - -void aes_encrypt_deinit(void *ctx) -{ - gcry_cipher_hd_t hd = ctx; - gcry_cipher_close(hd); -} - - -void * aes_decrypt_init(const u8 *key, size_t len) -{ - gcry_cipher_hd_t hd; - - if (gcry_cipher_open(&hd, GCRY_CIPHER_AES, GCRY_CIPHER_MODE_ECB, 0) != - GPG_ERR_NO_ERROR) - return NULL; - if (gcry_cipher_setkey(hd, key, len) != GPG_ERR_NO_ERROR) { - gcry_cipher_close(hd); - return NULL; - } - - return hd; -} - - -void aes_decrypt(void *ctx, const u8 *crypt, u8 *plain) -{ - gcry_cipher_hd_t hd = ctx; - gcry_cipher_decrypt(hd, plain, 16, crypt, 16); -} - - -void aes_decrypt_deinit(void *ctx) -{ - gcry_cipher_hd_t hd = ctx; - gcry_cipher_close(hd); -} - - -int crypto_mod_exp(const u8 *base, size_t base_len, - const u8 *power, size_t power_len, - const u8 *modulus, size_t modulus_len, - u8 *result, size_t *result_len) -{ - gcry_mpi_t bn_base = NULL, bn_exp = NULL, bn_modulus = NULL, - bn_result = NULL; - int ret = -1; - - if (gcry_mpi_scan(&bn_base, GCRYMPI_FMT_USG, base, base_len, NULL) != - GPG_ERR_NO_ERROR || - gcry_mpi_scan(&bn_exp, GCRYMPI_FMT_USG, power, power_len, NULL) != - GPG_ERR_NO_ERROR || - gcry_mpi_scan(&bn_modulus, GCRYMPI_FMT_USG, modulus, modulus_len, - NULL) != GPG_ERR_NO_ERROR) - goto error; - bn_result = gcry_mpi_new(modulus_len * 8); - - gcry_mpi_powm(bn_result, bn_base, bn_exp, bn_modulus); - - if (gcry_mpi_print(GCRYMPI_FMT_USG, result, *result_len, result_len, - bn_result) != GPG_ERR_NO_ERROR) - goto error; - - ret = 0; - -error: - gcry_mpi_release(bn_base); - gcry_mpi_release(bn_exp); - gcry_mpi_release(bn_modulus); - gcry_mpi_release(bn_result); - return ret; -} - - -struct crypto_cipher { - gcry_cipher_hd_t enc; - gcry_cipher_hd_t dec; -}; - - -struct crypto_cipher * crypto_cipher_init(enum crypto_cipher_alg alg, - const u8 *iv, const u8 *key, - size_t key_len) -{ - struct crypto_cipher *ctx; - gcry_error_t res; - enum gcry_cipher_algos a; - int ivlen; - - ctx = os_zalloc(sizeof(*ctx)); - if (ctx == NULL) - return NULL; - - switch (alg) { - case CRYPTO_CIPHER_ALG_RC4: - a = GCRY_CIPHER_ARCFOUR; - res = gcry_cipher_open(&ctx->enc, a, GCRY_CIPHER_MODE_STREAM, - 0); - gcry_cipher_open(&ctx->dec, a, GCRY_CIPHER_MODE_STREAM, 0); - break; - case CRYPTO_CIPHER_ALG_AES: - if (key_len == 24) - a = GCRY_CIPHER_AES192; - else if (key_len == 32) - a = GCRY_CIPHER_AES256; - else - a = GCRY_CIPHER_AES; - res = gcry_cipher_open(&ctx->enc, a, GCRY_CIPHER_MODE_CBC, 0); - gcry_cipher_open(&ctx->dec, a, GCRY_CIPHER_MODE_CBC, 0); - break; - case CRYPTO_CIPHER_ALG_3DES: - a = GCRY_CIPHER_3DES; - res = gcry_cipher_open(&ctx->enc, a, GCRY_CIPHER_MODE_CBC, 0); - gcry_cipher_open(&ctx->dec, a, GCRY_CIPHER_MODE_CBC, 0); - break; - case CRYPTO_CIPHER_ALG_DES: - a = GCRY_CIPHER_DES; - res = gcry_cipher_open(&ctx->enc, a, GCRY_CIPHER_MODE_CBC, 0); - gcry_cipher_open(&ctx->dec, a, GCRY_CIPHER_MODE_CBC, 0); - break; - case CRYPTO_CIPHER_ALG_RC2: - if (key_len == 5) - a = GCRY_CIPHER_RFC2268_40; - else - a = GCRY_CIPHER_RFC2268_128; - res = gcry_cipher_open(&ctx->enc, a, GCRY_CIPHER_MODE_CBC, 0); - gcry_cipher_open(&ctx->dec, a, GCRY_CIPHER_MODE_CBC, 0); - break; - default: - os_free(ctx); - return NULL; - } - - if (res != GPG_ERR_NO_ERROR) { - os_free(ctx); - return NULL; - } - - if (gcry_cipher_setkey(ctx->enc, key, key_len) != GPG_ERR_NO_ERROR || - gcry_cipher_setkey(ctx->dec, key, key_len) != GPG_ERR_NO_ERROR) { - gcry_cipher_close(ctx->enc); - gcry_cipher_close(ctx->dec); - os_free(ctx); - return NULL; - } - - ivlen = gcry_cipher_get_algo_blklen(a); - if (gcry_cipher_setiv(ctx->enc, iv, ivlen) != GPG_ERR_NO_ERROR || - gcry_cipher_setiv(ctx->dec, iv, ivlen) != GPG_ERR_NO_ERROR) { - gcry_cipher_close(ctx->enc); - gcry_cipher_close(ctx->dec); - os_free(ctx); - return NULL; - } - - return ctx; -} - - -int crypto_cipher_encrypt(struct crypto_cipher *ctx, const u8 *plain, - u8 *crypt, size_t len) -{ - if (gcry_cipher_encrypt(ctx->enc, crypt, len, plain, len) != - GPG_ERR_NO_ERROR) - return -1; - return 0; -} - - -int crypto_cipher_decrypt(struct crypto_cipher *ctx, const u8 *crypt, - u8 *plain, size_t len) -{ - if (gcry_cipher_decrypt(ctx->dec, plain, len, crypt, len) != - GPG_ERR_NO_ERROR) - return -1; - return 0; -} - - -void crypto_cipher_deinit(struct crypto_cipher *ctx) -{ - gcry_cipher_close(ctx->enc); - gcry_cipher_close(ctx->dec); - os_free(ctx); -} diff --git a/hostapd-0.8/src/crypto/crypto_internal-cipher.c b/hostapd-0.8/src/crypto/crypto_internal-cipher.c deleted file mode 100644 index 75134f0..0000000 --- a/hostapd-0.8/src/crypto/crypto_internal-cipher.c +++ /dev/null @@ -1,256 +0,0 @@ -/* - * Crypto wrapper for internal crypto implementation - Cipher wrappers - * Copyright (c) 2006-2009, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#include "includes.h" - -#include "common.h" -#include "crypto.h" -#include "aes.h" -#include "des_i.h" - - -struct crypto_cipher { - enum crypto_cipher_alg alg; - union { - struct { - size_t used_bytes; - u8 key[16]; - size_t keylen; - } rc4; - struct { - u8 cbc[32]; - size_t block_size; - void *ctx_enc; - void *ctx_dec; - } aes; - struct { - struct des3_key_s key; - u8 cbc[8]; - } des3; - struct { - u32 ek[32]; - u32 dk[32]; - u8 cbc[8]; - } des; - } u; -}; - - -struct crypto_cipher * crypto_cipher_init(enum crypto_cipher_alg alg, - const u8 *iv, const u8 *key, - size_t key_len) -{ - struct crypto_cipher *ctx; - - ctx = os_zalloc(sizeof(*ctx)); - if (ctx == NULL) - return NULL; - - ctx->alg = alg; - - switch (alg) { - case CRYPTO_CIPHER_ALG_RC4: - if (key_len > sizeof(ctx->u.rc4.key)) { - os_free(ctx); - return NULL; - } - ctx->u.rc4.keylen = key_len; - os_memcpy(ctx->u.rc4.key, key, key_len); - break; - case CRYPTO_CIPHER_ALG_AES: - if (key_len > sizeof(ctx->u.aes.cbc)) { - os_free(ctx); - return NULL; - } - ctx->u.aes.ctx_enc = aes_encrypt_init(key, key_len); - if (ctx->u.aes.ctx_enc == NULL) { - os_free(ctx); - return NULL; - } - ctx->u.aes.ctx_dec = aes_decrypt_init(key, key_len); - if (ctx->u.aes.ctx_dec == NULL) { - aes_encrypt_deinit(ctx->u.aes.ctx_enc); - os_free(ctx); - return NULL; - } - ctx->u.aes.block_size = key_len; - os_memcpy(ctx->u.aes.cbc, iv, ctx->u.aes.block_size); - break; - case CRYPTO_CIPHER_ALG_3DES: - if (key_len != 24) { - os_free(ctx); - return NULL; - } - des3_key_setup(key, &ctx->u.des3.key); - os_memcpy(ctx->u.des3.cbc, iv, 8); - break; - case CRYPTO_CIPHER_ALG_DES: - if (key_len != 8) { - os_free(ctx); - return NULL; - } - des_key_setup(key, ctx->u.des.ek, ctx->u.des.dk); - os_memcpy(ctx->u.des.cbc, iv, 8); - break; - default: - os_free(ctx); - return NULL; - } - - return ctx; -} - - -int crypto_cipher_encrypt(struct crypto_cipher *ctx, const u8 *plain, - u8 *crypt, size_t len) -{ - size_t i, j, blocks; - - switch (ctx->alg) { - case CRYPTO_CIPHER_ALG_RC4: - if (plain != crypt) - os_memcpy(crypt, plain, len); - rc4_skip(ctx->u.rc4.key, ctx->u.rc4.keylen, - ctx->u.rc4.used_bytes, crypt, len); - ctx->u.rc4.used_bytes += len; - break; - case CRYPTO_CIPHER_ALG_AES: - if (len % ctx->u.aes.block_size) - return -1; - blocks = len / ctx->u.aes.block_size; - for (i = 0; i < blocks; i++) { - for (j = 0; j < ctx->u.aes.block_size; j++) - ctx->u.aes.cbc[j] ^= plain[j]; - aes_encrypt(ctx->u.aes.ctx_enc, ctx->u.aes.cbc, - ctx->u.aes.cbc); - os_memcpy(crypt, ctx->u.aes.cbc, - ctx->u.aes.block_size); - plain += ctx->u.aes.block_size; - crypt += ctx->u.aes.block_size; - } - break; - case CRYPTO_CIPHER_ALG_3DES: - if (len % 8) - return -1; - blocks = len / 8; - for (i = 0; i < blocks; i++) { - for (j = 0; j < 8; j++) - ctx->u.des3.cbc[j] ^= plain[j]; - des3_encrypt(ctx->u.des3.cbc, &ctx->u.des3.key, - ctx->u.des3.cbc); - os_memcpy(crypt, ctx->u.des3.cbc, 8); - plain += 8; - crypt += 8; - } - break; - case CRYPTO_CIPHER_ALG_DES: - if (len % 8) - return -1; - blocks = len / 8; - for (i = 0; i < blocks; i++) { - for (j = 0; j < 8; j++) - ctx->u.des3.cbc[j] ^= plain[j]; - des_block_encrypt(ctx->u.des.cbc, ctx->u.des.ek, - ctx->u.des.cbc); - os_memcpy(crypt, ctx->u.des.cbc, 8); - plain += 8; - crypt += 8; - } - break; - default: - return -1; - } - - return 0; -} - - -int crypto_cipher_decrypt(struct crypto_cipher *ctx, const u8 *crypt, - u8 *plain, size_t len) -{ - size_t i, j, blocks; - u8 tmp[32]; - - switch (ctx->alg) { - case CRYPTO_CIPHER_ALG_RC4: - if (plain != crypt) - os_memcpy(plain, crypt, len); - rc4_skip(ctx->u.rc4.key, ctx->u.rc4.keylen, - ctx->u.rc4.used_bytes, plain, len); - ctx->u.rc4.used_bytes += len; - break; - case CRYPTO_CIPHER_ALG_AES: - if (len % ctx->u.aes.block_size) - return -1; - blocks = len / ctx->u.aes.block_size; - for (i = 0; i < blocks; i++) { - os_memcpy(tmp, crypt, ctx->u.aes.block_size); - aes_decrypt(ctx->u.aes.ctx_dec, crypt, plain); - for (j = 0; j < ctx->u.aes.block_size; j++) - plain[j] ^= ctx->u.aes.cbc[j]; - os_memcpy(ctx->u.aes.cbc, tmp, ctx->u.aes.block_size); - plain += ctx->u.aes.block_size; - crypt += ctx->u.aes.block_size; - } - break; - case CRYPTO_CIPHER_ALG_3DES: - if (len % 8) - return -1; - blocks = len / 8; - for (i = 0; i < blocks; i++) { - os_memcpy(tmp, crypt, 8); - des3_decrypt(crypt, &ctx->u.des3.key, plain); - for (j = 0; j < 8; j++) - plain[j] ^= ctx->u.des3.cbc[j]; - os_memcpy(ctx->u.des3.cbc, tmp, 8); - plain += 8; - crypt += 8; - } - break; - case CRYPTO_CIPHER_ALG_DES: - if (len % 8) - return -1; - blocks = len / 8; - for (i = 0; i < blocks; i++) { - os_memcpy(tmp, crypt, 8); - des_block_decrypt(crypt, ctx->u.des.dk, plain); - for (j = 0; j < 8; j++) - plain[j] ^= ctx->u.des.cbc[j]; - os_memcpy(ctx->u.des.cbc, tmp, 8); - plain += 8; - crypt += 8; - } - break; - default: - return -1; - } - - return 0; -} - - -void crypto_cipher_deinit(struct crypto_cipher *ctx) -{ - switch (ctx->alg) { - case CRYPTO_CIPHER_ALG_AES: - aes_encrypt_deinit(ctx->u.aes.ctx_enc); - aes_decrypt_deinit(ctx->u.aes.ctx_dec); - break; - case CRYPTO_CIPHER_ALG_3DES: - break; - default: - break; - } - os_free(ctx); -} diff --git a/hostapd-0.8/src/crypto/crypto_internal-modexp.c b/hostapd-0.8/src/crypto/crypto_internal-modexp.c deleted file mode 100644 index 3124742..0000000 --- a/hostapd-0.8/src/crypto/crypto_internal-modexp.c +++ /dev/null @@ -1,55 +0,0 @@ -/* - * Crypto wrapper for internal crypto implementation - modexp - * Copyright (c) 2006-2009, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#include "includes.h" - -#include "common.h" -#include "tls/bignum.h" -#include "crypto.h" - - -int crypto_mod_exp(const u8 *base, size_t base_len, - const u8 *power, size_t power_len, - const u8 *modulus, size_t modulus_len, - u8 *result, size_t *result_len) -{ - struct bignum *bn_base, *bn_exp, *bn_modulus, *bn_result; - int ret = -1; - - bn_base = bignum_init(); - bn_exp = bignum_init(); - bn_modulus = bignum_init(); - bn_result = bignum_init(); - - if (bn_base == NULL || bn_exp == NULL || bn_modulus == NULL || - bn_result == NULL) - goto error; - - if (bignum_set_unsigned_bin(bn_base, base, base_len) < 0 || - bignum_set_unsigned_bin(bn_exp, power, power_len) < 0 || - bignum_set_unsigned_bin(bn_modulus, modulus, modulus_len) < 0) - goto error; - - if (bignum_exptmod(bn_base, bn_exp, bn_modulus, bn_result) < 0) - goto error; - - ret = bignum_get_unsigned_bin(bn_result, result, result_len); - -error: - bignum_deinit(bn_base); - bignum_deinit(bn_exp); - bignum_deinit(bn_modulus); - bignum_deinit(bn_result); - return ret; -} diff --git a/hostapd-0.8/src/crypto/crypto_internal-rsa.c b/hostapd-0.8/src/crypto/crypto_internal-rsa.c deleted file mode 100644 index 205042c..0000000 --- a/hostapd-0.8/src/crypto/crypto_internal-rsa.c +++ /dev/null @@ -1,115 +0,0 @@ -/* - * Crypto wrapper for internal crypto implementation - RSA parts - * Copyright (c) 2006-2009, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#include "includes.h" - -#include "common.h" -#include "crypto.h" -#include "tls/rsa.h" -#include "tls/bignum.h" -#include "tls/pkcs1.h" -#include "tls/pkcs8.h" - -/* Dummy structures; these are just typecast to struct crypto_rsa_key */ -struct crypto_public_key; -struct crypto_private_key; - - -struct crypto_public_key * crypto_public_key_import(const u8 *key, size_t len) -{ - return (struct crypto_public_key *) - crypto_rsa_import_public_key(key, len); -} - - -struct crypto_private_key * crypto_private_key_import(const u8 *key, - size_t len, - const char *passwd) -{ - struct crypto_private_key *res; - - /* First, check for possible PKCS #8 encoding */ - res = pkcs8_key_import(key, len); - if (res) - return res; - - if (passwd) { - /* Try to parse as encrypted PKCS #8 */ - res = pkcs8_enc_key_import(key, len, passwd); - if (res) - return res; - } - - /* Not PKCS#8, so try to import PKCS #1 encoded RSA private key */ - wpa_printf(MSG_DEBUG, "Trying to parse PKCS #1 encoded RSA private " - "key"); - return (struct crypto_private_key *) - crypto_rsa_import_private_key(key, len); -} - - -struct crypto_public_key * crypto_public_key_from_cert(const u8 *buf, - size_t len) -{ - /* No X.509 support in crypto_internal.c */ - return NULL; -} - - -int crypto_public_key_encrypt_pkcs1_v15(struct crypto_public_key *key, - const u8 *in, size_t inlen, - u8 *out, size_t *outlen) -{ - return pkcs1_encrypt(2, (struct crypto_rsa_key *) key, - 0, in, inlen, out, outlen); -} - - -int crypto_private_key_decrypt_pkcs1_v15(struct crypto_private_key *key, - const u8 *in, size_t inlen, - u8 *out, size_t *outlen) -{ - return pkcs1_v15_private_key_decrypt((struct crypto_rsa_key *) key, - in, inlen, out, outlen); -} - - -int crypto_private_key_sign_pkcs1(struct crypto_private_key *key, - const u8 *in, size_t inlen, - u8 *out, size_t *outlen) -{ - return pkcs1_encrypt(1, (struct crypto_rsa_key *) key, - 1, in, inlen, out, outlen); -} - - -void crypto_public_key_free(struct crypto_public_key *key) -{ - crypto_rsa_free((struct crypto_rsa_key *) key); -} - - -void crypto_private_key_free(struct crypto_private_key *key) -{ - crypto_rsa_free((struct crypto_rsa_key *) key); -} - - -int crypto_public_key_decrypt_pkcs1(struct crypto_public_key *key, - const u8 *crypt, size_t crypt_len, - u8 *plain, size_t *plain_len) -{ - return pkcs1_decrypt_public_key((struct crypto_rsa_key *) key, - crypt, crypt_len, plain, plain_len); -} diff --git a/hostapd-0.8/src/crypto/crypto_internal.c b/hostapd-0.8/src/crypto/crypto_internal.c deleted file mode 100644 index 8fdba65..0000000 --- a/hostapd-0.8/src/crypto/crypto_internal.c +++ /dev/null @@ -1,205 +0,0 @@ -/* - * Crypto wrapper for internal crypto implementation - * Copyright (c) 2006-2009, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#include "includes.h" - -#include "common.h" -#include "crypto.h" -#include "sha1_i.h" -#include "md5_i.h" - -struct crypto_hash { - enum crypto_hash_alg alg; - union { - struct MD5Context md5; - struct SHA1Context sha1; - } u; - u8 key[64]; - size_t key_len; -}; - - -struct crypto_hash * crypto_hash_init(enum crypto_hash_alg alg, const u8 *key, - size_t key_len) -{ - struct crypto_hash *ctx; - u8 k_pad[64]; - u8 tk[20]; - size_t i; - - ctx = os_zalloc(sizeof(*ctx)); - if (ctx == NULL) - return NULL; - - ctx->alg = alg; - - switch (alg) { - case CRYPTO_HASH_ALG_MD5: - MD5Init(&ctx->u.md5); - break; - case CRYPTO_HASH_ALG_SHA1: - SHA1Init(&ctx->u.sha1); - break; - case CRYPTO_HASH_ALG_HMAC_MD5: - if (key_len > sizeof(k_pad)) { - MD5Init(&ctx->u.md5); - MD5Update(&ctx->u.md5, key, key_len); - MD5Final(tk, &ctx->u.md5); - key = tk; - key_len = 16; - } - os_memcpy(ctx->key, key, key_len); - ctx->key_len = key_len; - - os_memcpy(k_pad, key, key_len); - os_memset(k_pad + key_len, 0, sizeof(k_pad) - key_len); - for (i = 0; i < sizeof(k_pad); i++) - k_pad[i] ^= 0x36; - MD5Init(&ctx->u.md5); - MD5Update(&ctx->u.md5, k_pad, sizeof(k_pad)); - break; - case CRYPTO_HASH_ALG_HMAC_SHA1: - if (key_len > sizeof(k_pad)) { - SHA1Init(&ctx->u.sha1); - SHA1Update(&ctx->u.sha1, key, key_len); - SHA1Final(tk, &ctx->u.sha1); - key = tk; - key_len = 20; - } - os_memcpy(ctx->key, key, key_len); - ctx->key_len = key_len; - - os_memcpy(k_pad, key, key_len); - os_memset(k_pad + key_len, 0, sizeof(k_pad) - key_len); - for (i = 0; i < sizeof(k_pad); i++) - k_pad[i] ^= 0x36; - SHA1Init(&ctx->u.sha1); - SHA1Update(&ctx->u.sha1, k_pad, sizeof(k_pad)); - break; - default: - os_free(ctx); - return NULL; - } - - return ctx; -} - - -void crypto_hash_update(struct crypto_hash *ctx, const u8 *data, size_t len) -{ - if (ctx == NULL) - return; - - switch (ctx->alg) { - case CRYPTO_HASH_ALG_MD5: - case CRYPTO_HASH_ALG_HMAC_MD5: - MD5Update(&ctx->u.md5, data, len); - break; - case CRYPTO_HASH_ALG_SHA1: - case CRYPTO_HASH_ALG_HMAC_SHA1: - SHA1Update(&ctx->u.sha1, data, len); - break; - } -} - - -int crypto_hash_finish(struct crypto_hash *ctx, u8 *mac, size_t *len) -{ - u8 k_pad[64]; - size_t i; - - if (ctx == NULL) - return -2; - - if (mac == NULL || len == NULL) { - os_free(ctx); - return 0; - } - - switch (ctx->alg) { - case CRYPTO_HASH_ALG_MD5: - if (*len < 16) { - *len = 16; - os_free(ctx); - return -1; - } - *len = 16; - MD5Final(mac, &ctx->u.md5); - break; - case CRYPTO_HASH_ALG_SHA1: - if (*len < 20) { - *len = 20; - os_free(ctx); - return -1; - } - *len = 20; - SHA1Final(mac, &ctx->u.sha1); - break; - case CRYPTO_HASH_ALG_HMAC_MD5: - if (*len < 16) { - *len = 16; - os_free(ctx); - return -1; - } - *len = 16; - - MD5Final(mac, &ctx->u.md5); - - os_memcpy(k_pad, ctx->key, ctx->key_len); - os_memset(k_pad + ctx->key_len, 0, - sizeof(k_pad) - ctx->key_len); - for (i = 0; i < sizeof(k_pad); i++) - k_pad[i] ^= 0x5c; - MD5Init(&ctx->u.md5); - MD5Update(&ctx->u.md5, k_pad, sizeof(k_pad)); - MD5Update(&ctx->u.md5, mac, 16); - MD5Final(mac, &ctx->u.md5); - break; - case CRYPTO_HASH_ALG_HMAC_SHA1: - if (*len < 20) { - *len = 20; - os_free(ctx); - return -1; - } - *len = 20; - - SHA1Final(mac, &ctx->u.sha1); - - os_memcpy(k_pad, ctx->key, ctx->key_len); - os_memset(k_pad + ctx->key_len, 0, - sizeof(k_pad) - ctx->key_len); - for (i = 0; i < sizeof(k_pad); i++) - k_pad[i] ^= 0x5c; - SHA1Init(&ctx->u.sha1); - SHA1Update(&ctx->u.sha1, k_pad, sizeof(k_pad)); - SHA1Update(&ctx->u.sha1, mac, 20); - SHA1Final(mac, &ctx->u.sha1); - break; - } - - os_free(ctx); - - return 0; -} - - -int crypto_global_init(void) -{ - return 0; -} - - -void crypto_global_deinit(void) -{ -} diff --git a/hostapd-0.8/src/crypto/crypto_libtomcrypt.c b/hostapd-0.8/src/crypto/crypto_libtomcrypt.c deleted file mode 100644 index 52b67a7..0000000 --- a/hostapd-0.8/src/crypto/crypto_libtomcrypt.c +++ /dev/null @@ -1,732 +0,0 @@ -/* - * WPA Supplicant / Crypto wrapper for LibTomCrypt (for internal TLSv1) - * Copyright (c) 2005-2006, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#include "includes.h" -#include - -#include "common.h" -#include "crypto.h" - -#ifndef mp_init_multi -#define mp_init_multi ltc_init_multi -#define mp_clear_multi ltc_deinit_multi -#define mp_unsigned_bin_size(a) ltc_mp.unsigned_size(a) -#define mp_to_unsigned_bin(a, b) ltc_mp.unsigned_write(a, b) -#define mp_read_unsigned_bin(a, b, c) ltc_mp.unsigned_read(a, b, c) -#define mp_exptmod(a,b,c,d) ltc_mp.exptmod(a,b,c,d) -#endif - - -int md4_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac) -{ - hash_state md; - size_t i; - - md4_init(&md); - for (i = 0; i < num_elem; i++) - md4_process(&md, addr[i], len[i]); - md4_done(&md, mac); - return 0; -} - - -void des_encrypt(const u8 *clear, const u8 *key, u8 *cypher) -{ - u8 pkey[8], next, tmp; - int i; - symmetric_key skey; - - /* Add parity bits to the key */ - next = 0; - for (i = 0; i < 7; i++) { - tmp = key[i]; - pkey[i] = (tmp >> i) | next | 1; - next = tmp << (7 - i); - } - pkey[i] = next | 1; - - des_setup(pkey, 8, 0, &skey); - des_ecb_encrypt(clear, cypher, &skey); - des_done(&skey); -} - - -int md5_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac) -{ - hash_state md; - size_t i; - - md5_init(&md); - for (i = 0; i < num_elem; i++) - md5_process(&md, addr[i], len[i]); - md5_done(&md, mac); - return 0; -} - - -int sha1_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac) -{ - hash_state md; - size_t i; - - sha1_init(&md); - for (i = 0; i < num_elem; i++) - sha1_process(&md, addr[i], len[i]); - sha1_done(&md, mac); - return 0; -} - - -void * aes_encrypt_init(const u8 *key, size_t len) -{ - symmetric_key *skey; - skey = os_malloc(sizeof(*skey)); - if (skey == NULL) - return NULL; - if (aes_setup(key, len, 0, skey) != CRYPT_OK) { - os_free(skey); - return NULL; - } - return skey; -} - - -void aes_encrypt(void *ctx, const u8 *plain, u8 *crypt) -{ - symmetric_key *skey = ctx; - aes_ecb_encrypt(plain, crypt, skey); -} - - -void aes_encrypt_deinit(void *ctx) -{ - symmetric_key *skey = ctx; - aes_done(skey); - os_free(skey); -} - - -void * aes_decrypt_init(const u8 *key, size_t len) -{ - symmetric_key *skey; - skey = os_malloc(sizeof(*skey)); - if (skey == NULL) - return NULL; - if (aes_setup(key, len, 0, skey) != CRYPT_OK) { - os_free(skey); - return NULL; - } - return skey; -} - - -void aes_decrypt(void *ctx, const u8 *crypt, u8 *plain) -{ - symmetric_key *skey = ctx; - aes_ecb_encrypt(plain, (u8 *) crypt, skey); -} - - -void aes_decrypt_deinit(void *ctx) -{ - symmetric_key *skey = ctx; - aes_done(skey); - os_free(skey); -} - - -struct crypto_hash { - enum crypto_hash_alg alg; - int error; - union { - hash_state md; - hmac_state hmac; - } u; -}; - - -struct crypto_hash * crypto_hash_init(enum crypto_hash_alg alg, const u8 *key, - size_t key_len) -{ - struct crypto_hash *ctx; - - ctx = os_zalloc(sizeof(*ctx)); - if (ctx == NULL) - return NULL; - - ctx->alg = alg; - - switch (alg) { - case CRYPTO_HASH_ALG_MD5: - if (md5_init(&ctx->u.md) != CRYPT_OK) - goto fail; - break; - case CRYPTO_HASH_ALG_SHA1: - if (sha1_init(&ctx->u.md) != CRYPT_OK) - goto fail; - break; - case CRYPTO_HASH_ALG_HMAC_MD5: - if (hmac_init(&ctx->u.hmac, find_hash("md5"), key, key_len) != - CRYPT_OK) - goto fail; - break; - case CRYPTO_HASH_ALG_HMAC_SHA1: - if (hmac_init(&ctx->u.hmac, find_hash("sha1"), key, key_len) != - CRYPT_OK) - goto fail; - break; - default: - goto fail; - } - - return ctx; - -fail: - os_free(ctx); - return NULL; -} - -void crypto_hash_update(struct crypto_hash *ctx, const u8 *data, size_t len) -{ - if (ctx == NULL || ctx->error) - return; - - switch (ctx->alg) { - case CRYPTO_HASH_ALG_MD5: - ctx->error = md5_process(&ctx->u.md, data, len) != CRYPT_OK; - break; - case CRYPTO_HASH_ALG_SHA1: - ctx->error = sha1_process(&ctx->u.md, data, len) != CRYPT_OK; - break; - case CRYPTO_HASH_ALG_HMAC_MD5: - case CRYPTO_HASH_ALG_HMAC_SHA1: - ctx->error = hmac_process(&ctx->u.hmac, data, len) != CRYPT_OK; - break; - } -} - - -int crypto_hash_finish(struct crypto_hash *ctx, u8 *mac, size_t *len) -{ - int ret = 0; - unsigned long clen; - - if (ctx == NULL) - return -2; - - if (mac == NULL || len == NULL) { - os_free(ctx); - return 0; - } - - if (ctx->error) { - os_free(ctx); - return -2; - } - - switch (ctx->alg) { - case CRYPTO_HASH_ALG_MD5: - if (*len < 16) { - *len = 16; - os_free(ctx); - return -1; - } - *len = 16; - if (md5_done(&ctx->u.md, mac) != CRYPT_OK) - ret = -2; - break; - case CRYPTO_HASH_ALG_SHA1: - if (*len < 20) { - *len = 20; - os_free(ctx); - return -1; - } - *len = 20; - if (sha1_done(&ctx->u.md, mac) != CRYPT_OK) - ret = -2; - break; - case CRYPTO_HASH_ALG_HMAC_SHA1: - if (*len < 20) { - *len = 20; - os_free(ctx); - return -1; - } - /* continue */ - case CRYPTO_HASH_ALG_HMAC_MD5: - if (*len < 16) { - *len = 16; - os_free(ctx); - return -1; - } - clen = *len; - if (hmac_done(&ctx->u.hmac, mac, &clen) != CRYPT_OK) { - os_free(ctx); - return -1; - } - *len = clen; - break; - default: - ret = -2; - break; - } - - os_free(ctx); - - return ret; -} - - -struct crypto_cipher { - int rc4; - union { - symmetric_CBC cbc; - struct { - size_t used_bytes; - u8 key[16]; - size_t keylen; - } rc4; - } u; -}; - - -struct crypto_cipher * crypto_cipher_init(enum crypto_cipher_alg alg, - const u8 *iv, const u8 *key, - size_t key_len) -{ - struct crypto_cipher *ctx; - int idx, res, rc4 = 0; - - switch (alg) { - case CRYPTO_CIPHER_ALG_AES: - idx = find_cipher("aes"); - break; - case CRYPTO_CIPHER_ALG_3DES: - idx = find_cipher("3des"); - break; - case CRYPTO_CIPHER_ALG_DES: - idx = find_cipher("des"); - break; - case CRYPTO_CIPHER_ALG_RC2: - idx = find_cipher("rc2"); - break; - case CRYPTO_CIPHER_ALG_RC4: - idx = -1; - rc4 = 1; - break; - default: - return NULL; - } - - ctx = os_zalloc(sizeof(*ctx)); - if (ctx == NULL) - return NULL; - - if (rc4) { - ctx->rc4 = 1; - if (key_len > sizeof(ctx->u.rc4.key)) { - os_free(ctx); - return NULL; - } - ctx->u.rc4.keylen = key_len; - os_memcpy(ctx->u.rc4.key, key, key_len); - } else { - res = cbc_start(idx, iv, key, key_len, 0, &ctx->u.cbc); - if (res != CRYPT_OK) { - wpa_printf(MSG_DEBUG, "LibTomCrypt: Cipher start " - "failed: %s", error_to_string(res)); - os_free(ctx); - return NULL; - } - } - - return ctx; -} - -int crypto_cipher_encrypt(struct crypto_cipher *ctx, const u8 *plain, - u8 *crypt, size_t len) -{ - int res; - - if (ctx->rc4) { - if (plain != crypt) - os_memcpy(crypt, plain, len); - rc4_skip(ctx->u.rc4.key, ctx->u.rc4.keylen, - ctx->u.rc4.used_bytes, crypt, len); - ctx->u.rc4.used_bytes += len; - return 0; - } - - res = cbc_encrypt(plain, crypt, len, &ctx->u.cbc); - if (res != CRYPT_OK) { - wpa_printf(MSG_DEBUG, "LibTomCrypt: CBC encryption " - "failed: %s", error_to_string(res)); - return -1; - } - return 0; -} - - -int crypto_cipher_decrypt(struct crypto_cipher *ctx, const u8 *crypt, - u8 *plain, size_t len) -{ - int res; - - if (ctx->rc4) { - if (plain != crypt) - os_memcpy(plain, crypt, len); - rc4_skip(ctx->u.rc4.key, ctx->u.rc4.keylen, - ctx->u.rc4.used_bytes, plain, len); - ctx->u.rc4.used_bytes += len; - return 0; - } - - res = cbc_decrypt(crypt, plain, len, &ctx->u.cbc); - if (res != CRYPT_OK) { - wpa_printf(MSG_DEBUG, "LibTomCrypt: CBC decryption " - "failed: %s", error_to_string(res)); - return -1; - } - - return 0; -} - - -void crypto_cipher_deinit(struct crypto_cipher *ctx) -{ - if (!ctx->rc4) - cbc_done(&ctx->u.cbc); - os_free(ctx); -} - - -struct crypto_public_key { - rsa_key rsa; -}; - -struct crypto_private_key { - rsa_key rsa; -}; - - -struct crypto_public_key * crypto_public_key_import(const u8 *key, size_t len) -{ - int res; - struct crypto_public_key *pk; - - pk = os_zalloc(sizeof(*pk)); - if (pk == NULL) - return NULL; - - res = rsa_import(key, len, &pk->rsa); - if (res != CRYPT_OK) { - wpa_printf(MSG_ERROR, "LibTomCrypt: Failed to import " - "public key (res=%d '%s')", - res, error_to_string(res)); - os_free(pk); - return NULL; - } - - if (pk->rsa.type != PK_PUBLIC) { - wpa_printf(MSG_ERROR, "LibTomCrypt: Public key was not of " - "correct type"); - rsa_free(&pk->rsa); - os_free(pk); - return NULL; - } - - return pk; -} - - -struct crypto_private_key * crypto_private_key_import(const u8 *key, - size_t len, - const char *passwd) -{ - int res; - struct crypto_private_key *pk; - - pk = os_zalloc(sizeof(*pk)); - if (pk == NULL) - return NULL; - - res = rsa_import(key, len, &pk->rsa); - if (res != CRYPT_OK) { - wpa_printf(MSG_ERROR, "LibTomCrypt: Failed to import " - "private key (res=%d '%s')", - res, error_to_string(res)); - os_free(pk); - return NULL; - } - - if (pk->rsa.type != PK_PRIVATE) { - wpa_printf(MSG_ERROR, "LibTomCrypt: Private key was not of " - "correct type"); - rsa_free(&pk->rsa); - os_free(pk); - return NULL; - } - - return pk; -} - - -struct crypto_public_key * crypto_public_key_from_cert(const u8 *buf, - size_t len) -{ - /* No X.509 support in LibTomCrypt */ - return NULL; -} - - -static int pkcs1_generate_encryption_block(u8 block_type, size_t modlen, - const u8 *in, size_t inlen, - u8 *out, size_t *outlen) -{ - size_t ps_len; - u8 *pos; - - /* - * PKCS #1 v1.5, 8.1: - * - * EB = 00 || BT || PS || 00 || D - * BT = 00 or 01 for private-key operation; 02 for public-key operation - * PS = k-3-||D||; at least eight octets - * (BT=0: PS=0x00, BT=1: PS=0xff, BT=2: PS=pseudorandom non-zero) - * k = length of modulus in octets (modlen) - */ - - if (modlen < 12 || modlen > *outlen || inlen > modlen - 11) { - wpa_printf(MSG_DEBUG, "PKCS #1: %s - Invalid buffer " - "lengths (modlen=%lu outlen=%lu inlen=%lu)", - __func__, (unsigned long) modlen, - (unsigned long) *outlen, - (unsigned long) inlen); - return -1; - } - - pos = out; - *pos++ = 0x00; - *pos++ = block_type; /* BT */ - ps_len = modlen - inlen - 3; - switch (block_type) { - case 0: - os_memset(pos, 0x00, ps_len); - pos += ps_len; - break; - case 1: - os_memset(pos, 0xff, ps_len); - pos += ps_len; - break; - case 2: - if (os_get_random(pos, ps_len) < 0) { - wpa_printf(MSG_DEBUG, "PKCS #1: %s - Failed to get " - "random data for PS", __func__); - return -1; - } - while (ps_len--) { - if (*pos == 0x00) - *pos = 0x01; - pos++; - } - break; - default: - wpa_printf(MSG_DEBUG, "PKCS #1: %s - Unsupported block type " - "%d", __func__, block_type); - return -1; - } - *pos++ = 0x00; - os_memcpy(pos, in, inlen); /* D */ - - return 0; -} - - -static int crypto_rsa_encrypt_pkcs1(int block_type, rsa_key *key, int key_type, - const u8 *in, size_t inlen, - u8 *out, size_t *outlen) -{ - unsigned long len, modlen; - int res; - - modlen = mp_unsigned_bin_size(key->N); - - if (pkcs1_generate_encryption_block(block_type, modlen, in, inlen, - out, outlen) < 0) - return -1; - - len = *outlen; - res = rsa_exptmod(out, modlen, out, &len, key_type, key); - if (res != CRYPT_OK) { - wpa_printf(MSG_DEBUG, "LibTomCrypt: rsa_exptmod failed: %s", - error_to_string(res)); - return -1; - } - *outlen = len; - - return 0; -} - - -int crypto_public_key_encrypt_pkcs1_v15(struct crypto_public_key *key, - const u8 *in, size_t inlen, - u8 *out, size_t *outlen) -{ - return crypto_rsa_encrypt_pkcs1(2, &key->rsa, PK_PUBLIC, in, inlen, - out, outlen); -} - - -int crypto_private_key_sign_pkcs1(struct crypto_private_key *key, - const u8 *in, size_t inlen, - u8 *out, size_t *outlen) -{ - return crypto_rsa_encrypt_pkcs1(1, &key->rsa, PK_PRIVATE, in, inlen, - out, outlen); -} - - -void crypto_public_key_free(struct crypto_public_key *key) -{ - if (key) { - rsa_free(&key->rsa); - os_free(key); - } -} - - -void crypto_private_key_free(struct crypto_private_key *key) -{ - if (key) { - rsa_free(&key->rsa); - os_free(key); - } -} - - -int crypto_public_key_decrypt_pkcs1(struct crypto_public_key *key, - const u8 *crypt, size_t crypt_len, - u8 *plain, size_t *plain_len) -{ - int res; - unsigned long len; - u8 *pos; - - len = *plain_len; - res = rsa_exptmod(crypt, crypt_len, plain, &len, PK_PUBLIC, - &key->rsa); - if (res != CRYPT_OK) { - wpa_printf(MSG_DEBUG, "LibTomCrypt: rsa_exptmod failed: %s", - error_to_string(res)); - return -1; - } - - /* - * PKCS #1 v1.5, 8.1: - * - * EB = 00 || BT || PS || 00 || D - * BT = 01 - * PS = k-3-||D|| times FF - * k = length of modulus in octets - */ - - if (len < 3 + 8 + 16 /* min hash len */ || - plain[0] != 0x00 || plain[1] != 0x01 || plain[2] != 0xff) { - wpa_printf(MSG_INFO, "LibTomCrypt: Invalid signature EB " - "structure"); - return -1; - } - - pos = plain + 3; - while (pos < plain + len && *pos == 0xff) - pos++; - if (pos - plain - 2 < 8) { - /* PKCS #1 v1.5, 8.1: At least eight octets long PS */ - wpa_printf(MSG_INFO, "LibTomCrypt: Too short signature " - "padding"); - return -1; - } - - if (pos + 16 /* min hash len */ >= plain + len || *pos != 0x00) { - wpa_printf(MSG_INFO, "LibTomCrypt: Invalid signature EB " - "structure (2)"); - return -1; - } - pos++; - len -= pos - plain; - - /* Strip PKCS #1 header */ - os_memmove(plain, pos, len); - *plain_len = len; - - return 0; -} - - -int crypto_global_init(void) -{ - ltc_mp = tfm_desc; - /* TODO: only register algorithms that are really needed */ - if (register_hash(&md4_desc) < 0 || - register_hash(&md5_desc) < 0 || - register_hash(&sha1_desc) < 0 || - register_cipher(&aes_desc) < 0 || - register_cipher(&des_desc) < 0 || - register_cipher(&des3_desc) < 0) { - wpa_printf(MSG_ERROR, "TLSv1: Failed to register " - "hash/cipher functions"); - return -1; - } - - return 0; -} - - -void crypto_global_deinit(void) -{ -} - - -#ifdef CONFIG_MODEXP - -int crypto_mod_exp(const u8 *base, size_t base_len, - const u8 *power, size_t power_len, - const u8 *modulus, size_t modulus_len, - u8 *result, size_t *result_len) -{ - void *b, *p, *m, *r; - - if (mp_init_multi(&b, &p, &m, &r, NULL) != CRYPT_OK) - return -1; - - if (mp_read_unsigned_bin(b, (u8 *) base, base_len) != CRYPT_OK || - mp_read_unsigned_bin(p, (u8 *) power, power_len) != CRYPT_OK || - mp_read_unsigned_bin(m, (u8 *) modulus, modulus_len) != CRYPT_OK) - goto fail; - - if (mp_exptmod(b, p, m, r) != CRYPT_OK) - goto fail; - - *result_len = mp_unsigned_bin_size(r); - if (mp_to_unsigned_bin(r, result) != CRYPT_OK) - goto fail; - - mp_clear_multi(b, p, m, r, NULL); - return 0; - -fail: - mp_clear_multi(b, p, m, r, NULL); - return -1; -} - -#endif /* CONFIG_MODEXP */ diff --git a/hostapd-0.8/src/crypto/crypto_none.c b/hostapd-0.8/src/crypto/crypto_none.c deleted file mode 100644 index 9f43775..0000000 --- a/hostapd-0.8/src/crypto/crypto_none.c +++ /dev/null @@ -1,29 +0,0 @@ -/* - * WPA Supplicant / Empty template functions for crypto wrapper - * Copyright (c) 2005, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#include "includes.h" - -#include "common.h" -#include "crypto.h" - - -int md4_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac) -{ - return 0; -} - - -void des_encrypt(const u8 *clear, const u8 *key, u8 *cypher) -{ -} diff --git a/hostapd-0.8/src/crypto/crypto_nss.c b/hostapd-0.8/src/crypto/crypto_nss.c deleted file mode 100644 index fee4195..0000000 --- a/hostapd-0.8/src/crypto/crypto_nss.c +++ /dev/null @@ -1,213 +0,0 @@ -/* - * Crypto wrapper functions for NSS - * Copyright (c) 2009, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#include "includes.h" -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "common.h" -#include "crypto.h" - - -static int nss_hash(HASH_HashType type, unsigned int max_res_len, - size_t num_elem, const u8 *addr[], const size_t *len, - u8 *mac) -{ - HASHContext *ctx; - size_t i; - unsigned int reslen; - - ctx = HASH_Create(type); - if (ctx == NULL) - return -1; - - HASH_Begin(ctx); - for (i = 0; i < num_elem; i++) - HASH_Update(ctx, addr[i], len[i]); - HASH_End(ctx, mac, &reslen, max_res_len); - HASH_Destroy(ctx); - - return 0; -} - - -void des_encrypt(const u8 *clear, const u8 *key, u8 *cypher) -{ - PK11Context *ctx = NULL; - PK11SlotInfo *slot; - SECItem *param = NULL; - PK11SymKey *symkey = NULL; - SECItem item; - int olen; - u8 pkey[8], next, tmp; - int i; - - /* Add parity bits to the key */ - next = 0; - for (i = 0; i < 7; i++) { - tmp = key[i]; - pkey[i] = (tmp >> i) | next | 1; - next = tmp << (7 - i); - } - pkey[i] = next | 1; - - slot = PK11_GetBestSlot(CKM_DES_ECB, NULL); - if (slot == NULL) { - wpa_printf(MSG_ERROR, "NSS: PK11_GetBestSlot failed"); - goto out; - } - - item.type = siBuffer; - item.data = pkey; - item.len = 8; - symkey = PK11_ImportSymKey(slot, CKM_DES_ECB, PK11_OriginDerive, - CKA_ENCRYPT, &item, NULL); - if (symkey == NULL) { - wpa_printf(MSG_ERROR, "NSS: PK11_ImportSymKey failed"); - goto out; - } - - param = PK11_GenerateNewParam(CKM_DES_ECB, symkey); - if (param == NULL) { - wpa_printf(MSG_ERROR, "NSS: PK11_GenerateNewParam failed"); - goto out; - } - - ctx = PK11_CreateContextBySymKey(CKM_DES_ECB, CKA_ENCRYPT, - symkey, param); - if (ctx == NULL) { - wpa_printf(MSG_ERROR, "NSS: PK11_CreateContextBySymKey(" - "CKM_DES_ECB) failed"); - goto out; - } - - if (PK11_CipherOp(ctx, cypher, &olen, 8, (void *) clear, 8) != - SECSuccess) { - wpa_printf(MSG_ERROR, "NSS: PK11_CipherOp failed"); - goto out; - } - -out: - if (ctx) - PK11_DestroyContext(ctx, PR_TRUE); - if (symkey) - PK11_FreeSymKey(symkey); - if (param) - SECITEM_FreeItem(param, PR_TRUE); -} - - -int rc4_skip(const u8 *key, size_t keylen, size_t skip, - u8 *data, size_t data_len) -{ - return -1; -} - - -int md5_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac) -{ - return nss_hash(HASH_AlgMD5, 16, num_elem, addr, len, mac); -} - - -int sha1_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac) -{ - return nss_hash(HASH_AlgSHA1, 20, num_elem, addr, len, mac); -} - - -int sha256_vector(size_t num_elem, const u8 *addr[], const size_t *len, - u8 *mac) -{ - return nss_hash(HASH_AlgSHA256, 32, num_elem, addr, len, mac); -} - - -void * aes_encrypt_init(const u8 *key, size_t len) -{ - return NULL; -} - - -void aes_encrypt(void *ctx, const u8 *plain, u8 *crypt) -{ -} - - -void aes_encrypt_deinit(void *ctx) -{ -} - - -void * aes_decrypt_init(const u8 *key, size_t len) -{ - return NULL; -} - - -void aes_decrypt(void *ctx, const u8 *crypt, u8 *plain) -{ -} - - -void aes_decrypt_deinit(void *ctx) -{ -} - - -int crypto_mod_exp(const u8 *base, size_t base_len, - const u8 *power, size_t power_len, - const u8 *modulus, size_t modulus_len, - u8 *result, size_t *result_len) -{ - return -1; -} - - -struct crypto_cipher { -}; - - -struct crypto_cipher * crypto_cipher_init(enum crypto_cipher_alg alg, - const u8 *iv, const u8 *key, - size_t key_len) -{ - return NULL; -} - - -int crypto_cipher_encrypt(struct crypto_cipher *ctx, const u8 *plain, - u8 *crypt, size_t len) -{ - return -1; -} - - -int crypto_cipher_decrypt(struct crypto_cipher *ctx, const u8 *crypt, - u8 *plain, size_t len) -{ - return -1; -} - - -void crypto_cipher_deinit(struct crypto_cipher *ctx) -{ -} diff --git a/hostapd-0.8/src/crypto/crypto_openssl.c b/hostapd-0.8/src/crypto/crypto_openssl.c deleted file mode 100644 index 08c98af..0000000 --- a/hostapd-0.8/src/crypto/crypto_openssl.c +++ /dev/null @@ -1,505 +0,0 @@ -/* - * WPA Supplicant / wrapper functions for libcrypto - * Copyright (c) 2004-2009, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#include "includes.h" -#include -#include -#include -#include -#include -#include -#include - -#include "common.h" -#include "wpabuf.h" -#include "dh_group5.h" -#include "crypto.h" - -#if OPENSSL_VERSION_NUMBER < 0x00907000 -#define DES_key_schedule des_key_schedule -#define DES_cblock des_cblock -#define DES_set_key(key, schedule) des_set_key((key), *(schedule)) -#define DES_ecb_encrypt(input, output, ks, enc) \ - des_ecb_encrypt((input), (output), *(ks), (enc)) -#endif /* openssl < 0.9.7 */ - -static BIGNUM * get_group5_prime(void) -{ -#if OPENSSL_VERSION_NUMBER < 0x00908000 - static const unsigned char RFC3526_PRIME_1536[] = { - 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xC9,0x0F,0xDA,0xA2, - 0x21,0x68,0xC2,0x34,0xC4,0xC6,0x62,0x8B,0x80,0xDC,0x1C,0xD1, - 0x29,0x02,0x4E,0x08,0x8A,0x67,0xCC,0x74,0x02,0x0B,0xBE,0xA6, - 0x3B,0x13,0x9B,0x22,0x51,0x4A,0x08,0x79,0x8E,0x34,0x04,0xDD, - 0xEF,0x95,0x19,0xB3,0xCD,0x3A,0x43,0x1B,0x30,0x2B,0x0A,0x6D, - 0xF2,0x5F,0x14,0x37,0x4F,0xE1,0x35,0x6D,0x6D,0x51,0xC2,0x45, - 0xE4,0x85,0xB5,0x76,0x62,0x5E,0x7E,0xC6,0xF4,0x4C,0x42,0xE9, - 0xA6,0x37,0xED,0x6B,0x0B,0xFF,0x5C,0xB6,0xF4,0x06,0xB7,0xED, - 0xEE,0x38,0x6B,0xFB,0x5A,0x89,0x9F,0xA5,0xAE,0x9F,0x24,0x11, - 0x7C,0x4B,0x1F,0xE6,0x49,0x28,0x66,0x51,0xEC,0xE4,0x5B,0x3D, - 0xC2,0x00,0x7C,0xB8,0xA1,0x63,0xBF,0x05,0x98,0xDA,0x48,0x36, - 0x1C,0x55,0xD3,0x9A,0x69,0x16,0x3F,0xA8,0xFD,0x24,0xCF,0x5F, - 0x83,0x65,0x5D,0x23,0xDC,0xA3,0xAD,0x96,0x1C,0x62,0xF3,0x56, - 0x20,0x85,0x52,0xBB,0x9E,0xD5,0x29,0x07,0x70,0x96,0x96,0x6D, - 0x67,0x0C,0x35,0x4E,0x4A,0xBC,0x98,0x04,0xF1,0x74,0x6C,0x08, - 0xCA,0x23,0x73,0x27,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, - }; - return BN_bin2bn(RFC3526_PRIME_1536, sizeof(RFC3526_PRIME_1536), NULL); -#else /* openssl < 0.9.8 */ - return get_rfc3526_prime_1536(NULL); -#endif /* openssl < 0.9.8 */ -} - -#if OPENSSL_VERSION_NUMBER < 0x00908000 -#ifndef OPENSSL_NO_SHA256 -#ifndef OPENSSL_FIPS -#define NO_SHA256_WRAPPER -#endif -#endif - -#endif /* openssl < 0.9.8 */ - -#ifdef OPENSSL_NO_SHA256 -#define NO_SHA256_WRAPPER -#endif - -static int openssl_digest_vector(const EVP_MD *type, int non_fips, - size_t num_elem, const u8 *addr[], - const size_t *len, u8 *mac) -{ - EVP_MD_CTX ctx; - size_t i; - unsigned int mac_len; - - EVP_MD_CTX_init(&ctx); -#ifdef CONFIG_FIPS -#ifdef OPENSSL_FIPS - if (non_fips) - EVP_MD_CTX_set_flags(&ctx, EVP_MD_CTX_FLAG_NON_FIPS_ALLOW); -#endif /* OPENSSL_FIPS */ -#endif /* CONFIG_FIPS */ - if (!EVP_DigestInit_ex(&ctx, type, NULL)) { - wpa_printf(MSG_ERROR, "OpenSSL: EVP_DigestInit_ex failed: %s", - ERR_error_string(ERR_get_error(), NULL)); - return -1; - } - for (i = 0; i < num_elem; i++) { - if (!EVP_DigestUpdate(&ctx, addr[i], len[i])) { - wpa_printf(MSG_ERROR, "OpenSSL: EVP_DigestUpdate " - "failed: %s", - ERR_error_string(ERR_get_error(), NULL)); - return -1; - } - } - if (!EVP_DigestFinal(&ctx, mac, &mac_len)) { - wpa_printf(MSG_ERROR, "OpenSSL: EVP_DigestFinal failed: %s", - ERR_error_string(ERR_get_error(), NULL)); - return -1; - } - - return 0; -} - - -int md4_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac) -{ - return openssl_digest_vector(EVP_md4(), 0, num_elem, addr, len, mac); -} - - -void des_encrypt(const u8 *clear, const u8 *key, u8 *cypher) -{ - u8 pkey[8], next, tmp; - int i; - DES_key_schedule ks; - - /* Add parity bits to the key */ - next = 0; - for (i = 0; i < 7; i++) { - tmp = key[i]; - pkey[i] = (tmp >> i) | next | 1; - next = tmp << (7 - i); - } - pkey[i] = next | 1; - - DES_set_key(&pkey, &ks); - DES_ecb_encrypt((DES_cblock *) clear, (DES_cblock *) cypher, &ks, - DES_ENCRYPT); -} - - -int rc4_skip(const u8 *key, size_t keylen, size_t skip, - u8 *data, size_t data_len) -{ -#ifdef OPENSSL_NO_RC4 - return -1; -#else /* OPENSSL_NO_RC4 */ - EVP_CIPHER_CTX ctx; - int outl; - int res = -1; - unsigned char skip_buf[16]; - - EVP_CIPHER_CTX_init(&ctx); - if (!EVP_CIPHER_CTX_set_padding(&ctx, 0) || - !EVP_CipherInit_ex(&ctx, EVP_rc4(), NULL, NULL, NULL, 1) || - !EVP_CIPHER_CTX_set_key_length(&ctx, keylen) || - !EVP_CipherInit_ex(&ctx, NULL, NULL, key, NULL, 1)) - goto out; - - while (skip >= sizeof(skip_buf)) { - size_t len = skip; - if (len > sizeof(skip_buf)) - len = sizeof(skip_buf); - if (!EVP_CipherUpdate(&ctx, skip_buf, &outl, skip_buf, len)) - goto out; - skip -= len; - } - - if (EVP_CipherUpdate(&ctx, data, &outl, data, data_len)) - res = 0; - -out: - EVP_CIPHER_CTX_cleanup(&ctx); - return res; -#endif /* OPENSSL_NO_RC4 */ -} - - -int md5_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac) -{ - return openssl_digest_vector(EVP_md5(), 0, num_elem, addr, len, mac); -} - - -#ifdef CONFIG_FIPS -int md5_vector_non_fips_allow(size_t num_elem, const u8 *addr[], - const size_t *len, u8 *mac) -{ - return openssl_digest_vector(EVP_md5(), 1, num_elem, addr, len, mac); -} -#endif /* CONFIG_FIPS */ - - -int sha1_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac) -{ - return openssl_digest_vector(EVP_sha1(), 0, num_elem, addr, len, mac); -} - - -#ifndef NO_SHA256_WRAPPER -int sha256_vector(size_t num_elem, const u8 *addr[], const size_t *len, - u8 *mac) -{ - return openssl_digest_vector(EVP_sha256(), 0, num_elem, addr, len, - mac); -} -#endif /* NO_SHA256_WRAPPER */ - - -void * aes_encrypt_init(const u8 *key, size_t len) -{ - AES_KEY *ak; - ak = os_malloc(sizeof(*ak)); - if (ak == NULL) - return NULL; - if (AES_set_encrypt_key(key, 8 * len, ak) < 0) { - os_free(ak); - return NULL; - } - return ak; -} - - -void aes_encrypt(void *ctx, const u8 *plain, u8 *crypt) -{ - AES_encrypt(plain, crypt, ctx); -} - - -void aes_encrypt_deinit(void *ctx) -{ - os_free(ctx); -} - - -void * aes_decrypt_init(const u8 *key, size_t len) -{ - AES_KEY *ak; - ak = os_malloc(sizeof(*ak)); - if (ak == NULL) - return NULL; - if (AES_set_decrypt_key(key, 8 * len, ak) < 0) { - os_free(ak); - return NULL; - } - return ak; -} - - -void aes_decrypt(void *ctx, const u8 *crypt, u8 *plain) -{ - AES_decrypt(crypt, plain, ctx); -} - - -void aes_decrypt_deinit(void *ctx) -{ - os_free(ctx); -} - - -int crypto_mod_exp(const u8 *base, size_t base_len, - const u8 *power, size_t power_len, - const u8 *modulus, size_t modulus_len, - u8 *result, size_t *result_len) -{ - BIGNUM *bn_base, *bn_exp, *bn_modulus, *bn_result; - int ret = -1; - BN_CTX *ctx; - - ctx = BN_CTX_new(); - if (ctx == NULL) - return -1; - - bn_base = BN_bin2bn(base, base_len, NULL); - bn_exp = BN_bin2bn(power, power_len, NULL); - bn_modulus = BN_bin2bn(modulus, modulus_len, NULL); - bn_result = BN_new(); - - if (bn_base == NULL || bn_exp == NULL || bn_modulus == NULL || - bn_result == NULL) - goto error; - - if (BN_mod_exp(bn_result, bn_base, bn_exp, bn_modulus, ctx) != 1) - goto error; - - *result_len = BN_bn2bin(bn_result, result); - ret = 0; - -error: - BN_free(bn_base); - BN_free(bn_exp); - BN_free(bn_modulus); - BN_free(bn_result); - BN_CTX_free(ctx); - return ret; -} - - -struct crypto_cipher { - EVP_CIPHER_CTX enc; - EVP_CIPHER_CTX dec; -}; - - -struct crypto_cipher * crypto_cipher_init(enum crypto_cipher_alg alg, - const u8 *iv, const u8 *key, - size_t key_len) -{ - struct crypto_cipher *ctx; - const EVP_CIPHER *cipher; - - ctx = os_zalloc(sizeof(*ctx)); - if (ctx == NULL) - return NULL; - - switch (alg) { -#ifndef OPENSSL_NO_RC4 - case CRYPTO_CIPHER_ALG_RC4: - cipher = EVP_rc4(); - break; -#endif /* OPENSSL_NO_RC4 */ -#ifndef OPENSSL_NO_AES - case CRYPTO_CIPHER_ALG_AES: - switch (key_len) { - case 16: - cipher = EVP_aes_128_cbc(); - break; - case 24: - cipher = EVP_aes_192_cbc(); - break; - case 32: - cipher = EVP_aes_256_cbc(); - break; - default: - os_free(ctx); - return NULL; - } - break; -#endif /* OPENSSL_NO_AES */ -#ifndef OPENSSL_NO_DES - case CRYPTO_CIPHER_ALG_3DES: - cipher = EVP_des_ede3_cbc(); - break; - case CRYPTO_CIPHER_ALG_DES: - cipher = EVP_des_cbc(); - break; -#endif /* OPENSSL_NO_DES */ -#ifndef OPENSSL_NO_RC2 - case CRYPTO_CIPHER_ALG_RC2: - cipher = EVP_rc2_ecb(); - break; -#endif /* OPENSSL_NO_RC2 */ - default: - os_free(ctx); - return NULL; - } - - EVP_CIPHER_CTX_init(&ctx->enc); - EVP_CIPHER_CTX_set_padding(&ctx->enc, 0); - if (!EVP_EncryptInit_ex(&ctx->enc, cipher, NULL, NULL, NULL) || - !EVP_CIPHER_CTX_set_key_length(&ctx->enc, key_len) || - !EVP_EncryptInit_ex(&ctx->enc, NULL, NULL, key, iv)) { - EVP_CIPHER_CTX_cleanup(&ctx->enc); - os_free(ctx); - return NULL; - } - - EVP_CIPHER_CTX_init(&ctx->dec); - EVP_CIPHER_CTX_set_padding(&ctx->dec, 0); - if (!EVP_DecryptInit_ex(&ctx->dec, cipher, NULL, NULL, NULL) || - !EVP_CIPHER_CTX_set_key_length(&ctx->dec, key_len) || - !EVP_DecryptInit_ex(&ctx->dec, NULL, NULL, key, iv)) { - EVP_CIPHER_CTX_cleanup(&ctx->enc); - EVP_CIPHER_CTX_cleanup(&ctx->dec); - os_free(ctx); - return NULL; - } - - return ctx; -} - - -int crypto_cipher_encrypt(struct crypto_cipher *ctx, const u8 *plain, - u8 *crypt, size_t len) -{ - int outl; - if (!EVP_EncryptUpdate(&ctx->enc, crypt, &outl, plain, len)) - return -1; - return 0; -} - - -int crypto_cipher_decrypt(struct crypto_cipher *ctx, const u8 *crypt, - u8 *plain, size_t len) -{ - int outl; - outl = len; - if (!EVP_DecryptUpdate(&ctx->dec, plain, &outl, crypt, len)) - return -1; - return 0; -} - - -void crypto_cipher_deinit(struct crypto_cipher *ctx) -{ - EVP_CIPHER_CTX_cleanup(&ctx->enc); - EVP_CIPHER_CTX_cleanup(&ctx->dec); - os_free(ctx); -} - - -void * dh5_init(struct wpabuf **priv, struct wpabuf **publ) -{ - DH *dh; - struct wpabuf *pubkey = NULL, *privkey = NULL; - size_t publen, privlen; - - *priv = NULL; - *publ = NULL; - - dh = DH_new(); - if (dh == NULL) - return NULL; - - dh->g = BN_new(); - if (dh->g == NULL || BN_set_word(dh->g, 2) != 1) - goto err; - - dh->p = get_group5_prime(); - if (dh->p == NULL) - goto err; - - if (DH_generate_key(dh) != 1) - goto err; - - publen = BN_num_bytes(dh->pub_key); - pubkey = wpabuf_alloc(publen); - if (pubkey == NULL) - goto err; - privlen = BN_num_bytes(dh->priv_key); - privkey = wpabuf_alloc(privlen); - if (privkey == NULL) - goto err; - - BN_bn2bin(dh->pub_key, wpabuf_put(pubkey, publen)); - BN_bn2bin(dh->priv_key, wpabuf_put(privkey, privlen)); - - *priv = privkey; - *publ = pubkey; - return dh; - -err: - wpabuf_free(pubkey); - wpabuf_free(privkey); - DH_free(dh); - return NULL; -} - - -struct wpabuf * dh5_derive_shared(void *ctx, const struct wpabuf *peer_public, - const struct wpabuf *own_private) -{ - BIGNUM *pub_key; - struct wpabuf *res = NULL; - size_t rlen; - DH *dh = ctx; - int keylen; - - if (ctx == NULL) - return NULL; - - pub_key = BN_bin2bn(wpabuf_head(peer_public), wpabuf_len(peer_public), - NULL); - if (pub_key == NULL) - return NULL; - - rlen = DH_size(dh); - res = wpabuf_alloc(rlen); - if (res == NULL) - goto err; - - keylen = DH_compute_key(wpabuf_mhead(res), pub_key, dh); - if (keylen < 0) - goto err; - wpabuf_put(res, keylen); - BN_free(pub_key); - - return res; - -err: - BN_free(pub_key); - wpabuf_free(res); - return NULL; -} - - -void dh5_free(void *ctx) -{ - DH *dh; - if (ctx == NULL) - return; - dh = ctx; - DH_free(dh); -} diff --git a/hostapd-0.8/src/crypto/des-internal.c b/hostapd-0.8/src/crypto/des-internal.c deleted file mode 100644 index ccea950..0000000 --- a/hostapd-0.8/src/crypto/des-internal.c +++ /dev/null @@ -1,499 +0,0 @@ -/* - * DES and 3DES-EDE ciphers - * - * Modifications to LibTomCrypt implementation: - * Copyright (c) 2006-2009, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#include "includes.h" - -#include "common.h" -#include "crypto.h" -#include "des_i.h" - -/* - * This implementation is based on a DES implementation included in - * LibTomCrypt. The version here is modified to fit in wpa_supplicant/hostapd - * coding style. - */ - -/* LibTomCrypt, modular cryptographic library -- Tom St Denis - * - * LibTomCrypt is a library that provides various cryptographic - * algorithms in a highly modular and flexible manner. - * - * The library is free for all purposes without any express - * guarantee it works. - * - * Tom St Denis, tomstdenis@gmail.com, http://libtomcrypt.com - */ - -/** - DES code submitted by Dobes Vandermeer -*/ - -#define ROLc(x, y) \ - ((((unsigned long) (x) << (unsigned long) ((y) & 31)) | \ - (((unsigned long) (x) & 0xFFFFFFFFUL) >> \ - (unsigned long) (32 - ((y) & 31)))) & 0xFFFFFFFFUL) -#define RORc(x, y) \ - (((((unsigned long) (x) & 0xFFFFFFFFUL) >> \ - (unsigned long) ((y) & 31)) | \ - ((unsigned long) (x) << (unsigned long) (32 - ((y) & 31)))) & \ - 0xFFFFFFFFUL) - - -static const u32 bytebit[8] = -{ - 0200, 0100, 040, 020, 010, 04, 02, 01 -}; - -static const u32 bigbyte[24] = -{ - 0x800000UL, 0x400000UL, 0x200000UL, 0x100000UL, - 0x80000UL, 0x40000UL, 0x20000UL, 0x10000UL, - 0x8000UL, 0x4000UL, 0x2000UL, 0x1000UL, - 0x800UL, 0x400UL, 0x200UL, 0x100UL, - 0x80UL, 0x40UL, 0x20UL, 0x10UL, - 0x8UL, 0x4UL, 0x2UL, 0x1L -}; - -/* Use the key schedule specific in the standard (ANSI X3.92-1981) */ - -static const u8 pc1[56] = { - 56, 48, 40, 32, 24, 16, 8, 0, 57, 49, 41, 33, 25, 17, - 9, 1, 58, 50, 42, 34, 26, 18, 10, 2, 59, 51, 43, 35, - 62, 54, 46, 38, 30, 22, 14, 6, 61, 53, 45, 37, 29, 21, - 13, 5, 60, 52, 44, 36, 28, 20, 12, 4, 27, 19, 11, 3 -}; - -static const u8 totrot[16] = { - 1, 2, 4, 6, - 8, 10, 12, 14, - 15, 17, 19, 21, - 23, 25, 27, 28 -}; - -static const u8 pc2[48] = { - 13, 16, 10, 23, 0, 4, 2, 27, 14, 5, 20, 9, - 22, 18, 11, 3, 25, 7, 15, 6, 26, 19, 12, 1, - 40, 51, 30, 36, 46, 54, 29, 39, 50, 44, 32, 47, - 43, 48, 38, 55, 33, 52, 45, 41, 49, 35, 28, 31 -}; - - -static const u32 SP1[64] = -{ - 0x01010400UL, 0x00000000UL, 0x00010000UL, 0x01010404UL, - 0x01010004UL, 0x00010404UL, 0x00000004UL, 0x00010000UL, - 0x00000400UL, 0x01010400UL, 0x01010404UL, 0x00000400UL, - 0x01000404UL, 0x01010004UL, 0x01000000UL, 0x00000004UL, - 0x00000404UL, 0x01000400UL, 0x01000400UL, 0x00010400UL, - 0x00010400UL, 0x01010000UL, 0x01010000UL, 0x01000404UL, - 0x00010004UL, 0x01000004UL, 0x01000004UL, 0x00010004UL, - 0x00000000UL, 0x00000404UL, 0x00010404UL, 0x01000000UL, - 0x00010000UL, 0x01010404UL, 0x00000004UL, 0x01010000UL, - 0x01010400UL, 0x01000000UL, 0x01000000UL, 0x00000400UL, - 0x01010004UL, 0x00010000UL, 0x00010400UL, 0x01000004UL, - 0x00000400UL, 0x00000004UL, 0x01000404UL, 0x00010404UL, - 0x01010404UL, 0x00010004UL, 0x01010000UL, 0x01000404UL, - 0x01000004UL, 0x00000404UL, 0x00010404UL, 0x01010400UL, - 0x00000404UL, 0x01000400UL, 0x01000400UL, 0x00000000UL, - 0x00010004UL, 0x00010400UL, 0x00000000UL, 0x01010004UL -}; - -static const u32 SP2[64] = -{ - 0x80108020UL, 0x80008000UL, 0x00008000UL, 0x00108020UL, - 0x00100000UL, 0x00000020UL, 0x80100020UL, 0x80008020UL, - 0x80000020UL, 0x80108020UL, 0x80108000UL, 0x80000000UL, - 0x80008000UL, 0x00100000UL, 0x00000020UL, 0x80100020UL, - 0x00108000UL, 0x00100020UL, 0x80008020UL, 0x00000000UL, - 0x80000000UL, 0x00008000UL, 0x00108020UL, 0x80100000UL, - 0x00100020UL, 0x80000020UL, 0x00000000UL, 0x00108000UL, - 0x00008020UL, 0x80108000UL, 0x80100000UL, 0x00008020UL, - 0x00000000UL, 0x00108020UL, 0x80100020UL, 0x00100000UL, - 0x80008020UL, 0x80100000UL, 0x80108000UL, 0x00008000UL, - 0x80100000UL, 0x80008000UL, 0x00000020UL, 0x80108020UL, - 0x00108020UL, 0x00000020UL, 0x00008000UL, 0x80000000UL, - 0x00008020UL, 0x80108000UL, 0x00100000UL, 0x80000020UL, - 0x00100020UL, 0x80008020UL, 0x80000020UL, 0x00100020UL, - 0x00108000UL, 0x00000000UL, 0x80008000UL, 0x00008020UL, - 0x80000000UL, 0x80100020UL, 0x80108020UL, 0x00108000UL -}; - -static const u32 SP3[64] = -{ - 0x00000208UL, 0x08020200UL, 0x00000000UL, 0x08020008UL, - 0x08000200UL, 0x00000000UL, 0x00020208UL, 0x08000200UL, - 0x00020008UL, 0x08000008UL, 0x08000008UL, 0x00020000UL, - 0x08020208UL, 0x00020008UL, 0x08020000UL, 0x00000208UL, - 0x08000000UL, 0x00000008UL, 0x08020200UL, 0x00000200UL, - 0x00020200UL, 0x08020000UL, 0x08020008UL, 0x00020208UL, - 0x08000208UL, 0x00020200UL, 0x00020000UL, 0x08000208UL, - 0x00000008UL, 0x08020208UL, 0x00000200UL, 0x08000000UL, - 0x08020200UL, 0x08000000UL, 0x00020008UL, 0x00000208UL, - 0x00020000UL, 0x08020200UL, 0x08000200UL, 0x00000000UL, - 0x00000200UL, 0x00020008UL, 0x08020208UL, 0x08000200UL, - 0x08000008UL, 0x00000200UL, 0x00000000UL, 0x08020008UL, - 0x08000208UL, 0x00020000UL, 0x08000000UL, 0x08020208UL, - 0x00000008UL, 0x00020208UL, 0x00020200UL, 0x08000008UL, - 0x08020000UL, 0x08000208UL, 0x00000208UL, 0x08020000UL, - 0x00020208UL, 0x00000008UL, 0x08020008UL, 0x00020200UL -}; - -static const u32 SP4[64] = -{ - 0x00802001UL, 0x00002081UL, 0x00002081UL, 0x00000080UL, - 0x00802080UL, 0x00800081UL, 0x00800001UL, 0x00002001UL, - 0x00000000UL, 0x00802000UL, 0x00802000UL, 0x00802081UL, - 0x00000081UL, 0x00000000UL, 0x00800080UL, 0x00800001UL, - 0x00000001UL, 0x00002000UL, 0x00800000UL, 0x00802001UL, - 0x00000080UL, 0x00800000UL, 0x00002001UL, 0x00002080UL, - 0x00800081UL, 0x00000001UL, 0x00002080UL, 0x00800080UL, - 0x00002000UL, 0x00802080UL, 0x00802081UL, 0x00000081UL, - 0x00800080UL, 0x00800001UL, 0x00802000UL, 0x00802081UL, - 0x00000081UL, 0x00000000UL, 0x00000000UL, 0x00802000UL, - 0x00002080UL, 0x00800080UL, 0x00800081UL, 0x00000001UL, - 0x00802001UL, 0x00002081UL, 0x00002081UL, 0x00000080UL, - 0x00802081UL, 0x00000081UL, 0x00000001UL, 0x00002000UL, - 0x00800001UL, 0x00002001UL, 0x00802080UL, 0x00800081UL, - 0x00002001UL, 0x00002080UL, 0x00800000UL, 0x00802001UL, - 0x00000080UL, 0x00800000UL, 0x00002000UL, 0x00802080UL -}; - -static const u32 SP5[64] = -{ - 0x00000100UL, 0x02080100UL, 0x02080000UL, 0x42000100UL, - 0x00080000UL, 0x00000100UL, 0x40000000UL, 0x02080000UL, - 0x40080100UL, 0x00080000UL, 0x02000100UL, 0x40080100UL, - 0x42000100UL, 0x42080000UL, 0x00080100UL, 0x40000000UL, - 0x02000000UL, 0x40080000UL, 0x40080000UL, 0x00000000UL, - 0x40000100UL, 0x42080100UL, 0x42080100UL, 0x02000100UL, - 0x42080000UL, 0x40000100UL, 0x00000000UL, 0x42000000UL, - 0x02080100UL, 0x02000000UL, 0x42000000UL, 0x00080100UL, - 0x00080000UL, 0x42000100UL, 0x00000100UL, 0x02000000UL, - 0x40000000UL, 0x02080000UL, 0x42000100UL, 0x40080100UL, - 0x02000100UL, 0x40000000UL, 0x42080000UL, 0x02080100UL, - 0x40080100UL, 0x00000100UL, 0x02000000UL, 0x42080000UL, - 0x42080100UL, 0x00080100UL, 0x42000000UL, 0x42080100UL, - 0x02080000UL, 0x00000000UL, 0x40080000UL, 0x42000000UL, - 0x00080100UL, 0x02000100UL, 0x40000100UL, 0x00080000UL, - 0x00000000UL, 0x40080000UL, 0x02080100UL, 0x40000100UL -}; - -static const u32 SP6[64] = -{ - 0x20000010UL, 0x20400000UL, 0x00004000UL, 0x20404010UL, - 0x20400000UL, 0x00000010UL, 0x20404010UL, 0x00400000UL, - 0x20004000UL, 0x00404010UL, 0x00400000UL, 0x20000010UL, - 0x00400010UL, 0x20004000UL, 0x20000000UL, 0x00004010UL, - 0x00000000UL, 0x00400010UL, 0x20004010UL, 0x00004000UL, - 0x00404000UL, 0x20004010UL, 0x00000010UL, 0x20400010UL, - 0x20400010UL, 0x00000000UL, 0x00404010UL, 0x20404000UL, - 0x00004010UL, 0x00404000UL, 0x20404000UL, 0x20000000UL, - 0x20004000UL, 0x00000010UL, 0x20400010UL, 0x00404000UL, - 0x20404010UL, 0x00400000UL, 0x00004010UL, 0x20000010UL, - 0x00400000UL, 0x20004000UL, 0x20000000UL, 0x00004010UL, - 0x20000010UL, 0x20404010UL, 0x00404000UL, 0x20400000UL, - 0x00404010UL, 0x20404000UL, 0x00000000UL, 0x20400010UL, - 0x00000010UL, 0x00004000UL, 0x20400000UL, 0x00404010UL, - 0x00004000UL, 0x00400010UL, 0x20004010UL, 0x00000000UL, - 0x20404000UL, 0x20000000UL, 0x00400010UL, 0x20004010UL -}; - -static const u32 SP7[64] = -{ - 0x00200000UL, 0x04200002UL, 0x04000802UL, 0x00000000UL, - 0x00000800UL, 0x04000802UL, 0x00200802UL, 0x04200800UL, - 0x04200802UL, 0x00200000UL, 0x00000000UL, 0x04000002UL, - 0x00000002UL, 0x04000000UL, 0x04200002UL, 0x00000802UL, - 0x04000800UL, 0x00200802UL, 0x00200002UL, 0x04000800UL, - 0x04000002UL, 0x04200000UL, 0x04200800UL, 0x00200002UL, - 0x04200000UL, 0x00000800UL, 0x00000802UL, 0x04200802UL, - 0x00200800UL, 0x00000002UL, 0x04000000UL, 0x00200800UL, - 0x04000000UL, 0x00200800UL, 0x00200000UL, 0x04000802UL, - 0x04000802UL, 0x04200002UL, 0x04200002UL, 0x00000002UL, - 0x00200002UL, 0x04000000UL, 0x04000800UL, 0x00200000UL, - 0x04200800UL, 0x00000802UL, 0x00200802UL, 0x04200800UL, - 0x00000802UL, 0x04000002UL, 0x04200802UL, 0x04200000UL, - 0x00200800UL, 0x00000000UL, 0x00000002UL, 0x04200802UL, - 0x00000000UL, 0x00200802UL, 0x04200000UL, 0x00000800UL, - 0x04000002UL, 0x04000800UL, 0x00000800UL, 0x00200002UL -}; - -static const u32 SP8[64] = -{ - 0x10001040UL, 0x00001000UL, 0x00040000UL, 0x10041040UL, - 0x10000000UL, 0x10001040UL, 0x00000040UL, 0x10000000UL, - 0x00040040UL, 0x10040000UL, 0x10041040UL, 0x00041000UL, - 0x10041000UL, 0x00041040UL, 0x00001000UL, 0x00000040UL, - 0x10040000UL, 0x10000040UL, 0x10001000UL, 0x00001040UL, - 0x00041000UL, 0x00040040UL, 0x10040040UL, 0x10041000UL, - 0x00001040UL, 0x00000000UL, 0x00000000UL, 0x10040040UL, - 0x10000040UL, 0x10001000UL, 0x00041040UL, 0x00040000UL, - 0x00041040UL, 0x00040000UL, 0x10041000UL, 0x00001000UL, - 0x00000040UL, 0x10040040UL, 0x00001000UL, 0x00041040UL, - 0x10001000UL, 0x00000040UL, 0x10000040UL, 0x10040000UL, - 0x10040040UL, 0x10000000UL, 0x00040000UL, 0x10001040UL, - 0x00000000UL, 0x10041040UL, 0x00040040UL, 0x10000040UL, - 0x10040000UL, 0x10001000UL, 0x10001040UL, 0x00000000UL, - 0x10041040UL, 0x00041000UL, 0x00041000UL, 0x00001040UL, - 0x00001040UL, 0x00040040UL, 0x10000000UL, 0x10041000UL -}; - - -static void cookey(const u32 *raw1, u32 *keyout) -{ - u32 *cook; - const u32 *raw0; - u32 dough[32]; - int i; - - cook = dough; - for (i = 0; i < 16; i++, raw1++) { - raw0 = raw1++; - *cook = (*raw0 & 0x00fc0000L) << 6; - *cook |= (*raw0 & 0x00000fc0L) << 10; - *cook |= (*raw1 & 0x00fc0000L) >> 10; - *cook++ |= (*raw1 & 0x00000fc0L) >> 6; - *cook = (*raw0 & 0x0003f000L) << 12; - *cook |= (*raw0 & 0x0000003fL) << 16; - *cook |= (*raw1 & 0x0003f000L) >> 4; - *cook++ |= (*raw1 & 0x0000003fL); - } - - os_memcpy(keyout, dough, sizeof(dough)); -} - - -static void deskey(const u8 *key, int decrypt, u32 *keyout) -{ - u32 i, j, l, m, n, kn[32]; - u8 pc1m[56], pcr[56]; - - for (j = 0; j < 56; j++) { - l = (u32) pc1[j]; - m = l & 7; - pc1m[j] = (u8) - ((key[l >> 3U] & bytebit[m]) == bytebit[m] ? 1 : 0); - } - - for (i = 0; i < 16; i++) { - if (decrypt) - m = (15 - i) << 1; - else - m = i << 1; - n = m + 1; - kn[m] = kn[n] = 0L; - for (j = 0; j < 28; j++) { - l = j + (u32) totrot[i]; - if (l < 28) - pcr[j] = pc1m[l]; - else - pcr[j] = pc1m[l - 28]; - } - for (/* j = 28 */; j < 56; j++) { - l = j + (u32) totrot[i]; - if (l < 56) - pcr[j] = pc1m[l]; - else - pcr[j] = pc1m[l - 28]; - } - for (j = 0; j < 24; j++) { - if ((int) pcr[(int) pc2[j]] != 0) - kn[m] |= bigbyte[j]; - if ((int) pcr[(int) pc2[j + 24]] != 0) - kn[n] |= bigbyte[j]; - } - } - - cookey(kn, keyout); -} - - -static void desfunc(u32 *block, const u32 *keys) -{ - u32 work, right, leftt; - int cur_round; - - leftt = block[0]; - right = block[1]; - - work = ((leftt >> 4) ^ right) & 0x0f0f0f0fL; - right ^= work; - leftt ^= (work << 4); - - work = ((leftt >> 16) ^ right) & 0x0000ffffL; - right ^= work; - leftt ^= (work << 16); - - work = ((right >> 2) ^ leftt) & 0x33333333L; - leftt ^= work; - right ^= (work << 2); - - work = ((right >> 8) ^ leftt) & 0x00ff00ffL; - leftt ^= work; - right ^= (work << 8); - - right = ROLc(right, 1); - work = (leftt ^ right) & 0xaaaaaaaaL; - - leftt ^= work; - right ^= work; - leftt = ROLc(leftt, 1); - - for (cur_round = 0; cur_round < 8; cur_round++) { - work = RORc(right, 4) ^ *keys++; - leftt ^= SP7[work & 0x3fL] - ^ SP5[(work >> 8) & 0x3fL] - ^ SP3[(work >> 16) & 0x3fL] - ^ SP1[(work >> 24) & 0x3fL]; - work = right ^ *keys++; - leftt ^= SP8[ work & 0x3fL] - ^ SP6[(work >> 8) & 0x3fL] - ^ SP4[(work >> 16) & 0x3fL] - ^ SP2[(work >> 24) & 0x3fL]; - - work = RORc(leftt, 4) ^ *keys++; - right ^= SP7[ work & 0x3fL] - ^ SP5[(work >> 8) & 0x3fL] - ^ SP3[(work >> 16) & 0x3fL] - ^ SP1[(work >> 24) & 0x3fL]; - work = leftt ^ *keys++; - right ^= SP8[ work & 0x3fL] - ^ SP6[(work >> 8) & 0x3fL] - ^ SP4[(work >> 16) & 0x3fL] - ^ SP2[(work >> 24) & 0x3fL]; - } - - right = RORc(right, 1); - work = (leftt ^ right) & 0xaaaaaaaaL; - leftt ^= work; - right ^= work; - leftt = RORc(leftt, 1); - work = ((leftt >> 8) ^ right) & 0x00ff00ffL; - right ^= work; - leftt ^= (work << 8); - /* -- */ - work = ((leftt >> 2) ^ right) & 0x33333333L; - right ^= work; - leftt ^= (work << 2); - work = ((right >> 16) ^ leftt) & 0x0000ffffL; - leftt ^= work; - right ^= (work << 16); - work = ((right >> 4) ^ leftt) & 0x0f0f0f0fL; - leftt ^= work; - right ^= (work << 4); - - block[0] = right; - block[1] = leftt; -} - - -/* wpa_supplicant/hostapd specific wrapper */ - -void des_encrypt(const u8 *clear, const u8 *key, u8 *cypher) -{ - u8 pkey[8], next, tmp; - int i; - u32 ek[32], work[2]; - - /* Add parity bits to the key */ - next = 0; - for (i = 0; i < 7; i++) { - tmp = key[i]; - pkey[i] = (tmp >> i) | next | 1; - next = tmp << (7 - i); - } - pkey[i] = next | 1; - - deskey(pkey, 0, ek); - - work[0] = WPA_GET_BE32(clear); - work[1] = WPA_GET_BE32(clear + 4); - desfunc(work, ek); - WPA_PUT_BE32(cypher, work[0]); - WPA_PUT_BE32(cypher + 4, work[1]); - - os_memset(pkey, 0, sizeof(pkey)); - os_memset(ek, 0, sizeof(ek)); -} - - -void des_key_setup(const u8 *key, u32 *ek, u32 *dk) -{ - deskey(key, 0, ek); - deskey(key, 1, dk); -} - - -void des_block_encrypt(const u8 *plain, const u32 *ek, u8 *crypt) -{ - u32 work[2]; - work[0] = WPA_GET_BE32(plain); - work[1] = WPA_GET_BE32(plain + 4); - desfunc(work, ek); - WPA_PUT_BE32(crypt, work[0]); - WPA_PUT_BE32(crypt + 4, work[1]); -} - - -void des_block_decrypt(const u8 *crypt, const u32 *dk, u8 *plain) -{ - u32 work[2]; - work[0] = WPA_GET_BE32(crypt); - work[1] = WPA_GET_BE32(crypt + 4); - desfunc(work, dk); - WPA_PUT_BE32(plain, work[0]); - WPA_PUT_BE32(plain + 4, work[1]); -} - - -void des3_key_setup(const u8 *key, struct des3_key_s *dkey) -{ - deskey(key, 0, dkey->ek[0]); - deskey(key + 8, 1, dkey->ek[1]); - deskey(key + 16, 0, dkey->ek[2]); - - deskey(key, 1, dkey->dk[2]); - deskey(key + 8, 0, dkey->dk[1]); - deskey(key + 16, 1, dkey->dk[0]); -} - - -void des3_encrypt(const u8 *plain, const struct des3_key_s *key, u8 *crypt) -{ - u32 work[2]; - - work[0] = WPA_GET_BE32(plain); - work[1] = WPA_GET_BE32(plain + 4); - desfunc(work, key->ek[0]); - desfunc(work, key->ek[1]); - desfunc(work, key->ek[2]); - WPA_PUT_BE32(crypt, work[0]); - WPA_PUT_BE32(crypt + 4, work[1]); -} - - -void des3_decrypt(const u8 *crypt, const struct des3_key_s *key, u8 *plain) -{ - u32 work[2]; - - work[0] = WPA_GET_BE32(crypt); - work[1] = WPA_GET_BE32(crypt + 4); - desfunc(work, key->dk[0]); - desfunc(work, key->dk[1]); - desfunc(work, key->dk[2]); - WPA_PUT_BE32(plain, work[0]); - WPA_PUT_BE32(plain + 4, work[1]); -} diff --git a/hostapd-0.8/src/crypto/des_i.h b/hostapd-0.8/src/crypto/des_i.h deleted file mode 100644 index 6f27414..0000000 --- a/hostapd-0.8/src/crypto/des_i.h +++ /dev/null @@ -1,31 +0,0 @@ -/* - * DES and 3DES-EDE ciphers - * Copyright (c) 2006-2009, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#ifndef DES_I_H -#define DES_I_H - -struct des3_key_s { - u32 ek[3][32]; - u32 dk[3][32]; -}; - -void des_key_setup(const u8 *key, u32 *ek, u32 *dk); -void des_block_encrypt(const u8 *plain, const u32 *ek, u8 *crypt); -void des_block_decrypt(const u8 *crypt, const u32 *dk, u8 *plain); - -void des3_key_setup(const u8 *key, struct des3_key_s *dkey); -void des3_encrypt(const u8 *plain, const struct des3_key_s *key, u8 *crypt); -void des3_decrypt(const u8 *crypt, const struct des3_key_s *key, u8 *plain); - -#endif /* DES_I_H */ diff --git a/hostapd-0.8/src/crypto/dh_group5.c b/hostapd-0.8/src/crypto/dh_group5.c deleted file mode 100644 index 8c475bf..0000000 --- a/hostapd-0.8/src/crypto/dh_group5.c +++ /dev/null @@ -1,40 +0,0 @@ -/* - * Diffie-Hellman group 5 operations - * Copyright (c) 2009, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#include "includes.h" - -#include "common.h" -#include "dh_groups.h" -#include "dh_group5.h" - - -void * dh5_init(struct wpabuf **priv, struct wpabuf **publ) -{ - *publ = dh_init(dh_groups_get(5), priv); - if (*publ == 0) - return NULL; - return (void *) 1; -} - - -struct wpabuf * dh5_derive_shared(void *ctx, const struct wpabuf *peer_public, - const struct wpabuf *own_private) -{ - return dh_derive_shared(peer_public, own_private, dh_groups_get(5)); -} - - -void dh5_free(void *ctx) -{ -} diff --git a/hostapd-0.8/src/crypto/dh_group5.h b/hostapd-0.8/src/crypto/dh_group5.h deleted file mode 100644 index 595f111..0000000 --- a/hostapd-0.8/src/crypto/dh_group5.h +++ /dev/null @@ -1,23 +0,0 @@ -/* - * Diffie-Hellman group 5 operations - * Copyright (c) 2009, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#ifndef DH_GROUP5_H -#define DH_GROUP5_H - -void * dh5_init(struct wpabuf **priv, struct wpabuf **publ); -struct wpabuf * dh5_derive_shared(void *ctx, const struct wpabuf *peer_public, - const struct wpabuf *own_private); -void dh5_free(void *ctx); - -#endif /* DH_GROUP5_H */ diff --git a/hostapd-0.8/src/crypto/dh_groups.c b/hostapd-0.8/src/crypto/dh_groups.c deleted file mode 100644 index e5b7d4c..0000000 --- a/hostapd-0.8/src/crypto/dh_groups.c +++ /dev/null @@ -1,633 +0,0 @@ -/* - * Diffie-Hellman groups - * Copyright (c) 2007, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#include "includes.h" - -#include "common.h" -#include "crypto.h" -#include "random.h" -#include "dh_groups.h" - - -#ifdef ALL_DH_GROUPS - -/* RFC 4306, B.1. Group 1 - 768 Bit MODP - * Generator: 2 - * Prime: 2^768 - 2 ^704 - 1 + 2^64 * { [2^638 pi] + 149686 } - */ -static const u8 dh_group1_generator[1] = { 0x02 }; -static const u8 dh_group1_prime[96] = { - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xC9, 0x0F, 0xDA, 0xA2, 0x21, 0x68, 0xC2, 0x34, - 0xC4, 0xC6, 0x62, 0x8B, 0x80, 0xDC, 0x1C, 0xD1, - 0x29, 0x02, 0x4E, 0x08, 0x8A, 0x67, 0xCC, 0x74, - 0x02, 0x0B, 0xBE, 0xA6, 0x3B, 0x13, 0x9B, 0x22, - 0x51, 0x4A, 0x08, 0x79, 0x8E, 0x34, 0x04, 0xDD, - 0xEF, 0x95, 0x19, 0xB3, 0xCD, 0x3A, 0x43, 0x1B, - 0x30, 0x2B, 0x0A, 0x6D, 0xF2, 0x5F, 0x14, 0x37, - 0x4F, 0xE1, 0x35, 0x6D, 0x6D, 0x51, 0xC2, 0x45, - 0xE4, 0x85, 0xB5, 0x76, 0x62, 0x5E, 0x7E, 0xC6, - 0xF4, 0x4C, 0x42, 0xE9, 0xA6, 0x3A, 0x36, 0x20, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF -}; - -/* RFC 4306, B.2. Group 2 - 1024 Bit MODP - * Generator: 2 - * Prime: 2^1024 - 2^960 - 1 + 2^64 * { [2^894 pi] + 129093 } - */ -static const u8 dh_group2_generator[1] = { 0x02 }; -static const u8 dh_group2_prime[128] = { - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xC9, 0x0F, 0xDA, 0xA2, 0x21, 0x68, 0xC2, 0x34, - 0xC4, 0xC6, 0x62, 0x8B, 0x80, 0xDC, 0x1C, 0xD1, - 0x29, 0x02, 0x4E, 0x08, 0x8A, 0x67, 0xCC, 0x74, - 0x02, 0x0B, 0xBE, 0xA6, 0x3B, 0x13, 0x9B, 0x22, - 0x51, 0x4A, 0x08, 0x79, 0x8E, 0x34, 0x04, 0xDD, - 0xEF, 0x95, 0x19, 0xB3, 0xCD, 0x3A, 0x43, 0x1B, - 0x30, 0x2B, 0x0A, 0x6D, 0xF2, 0x5F, 0x14, 0x37, - 0x4F, 0xE1, 0x35, 0x6D, 0x6D, 0x51, 0xC2, 0x45, - 0xE4, 0x85, 0xB5, 0x76, 0x62, 0x5E, 0x7E, 0xC6, - 0xF4, 0x4C, 0x42, 0xE9, 0xA6, 0x37, 0xED, 0x6B, - 0x0B, 0xFF, 0x5C, 0xB6, 0xF4, 0x06, 0xB7, 0xED, - 0xEE, 0x38, 0x6B, 0xFB, 0x5A, 0x89, 0x9F, 0xA5, - 0xAE, 0x9F, 0x24, 0x11, 0x7C, 0x4B, 0x1F, 0xE6, - 0x49, 0x28, 0x66, 0x51, 0xEC, 0xE6, 0x53, 0x81, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF -}; - -#endif /* ALL_DH_GROUPS */ - -/* RFC 3526, 2. Group 5 - 1536 Bit MODP - * Generator: 2 - * Prime: 2^1536 - 2^1472 - 1 + 2^64 * { [2^1406 pi] + 741804 } - */ -static const u8 dh_group5_generator[1] = { 0x02 }; -static const u8 dh_group5_prime[192] = { - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xC9, 0x0F, 0xDA, 0xA2, 0x21, 0x68, 0xC2, 0x34, - 0xC4, 0xC6, 0x62, 0x8B, 0x80, 0xDC, 0x1C, 0xD1, - 0x29, 0x02, 0x4E, 0x08, 0x8A, 0x67, 0xCC, 0x74, - 0x02, 0x0B, 0xBE, 0xA6, 0x3B, 0x13, 0x9B, 0x22, - 0x51, 0x4A, 0x08, 0x79, 0x8E, 0x34, 0x04, 0xDD, - 0xEF, 0x95, 0x19, 0xB3, 0xCD, 0x3A, 0x43, 0x1B, - 0x30, 0x2B, 0x0A, 0x6D, 0xF2, 0x5F, 0x14, 0x37, - 0x4F, 0xE1, 0x35, 0x6D, 0x6D, 0x51, 0xC2, 0x45, - 0xE4, 0x85, 0xB5, 0x76, 0x62, 0x5E, 0x7E, 0xC6, - 0xF4, 0x4C, 0x42, 0xE9, 0xA6, 0x37, 0xED, 0x6B, - 0x0B, 0xFF, 0x5C, 0xB6, 0xF4, 0x06, 0xB7, 0xED, - 0xEE, 0x38, 0x6B, 0xFB, 0x5A, 0x89, 0x9F, 0xA5, - 0xAE, 0x9F, 0x24, 0x11, 0x7C, 0x4B, 0x1F, 0xE6, - 0x49, 0x28, 0x66, 0x51, 0xEC, 0xE4, 0x5B, 0x3D, - 0xC2, 0x00, 0x7C, 0xB8, 0xA1, 0x63, 0xBF, 0x05, - 0x98, 0xDA, 0x48, 0x36, 0x1C, 0x55, 0xD3, 0x9A, - 0x69, 0x16, 0x3F, 0xA8, 0xFD, 0x24, 0xCF, 0x5F, - 0x83, 0x65, 0x5D, 0x23, 0xDC, 0xA3, 0xAD, 0x96, - 0x1C, 0x62, 0xF3, 0x56, 0x20, 0x85, 0x52, 0xBB, - 0x9E, 0xD5, 0x29, 0x07, 0x70, 0x96, 0x96, 0x6D, - 0x67, 0x0C, 0x35, 0x4E, 0x4A, 0xBC, 0x98, 0x04, - 0xF1, 0x74, 0x6C, 0x08, 0xCA, 0x23, 0x73, 0x27, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF -}; - -#ifdef ALL_DH_GROUPS - -/* RFC 3526, 3. Group 14 - 2048 Bit MODP - * Generator: 2 - * Prime: 2^2048 - 2^1984 - 1 + 2^64 * { [2^1918 pi] + 124476 } - */ -static const u8 dh_group14_generator[1] = { 0x02 }; -static const u8 dh_group14_prime[256] = { - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xC9, 0x0F, 0xDA, 0xA2, 0x21, 0x68, 0xC2, 0x34, - 0xC4, 0xC6, 0x62, 0x8B, 0x80, 0xDC, 0x1C, 0xD1, - 0x29, 0x02, 0x4E, 0x08, 0x8A, 0x67, 0xCC, 0x74, - 0x02, 0x0B, 0xBE, 0xA6, 0x3B, 0x13, 0x9B, 0x22, - 0x51, 0x4A, 0x08, 0x79, 0x8E, 0x34, 0x04, 0xDD, - 0xEF, 0x95, 0x19, 0xB3, 0xCD, 0x3A, 0x43, 0x1B, - 0x30, 0x2B, 0x0A, 0x6D, 0xF2, 0x5F, 0x14, 0x37, - 0x4F, 0xE1, 0x35, 0x6D, 0x6D, 0x51, 0xC2, 0x45, - 0xE4, 0x85, 0xB5, 0x76, 0x62, 0x5E, 0x7E, 0xC6, - 0xF4, 0x4C, 0x42, 0xE9, 0xA6, 0x37, 0xED, 0x6B, - 0x0B, 0xFF, 0x5C, 0xB6, 0xF4, 0x06, 0xB7, 0xED, - 0xEE, 0x38, 0x6B, 0xFB, 0x5A, 0x89, 0x9F, 0xA5, - 0xAE, 0x9F, 0x24, 0x11, 0x7C, 0x4B, 0x1F, 0xE6, - 0x49, 0x28, 0x66, 0x51, 0xEC, 0xE4, 0x5B, 0x3D, - 0xC2, 0x00, 0x7C, 0xB8, 0xA1, 0x63, 0xBF, 0x05, - 0x98, 0xDA, 0x48, 0x36, 0x1C, 0x55, 0xD3, 0x9A, - 0x69, 0x16, 0x3F, 0xA8, 0xFD, 0x24, 0xCF, 0x5F, - 0x83, 0x65, 0x5D, 0x23, 0xDC, 0xA3, 0xAD, 0x96, - 0x1C, 0x62, 0xF3, 0x56, 0x20, 0x85, 0x52, 0xBB, - 0x9E, 0xD5, 0x29, 0x07, 0x70, 0x96, 0x96, 0x6D, - 0x67, 0x0C, 0x35, 0x4E, 0x4A, 0xBC, 0x98, 0x04, - 0xF1, 0x74, 0x6C, 0x08, 0xCA, 0x18, 0x21, 0x7C, - 0x32, 0x90, 0x5E, 0x46, 0x2E, 0x36, 0xCE, 0x3B, - 0xE3, 0x9E, 0x77, 0x2C, 0x18, 0x0E, 0x86, 0x03, - 0x9B, 0x27, 0x83, 0xA2, 0xEC, 0x07, 0xA2, 0x8F, - 0xB5, 0xC5, 0x5D, 0xF0, 0x6F, 0x4C, 0x52, 0xC9, - 0xDE, 0x2B, 0xCB, 0xF6, 0x95, 0x58, 0x17, 0x18, - 0x39, 0x95, 0x49, 0x7C, 0xEA, 0x95, 0x6A, 0xE5, - 0x15, 0xD2, 0x26, 0x18, 0x98, 0xFA, 0x05, 0x10, - 0x15, 0x72, 0x8E, 0x5A, 0x8A, 0xAC, 0xAA, 0x68, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF -}; - -/* RFC 3526, 4. Group 15 - 3072 Bit MODP - * Generator: 2 - * Prime: 2^3072 - 2^3008 - 1 + 2^64 * { [2^2942 pi] + 1690314 } - */ -static const u8 dh_group15_generator[1] = { 0x02 }; -static const u8 dh_group15_prime[384] = { - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xC9, 0x0F, 0xDA, 0xA2, 0x21, 0x68, 0xC2, 0x34, - 0xC4, 0xC6, 0x62, 0x8B, 0x80, 0xDC, 0x1C, 0xD1, - 0x29, 0x02, 0x4E, 0x08, 0x8A, 0x67, 0xCC, 0x74, - 0x02, 0x0B, 0xBE, 0xA6, 0x3B, 0x13, 0x9B, 0x22, - 0x51, 0x4A, 0x08, 0x79, 0x8E, 0x34, 0x04, 0xDD, - 0xEF, 0x95, 0x19, 0xB3, 0xCD, 0x3A, 0x43, 0x1B, - 0x30, 0x2B, 0x0A, 0x6D, 0xF2, 0x5F, 0x14, 0x37, - 0x4F, 0xE1, 0x35, 0x6D, 0x6D, 0x51, 0xC2, 0x45, - 0xE4, 0x85, 0xB5, 0x76, 0x62, 0x5E, 0x7E, 0xC6, - 0xF4, 0x4C, 0x42, 0xE9, 0xA6, 0x37, 0xED, 0x6B, - 0x0B, 0xFF, 0x5C, 0xB6, 0xF4, 0x06, 0xB7, 0xED, - 0xEE, 0x38, 0x6B, 0xFB, 0x5A, 0x89, 0x9F, 0xA5, - 0xAE, 0x9F, 0x24, 0x11, 0x7C, 0x4B, 0x1F, 0xE6, - 0x49, 0x28, 0x66, 0x51, 0xEC, 0xE4, 0x5B, 0x3D, - 0xC2, 0x00, 0x7C, 0xB8, 0xA1, 0x63, 0xBF, 0x05, - 0x98, 0xDA, 0x48, 0x36, 0x1C, 0x55, 0xD3, 0x9A, - 0x69, 0x16, 0x3F, 0xA8, 0xFD, 0x24, 0xCF, 0x5F, - 0x83, 0x65, 0x5D, 0x23, 0xDC, 0xA3, 0xAD, 0x96, - 0x1C, 0x62, 0xF3, 0x56, 0x20, 0x85, 0x52, 0xBB, - 0x9E, 0xD5, 0x29, 0x07, 0x70, 0x96, 0x96, 0x6D, - 0x67, 0x0C, 0x35, 0x4E, 0x4A, 0xBC, 0x98, 0x04, - 0xF1, 0x74, 0x6C, 0x08, 0xCA, 0x18, 0x21, 0x7C, - 0x32, 0x90, 0x5E, 0x46, 0x2E, 0x36, 0xCE, 0x3B, - 0xE3, 0x9E, 0x77, 0x2C, 0x18, 0x0E, 0x86, 0x03, - 0x9B, 0x27, 0x83, 0xA2, 0xEC, 0x07, 0xA2, 0x8F, - 0xB5, 0xC5, 0x5D, 0xF0, 0x6F, 0x4C, 0x52, 0xC9, - 0xDE, 0x2B, 0xCB, 0xF6, 0x95, 0x58, 0x17, 0x18, - 0x39, 0x95, 0x49, 0x7C, 0xEA, 0x95, 0x6A, 0xE5, - 0x15, 0xD2, 0x26, 0x18, 0x98, 0xFA, 0x05, 0x10, - 0x15, 0x72, 0x8E, 0x5A, 0x8A, 0xAA, 0xC4, 0x2D, - 0xAD, 0x33, 0x17, 0x0D, 0x04, 0x50, 0x7A, 0x33, - 0xA8, 0x55, 0x21, 0xAB, 0xDF, 0x1C, 0xBA, 0x64, - 0xEC, 0xFB, 0x85, 0x04, 0x58, 0xDB, 0xEF, 0x0A, - 0x8A, 0xEA, 0x71, 0x57, 0x5D, 0x06, 0x0C, 0x7D, - 0xB3, 0x97, 0x0F, 0x85, 0xA6, 0xE1, 0xE4, 0xC7, - 0xAB, 0xF5, 0xAE, 0x8C, 0xDB, 0x09, 0x33, 0xD7, - 0x1E, 0x8C, 0x94, 0xE0, 0x4A, 0x25, 0x61, 0x9D, - 0xCE, 0xE3, 0xD2, 0x26, 0x1A, 0xD2, 0xEE, 0x6B, - 0xF1, 0x2F, 0xFA, 0x06, 0xD9, 0x8A, 0x08, 0x64, - 0xD8, 0x76, 0x02, 0x73, 0x3E, 0xC8, 0x6A, 0x64, - 0x52, 0x1F, 0x2B, 0x18, 0x17, 0x7B, 0x20, 0x0C, - 0xBB, 0xE1, 0x17, 0x57, 0x7A, 0x61, 0x5D, 0x6C, - 0x77, 0x09, 0x88, 0xC0, 0xBA, 0xD9, 0x46, 0xE2, - 0x08, 0xE2, 0x4F, 0xA0, 0x74, 0xE5, 0xAB, 0x31, - 0x43, 0xDB, 0x5B, 0xFC, 0xE0, 0xFD, 0x10, 0x8E, - 0x4B, 0x82, 0xD1, 0x20, 0xA9, 0x3A, 0xD2, 0xCA, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF -}; - -/* RFC 3526, 5. Group 16 - 4096 Bit MODP - * Generator: 2 - * Prime: 2^4096 - 2^4032 - 1 + 2^64 * { [2^3966 pi] + 240904 } - */ -static const u8 dh_group16_generator[1] = { 0x02 }; -static const u8 dh_group16_prime[512] = { - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xC9, 0x0F, 0xDA, 0xA2, 0x21, 0x68, 0xC2, 0x34, - 0xC4, 0xC6, 0x62, 0x8B, 0x80, 0xDC, 0x1C, 0xD1, - 0x29, 0x02, 0x4E, 0x08, 0x8A, 0x67, 0xCC, 0x74, - 0x02, 0x0B, 0xBE, 0xA6, 0x3B, 0x13, 0x9B, 0x22, - 0x51, 0x4A, 0x08, 0x79, 0x8E, 0x34, 0x04, 0xDD, - 0xEF, 0x95, 0x19, 0xB3, 0xCD, 0x3A, 0x43, 0x1B, - 0x30, 0x2B, 0x0A, 0x6D, 0xF2, 0x5F, 0x14, 0x37, - 0x4F, 0xE1, 0x35, 0x6D, 0x6D, 0x51, 0xC2, 0x45, - 0xE4, 0x85, 0xB5, 0x76, 0x62, 0x5E, 0x7E, 0xC6, - 0xF4, 0x4C, 0x42, 0xE9, 0xA6, 0x37, 0xED, 0x6B, - 0x0B, 0xFF, 0x5C, 0xB6, 0xF4, 0x06, 0xB7, 0xED, - 0xEE, 0x38, 0x6B, 0xFB, 0x5A, 0x89, 0x9F, 0xA5, - 0xAE, 0x9F, 0x24, 0x11, 0x7C, 0x4B, 0x1F, 0xE6, - 0x49, 0x28, 0x66, 0x51, 0xEC, 0xE4, 0x5B, 0x3D, - 0xC2, 0x00, 0x7C, 0xB8, 0xA1, 0x63, 0xBF, 0x05, - 0x98, 0xDA, 0x48, 0x36, 0x1C, 0x55, 0xD3, 0x9A, - 0x69, 0x16, 0x3F, 0xA8, 0xFD, 0x24, 0xCF, 0x5F, - 0x83, 0x65, 0x5D, 0x23, 0xDC, 0xA3, 0xAD, 0x96, - 0x1C, 0x62, 0xF3, 0x56, 0x20, 0x85, 0x52, 0xBB, - 0x9E, 0xD5, 0x29, 0x07, 0x70, 0x96, 0x96, 0x6D, - 0x67, 0x0C, 0x35, 0x4E, 0x4A, 0xBC, 0x98, 0x04, - 0xF1, 0x74, 0x6C, 0x08, 0xCA, 0x18, 0x21, 0x7C, - 0x32, 0x90, 0x5E, 0x46, 0x2E, 0x36, 0xCE, 0x3B, - 0xE3, 0x9E, 0x77, 0x2C, 0x18, 0x0E, 0x86, 0x03, - 0x9B, 0x27, 0x83, 0xA2, 0xEC, 0x07, 0xA2, 0x8F, - 0xB5, 0xC5, 0x5D, 0xF0, 0x6F, 0x4C, 0x52, 0xC9, - 0xDE, 0x2B, 0xCB, 0xF6, 0x95, 0x58, 0x17, 0x18, - 0x39, 0x95, 0x49, 0x7C, 0xEA, 0x95, 0x6A, 0xE5, - 0x15, 0xD2, 0x26, 0x18, 0x98, 0xFA, 0x05, 0x10, - 0x15, 0x72, 0x8E, 0x5A, 0x8A, 0xAA, 0xC4, 0x2D, - 0xAD, 0x33, 0x17, 0x0D, 0x04, 0x50, 0x7A, 0x33, - 0xA8, 0x55, 0x21, 0xAB, 0xDF, 0x1C, 0xBA, 0x64, - 0xEC, 0xFB, 0x85, 0x04, 0x58, 0xDB, 0xEF, 0x0A, - 0x8A, 0xEA, 0x71, 0x57, 0x5D, 0x06, 0x0C, 0x7D, - 0xB3, 0x97, 0x0F, 0x85, 0xA6, 0xE1, 0xE4, 0xC7, - 0xAB, 0xF5, 0xAE, 0x8C, 0xDB, 0x09, 0x33, 0xD7, - 0x1E, 0x8C, 0x94, 0xE0, 0x4A, 0x25, 0x61, 0x9D, - 0xCE, 0xE3, 0xD2, 0x26, 0x1A, 0xD2, 0xEE, 0x6B, - 0xF1, 0x2F, 0xFA, 0x06, 0xD9, 0x8A, 0x08, 0x64, - 0xD8, 0x76, 0x02, 0x73, 0x3E, 0xC8, 0x6A, 0x64, - 0x52, 0x1F, 0x2B, 0x18, 0x17, 0x7B, 0x20, 0x0C, - 0xBB, 0xE1, 0x17, 0x57, 0x7A, 0x61, 0x5D, 0x6C, - 0x77, 0x09, 0x88, 0xC0, 0xBA, 0xD9, 0x46, 0xE2, - 0x08, 0xE2, 0x4F, 0xA0, 0x74, 0xE5, 0xAB, 0x31, - 0x43, 0xDB, 0x5B, 0xFC, 0xE0, 0xFD, 0x10, 0x8E, - 0x4B, 0x82, 0xD1, 0x20, 0xA9, 0x21, 0x08, 0x01, - 0x1A, 0x72, 0x3C, 0x12, 0xA7, 0x87, 0xE6, 0xD7, - 0x88, 0x71, 0x9A, 0x10, 0xBD, 0xBA, 0x5B, 0x26, - 0x99, 0xC3, 0x27, 0x18, 0x6A, 0xF4, 0xE2, 0x3C, - 0x1A, 0x94, 0x68, 0x34, 0xB6, 0x15, 0x0B, 0xDA, - 0x25, 0x83, 0xE9, 0xCA, 0x2A, 0xD4, 0x4C, 0xE8, - 0xDB, 0xBB, 0xC2, 0xDB, 0x04, 0xDE, 0x8E, 0xF9, - 0x2E, 0x8E, 0xFC, 0x14, 0x1F, 0xBE, 0xCA, 0xA6, - 0x28, 0x7C, 0x59, 0x47, 0x4E, 0x6B, 0xC0, 0x5D, - 0x99, 0xB2, 0x96, 0x4F, 0xA0, 0x90, 0xC3, 0xA2, - 0x23, 0x3B, 0xA1, 0x86, 0x51, 0x5B, 0xE7, 0xED, - 0x1F, 0x61, 0x29, 0x70, 0xCE, 0xE2, 0xD7, 0xAF, - 0xB8, 0x1B, 0xDD, 0x76, 0x21, 0x70, 0x48, 0x1C, - 0xD0, 0x06, 0x91, 0x27, 0xD5, 0xB0, 0x5A, 0xA9, - 0x93, 0xB4, 0xEA, 0x98, 0x8D, 0x8F, 0xDD, 0xC1, - 0x86, 0xFF, 0xB7, 0xDC, 0x90, 0xA6, 0xC0, 0x8F, - 0x4D, 0xF4, 0x35, 0xC9, 0x34, 0x06, 0x31, 0x99, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF -}; - -/* RFC 3526, 6. Group 17 - 6144 Bit MODP - * Generator: 2 - * Prime: 2^6144 - 2^6080 - 1 + 2^64 * { [2^6014 pi] + 929484 } - */ -static const u8 dh_group17_generator[1] = { 0x02 }; -static const u8 dh_group17_prime[768] = { - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xC9, 0x0F, 0xDA, 0xA2, 0x21, 0x68, 0xC2, 0x34, - 0xC4, 0xC6, 0x62, 0x8B, 0x80, 0xDC, 0x1C, 0xD1, - 0x29, 0x02, 0x4E, 0x08, 0x8A, 0x67, 0xCC, 0x74, - 0x02, 0x0B, 0xBE, 0xA6, 0x3B, 0x13, 0x9B, 0x22, - 0x51, 0x4A, 0x08, 0x79, 0x8E, 0x34, 0x04, 0xDD, - 0xEF, 0x95, 0x19, 0xB3, 0xCD, 0x3A, 0x43, 0x1B, - 0x30, 0x2B, 0x0A, 0x6D, 0xF2, 0x5F, 0x14, 0x37, - 0x4F, 0xE1, 0x35, 0x6D, 0x6D, 0x51, 0xC2, 0x45, - 0xE4, 0x85, 0xB5, 0x76, 0x62, 0x5E, 0x7E, 0xC6, - 0xF4, 0x4C, 0x42, 0xE9, 0xA6, 0x37, 0xED, 0x6B, - 0x0B, 0xFF, 0x5C, 0xB6, 0xF4, 0x06, 0xB7, 0xED, - 0xEE, 0x38, 0x6B, 0xFB, 0x5A, 0x89, 0x9F, 0xA5, - 0xAE, 0x9F, 0x24, 0x11, 0x7C, 0x4B, 0x1F, 0xE6, - 0x49, 0x28, 0x66, 0x51, 0xEC, 0xE4, 0x5B, 0x3D, - 0xC2, 0x00, 0x7C, 0xB8, 0xA1, 0x63, 0xBF, 0x05, - 0x98, 0xDA, 0x48, 0x36, 0x1C, 0x55, 0xD3, 0x9A, - 0x69, 0x16, 0x3F, 0xA8, 0xFD, 0x24, 0xCF, 0x5F, - 0x83, 0x65, 0x5D, 0x23, 0xDC, 0xA3, 0xAD, 0x96, - 0x1C, 0x62, 0xF3, 0x56, 0x20, 0x85, 0x52, 0xBB, - 0x9E, 0xD5, 0x29, 0x07, 0x70, 0x96, 0x96, 0x6D, - 0x67, 0x0C, 0x35, 0x4E, 0x4A, 0xBC, 0x98, 0x04, - 0xF1, 0x74, 0x6C, 0x08, 0xCA, 0x18, 0x21, 0x7C, - 0x32, 0x90, 0x5E, 0x46, 0x2E, 0x36, 0xCE, 0x3B, - 0xE3, 0x9E, 0x77, 0x2C, 0x18, 0x0E, 0x86, 0x03, - 0x9B, 0x27, 0x83, 0xA2, 0xEC, 0x07, 0xA2, 0x8F, - 0xB5, 0xC5, 0x5D, 0xF0, 0x6F, 0x4C, 0x52, 0xC9, - 0xDE, 0x2B, 0xCB, 0xF6, 0x95, 0x58, 0x17, 0x18, - 0x39, 0x95, 0x49, 0x7C, 0xEA, 0x95, 0x6A, 0xE5, - 0x15, 0xD2, 0x26, 0x18, 0x98, 0xFA, 0x05, 0x10, - 0x15, 0x72, 0x8E, 0x5A, 0x8A, 0xAA, 0xC4, 0x2D, - 0xAD, 0x33, 0x17, 0x0D, 0x04, 0x50, 0x7A, 0x33, - 0xA8, 0x55, 0x21, 0xAB, 0xDF, 0x1C, 0xBA, 0x64, - 0xEC, 0xFB, 0x85, 0x04, 0x58, 0xDB, 0xEF, 0x0A, - 0x8A, 0xEA, 0x71, 0x57, 0x5D, 0x06, 0x0C, 0x7D, - 0xB3, 0x97, 0x0F, 0x85, 0xA6, 0xE1, 0xE4, 0xC7, - 0xAB, 0xF5, 0xAE, 0x8C, 0xDB, 0x09, 0x33, 0xD7, - 0x1E, 0x8C, 0x94, 0xE0, 0x4A, 0x25, 0x61, 0x9D, - 0xCE, 0xE3, 0xD2, 0x26, 0x1A, 0xD2, 0xEE, 0x6B, - 0xF1, 0x2F, 0xFA, 0x06, 0xD9, 0x8A, 0x08, 0x64, - 0xD8, 0x76, 0x02, 0x73, 0x3E, 0xC8, 0x6A, 0x64, - 0x52, 0x1F, 0x2B, 0x18, 0x17, 0x7B, 0x20, 0x0C, - 0xBB, 0xE1, 0x17, 0x57, 0x7A, 0x61, 0x5D, 0x6C, - 0x77, 0x09, 0x88, 0xC0, 0xBA, 0xD9, 0x46, 0xE2, - 0x08, 0xE2, 0x4F, 0xA0, 0x74, 0xE5, 0xAB, 0x31, - 0x43, 0xDB, 0x5B, 0xFC, 0xE0, 0xFD, 0x10, 0x8E, - 0x4B, 0x82, 0xD1, 0x20, 0xA9, 0x21, 0x08, 0x01, - 0x1A, 0x72, 0x3C, 0x12, 0xA7, 0x87, 0xE6, 0xD7, - 0x88, 0x71, 0x9A, 0x10, 0xBD, 0xBA, 0x5B, 0x26, - 0x99, 0xC3, 0x27, 0x18, 0x6A, 0xF4, 0xE2, 0x3C, - 0x1A, 0x94, 0x68, 0x34, 0xB6, 0x15, 0x0B, 0xDA, - 0x25, 0x83, 0xE9, 0xCA, 0x2A, 0xD4, 0x4C, 0xE8, - 0xDB, 0xBB, 0xC2, 0xDB, 0x04, 0xDE, 0x8E, 0xF9, - 0x2E, 0x8E, 0xFC, 0x14, 0x1F, 0xBE, 0xCA, 0xA6, - 0x28, 0x7C, 0x59, 0x47, 0x4E, 0x6B, 0xC0, 0x5D, - 0x99, 0xB2, 0x96, 0x4F, 0xA0, 0x90, 0xC3, 0xA2, - 0x23, 0x3B, 0xA1, 0x86, 0x51, 0x5B, 0xE7, 0xED, - 0x1F, 0x61, 0x29, 0x70, 0xCE, 0xE2, 0xD7, 0xAF, - 0xB8, 0x1B, 0xDD, 0x76, 0x21, 0x70, 0x48, 0x1C, - 0xD0, 0x06, 0x91, 0x27, 0xD5, 0xB0, 0x5A, 0xA9, - 0x93, 0xB4, 0xEA, 0x98, 0x8D, 0x8F, 0xDD, 0xC1, - 0x86, 0xFF, 0xB7, 0xDC, 0x90, 0xA6, 0xC0, 0x8F, - 0x4D, 0xF4, 0x35, 0xC9, 0x34, 0x02, 0x84, 0x92, - 0x36, 0xC3, 0xFA, 0xB4, 0xD2, 0x7C, 0x70, 0x26, - 0xC1, 0xD4, 0xDC, 0xB2, 0x60, 0x26, 0x46, 0xDE, - 0xC9, 0x75, 0x1E, 0x76, 0x3D, 0xBA, 0x37, 0xBD, - 0xF8, 0xFF, 0x94, 0x06, 0xAD, 0x9E, 0x53, 0x0E, - 0xE5, 0xDB, 0x38, 0x2F, 0x41, 0x30, 0x01, 0xAE, - 0xB0, 0x6A, 0x53, 0xED, 0x90, 0x27, 0xD8, 0x31, - 0x17, 0x97, 0x27, 0xB0, 0x86, 0x5A, 0x89, 0x18, - 0xDA, 0x3E, 0xDB, 0xEB, 0xCF, 0x9B, 0x14, 0xED, - 0x44, 0xCE, 0x6C, 0xBA, 0xCE, 0xD4, 0xBB, 0x1B, - 0xDB, 0x7F, 0x14, 0x47, 0xE6, 0xCC, 0x25, 0x4B, - 0x33, 0x20, 0x51, 0x51, 0x2B, 0xD7, 0xAF, 0x42, - 0x6F, 0xB8, 0xF4, 0x01, 0x37, 0x8C, 0xD2, 0xBF, - 0x59, 0x83, 0xCA, 0x01, 0xC6, 0x4B, 0x92, 0xEC, - 0xF0, 0x32, 0xEA, 0x15, 0xD1, 0x72, 0x1D, 0x03, - 0xF4, 0x82, 0xD7, 0xCE, 0x6E, 0x74, 0xFE, 0xF6, - 0xD5, 0x5E, 0x70, 0x2F, 0x46, 0x98, 0x0C, 0x82, - 0xB5, 0xA8, 0x40, 0x31, 0x90, 0x0B, 0x1C, 0x9E, - 0x59, 0xE7, 0xC9, 0x7F, 0xBE, 0xC7, 0xE8, 0xF3, - 0x23, 0xA9, 0x7A, 0x7E, 0x36, 0xCC, 0x88, 0xBE, - 0x0F, 0x1D, 0x45, 0xB7, 0xFF, 0x58, 0x5A, 0xC5, - 0x4B, 0xD4, 0x07, 0xB2, 0x2B, 0x41, 0x54, 0xAA, - 0xCC, 0x8F, 0x6D, 0x7E, 0xBF, 0x48, 0xE1, 0xD8, - 0x14, 0xCC, 0x5E, 0xD2, 0x0F, 0x80, 0x37, 0xE0, - 0xA7, 0x97, 0x15, 0xEE, 0xF2, 0x9B, 0xE3, 0x28, - 0x06, 0xA1, 0xD5, 0x8B, 0xB7, 0xC5, 0xDA, 0x76, - 0xF5, 0x50, 0xAA, 0x3D, 0x8A, 0x1F, 0xBF, 0xF0, - 0xEB, 0x19, 0xCC, 0xB1, 0xA3, 0x13, 0xD5, 0x5C, - 0xDA, 0x56, 0xC9, 0xEC, 0x2E, 0xF2, 0x96, 0x32, - 0x38, 0x7F, 0xE8, 0xD7, 0x6E, 0x3C, 0x04, 0x68, - 0x04, 0x3E, 0x8F, 0x66, 0x3F, 0x48, 0x60, 0xEE, - 0x12, 0xBF, 0x2D, 0x5B, 0x0B, 0x74, 0x74, 0xD6, - 0xE6, 0x94, 0xF9, 0x1E, 0x6D, 0xCC, 0x40, 0x24, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF -}; - -/* RFC 3526, 7. Group 18 - 8192 Bit MODP - * Generator: 2 - * Prime: 2^8192 - 2^8128 - 1 + 2^64 * { [2^8062 pi] + 4743158 } - */ -static const u8 dh_group18_generator[1] = { 0x02 }; -static const u8 dh_group18_prime[1024] = { - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xC9, 0x0F, 0xDA, 0xA2, 0x21, 0x68, 0xC2, 0x34, - 0xC4, 0xC6, 0x62, 0x8B, 0x80, 0xDC, 0x1C, 0xD1, - 0x29, 0x02, 0x4E, 0x08, 0x8A, 0x67, 0xCC, 0x74, - 0x02, 0x0B, 0xBE, 0xA6, 0x3B, 0x13, 0x9B, 0x22, - 0x51, 0x4A, 0x08, 0x79, 0x8E, 0x34, 0x04, 0xDD, - 0xEF, 0x95, 0x19, 0xB3, 0xCD, 0x3A, 0x43, 0x1B, - 0x30, 0x2B, 0x0A, 0x6D, 0xF2, 0x5F, 0x14, 0x37, - 0x4F, 0xE1, 0x35, 0x6D, 0x6D, 0x51, 0xC2, 0x45, - 0xE4, 0x85, 0xB5, 0x76, 0x62, 0x5E, 0x7E, 0xC6, - 0xF4, 0x4C, 0x42, 0xE9, 0xA6, 0x37, 0xED, 0x6B, - 0x0B, 0xFF, 0x5C, 0xB6, 0xF4, 0x06, 0xB7, 0xED, - 0xEE, 0x38, 0x6B, 0xFB, 0x5A, 0x89, 0x9F, 0xA5, - 0xAE, 0x9F, 0x24, 0x11, 0x7C, 0x4B, 0x1F, 0xE6, - 0x49, 0x28, 0x66, 0x51, 0xEC, 0xE4, 0x5B, 0x3D, - 0xC2, 0x00, 0x7C, 0xB8, 0xA1, 0x63, 0xBF, 0x05, - 0x98, 0xDA, 0x48, 0x36, 0x1C, 0x55, 0xD3, 0x9A, - 0x69, 0x16, 0x3F, 0xA8, 0xFD, 0x24, 0xCF, 0x5F, - 0x83, 0x65, 0x5D, 0x23, 0xDC, 0xA3, 0xAD, 0x96, - 0x1C, 0x62, 0xF3, 0x56, 0x20, 0x85, 0x52, 0xBB, - 0x9E, 0xD5, 0x29, 0x07, 0x70, 0x96, 0x96, 0x6D, - 0x67, 0x0C, 0x35, 0x4E, 0x4A, 0xBC, 0x98, 0x04, - 0xF1, 0x74, 0x6C, 0x08, 0xCA, 0x18, 0x21, 0x7C, - 0x32, 0x90, 0x5E, 0x46, 0x2E, 0x36, 0xCE, 0x3B, - 0xE3, 0x9E, 0x77, 0x2C, 0x18, 0x0E, 0x86, 0x03, - 0x9B, 0x27, 0x83, 0xA2, 0xEC, 0x07, 0xA2, 0x8F, - 0xB5, 0xC5, 0x5D, 0xF0, 0x6F, 0x4C, 0x52, 0xC9, - 0xDE, 0x2B, 0xCB, 0xF6, 0x95, 0x58, 0x17, 0x18, - 0x39, 0x95, 0x49, 0x7C, 0xEA, 0x95, 0x6A, 0xE5, - 0x15, 0xD2, 0x26, 0x18, 0x98, 0xFA, 0x05, 0x10, - 0x15, 0x72, 0x8E, 0x5A, 0x8A, 0xAA, 0xC4, 0x2D, - 0xAD, 0x33, 0x17, 0x0D, 0x04, 0x50, 0x7A, 0x33, - 0xA8, 0x55, 0x21, 0xAB, 0xDF, 0x1C, 0xBA, 0x64, - 0xEC, 0xFB, 0x85, 0x04, 0x58, 0xDB, 0xEF, 0x0A, - 0x8A, 0xEA, 0x71, 0x57, 0x5D, 0x06, 0x0C, 0x7D, - 0xB3, 0x97, 0x0F, 0x85, 0xA6, 0xE1, 0xE4, 0xC7, - 0xAB, 0xF5, 0xAE, 0x8C, 0xDB, 0x09, 0x33, 0xD7, - 0x1E, 0x8C, 0x94, 0xE0, 0x4A, 0x25, 0x61, 0x9D, - 0xCE, 0xE3, 0xD2, 0x26, 0x1A, 0xD2, 0xEE, 0x6B, - 0xF1, 0x2F, 0xFA, 0x06, 0xD9, 0x8A, 0x08, 0x64, - 0xD8, 0x76, 0x02, 0x73, 0x3E, 0xC8, 0x6A, 0x64, - 0x52, 0x1F, 0x2B, 0x18, 0x17, 0x7B, 0x20, 0x0C, - 0xBB, 0xE1, 0x17, 0x57, 0x7A, 0x61, 0x5D, 0x6C, - 0x77, 0x09, 0x88, 0xC0, 0xBA, 0xD9, 0x46, 0xE2, - 0x08, 0xE2, 0x4F, 0xA0, 0x74, 0xE5, 0xAB, 0x31, - 0x43, 0xDB, 0x5B, 0xFC, 0xE0, 0xFD, 0x10, 0x8E, - 0x4B, 0x82, 0xD1, 0x20, 0xA9, 0x21, 0x08, 0x01, - 0x1A, 0x72, 0x3C, 0x12, 0xA7, 0x87, 0xE6, 0xD7, - 0x88, 0x71, 0x9A, 0x10, 0xBD, 0xBA, 0x5B, 0x26, - 0x99, 0xC3, 0x27, 0x18, 0x6A, 0xF4, 0xE2, 0x3C, - 0x1A, 0x94, 0x68, 0x34, 0xB6, 0x15, 0x0B, 0xDA, - 0x25, 0x83, 0xE9, 0xCA, 0x2A, 0xD4, 0x4C, 0xE8, - 0xDB, 0xBB, 0xC2, 0xDB, 0x04, 0xDE, 0x8E, 0xF9, - 0x2E, 0x8E, 0xFC, 0x14, 0x1F, 0xBE, 0xCA, 0xA6, - 0x28, 0x7C, 0x59, 0x47, 0x4E, 0x6B, 0xC0, 0x5D, - 0x99, 0xB2, 0x96, 0x4F, 0xA0, 0x90, 0xC3, 0xA2, - 0x23, 0x3B, 0xA1, 0x86, 0x51, 0x5B, 0xE7, 0xED, - 0x1F, 0x61, 0x29, 0x70, 0xCE, 0xE2, 0xD7, 0xAF, - 0xB8, 0x1B, 0xDD, 0x76, 0x21, 0x70, 0x48, 0x1C, - 0xD0, 0x06, 0x91, 0x27, 0xD5, 0xB0, 0x5A, 0xA9, - 0x93, 0xB4, 0xEA, 0x98, 0x8D, 0x8F, 0xDD, 0xC1, - 0x86, 0xFF, 0xB7, 0xDC, 0x90, 0xA6, 0xC0, 0x8F, - 0x4D, 0xF4, 0x35, 0xC9, 0x34, 0x02, 0x84, 0x92, - 0x36, 0xC3, 0xFA, 0xB4, 0xD2, 0x7C, 0x70, 0x26, - 0xC1, 0xD4, 0xDC, 0xB2, 0x60, 0x26, 0x46, 0xDE, - 0xC9, 0x75, 0x1E, 0x76, 0x3D, 0xBA, 0x37, 0xBD, - 0xF8, 0xFF, 0x94, 0x06, 0xAD, 0x9E, 0x53, 0x0E, - 0xE5, 0xDB, 0x38, 0x2F, 0x41, 0x30, 0x01, 0xAE, - 0xB0, 0x6A, 0x53, 0xED, 0x90, 0x27, 0xD8, 0x31, - 0x17, 0x97, 0x27, 0xB0, 0x86, 0x5A, 0x89, 0x18, - 0xDA, 0x3E, 0xDB, 0xEB, 0xCF, 0x9B, 0x14, 0xED, - 0x44, 0xCE, 0x6C, 0xBA, 0xCE, 0xD4, 0xBB, 0x1B, - 0xDB, 0x7F, 0x14, 0x47, 0xE6, 0xCC, 0x25, 0x4B, - 0x33, 0x20, 0x51, 0x51, 0x2B, 0xD7, 0xAF, 0x42, - 0x6F, 0xB8, 0xF4, 0x01, 0x37, 0x8C, 0xD2, 0xBF, - 0x59, 0x83, 0xCA, 0x01, 0xC6, 0x4B, 0x92, 0xEC, - 0xF0, 0x32, 0xEA, 0x15, 0xD1, 0x72, 0x1D, 0x03, - 0xF4, 0x82, 0xD7, 0xCE, 0x6E, 0x74, 0xFE, 0xF6, - 0xD5, 0x5E, 0x70, 0x2F, 0x46, 0x98, 0x0C, 0x82, - 0xB5, 0xA8, 0x40, 0x31, 0x90, 0x0B, 0x1C, 0x9E, - 0x59, 0xE7, 0xC9, 0x7F, 0xBE, 0xC7, 0xE8, 0xF3, - 0x23, 0xA9, 0x7A, 0x7E, 0x36, 0xCC, 0x88, 0xBE, - 0x0F, 0x1D, 0x45, 0xB7, 0xFF, 0x58, 0x5A, 0xC5, - 0x4B, 0xD4, 0x07, 0xB2, 0x2B, 0x41, 0x54, 0xAA, - 0xCC, 0x8F, 0x6D, 0x7E, 0xBF, 0x48, 0xE1, 0xD8, - 0x14, 0xCC, 0x5E, 0xD2, 0x0F, 0x80, 0x37, 0xE0, - 0xA7, 0x97, 0x15, 0xEE, 0xF2, 0x9B, 0xE3, 0x28, - 0x06, 0xA1, 0xD5, 0x8B, 0xB7, 0xC5, 0xDA, 0x76, - 0xF5, 0x50, 0xAA, 0x3D, 0x8A, 0x1F, 0xBF, 0xF0, - 0xEB, 0x19, 0xCC, 0xB1, 0xA3, 0x13, 0xD5, 0x5C, - 0xDA, 0x56, 0xC9, 0xEC, 0x2E, 0xF2, 0x96, 0x32, - 0x38, 0x7F, 0xE8, 0xD7, 0x6E, 0x3C, 0x04, 0x68, - 0x04, 0x3E, 0x8F, 0x66, 0x3F, 0x48, 0x60, 0xEE, - 0x12, 0xBF, 0x2D, 0x5B, 0x0B, 0x74, 0x74, 0xD6, - 0xE6, 0x94, 0xF9, 0x1E, 0x6D, 0xBE, 0x11, 0x59, - 0x74, 0xA3, 0x92, 0x6F, 0x12, 0xFE, 0xE5, 0xE4, - 0x38, 0x77, 0x7C, 0xB6, 0xA9, 0x32, 0xDF, 0x8C, - 0xD8, 0xBE, 0xC4, 0xD0, 0x73, 0xB9, 0x31, 0xBA, - 0x3B, 0xC8, 0x32, 0xB6, 0x8D, 0x9D, 0xD3, 0x00, - 0x74, 0x1F, 0xA7, 0xBF, 0x8A, 0xFC, 0x47, 0xED, - 0x25, 0x76, 0xF6, 0x93, 0x6B, 0xA4, 0x24, 0x66, - 0x3A, 0xAB, 0x63, 0x9C, 0x5A, 0xE4, 0xF5, 0x68, - 0x34, 0x23, 0xB4, 0x74, 0x2B, 0xF1, 0xC9, 0x78, - 0x23, 0x8F, 0x16, 0xCB, 0xE3, 0x9D, 0x65, 0x2D, - 0xE3, 0xFD, 0xB8, 0xBE, 0xFC, 0x84, 0x8A, 0xD9, - 0x22, 0x22, 0x2E, 0x04, 0xA4, 0x03, 0x7C, 0x07, - 0x13, 0xEB, 0x57, 0xA8, 0x1A, 0x23, 0xF0, 0xC7, - 0x34, 0x73, 0xFC, 0x64, 0x6C, 0xEA, 0x30, 0x6B, - 0x4B, 0xCB, 0xC8, 0x86, 0x2F, 0x83, 0x85, 0xDD, - 0xFA, 0x9D, 0x4B, 0x7F, 0xA2, 0xC0, 0x87, 0xE8, - 0x79, 0x68, 0x33, 0x03, 0xED, 0x5B, 0xDD, 0x3A, - 0x06, 0x2B, 0x3C, 0xF5, 0xB3, 0xA2, 0x78, 0xA6, - 0x6D, 0x2A, 0x13, 0xF8, 0x3F, 0x44, 0xF8, 0x2D, - 0xDF, 0x31, 0x0E, 0xE0, 0x74, 0xAB, 0x6A, 0x36, - 0x45, 0x97, 0xE8, 0x99, 0xA0, 0x25, 0x5D, 0xC1, - 0x64, 0xF3, 0x1C, 0xC5, 0x08, 0x46, 0x85, 0x1D, - 0xF9, 0xAB, 0x48, 0x19, 0x5D, 0xED, 0x7E, 0xA1, - 0xB1, 0xD5, 0x10, 0xBD, 0x7E, 0xE7, 0x4D, 0x73, - 0xFA, 0xF3, 0x6B, 0xC3, 0x1E, 0xCF, 0xA2, 0x68, - 0x35, 0x90, 0x46, 0xF4, 0xEB, 0x87, 0x9F, 0x92, - 0x40, 0x09, 0x43, 0x8B, 0x48, 0x1C, 0x6C, 0xD7, - 0x88, 0x9A, 0x00, 0x2E, 0xD5, 0xEE, 0x38, 0x2B, - 0xC9, 0x19, 0x0D, 0xA6, 0xFC, 0x02, 0x6E, 0x47, - 0x95, 0x58, 0xE4, 0x47, 0x56, 0x77, 0xE9, 0xAA, - 0x9E, 0x30, 0x50, 0xE2, 0x76, 0x56, 0x94, 0xDF, - 0xC8, 0x1F, 0x56, 0xE8, 0x80, 0xB9, 0x6E, 0x71, - 0x60, 0xC9, 0x80, 0xDD, 0x98, 0xED, 0xD3, 0xDF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF -}; - -#endif /* ALL_DH_GROUPS */ - - -#define DH_GROUP(id) \ -{ id, dh_group ## id ## _generator, sizeof(dh_group ## id ## _generator), \ -dh_group ## id ## _prime, sizeof(dh_group ## id ## _prime) } - - -static struct dh_group dh_groups[] = { - DH_GROUP(5), -#ifdef ALL_DH_GROUPS - DH_GROUP(1), - DH_GROUP(2), - DH_GROUP(14), - DH_GROUP(15), - DH_GROUP(16), - DH_GROUP(17), - DH_GROUP(18) -#endif /* ALL_DH_GROUPS */ -}; - -#define NUM_DH_GROUPS (sizeof(dh_groups) / sizeof(dh_groups[0])) - - -const struct dh_group * dh_groups_get(int id) -{ - size_t i; - - for (i = 0; i < NUM_DH_GROUPS; i++) { - if (dh_groups[i].id == id) - return &dh_groups[i]; - } - return NULL; -} - - -/** - * dh_init - Initialize Diffie-Hellman handshake - * @dh: Selected Diffie-Hellman group - * @priv: Pointer for returning Diffie-Hellman private key - * Returns: Diffie-Hellman public value - */ -struct wpabuf * dh_init(const struct dh_group *dh, struct wpabuf **priv) -{ - struct wpabuf *pv; - size_t pv_len; - - if (dh == NULL) - return NULL; - - wpabuf_free(*priv); - *priv = wpabuf_alloc(dh->prime_len); - if (*priv == NULL) - return NULL; - - if (random_get_bytes(wpabuf_put(*priv, dh->prime_len), dh->prime_len)) - { - wpabuf_free(*priv); - *priv = NULL; - return NULL; - } - - if (os_memcmp(wpabuf_head(*priv), dh->prime, dh->prime_len) > 0) { - /* Make sure private value is smaller than prime */ - *(wpabuf_mhead_u8(*priv)) = 0; - } - wpa_hexdump_buf_key(MSG_DEBUG, "DH: private value", *priv); - - pv_len = dh->prime_len; - pv = wpabuf_alloc(pv_len); - if (pv == NULL) - return NULL; - if (crypto_mod_exp(dh->generator, dh->generator_len, - wpabuf_head(*priv), wpabuf_len(*priv), - dh->prime, dh->prime_len, wpabuf_mhead(pv), - &pv_len) < 0) { - wpabuf_free(pv); - wpa_printf(MSG_INFO, "DH: crypto_mod_exp failed"); - return NULL; - } - wpabuf_put(pv, pv_len); - wpa_hexdump_buf(MSG_DEBUG, "DH: public value", pv); - - return pv; -} - - -/** - * dh_derive_shared - Derive shared Diffie-Hellman key - * @peer_public: Diffie-Hellman public value from peer - * @own_private: Diffie-Hellman private key from dh_init() - * @dh: Selected Diffie-Hellman group - * Returns: Diffie-Hellman shared key - */ -struct wpabuf * dh_derive_shared(const struct wpabuf *peer_public, - const struct wpabuf *own_private, - const struct dh_group *dh) -{ - struct wpabuf *shared; - size_t shared_len; - - if (dh == NULL || peer_public == NULL || own_private == NULL) - return NULL; - - shared_len = dh->prime_len; - shared = wpabuf_alloc(shared_len); - if (shared == NULL) - return NULL; - if (crypto_mod_exp(wpabuf_head(peer_public), wpabuf_len(peer_public), - wpabuf_head(own_private), wpabuf_len(own_private), - dh->prime, dh->prime_len, - wpabuf_mhead(shared), &shared_len) < 0) { - wpabuf_free(shared); - wpa_printf(MSG_INFO, "DH: crypto_mod_exp failed"); - return NULL; - } - wpabuf_put(shared, shared_len); - wpa_hexdump_buf_key(MSG_DEBUG, "DH: shared key", shared); - - return shared; -} diff --git a/hostapd-0.8/src/crypto/dh_groups.h b/hostapd-0.8/src/crypto/dh_groups.h deleted file mode 100644 index 5c61539..0000000 --- a/hostapd-0.8/src/crypto/dh_groups.h +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Diffie-Hellman groups - * Copyright (c) 2007, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#ifndef DH_GROUPS_H -#define DH_GROUPS_H - -struct dh_group { - int id; - const u8 *generator; - size_t generator_len; - const u8 *prime; - size_t prime_len; -}; - -const struct dh_group * dh_groups_get(int id); -struct wpabuf * dh_init(const struct dh_group *dh, struct wpabuf **priv); -struct wpabuf * dh_derive_shared(const struct wpabuf *peer_public, - const struct wpabuf *own_private, - const struct dh_group *dh); - -#endif /* DH_GROUPS_H */ diff --git a/hostapd-0.8/src/crypto/fips_prf_cryptoapi.c b/hostapd-0.8/src/crypto/fips_prf_cryptoapi.c deleted file mode 100644 index 17d3116..0000000 --- a/hostapd-0.8/src/crypto/fips_prf_cryptoapi.c +++ /dev/null @@ -1,25 +0,0 @@ -/* - * FIPS 186-2 PRF for Microsoft CryptoAPI - * Copyright (c) 2009, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#include "includes.h" - -#include "common.h" -#include "crypto.h" - - -int fips186_2_prf(const u8 *seed, size_t seed_len, u8 *x, size_t xlen) -{ - /* FIX: how to do this with CryptoAPI? */ - return -1; -} diff --git a/hostapd-0.8/src/crypto/fips_prf_gnutls.c b/hostapd-0.8/src/crypto/fips_prf_gnutls.c deleted file mode 100644 index f742e98..0000000 --- a/hostapd-0.8/src/crypto/fips_prf_gnutls.c +++ /dev/null @@ -1,26 +0,0 @@ -/* - * FIPS 186-2 PRF for libgcrypt - * Copyright (c) 2004-2009, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#include "includes.h" -#include - -#include "common.h" -#include "crypto.h" - - -int fips186_2_prf(const u8 *seed, size_t seed_len, u8 *x, size_t xlen) -{ - /* FIX: how to do this with libgcrypt? */ - return -1; -} diff --git a/hostapd-0.8/src/crypto/fips_prf_internal.c b/hostapd-0.8/src/crypto/fips_prf_internal.c deleted file mode 100644 index a85cb14..0000000 --- a/hostapd-0.8/src/crypto/fips_prf_internal.c +++ /dev/null @@ -1,74 +0,0 @@ -/* - * FIPS 186-2 PRF for internal crypto implementation - * Copyright (c) 2006-2007, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#include "includes.h" - -#include "common.h" -#include "sha1.h" -#include "sha1_i.h" -#include "crypto.h" - - -int fips186_2_prf(const u8 *seed, size_t seed_len, u8 *x, size_t xlen) -{ - u8 xkey[64]; - u32 t[5], _t[5]; - int i, j, m, k; - u8 *xpos = x; - u32 carry; - - if (seed_len > sizeof(xkey)) - seed_len = sizeof(xkey); - - /* FIPS 186-2 + change notice 1 */ - - os_memcpy(xkey, seed, seed_len); - os_memset(xkey + seed_len, 0, 64 - seed_len); - t[0] = 0x67452301; - t[1] = 0xEFCDAB89; - t[2] = 0x98BADCFE; - t[3] = 0x10325476; - t[4] = 0xC3D2E1F0; - - m = xlen / 40; - for (j = 0; j < m; j++) { - /* XSEED_j = 0 */ - for (i = 0; i < 2; i++) { - /* XVAL = (XKEY + XSEED_j) mod 2^b */ - - /* w_i = G(t, XVAL) */ - os_memcpy(_t, t, 20); - SHA1Transform(_t, xkey); - _t[0] = host_to_be32(_t[0]); - _t[1] = host_to_be32(_t[1]); - _t[2] = host_to_be32(_t[2]); - _t[3] = host_to_be32(_t[3]); - _t[4] = host_to_be32(_t[4]); - os_memcpy(xpos, _t, 20); - - /* XKEY = (1 + XKEY + w_i) mod 2^b */ - carry = 1; - for (k = 19; k >= 0; k--) { - carry += xkey[k] + xpos[k]; - xkey[k] = carry & 0xff; - carry >>= 8; - } - - xpos += SHA1_MAC_LEN; - } - /* x_j = w_0|w_1 */ - } - - return 0; -} diff --git a/hostapd-0.8/src/crypto/fips_prf_nss.c b/hostapd-0.8/src/crypto/fips_prf_nss.c deleted file mode 100644 index f941983..0000000 --- a/hostapd-0.8/src/crypto/fips_prf_nss.c +++ /dev/null @@ -1,25 +0,0 @@ -/* - * FIPS 186-2 PRF for NSS - * Copyright (c) 2009, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#include "includes.h" -#include - -#include "common.h" -#include "crypto.h" - - -int fips186_2_prf(const u8 *seed, size_t seed_len, u8 *x, size_t xlen) -{ - return -1; -} diff --git a/hostapd-0.8/src/crypto/fips_prf_openssl.c b/hostapd-0.8/src/crypto/fips_prf_openssl.c deleted file mode 100644 index d0af983..0000000 --- a/hostapd-0.8/src/crypto/fips_prf_openssl.c +++ /dev/null @@ -1,83 +0,0 @@ -/* - * FIPS 186-2 PRF for libcrypto - * Copyright (c) 2004-2005, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#include "includes.h" -#include - -#include "common.h" -#include "crypto.h" - - -static void sha1_transform(u8 *state, const u8 data[64]) -{ - SHA_CTX context; - os_memset(&context, 0, sizeof(context)); - os_memcpy(&context.h0, state, 5 * 4); - SHA1_Transform(&context, data); - os_memcpy(state, &context.h0, 5 * 4); -} - - -int fips186_2_prf(const u8 *seed, size_t seed_len, u8 *x, size_t xlen) -{ - u8 xkey[64]; - u32 t[5], _t[5]; - int i, j, m, k; - u8 *xpos = x; - u32 carry; - - if (seed_len > sizeof(xkey)) - seed_len = sizeof(xkey); - - /* FIPS 186-2 + change notice 1 */ - - os_memcpy(xkey, seed, seed_len); - os_memset(xkey + seed_len, 0, 64 - seed_len); - t[0] = 0x67452301; - t[1] = 0xEFCDAB89; - t[2] = 0x98BADCFE; - t[3] = 0x10325476; - t[4] = 0xC3D2E1F0; - - m = xlen / 40; - for (j = 0; j < m; j++) { - /* XSEED_j = 0 */ - for (i = 0; i < 2; i++) { - /* XVAL = (XKEY + XSEED_j) mod 2^b */ - - /* w_i = G(t, XVAL) */ - os_memcpy(_t, t, 20); - sha1_transform((u8 *) _t, xkey); - _t[0] = host_to_be32(_t[0]); - _t[1] = host_to_be32(_t[1]); - _t[2] = host_to_be32(_t[2]); - _t[3] = host_to_be32(_t[3]); - _t[4] = host_to_be32(_t[4]); - os_memcpy(xpos, _t, 20); - - /* XKEY = (1 + XKEY + w_i) mod 2^b */ - carry = 1; - for (k = 19; k >= 0; k--) { - carry += xkey[k] + xpos[k]; - xkey[k] = carry & 0xff; - carry >>= 8; - } - - xpos += 20; - } - /* x_j = w_0|w_1 */ - } - - return 0; -} diff --git a/hostapd-0.8/src/crypto/md4-internal.c b/hostapd-0.8/src/crypto/md4-internal.c deleted file mode 100644 index d9f499f..0000000 --- a/hostapd-0.8/src/crypto/md4-internal.c +++ /dev/null @@ -1,278 +0,0 @@ -/* - * MD4 hash implementation - * Copyright (c) 2006, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#include "includes.h" - -#include "common.h" -#include "crypto.h" - -#define MD4_BLOCK_LENGTH 64 -#define MD4_DIGEST_LENGTH 16 - -typedef struct MD4Context { - u32 state[4]; /* state */ - u64 count; /* number of bits, mod 2^64 */ - u8 buffer[MD4_BLOCK_LENGTH]; /* input buffer */ -} MD4_CTX; - - -static void MD4Init(MD4_CTX *ctx); -static void MD4Update(MD4_CTX *ctx, const unsigned char *input, size_t len); -static void MD4Final(unsigned char digest[MD4_DIGEST_LENGTH], MD4_CTX *ctx); - - -int md4_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac) -{ - MD4_CTX ctx; - size_t i; - - MD4Init(&ctx); - for (i = 0; i < num_elem; i++) - MD4Update(&ctx, addr[i], len[i]); - MD4Final(mac, &ctx); - return 0; -} - - -/* ===== start - public domain MD4 implementation ===== */ -/* $OpenBSD: md4.c,v 1.7 2005/08/08 08:05:35 espie Exp $ */ - -/* - * This code implements the MD4 message-digest algorithm. - * The algorithm is due to Ron Rivest. This code was - * written by Colin Plumb in 1993, no copyright is claimed. - * This code is in the public domain; do with it what you wish. - * Todd C. Miller modified the MD5 code to do MD4 based on RFC 1186. - * - * Equivalent code is available from RSA Data Security, Inc. - * This code has been tested against that, and is equivalent, - * except that you don't need to include two pages of legalese - * with every copy. - * - * To compute the message digest of a chunk of bytes, declare an - * MD4Context structure, pass it to MD4Init, call MD4Update as - * needed on buffers full of bytes, and then call MD4Final, which - * will fill a supplied 16-byte array with the digest. - */ - -#define MD4_DIGEST_STRING_LENGTH (MD4_DIGEST_LENGTH * 2 + 1) - - -static void -MD4Transform(u32 state[4], const u8 block[MD4_BLOCK_LENGTH]); - -#define PUT_64BIT_LE(cp, value) do { \ - (cp)[7] = (value) >> 56; \ - (cp)[6] = (value) >> 48; \ - (cp)[5] = (value) >> 40; \ - (cp)[4] = (value) >> 32; \ - (cp)[3] = (value) >> 24; \ - (cp)[2] = (value) >> 16; \ - (cp)[1] = (value) >> 8; \ - (cp)[0] = (value); } while (0) - -#define PUT_32BIT_LE(cp, value) do { \ - (cp)[3] = (value) >> 24; \ - (cp)[2] = (value) >> 16; \ - (cp)[1] = (value) >> 8; \ - (cp)[0] = (value); } while (0) - -static u8 PADDING[MD4_BLOCK_LENGTH] = { - 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 -}; - -/* - * Start MD4 accumulation. - * Set bit count to 0 and buffer to mysterious initialization constants. - */ -static void MD4Init(MD4_CTX *ctx) -{ - ctx->count = 0; - ctx->state[0] = 0x67452301; - ctx->state[1] = 0xefcdab89; - ctx->state[2] = 0x98badcfe; - ctx->state[3] = 0x10325476; -} - -/* - * Update context to reflect the concatenation of another buffer full - * of bytes. - */ -static void MD4Update(MD4_CTX *ctx, const unsigned char *input, size_t len) -{ - size_t have, need; - - /* Check how many bytes we already have and how many more we need. */ - have = (size_t)((ctx->count >> 3) & (MD4_BLOCK_LENGTH - 1)); - need = MD4_BLOCK_LENGTH - have; - - /* Update bitcount */ - ctx->count += (u64)len << 3; - - if (len >= need) { - if (have != 0) { - os_memcpy(ctx->buffer + have, input, need); - MD4Transform(ctx->state, ctx->buffer); - input += need; - len -= need; - have = 0; - } - - /* Process data in MD4_BLOCK_LENGTH-byte chunks. */ - while (len >= MD4_BLOCK_LENGTH) { - MD4Transform(ctx->state, input); - input += MD4_BLOCK_LENGTH; - len -= MD4_BLOCK_LENGTH; - } - } - - /* Handle any remaining bytes of data. */ - if (len != 0) - os_memcpy(ctx->buffer + have, input, len); -} - -/* - * Pad pad to 64-byte boundary with the bit pattern - * 1 0* (64-bit count of bits processed, MSB-first) - */ -static void MD4Pad(MD4_CTX *ctx) -{ - u8 count[8]; - size_t padlen; - - /* Convert count to 8 bytes in little endian order. */ - PUT_64BIT_LE(count, ctx->count); - - /* Pad out to 56 mod 64. */ - padlen = MD4_BLOCK_LENGTH - - ((ctx->count >> 3) & (MD4_BLOCK_LENGTH - 1)); - if (padlen < 1 + 8) - padlen += MD4_BLOCK_LENGTH; - MD4Update(ctx, PADDING, padlen - 8); /* padlen - 8 <= 64 */ - MD4Update(ctx, count, 8); -} - -/* - * Final wrapup--call MD4Pad, fill in digest and zero out ctx. - */ -static void MD4Final(unsigned char digest[MD4_DIGEST_LENGTH], MD4_CTX *ctx) -{ - int i; - - MD4Pad(ctx); - if (digest != NULL) { - for (i = 0; i < 4; i++) - PUT_32BIT_LE(digest + i * 4, ctx->state[i]); - os_memset(ctx, 0, sizeof(*ctx)); - } -} - - -/* The three core functions - F1 is optimized somewhat */ - -/* #define F1(x, y, z) (x & y | ~x & z) */ -#define F1(x, y, z) (z ^ (x & (y ^ z))) -#define F2(x, y, z) ((x & y) | (x & z) | (y & z)) -#define F3(x, y, z) (x ^ y ^ z) - -/* This is the central step in the MD4 algorithm. */ -#define MD4STEP(f, w, x, y, z, data, s) \ - ( w += f(x, y, z) + data, w = w<>(32-s) ) - -/* - * The core of the MD4 algorithm, this alters an existing MD4 hash to - * reflect the addition of 16 longwords of new data. MD4Update blocks - * the data and converts bytes into longwords for this routine. - */ -static void -MD4Transform(u32 state[4], const u8 block[MD4_BLOCK_LENGTH]) -{ - u32 a, b, c, d, in[MD4_BLOCK_LENGTH / 4]; - -#if BYTE_ORDER == LITTLE_ENDIAN - os_memcpy(in, block, sizeof(in)); -#else - for (a = 0; a < MD4_BLOCK_LENGTH / 4; a++) { - in[a] = (u32)( - (u32)(block[a * 4 + 0]) | - (u32)(block[a * 4 + 1]) << 8 | - (u32)(block[a * 4 + 2]) << 16 | - (u32)(block[a * 4 + 3]) << 24); - } -#endif - - a = state[0]; - b = state[1]; - c = state[2]; - d = state[3]; - - MD4STEP(F1, a, b, c, d, in[ 0], 3); - MD4STEP(F1, d, a, b, c, in[ 1], 7); - MD4STEP(F1, c, d, a, b, in[ 2], 11); - MD4STEP(F1, b, c, d, a, in[ 3], 19); - MD4STEP(F1, a, b, c, d, in[ 4], 3); - MD4STEP(F1, d, a, b, c, in[ 5], 7); - MD4STEP(F1, c, d, a, b, in[ 6], 11); - MD4STEP(F1, b, c, d, a, in[ 7], 19); - MD4STEP(F1, a, b, c, d, in[ 8], 3); - MD4STEP(F1, d, a, b, c, in[ 9], 7); - MD4STEP(F1, c, d, a, b, in[10], 11); - MD4STEP(F1, b, c, d, a, in[11], 19); - MD4STEP(F1, a, b, c, d, in[12], 3); - MD4STEP(F1, d, a, b, c, in[13], 7); - MD4STEP(F1, c, d, a, b, in[14], 11); - MD4STEP(F1, b, c, d, a, in[15], 19); - - MD4STEP(F2, a, b, c, d, in[ 0] + 0x5a827999, 3); - MD4STEP(F2, d, a, b, c, in[ 4] + 0x5a827999, 5); - MD4STEP(F2, c, d, a, b, in[ 8] + 0x5a827999, 9); - MD4STEP(F2, b, c, d, a, in[12] + 0x5a827999, 13); - MD4STEP(F2, a, b, c, d, in[ 1] + 0x5a827999, 3); - MD4STEP(F2, d, a, b, c, in[ 5] + 0x5a827999, 5); - MD4STEP(F2, c, d, a, b, in[ 9] + 0x5a827999, 9); - MD4STEP(F2, b, c, d, a, in[13] + 0x5a827999, 13); - MD4STEP(F2, a, b, c, d, in[ 2] + 0x5a827999, 3); - MD4STEP(F2, d, a, b, c, in[ 6] + 0x5a827999, 5); - MD4STEP(F2, c, d, a, b, in[10] + 0x5a827999, 9); - MD4STEP(F2, b, c, d, a, in[14] + 0x5a827999, 13); - MD4STEP(F2, a, b, c, d, in[ 3] + 0x5a827999, 3); - MD4STEP(F2, d, a, b, c, in[ 7] + 0x5a827999, 5); - MD4STEP(F2, c, d, a, b, in[11] + 0x5a827999, 9); - MD4STEP(F2, b, c, d, a, in[15] + 0x5a827999, 13); - - MD4STEP(F3, a, b, c, d, in[ 0] + 0x6ed9eba1, 3); - MD4STEP(F3, d, a, b, c, in[ 8] + 0x6ed9eba1, 9); - MD4STEP(F3, c, d, a, b, in[ 4] + 0x6ed9eba1, 11); - MD4STEP(F3, b, c, d, a, in[12] + 0x6ed9eba1, 15); - MD4STEP(F3, a, b, c, d, in[ 2] + 0x6ed9eba1, 3); - MD4STEP(F3, d, a, b, c, in[10] + 0x6ed9eba1, 9); - MD4STEP(F3, c, d, a, b, in[ 6] + 0x6ed9eba1, 11); - MD4STEP(F3, b, c, d, a, in[14] + 0x6ed9eba1, 15); - MD4STEP(F3, a, b, c, d, in[ 1] + 0x6ed9eba1, 3); - MD4STEP(F3, d, a, b, c, in[ 9] + 0x6ed9eba1, 9); - MD4STEP(F3, c, d, a, b, in[ 5] + 0x6ed9eba1, 11); - MD4STEP(F3, b, c, d, a, in[13] + 0x6ed9eba1, 15); - MD4STEP(F3, a, b, c, d, in[ 3] + 0x6ed9eba1, 3); - MD4STEP(F3, d, a, b, c, in[11] + 0x6ed9eba1, 9); - MD4STEP(F3, c, d, a, b, in[ 7] + 0x6ed9eba1, 11); - MD4STEP(F3, b, c, d, a, in[15] + 0x6ed9eba1, 15); - - state[0] += a; - state[1] += b; - state[2] += c; - state[3] += d; -} -/* ===== end - public domain MD4 implementation ===== */ diff --git a/hostapd-0.8/src/crypto/md5-internal.c b/hostapd-0.8/src/crypto/md5-internal.c deleted file mode 100644 index 05f4fc2..0000000 --- a/hostapd-0.8/src/crypto/md5-internal.c +++ /dev/null @@ -1,293 +0,0 @@ -/* - * MD5 hash implementation and interface functions - * Copyright (c) 2003-2005, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#include "includes.h" - -#include "common.h" -#include "md5.h" -#include "md5_i.h" -#include "crypto.h" - - -static void MD5Transform(u32 buf[4], u32 const in[16]); - - -typedef struct MD5Context MD5_CTX; - - -/** - * md5_vector - MD5 hash for data vector - * @num_elem: Number of elements in the data vector - * @addr: Pointers to the data areas - * @len: Lengths of the data blocks - * @mac: Buffer for the hash - * Returns: 0 on success, -1 of failure - */ -int md5_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac) -{ - MD5_CTX ctx; - size_t i; - - MD5Init(&ctx); - for (i = 0; i < num_elem; i++) - MD5Update(&ctx, addr[i], len[i]); - MD5Final(mac, &ctx); - return 0; -} - - -/* ===== start - public domain MD5 implementation ===== */ -/* - * This code implements the MD5 message-digest algorithm. - * The algorithm is due to Ron Rivest. This code was - * written by Colin Plumb in 1993, no copyright is claimed. - * This code is in the public domain; do with it what you wish. - * - * Equivalent code is available from RSA Data Security, Inc. - * This code has been tested against that, and is equivalent, - * except that you don't need to include two pages of legalese - * with every copy. - * - * To compute the message digest of a chunk of bytes, declare an - * MD5Context structure, pass it to MD5Init, call MD5Update as - * needed on buffers full of bytes, and then call MD5Final, which - * will fill a supplied 16-byte array with the digest. - */ - -#ifndef WORDS_BIGENDIAN -#define byteReverse(buf, len) /* Nothing */ -#else -/* - * Note: this code is harmless on little-endian machines. - */ -static void byteReverse(unsigned char *buf, unsigned longs) -{ - u32 t; - do { - t = (u32) ((unsigned) buf[3] << 8 | buf[2]) << 16 | - ((unsigned) buf[1] << 8 | buf[0]); - *(u32 *) buf = t; - buf += 4; - } while (--longs); -} -#endif - -/* - * Start MD5 accumulation. Set bit count to 0 and buffer to mysterious - * initialization constants. - */ -void MD5Init(struct MD5Context *ctx) -{ - ctx->buf[0] = 0x67452301; - ctx->buf[1] = 0xefcdab89; - ctx->buf[2] = 0x98badcfe; - ctx->buf[3] = 0x10325476; - - ctx->bits[0] = 0; - ctx->bits[1] = 0; -} - -/* - * Update context to reflect the concatenation of another buffer full - * of bytes. - */ -void MD5Update(struct MD5Context *ctx, unsigned char const *buf, unsigned len) -{ - u32 t; - - /* Update bitcount */ - - t = ctx->bits[0]; - if ((ctx->bits[0] = t + ((u32) len << 3)) < t) - ctx->bits[1]++; /* Carry from low to high */ - ctx->bits[1] += len >> 29; - - t = (t >> 3) & 0x3f; /* Bytes already in shsInfo->data */ - - /* Handle any leading odd-sized chunks */ - - if (t) { - unsigned char *p = (unsigned char *) ctx->in + t; - - t = 64 - t; - if (len < t) { - os_memcpy(p, buf, len); - return; - } - os_memcpy(p, buf, t); - byteReverse(ctx->in, 16); - MD5Transform(ctx->buf, (u32 *) ctx->in); - buf += t; - len -= t; - } - /* Process data in 64-byte chunks */ - - while (len >= 64) { - os_memcpy(ctx->in, buf, 64); - byteReverse(ctx->in, 16); - MD5Transform(ctx->buf, (u32 *) ctx->in); - buf += 64; - len -= 64; - } - - /* Handle any remaining bytes of data. */ - - os_memcpy(ctx->in, buf, len); -} - -/* - * Final wrapup - pad to 64-byte boundary with the bit pattern - * 1 0* (64-bit count of bits processed, MSB-first) - */ -void MD5Final(unsigned char digest[16], struct MD5Context *ctx) -{ - unsigned count; - unsigned char *p; - - /* Compute number of bytes mod 64 */ - count = (ctx->bits[0] >> 3) & 0x3F; - - /* Set the first char of padding to 0x80. This is safe since there is - always at least one byte free */ - p = ctx->in + count; - *p++ = 0x80; - - /* Bytes of padding needed to make 64 bytes */ - count = 64 - 1 - count; - - /* Pad out to 56 mod 64 */ - if (count < 8) { - /* Two lots of padding: Pad the first block to 64 bytes */ - os_memset(p, 0, count); - byteReverse(ctx->in, 16); - MD5Transform(ctx->buf, (u32 *) ctx->in); - - /* Now fill the next block with 56 bytes */ - os_memset(ctx->in, 0, 56); - } else { - /* Pad block to 56 bytes */ - os_memset(p, 0, count - 8); - } - byteReverse(ctx->in, 14); - - /* Append length in bits and transform */ - ((u32 *) ctx->in)[14] = ctx->bits[0]; - ((u32 *) ctx->in)[15] = ctx->bits[1]; - - MD5Transform(ctx->buf, (u32 *) ctx->in); - byteReverse((unsigned char *) ctx->buf, 4); - os_memcpy(digest, ctx->buf, 16); - os_memset(ctx, 0, sizeof(struct MD5Context)); /* In case it's sensitive */ -} - -/* The four core functions - F1 is optimized somewhat */ - -/* #define F1(x, y, z) (x & y | ~x & z) */ -#define F1(x, y, z) (z ^ (x & (y ^ z))) -#define F2(x, y, z) F1(z, x, y) -#define F3(x, y, z) (x ^ y ^ z) -#define F4(x, y, z) (y ^ (x | ~z)) - -/* This is the central step in the MD5 algorithm. */ -#define MD5STEP(f, w, x, y, z, data, s) \ - ( w += f(x, y, z) + data, w = w<>(32-s), w += x ) - -/* - * The core of the MD5 algorithm, this alters an existing MD5 hash to - * reflect the addition of 16 longwords of new data. MD5Update blocks - * the data and converts bytes into longwords for this routine. - */ -static void MD5Transform(u32 buf[4], u32 const in[16]) -{ - register u32 a, b, c, d; - - a = buf[0]; - b = buf[1]; - c = buf[2]; - d = buf[3]; - - MD5STEP(F1, a, b, c, d, in[0] + 0xd76aa478, 7); - MD5STEP(F1, d, a, b, c, in[1] + 0xe8c7b756, 12); - MD5STEP(F1, c, d, a, b, in[2] + 0x242070db, 17); - MD5STEP(F1, b, c, d, a, in[3] + 0xc1bdceee, 22); - MD5STEP(F1, a, b, c, d, in[4] + 0xf57c0faf, 7); - MD5STEP(F1, d, a, b, c, in[5] + 0x4787c62a, 12); - MD5STEP(F1, c, d, a, b, in[6] + 0xa8304613, 17); - MD5STEP(F1, b, c, d, a, in[7] + 0xfd469501, 22); - MD5STEP(F1, a, b, c, d, in[8] + 0x698098d8, 7); - MD5STEP(F1, d, a, b, c, in[9] + 0x8b44f7af, 12); - MD5STEP(F1, c, d, a, b, in[10] + 0xffff5bb1, 17); - MD5STEP(F1, b, c, d, a, in[11] + 0x895cd7be, 22); - MD5STEP(F1, a, b, c, d, in[12] + 0x6b901122, 7); - MD5STEP(F1, d, a, b, c, in[13] + 0xfd987193, 12); - MD5STEP(F1, c, d, a, b, in[14] + 0xa679438e, 17); - MD5STEP(F1, b, c, d, a, in[15] + 0x49b40821, 22); - - MD5STEP(F2, a, b, c, d, in[1] + 0xf61e2562, 5); - MD5STEP(F2, d, a, b, c, in[6] + 0xc040b340, 9); - MD5STEP(F2, c, d, a, b, in[11] + 0x265e5a51, 14); - MD5STEP(F2, b, c, d, a, in[0] + 0xe9b6c7aa, 20); - MD5STEP(F2, a, b, c, d, in[5] + 0xd62f105d, 5); - MD5STEP(F2, d, a, b, c, in[10] + 0x02441453, 9); - MD5STEP(F2, c, d, a, b, in[15] + 0xd8a1e681, 14); - MD5STEP(F2, b, c, d, a, in[4] + 0xe7d3fbc8, 20); - MD5STEP(F2, a, b, c, d, in[9] + 0x21e1cde6, 5); - MD5STEP(F2, d, a, b, c, in[14] + 0xc33707d6, 9); - MD5STEP(F2, c, d, a, b, in[3] + 0xf4d50d87, 14); - MD5STEP(F2, b, c, d, a, in[8] + 0x455a14ed, 20); - MD5STEP(F2, a, b, c, d, in[13] + 0xa9e3e905, 5); - MD5STEP(F2, d, a, b, c, in[2] + 0xfcefa3f8, 9); - MD5STEP(F2, c, d, a, b, in[7] + 0x676f02d9, 14); - MD5STEP(F2, b, c, d, a, in[12] + 0x8d2a4c8a, 20); - - MD5STEP(F3, a, b, c, d, in[5] + 0xfffa3942, 4); - MD5STEP(F3, d, a, b, c, in[8] + 0x8771f681, 11); - MD5STEP(F3, c, d, a, b, in[11] + 0x6d9d6122, 16); - MD5STEP(F3, b, c, d, a, in[14] + 0xfde5380c, 23); - MD5STEP(F3, a, b, c, d, in[1] + 0xa4beea44, 4); - MD5STEP(F3, d, a, b, c, in[4] + 0x4bdecfa9, 11); - MD5STEP(F3, c, d, a, b, in[7] + 0xf6bb4b60, 16); - MD5STEP(F3, b, c, d, a, in[10] + 0xbebfbc70, 23); - MD5STEP(F3, a, b, c, d, in[13] + 0x289b7ec6, 4); - MD5STEP(F3, d, a, b, c, in[0] + 0xeaa127fa, 11); - MD5STEP(F3, c, d, a, b, in[3] + 0xd4ef3085, 16); - MD5STEP(F3, b, c, d, a, in[6] + 0x04881d05, 23); - MD5STEP(F3, a, b, c, d, in[9] + 0xd9d4d039, 4); - MD5STEP(F3, d, a, b, c, in[12] + 0xe6db99e5, 11); - MD5STEP(F3, c, d, a, b, in[15] + 0x1fa27cf8, 16); - MD5STEP(F3, b, c, d, a, in[2] + 0xc4ac5665, 23); - - MD5STEP(F4, a, b, c, d, in[0] + 0xf4292244, 6); - MD5STEP(F4, d, a, b, c, in[7] + 0x432aff97, 10); - MD5STEP(F4, c, d, a, b, in[14] + 0xab9423a7, 15); - MD5STEP(F4, b, c, d, a, in[5] + 0xfc93a039, 21); - MD5STEP(F4, a, b, c, d, in[12] + 0x655b59c3, 6); - MD5STEP(F4, d, a, b, c, in[3] + 0x8f0ccc92, 10); - MD5STEP(F4, c, d, a, b, in[10] + 0xffeff47d, 15); - MD5STEP(F4, b, c, d, a, in[1] + 0x85845dd1, 21); - MD5STEP(F4, a, b, c, d, in[8] + 0x6fa87e4f, 6); - MD5STEP(F4, d, a, b, c, in[15] + 0xfe2ce6e0, 10); - MD5STEP(F4, c, d, a, b, in[6] + 0xa3014314, 15); - MD5STEP(F4, b, c, d, a, in[13] + 0x4e0811a1, 21); - MD5STEP(F4, a, b, c, d, in[4] + 0xf7537e82, 6); - MD5STEP(F4, d, a, b, c, in[11] + 0xbd3af235, 10); - MD5STEP(F4, c, d, a, b, in[2] + 0x2ad7d2bb, 15); - MD5STEP(F4, b, c, d, a, in[9] + 0xeb86d391, 21); - - buf[0] += a; - buf[1] += b; - buf[2] += c; - buf[3] += d; -} -/* ===== end - public domain MD5 implementation ===== */ diff --git a/hostapd-0.8/src/crypto/md5-non-fips.c b/hostapd-0.8/src/crypto/md5-non-fips.c deleted file mode 100644 index 6f29201..0000000 --- a/hostapd-0.8/src/crypto/md5-non-fips.c +++ /dev/null @@ -1,113 +0,0 @@ -/* - * MD5 hash implementation and interface functions (non-FIPS allowed cases) - * Copyright (c) 2003-2009, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#include "includes.h" - -#include "common.h" -#include "md5.h" -#include "crypto.h" - - -/** - * hmac_md5_vector_non_fips_allow - HMAC-MD5 over data vector (RFC 2104) - * @key: Key for HMAC operations - * @key_len: Length of the key in bytes - * @num_elem: Number of elements in the data vector - * @addr: Pointers to the data areas - * @len: Lengths of the data blocks - * @mac: Buffer for the hash (16 bytes) - * Returns: 0 on success, -1 on failure - */ -int hmac_md5_vector_non_fips_allow(const u8 *key, size_t key_len, - size_t num_elem, const u8 *addr[], - const size_t *len, u8 *mac) -{ - u8 k_pad[64]; /* padding - key XORd with ipad/opad */ - u8 tk[16]; - const u8 *_addr[6]; - size_t i, _len[6]; - - if (num_elem > 5) { - /* - * Fixed limit on the number of fragments to avoid having to - * allocate memory (which could fail). - */ - return -1; - } - - /* if key is longer than 64 bytes reset it to key = MD5(key) */ - if (key_len > 64) { - if (md5_vector_non_fips_allow(1, &key, &key_len, tk)) - return -1; - key = tk; - key_len = 16; - } - - /* the HMAC_MD5 transform looks like: - * - * MD5(K XOR opad, MD5(K XOR ipad, text)) - * - * where K is an n byte key - * ipad is the byte 0x36 repeated 64 times - * opad is the byte 0x5c repeated 64 times - * and text is the data being protected */ - - /* start out by storing key in ipad */ - os_memset(k_pad, 0, sizeof(k_pad)); - os_memcpy(k_pad, key, key_len); - - /* XOR key with ipad values */ - for (i = 0; i < 64; i++) - k_pad[i] ^= 0x36; - - /* perform inner MD5 */ - _addr[0] = k_pad; - _len[0] = 64; - for (i = 0; i < num_elem; i++) { - _addr[i + 1] = addr[i]; - _len[i + 1] = len[i]; - } - if (md5_vector_non_fips_allow(1 + num_elem, _addr, _len, mac)) - return -1; - - os_memset(k_pad, 0, sizeof(k_pad)); - os_memcpy(k_pad, key, key_len); - /* XOR key with opad values */ - for (i = 0; i < 64; i++) - k_pad[i] ^= 0x5c; - - /* perform outer MD5 */ - _addr[0] = k_pad; - _len[0] = 64; - _addr[1] = mac; - _len[1] = MD5_MAC_LEN; - return md5_vector_non_fips_allow(2, _addr, _len, mac); -} - - -/** - * hmac_md5_non_fips_allow - HMAC-MD5 over data buffer (RFC 2104) - * @key: Key for HMAC operations - * @key_len: Length of the key in bytes - * @data: Pointers to the data area - * @data_len: Length of the data area - * @mac: Buffer for the hash (16 bytes) - * Returns: 0 on success, -1 on failure - */ -int hmac_md5_non_fips_allow(const u8 *key, size_t key_len, const u8 *data, - size_t data_len, u8 *mac) -{ - return hmac_md5_vector_non_fips_allow(key, key_len, 1, &data, - &data_len, mac); -} diff --git a/hostapd-0.8/src/crypto/md5.c b/hostapd-0.8/src/crypto/md5.c deleted file mode 100644 index 7f14e9b..0000000 --- a/hostapd-0.8/src/crypto/md5.c +++ /dev/null @@ -1,111 +0,0 @@ -/* - * MD5 hash implementation and interface functions - * Copyright (c) 2003-2005, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#include "includes.h" - -#include "common.h" -#include "md5.h" -#include "crypto.h" - - -/** - * hmac_md5_vector - HMAC-MD5 over data vector (RFC 2104) - * @key: Key for HMAC operations - * @key_len: Length of the key in bytes - * @num_elem: Number of elements in the data vector - * @addr: Pointers to the data areas - * @len: Lengths of the data blocks - * @mac: Buffer for the hash (16 bytes) - * Returns: 0 on success, -1 on failure - */ -int hmac_md5_vector(const u8 *key, size_t key_len, size_t num_elem, - const u8 *addr[], const size_t *len, u8 *mac) -{ - u8 k_pad[64]; /* padding - key XORd with ipad/opad */ - u8 tk[16]; - const u8 *_addr[6]; - size_t i, _len[6]; - - if (num_elem > 5) { - /* - * Fixed limit on the number of fragments to avoid having to - * allocate memory (which could fail). - */ - return -1; - } - - /* if key is longer than 64 bytes reset it to key = MD5(key) */ - if (key_len > 64) { - if (md5_vector(1, &key, &key_len, tk)) - return -1; - key = tk; - key_len = 16; - } - - /* the HMAC_MD5 transform looks like: - * - * MD5(K XOR opad, MD5(K XOR ipad, text)) - * - * where K is an n byte key - * ipad is the byte 0x36 repeated 64 times - * opad is the byte 0x5c repeated 64 times - * and text is the data being protected */ - - /* start out by storing key in ipad */ - os_memset(k_pad, 0, sizeof(k_pad)); - os_memcpy(k_pad, key, key_len); - - /* XOR key with ipad values */ - for (i = 0; i < 64; i++) - k_pad[i] ^= 0x36; - - /* perform inner MD5 */ - _addr[0] = k_pad; - _len[0] = 64; - for (i = 0; i < num_elem; i++) { - _addr[i + 1] = addr[i]; - _len[i + 1] = len[i]; - } - if (md5_vector(1 + num_elem, _addr, _len, mac)) - return -1; - - os_memset(k_pad, 0, sizeof(k_pad)); - os_memcpy(k_pad, key, key_len); - /* XOR key with opad values */ - for (i = 0; i < 64; i++) - k_pad[i] ^= 0x5c; - - /* perform outer MD5 */ - _addr[0] = k_pad; - _len[0] = 64; - _addr[1] = mac; - _len[1] = MD5_MAC_LEN; - return md5_vector(2, _addr, _len, mac); -} - - -/** - * hmac_md5 - HMAC-MD5 over data buffer (RFC 2104) - * @key: Key for HMAC operations - * @key_len: Length of the key in bytes - * @data: Pointers to the data area - * @data_len: Length of the data area - * @mac: Buffer for the hash (16 bytes) - * Returns: 0 on success, -1 on failure - */ -int hmac_md5(const u8 *key, size_t key_len, const u8 *data, size_t data_len, - u8 *mac) -{ - return hmac_md5_vector(key, key_len, 1, &data, &data_len, mac); -} diff --git a/hostapd-0.8/src/crypto/md5.h b/hostapd-0.8/src/crypto/md5.h deleted file mode 100644 index 8952590..0000000 --- a/hostapd-0.8/src/crypto/md5.h +++ /dev/null @@ -1,35 +0,0 @@ -/* - * MD5 hash implementation and interface functions - * Copyright (c) 2003-2009, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#ifndef MD5_H -#define MD5_H - -#define MD5_MAC_LEN 16 - -int hmac_md5_vector(const u8 *key, size_t key_len, size_t num_elem, - const u8 *addr[], const size_t *len, u8 *mac); -int hmac_md5(const u8 *key, size_t key_len, const u8 *data, size_t data_len, - u8 *mac); -#ifdef CONFIG_FIPS -int hmac_md5_vector_non_fips_allow(const u8 *key, size_t key_len, - size_t num_elem, const u8 *addr[], - const size_t *len, u8 *mac); -int hmac_md5_non_fips_allow(const u8 *key, size_t key_len, const u8 *data, - size_t data_len, u8 *mac); -#else /* CONFIG_FIPS */ -#define hmac_md5_vector_non_fips_allow hmac_md5_vector -#define hmac_md5_non_fips_allow hmac_md5 -#endif /* CONFIG_FIPS */ - -#endif /* MD5_H */ diff --git a/hostapd-0.8/src/crypto/md5_i.h b/hostapd-0.8/src/crypto/md5_i.h deleted file mode 100644 index b7f6596..0000000 --- a/hostapd-0.8/src/crypto/md5_i.h +++ /dev/null @@ -1,29 +0,0 @@ -/* - * MD5 internal definitions - * Copyright (c) 2003-2005, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#ifndef MD5_I_H -#define MD5_I_H - -struct MD5Context { - u32 buf[4]; - u32 bits[2]; - u8 in[64]; -}; - -void MD5Init(struct MD5Context *context); -void MD5Update(struct MD5Context *context, unsigned char const *buf, - unsigned len); -void MD5Final(unsigned char digest[16], struct MD5Context *context); - -#endif /* MD5_I_H */ diff --git a/hostapd-0.8/src/crypto/milenage.c b/hostapd-0.8/src/crypto/milenage.c deleted file mode 100644 index cf0c60e..0000000 --- a/hostapd-0.8/src/crypto/milenage.c +++ /dev/null @@ -1,329 +0,0 @@ -/* - * 3GPP AKA - Milenage algorithm (3GPP TS 35.205, .206, .207, .208) - * Copyright (c) 2006-2007 - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - * - * This file implements an example authentication algorithm defined for 3GPP - * AKA. This can be used to implement a simple HLR/AuC into hlr_auc_gw to allow - * EAP-AKA to be tested properly with real USIM cards. - * - * This implementations assumes that the r1..r5 and c1..c5 constants defined in - * TS 35.206 are used, i.e., r1=64, r2=0, r3=32, r4=64, r5=96, c1=00..00, - * c2=00..01, c3=00..02, c4=00..04, c5=00..08. The block cipher is assumed to - * be AES (Rijndael). - */ - -#include "includes.h" - -#include "common.h" -#include "crypto/aes_wrap.h" -#include "milenage.h" - - -/** - * milenage_f1 - Milenage f1 and f1* algorithms - * @opc: OPc = 128-bit value derived from OP and K - * @k: K = 128-bit subscriber key - * @_rand: RAND = 128-bit random challenge - * @sqn: SQN = 48-bit sequence number - * @amf: AMF = 16-bit authentication management field - * @mac_a: Buffer for MAC-A = 64-bit network authentication code, or %NULL - * @mac_s: Buffer for MAC-S = 64-bit resync authentication code, or %NULL - * Returns: 0 on success, -1 on failure - */ -int milenage_f1(const u8 *opc, const u8 *k, const u8 *_rand, - const u8 *sqn, const u8 *amf, u8 *mac_a, u8 *mac_s) -{ - u8 tmp1[16], tmp2[16], tmp3[16]; - int i; - - /* tmp1 = TEMP = E_K(RAND XOR OP_C) */ - for (i = 0; i < 16; i++) - tmp1[i] = _rand[i] ^ opc[i]; - if (aes_128_encrypt_block(k, tmp1, tmp1)) - return -1; - - /* tmp2 = IN1 = SQN || AMF || SQN || AMF */ - os_memcpy(tmp2, sqn, 6); - os_memcpy(tmp2 + 6, amf, 2); - os_memcpy(tmp2 + 8, tmp2, 8); - - /* OUT1 = E_K(TEMP XOR rot(IN1 XOR OP_C, r1) XOR c1) XOR OP_C */ - - /* rotate (tmp2 XOR OP_C) by r1 (= 0x40 = 8 bytes) */ - for (i = 0; i < 16; i++) - tmp3[(i + 8) % 16] = tmp2[i] ^ opc[i]; - /* XOR with TEMP = E_K(RAND XOR OP_C) */ - for (i = 0; i < 16; i++) - tmp3[i] ^= tmp1[i]; - /* XOR with c1 (= ..00, i.e., NOP) */ - - /* f1 || f1* = E_K(tmp3) XOR OP_c */ - if (aes_128_encrypt_block(k, tmp3, tmp1)) - return -1; - for (i = 0; i < 16; i++) - tmp1[i] ^= opc[i]; - if (mac_a) - os_memcpy(mac_a, tmp1, 8); /* f1 */ - if (mac_s) - os_memcpy(mac_s, tmp1 + 8, 8); /* f1* */ - return 0; -} - - -/** - * milenage_f2345 - Milenage f2, f3, f4, f5, f5* algorithms - * @opc: OPc = 128-bit value derived from OP and K - * @k: K = 128-bit subscriber key - * @_rand: RAND = 128-bit random challenge - * @res: Buffer for RES = 64-bit signed response (f2), or %NULL - * @ck: Buffer for CK = 128-bit confidentiality key (f3), or %NULL - * @ik: Buffer for IK = 128-bit integrity key (f4), or %NULL - * @ak: Buffer for AK = 48-bit anonymity key (f5), or %NULL - * @akstar: Buffer for AK = 48-bit anonymity key (f5*), or %NULL - * Returns: 0 on success, -1 on failure - */ -int milenage_f2345(const u8 *opc, const u8 *k, const u8 *_rand, - u8 *res, u8 *ck, u8 *ik, u8 *ak, u8 *akstar) -{ - u8 tmp1[16], tmp2[16], tmp3[16]; - int i; - - /* tmp2 = TEMP = E_K(RAND XOR OP_C) */ - for (i = 0; i < 16; i++) - tmp1[i] = _rand[i] ^ opc[i]; - if (aes_128_encrypt_block(k, tmp1, tmp2)) - return -1; - - /* OUT2 = E_K(rot(TEMP XOR OP_C, r2) XOR c2) XOR OP_C */ - /* OUT3 = E_K(rot(TEMP XOR OP_C, r3) XOR c3) XOR OP_C */ - /* OUT4 = E_K(rot(TEMP XOR OP_C, r4) XOR c4) XOR OP_C */ - /* OUT5 = E_K(rot(TEMP XOR OP_C, r5) XOR c5) XOR OP_C */ - - /* f2 and f5 */ - /* rotate by r2 (= 0, i.e., NOP) */ - for (i = 0; i < 16; i++) - tmp1[i] = tmp2[i] ^ opc[i]; - tmp1[15] ^= 1; /* XOR c2 (= ..01) */ - /* f5 || f2 = E_K(tmp1) XOR OP_c */ - if (aes_128_encrypt_block(k, tmp1, tmp3)) - return -1; - for (i = 0; i < 16; i++) - tmp3[i] ^= opc[i]; - if (res) - os_memcpy(res, tmp3 + 8, 8); /* f2 */ - if (ak) - os_memcpy(ak, tmp3, 6); /* f5 */ - - /* f3 */ - if (ck) { - /* rotate by r3 = 0x20 = 4 bytes */ - for (i = 0; i < 16; i++) - tmp1[(i + 12) % 16] = tmp2[i] ^ opc[i]; - tmp1[15] ^= 2; /* XOR c3 (= ..02) */ - if (aes_128_encrypt_block(k, tmp1, ck)) - return -1; - for (i = 0; i < 16; i++) - ck[i] ^= opc[i]; - } - - /* f4 */ - if (ik) { - /* rotate by r4 = 0x40 = 8 bytes */ - for (i = 0; i < 16; i++) - tmp1[(i + 8) % 16] = tmp2[i] ^ opc[i]; - tmp1[15] ^= 4; /* XOR c4 (= ..04) */ - if (aes_128_encrypt_block(k, tmp1, ik)) - return -1; - for (i = 0; i < 16; i++) - ik[i] ^= opc[i]; - } - - /* f5* */ - if (akstar) { - /* rotate by r5 = 0x60 = 12 bytes */ - for (i = 0; i < 16; i++) - tmp1[(i + 4) % 16] = tmp2[i] ^ opc[i]; - tmp1[15] ^= 8; /* XOR c5 (= ..08) */ - if (aes_128_encrypt_block(k, tmp1, tmp1)) - return -1; - for (i = 0; i < 6; i++) - akstar[i] = tmp1[i] ^ opc[i]; - } - - return 0; -} - - -/** - * milenage_generate - Generate AKA AUTN,IK,CK,RES - * @opc: OPc = 128-bit operator variant algorithm configuration field (encr.) - * @amf: AMF = 16-bit authentication management field - * @k: K = 128-bit subscriber key - * @sqn: SQN = 48-bit sequence number - * @_rand: RAND = 128-bit random challenge - * @autn: Buffer for AUTN = 128-bit authentication token - * @ik: Buffer for IK = 128-bit integrity key (f4), or %NULL - * @ck: Buffer for CK = 128-bit confidentiality key (f3), or %NULL - * @res: Buffer for RES = 64-bit signed response (f2), or %NULL - * @res_len: Max length for res; set to used length or 0 on failure - */ -void milenage_generate(const u8 *opc, const u8 *amf, const u8 *k, - const u8 *sqn, const u8 *_rand, u8 *autn, u8 *ik, - u8 *ck, u8 *res, size_t *res_len) -{ - int i; - u8 mac_a[8], ak[6]; - - if (*res_len < 8) { - *res_len = 0; - return; - } - if (milenage_f1(opc, k, _rand, sqn, amf, mac_a, NULL) || - milenage_f2345(opc, k, _rand, res, ck, ik, ak, NULL)) { - *res_len = 0; - return; - } - *res_len = 8; - - /* AUTN = (SQN ^ AK) || AMF || MAC */ - for (i = 0; i < 6; i++) - autn[i] = sqn[i] ^ ak[i]; - os_memcpy(autn + 6, amf, 2); - os_memcpy(autn + 8, mac_a, 8); -} - - -/** - * milenage_auts - Milenage AUTS validation - * @opc: OPc = 128-bit operator variant algorithm configuration field (encr.) - * @k: K = 128-bit subscriber key - * @_rand: RAND = 128-bit random challenge - * @auts: AUTS = 112-bit authentication token from client - * @sqn: Buffer for SQN = 48-bit sequence number - * Returns: 0 = success (sqn filled), -1 on failure - */ -int milenage_auts(const u8 *opc, const u8 *k, const u8 *_rand, const u8 *auts, - u8 *sqn) -{ - u8 amf[2] = { 0x00, 0x00 }; /* TS 33.102 v7.0.0, 6.3.3 */ - u8 ak[6], mac_s[8]; - int i; - - if (milenage_f2345(opc, k, _rand, NULL, NULL, NULL, NULL, ak)) - return -1; - for (i = 0; i < 6; i++) - sqn[i] = auts[i] ^ ak[i]; - if (milenage_f1(opc, k, _rand, sqn, amf, NULL, mac_s) || - memcmp(mac_s, auts + 6, 8) != 0) - return -1; - return 0; -} - - -/** - * gsm_milenage - Generate GSM-Milenage (3GPP TS 55.205) authentication triplet - * @opc: OPc = 128-bit operator variant algorithm configuration field (encr.) - * @k: K = 128-bit subscriber key - * @_rand: RAND = 128-bit random challenge - * @sres: Buffer for SRES = 32-bit SRES - * @kc: Buffer for Kc = 64-bit Kc - * Returns: 0 on success, -1 on failure - */ -int gsm_milenage(const u8 *opc, const u8 *k, const u8 *_rand, u8 *sres, u8 *kc) -{ - u8 res[8], ck[16], ik[16]; - int i; - - if (milenage_f2345(opc, k, _rand, res, ck, ik, NULL, NULL)) - return -1; - - for (i = 0; i < 8; i++) - kc[i] = ck[i] ^ ck[i + 8] ^ ik[i] ^ ik[i + 8]; - -#ifdef GSM_MILENAGE_ALT_SRES - os_memcpy(sres, res, 4); -#else /* GSM_MILENAGE_ALT_SRES */ - for (i = 0; i < 4; i++) - sres[i] = res[i] ^ res[i + 4]; -#endif /* GSM_MILENAGE_ALT_SRES */ - return 0; -} - - -/** - * milenage_generate - Generate AKA AUTN,IK,CK,RES - * @opc: OPc = 128-bit operator variant algorithm configuration field (encr.) - * @k: K = 128-bit subscriber key - * @sqn: SQN = 48-bit sequence number - * @_rand: RAND = 128-bit random challenge - * @autn: AUTN = 128-bit authentication token - * @ik: Buffer for IK = 128-bit integrity key (f4), or %NULL - * @ck: Buffer for CK = 128-bit confidentiality key (f3), or %NULL - * @res: Buffer for RES = 64-bit signed response (f2), or %NULL - * @res_len: Variable that will be set to RES length - * @auts: 112-bit buffer for AUTS - * Returns: 0 on success, -1 on failure, or -2 on synchronization failure - */ -int milenage_check(const u8 *opc, const u8 *k, const u8 *sqn, const u8 *_rand, - const u8 *autn, u8 *ik, u8 *ck, u8 *res, size_t *res_len, - u8 *auts) -{ - int i; - u8 mac_a[8], ak[6], rx_sqn[6]; - const u8 *amf; - - wpa_hexdump(MSG_DEBUG, "Milenage: AUTN", autn, 16); - wpa_hexdump(MSG_DEBUG, "Milenage: RAND", _rand, 16); - - if (milenage_f2345(opc, k, _rand, res, ck, ik, ak, NULL)) - return -1; - - *res_len = 8; - wpa_hexdump_key(MSG_DEBUG, "Milenage: RES", res, *res_len); - wpa_hexdump_key(MSG_DEBUG, "Milenage: CK", ck, 16); - wpa_hexdump_key(MSG_DEBUG, "Milenage: IK", ik, 16); - wpa_hexdump_key(MSG_DEBUG, "Milenage: AK", ak, 6); - - /* AUTN = (SQN ^ AK) || AMF || MAC */ - for (i = 0; i < 6; i++) - rx_sqn[i] = autn[i] ^ ak[i]; - wpa_hexdump(MSG_DEBUG, "Milenage: SQN", rx_sqn, 6); - - if (os_memcmp(rx_sqn, sqn, 6) <= 0) { - u8 auts_amf[2] = { 0x00, 0x00 }; /* TS 33.102 v7.0.0, 6.3.3 */ - if (milenage_f2345(opc, k, _rand, NULL, NULL, NULL, NULL, ak)) - return -1; - wpa_hexdump_key(MSG_DEBUG, "Milenage: AK*", ak, 6); - for (i = 0; i < 6; i++) - auts[i] = sqn[i] ^ ak[i]; - if (milenage_f1(opc, k, _rand, sqn, auts_amf, NULL, auts + 6)) - return -1; - wpa_hexdump(MSG_DEBUG, "Milenage: AUTS", auts, 14); - return -2; - } - - amf = autn + 6; - wpa_hexdump(MSG_DEBUG, "Milenage: AMF", amf, 2); - if (milenage_f1(opc, k, _rand, rx_sqn, amf, mac_a, NULL)) - return -1; - - wpa_hexdump(MSG_DEBUG, "Milenage: MAC_A", mac_a, 8); - - if (os_memcmp(mac_a, autn + 8, 8) != 0) { - wpa_printf(MSG_DEBUG, "Milenage: MAC mismatch"); - wpa_hexdump(MSG_DEBUG, "Milenage: Received MAC_A", - autn + 8, 8); - return -1; - } - - return 0; -} diff --git a/hostapd-0.8/src/crypto/milenage.h b/hostapd-0.8/src/crypto/milenage.h deleted file mode 100644 index d5054d6..0000000 --- a/hostapd-0.8/src/crypto/milenage.h +++ /dev/null @@ -1,33 +0,0 @@ -/* - * UMTS AKA - Milenage algorithm (3GPP TS 35.205, .206, .207, .208) - * Copyright (c) 2006-2007 - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#ifndef MILENAGE_H -#define MILENAGE_H - -void milenage_generate(const u8 *opc, const u8 *amf, const u8 *k, - const u8 *sqn, const u8 *_rand, u8 *autn, u8 *ik, - u8 *ck, u8 *res, size_t *res_len); -int milenage_auts(const u8 *opc, const u8 *k, const u8 *_rand, const u8 *auts, - u8 *sqn); -int gsm_milenage(const u8 *opc, const u8 *k, const u8 *_rand, u8 *sres, - u8 *kc); -int milenage_check(const u8 *opc, const u8 *k, const u8 *sqn, const u8 *_rand, - const u8 *autn, u8 *ik, u8 *ck, u8 *res, size_t *res_len, - u8 *auts); -int milenage_f1(const u8 *opc, const u8 *k, const u8 *_rand, - const u8 *sqn, const u8 *amf, u8 *mac_a, u8 *mac_s); -int milenage_f2345(const u8 *opc, const u8 *k, const u8 *_rand, - u8 *res, u8 *ck, u8 *ik, u8 *ak, u8 *akstar); - -#endif /* MILENAGE_H */ diff --git a/hostapd-0.8/src/crypto/ms_funcs.c b/hostapd-0.8/src/crypto/ms_funcs.c deleted file mode 100644 index dae15ab..0000000 --- a/hostapd-0.8/src/crypto/ms_funcs.c +++ /dev/null @@ -1,476 +0,0 @@ -/* - * WPA Supplicant / shared MSCHAPV2 helper functions / RFC 2433 / RFC 2759 - * Copyright (c) 2004-2009, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#include "includes.h" - -#include "common.h" -#include "sha1.h" -#include "ms_funcs.h" -#include "crypto.h" - - -/** - * challenge_hash - ChallengeHash() - RFC 2759, Sect. 8.2 - * @peer_challenge: 16-octet PeerChallenge (IN) - * @auth_challenge: 16-octet AuthenticatorChallenge (IN) - * @username: 0-to-256-char UserName (IN) - * @username_len: Length of username - * @challenge: 8-octet Challenge (OUT) - * Returns: 0 on success, -1 on failure - */ -static int challenge_hash(const u8 *peer_challenge, const u8 *auth_challenge, - const u8 *username, size_t username_len, - u8 *challenge) -{ - u8 hash[SHA1_MAC_LEN]; - const unsigned char *addr[3]; - size_t len[3]; - - addr[0] = peer_challenge; - len[0] = 16; - addr[1] = auth_challenge; - len[1] = 16; - addr[2] = username; - len[2] = username_len; - - if (sha1_vector(3, addr, len, hash)) - return -1; - os_memcpy(challenge, hash, 8); - return 0; -} - - -/** - * nt_password_hash - NtPasswordHash() - RFC 2759, Sect. 8.3 - * @password: 0-to-256-unicode-char Password (IN; ASCII) - * @password_len: Length of password - * @password_hash: 16-octet PasswordHash (OUT) - * Returns: 0 on success, -1 on failure - */ -int nt_password_hash(const u8 *password, size_t password_len, - u8 *password_hash) -{ - u8 buf[512], *pos; - size_t i, len; - - if (password_len > 256) - password_len = 256; - - /* Convert password into unicode */ - for (i = 0; i < password_len; i++) { - buf[2 * i] = password[i]; - buf[2 * i + 1] = 0; - } - - len = password_len * 2; - pos = buf; - return md4_vector(1, (const u8 **) &pos, &len, password_hash); -} - - -/** - * hash_nt_password_hash - HashNtPasswordHash() - RFC 2759, Sect. 8.4 - * @password_hash: 16-octet PasswordHash (IN) - * @password_hash_hash: 16-octet PasswordHashHash (OUT) - * Returns: 0 on success, -1 on failure - */ -int hash_nt_password_hash(const u8 *password_hash, u8 *password_hash_hash) -{ - size_t len = 16; - return md4_vector(1, &password_hash, &len, password_hash_hash); -} - - -/** - * challenge_response - ChallengeResponse() - RFC 2759, Sect. 8.5 - * @challenge: 8-octet Challenge (IN) - * @password_hash: 16-octet PasswordHash (IN) - * @response: 24-octet Response (OUT) - */ -void challenge_response(const u8 *challenge, const u8 *password_hash, - u8 *response) -{ - u8 zpwd[7]; - des_encrypt(challenge, password_hash, response); - des_encrypt(challenge, password_hash + 7, response + 8); - zpwd[0] = password_hash[14]; - zpwd[1] = password_hash[15]; - os_memset(zpwd + 2, 0, 5); - des_encrypt(challenge, zpwd, response + 16); -} - - -/** - * generate_nt_response - GenerateNTResponse() - RFC 2759, Sect. 8.1 - * @auth_challenge: 16-octet AuthenticatorChallenge (IN) - * @peer_challenge: 16-octet PeerChallenge (IN) - * @username: 0-to-256-char UserName (IN) - * @username_len: Length of username - * @password: 0-to-256-unicode-char Password (IN; ASCII) - * @password_len: Length of password - * @response: 24-octet Response (OUT) - * Returns: 0 on success, -1 on failure - */ -int generate_nt_response(const u8 *auth_challenge, const u8 *peer_challenge, - const u8 *username, size_t username_len, - const u8 *password, size_t password_len, - u8 *response) -{ - u8 challenge[8]; - u8 password_hash[16]; - - challenge_hash(peer_challenge, auth_challenge, username, username_len, - challenge); - if (nt_password_hash(password, password_len, password_hash)) - return -1; - challenge_response(challenge, password_hash, response); - return 0; -} - - -/** - * generate_nt_response_pwhash - GenerateNTResponse() - RFC 2759, Sect. 8.1 - * @auth_challenge: 16-octet AuthenticatorChallenge (IN) - * @peer_challenge: 16-octet PeerChallenge (IN) - * @username: 0-to-256-char UserName (IN) - * @username_len: Length of username - * @password_hash: 16-octet PasswordHash (IN) - * @response: 24-octet Response (OUT) - * Returns: 0 on success, -1 on failure - */ -int generate_nt_response_pwhash(const u8 *auth_challenge, - const u8 *peer_challenge, - const u8 *username, size_t username_len, - const u8 *password_hash, - u8 *response) -{ - u8 challenge[8]; - - if (challenge_hash(peer_challenge, auth_challenge, - username, username_len, - challenge)) - return -1; - challenge_response(challenge, password_hash, response); - return 0; -} - - -/** - * generate_authenticator_response_pwhash - GenerateAuthenticatorResponse() - RFC 2759, Sect. 8.7 - * @password_hash: 16-octet PasswordHash (IN) - * @nt_response: 24-octet NT-Response (IN) - * @peer_challenge: 16-octet PeerChallenge (IN) - * @auth_challenge: 16-octet AuthenticatorChallenge (IN) - * @username: 0-to-256-char UserName (IN) - * @username_len: Length of username - * @response: 20-octet AuthenticatorResponse (OUT) (note: this value is usually - * encoded as a 42-octet ASCII string (S=hexdump_of_response) - * Returns: 0 on success, -1 on failure - */ -int generate_authenticator_response_pwhash( - const u8 *password_hash, - const u8 *peer_challenge, const u8 *auth_challenge, - const u8 *username, size_t username_len, - const u8 *nt_response, u8 *response) -{ - static const u8 magic1[39] = { - 0x4D, 0x61, 0x67, 0x69, 0x63, 0x20, 0x73, 0x65, 0x72, 0x76, - 0x65, 0x72, 0x20, 0x74, 0x6F, 0x20, 0x63, 0x6C, 0x69, 0x65, - 0x6E, 0x74, 0x20, 0x73, 0x69, 0x67, 0x6E, 0x69, 0x6E, 0x67, - 0x20, 0x63, 0x6F, 0x6E, 0x73, 0x74, 0x61, 0x6E, 0x74 - }; - static const u8 magic2[41] = { - 0x50, 0x61, 0x64, 0x20, 0x74, 0x6F, 0x20, 0x6D, 0x61, 0x6B, - 0x65, 0x20, 0x69, 0x74, 0x20, 0x64, 0x6F, 0x20, 0x6D, 0x6F, - 0x72, 0x65, 0x20, 0x74, 0x68, 0x61, 0x6E, 0x20, 0x6F, 0x6E, - 0x65, 0x20, 0x69, 0x74, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6F, - 0x6E - }; - - u8 password_hash_hash[16], challenge[8]; - const unsigned char *addr1[3]; - const size_t len1[3] = { 16, 24, sizeof(magic1) }; - const unsigned char *addr2[3]; - const size_t len2[3] = { SHA1_MAC_LEN, 8, sizeof(magic2) }; - - addr1[0] = password_hash_hash; - addr1[1] = nt_response; - addr1[2] = magic1; - - addr2[0] = response; - addr2[1] = challenge; - addr2[2] = magic2; - - if (hash_nt_password_hash(password_hash, password_hash_hash)) - return -1; - if (sha1_vector(3, addr1, len1, response)) - return -1; - - challenge_hash(peer_challenge, auth_challenge, username, username_len, - challenge); - return sha1_vector(3, addr2, len2, response); -} - - -/** - * generate_authenticator_response - GenerateAuthenticatorResponse() - RFC 2759, Sect. 8.7 - * @password: 0-to-256-unicode-char Password (IN; ASCII) - * @password_len: Length of password - * @nt_response: 24-octet NT-Response (IN) - * @peer_challenge: 16-octet PeerChallenge (IN) - * @auth_challenge: 16-octet AuthenticatorChallenge (IN) - * @username: 0-to-256-char UserName (IN) - * @username_len: Length of username - * @response: 20-octet AuthenticatorResponse (OUT) (note: this value is usually - * encoded as a 42-octet ASCII string (S=hexdump_of_response) - * Returns: 0 on success, -1 on failure - */ -int generate_authenticator_response(const u8 *password, size_t password_len, - const u8 *peer_challenge, - const u8 *auth_challenge, - const u8 *username, size_t username_len, - const u8 *nt_response, u8 *response) -{ - u8 password_hash[16]; - if (nt_password_hash(password, password_len, password_hash)) - return -1; - return generate_authenticator_response_pwhash( - password_hash, peer_challenge, auth_challenge, - username, username_len, nt_response, response); -} - - -/** - * nt_challenge_response - NtChallengeResponse() - RFC 2433, Sect. A.5 - * @challenge: 8-octet Challenge (IN) - * @password: 0-to-256-unicode-char Password (IN; ASCII) - * @password_len: Length of password - * @response: 24-octet Response (OUT) - * Returns: 0 on success, -1 on failure - */ -int nt_challenge_response(const u8 *challenge, const u8 *password, - size_t password_len, u8 *response) -{ - u8 password_hash[16]; - if (nt_password_hash(password, password_len, password_hash)) - return -1; - challenge_response(challenge, password_hash, response); - return 0; -} - - -/** - * get_master_key - GetMasterKey() - RFC 3079, Sect. 3.4 - * @password_hash_hash: 16-octet PasswordHashHash (IN) - * @nt_response: 24-octet NTResponse (IN) - * @master_key: 16-octet MasterKey (OUT) - * Returns: 0 on success, -1 on failure - */ -int get_master_key(const u8 *password_hash_hash, const u8 *nt_response, - u8 *master_key) -{ - static const u8 magic1[27] = { - 0x54, 0x68, 0x69, 0x73, 0x20, 0x69, 0x73, 0x20, 0x74, - 0x68, 0x65, 0x20, 0x4d, 0x50, 0x50, 0x45, 0x20, 0x4d, - 0x61, 0x73, 0x74, 0x65, 0x72, 0x20, 0x4b, 0x65, 0x79 - }; - const unsigned char *addr[3]; - const size_t len[3] = { 16, 24, sizeof(magic1) }; - u8 hash[SHA1_MAC_LEN]; - - addr[0] = password_hash_hash; - addr[1] = nt_response; - addr[2] = magic1; - - if (sha1_vector(3, addr, len, hash)) - return -1; - os_memcpy(master_key, hash, 16); - return 0; -} - - -/** - * get_asymetric_start_key - GetAsymetricStartKey() - RFC 3079, Sect. 3.4 - * @master_key: 16-octet MasterKey (IN) - * @session_key: 8-to-16 octet SessionKey (OUT) - * @session_key_len: SessionKeyLength (Length of session_key) (IN) - * @is_send: IsSend (IN, BOOLEAN) - * @is_server: IsServer (IN, BOOLEAN) - * Returns: 0 on success, -1 on failure - */ -int get_asymetric_start_key(const u8 *master_key, u8 *session_key, - size_t session_key_len, int is_send, - int is_server) -{ - static const u8 magic2[84] = { - 0x4f, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x63, 0x6c, 0x69, - 0x65, 0x6e, 0x74, 0x20, 0x73, 0x69, 0x64, 0x65, 0x2c, 0x20, - 0x74, 0x68, 0x69, 0x73, 0x20, 0x69, 0x73, 0x20, 0x74, 0x68, - 0x65, 0x20, 0x73, 0x65, 0x6e, 0x64, 0x20, 0x6b, 0x65, 0x79, - 0x3b, 0x20, 0x6f, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x73, - 0x65, 0x72, 0x76, 0x65, 0x72, 0x20, 0x73, 0x69, 0x64, 0x65, - 0x2c, 0x20, 0x69, 0x74, 0x20, 0x69, 0x73, 0x20, 0x74, 0x68, - 0x65, 0x20, 0x72, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 0x20, - 0x6b, 0x65, 0x79, 0x2e - }; - static const u8 magic3[84] = { - 0x4f, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x63, 0x6c, 0x69, - 0x65, 0x6e, 0x74, 0x20, 0x73, 0x69, 0x64, 0x65, 0x2c, 0x20, - 0x74, 0x68, 0x69, 0x73, 0x20, 0x69, 0x73, 0x20, 0x74, 0x68, - 0x65, 0x20, 0x72, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 0x20, - 0x6b, 0x65, 0x79, 0x3b, 0x20, 0x6f, 0x6e, 0x20, 0x74, 0x68, - 0x65, 0x20, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x20, 0x73, - 0x69, 0x64, 0x65, 0x2c, 0x20, 0x69, 0x74, 0x20, 0x69, 0x73, - 0x20, 0x74, 0x68, 0x65, 0x20, 0x73, 0x65, 0x6e, 0x64, 0x20, - 0x6b, 0x65, 0x79, 0x2e - }; - static const u8 shs_pad1[40] = { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }; - - static const u8 shs_pad2[40] = { - 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, - 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, - 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, - 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2 - }; - u8 digest[SHA1_MAC_LEN]; - const unsigned char *addr[4]; - const size_t len[4] = { 16, 40, 84, 40 }; - - addr[0] = master_key; - addr[1] = shs_pad1; - if (is_send) { - addr[2] = is_server ? magic3 : magic2; - } else { - addr[2] = is_server ? magic2 : magic3; - } - addr[3] = shs_pad2; - - if (sha1_vector(4, addr, len, digest)) - return -1; - - if (session_key_len > SHA1_MAC_LEN) - session_key_len = SHA1_MAC_LEN; - os_memcpy(session_key, digest, session_key_len); - return 0; -} - - -#define PWBLOCK_LEN 516 - -/** - * encrypt_pw_block_with_password_hash - EncryptPwBlockWithPasswordHash() - RFC 2759, Sect. 8.10 - * @password: 0-to-256-unicode-char Password (IN; ASCII) - * @password_len: Length of password - * @password_hash: 16-octet PasswordHash (IN) - * @pw_block: 516-byte PwBlock (OUT) - * Returns: 0 on success, -1 on failure - */ -int encrypt_pw_block_with_password_hash( - const u8 *password, size_t password_len, - const u8 *password_hash, u8 *pw_block) -{ - size_t i, offset; - u8 *pos; - - if (password_len > 256) - return -1; - - os_memset(pw_block, 0, PWBLOCK_LEN); - offset = (256 - password_len) * 2; - if (os_get_random(pw_block, offset) < 0) - return -1; - for (i = 0; i < password_len; i++) - pw_block[offset + i * 2] = password[i]; - /* - * PasswordLength is 4 octets, but since the maximum password length is - * 256, only first two (in little endian byte order) can be non-zero. - */ - pos = &pw_block[2 * 256]; - WPA_PUT_LE16(pos, password_len * 2); - rc4_skip(password_hash, 16, 0, pw_block, PWBLOCK_LEN); - return 0; -} - - -/** - * new_password_encrypted_with_old_nt_password_hash - NewPasswordEncryptedWithOldNtPasswordHash() - RFC 2759, Sect. 8.9 - * @new_password: 0-to-256-unicode-char NewPassword (IN; ASCII) - * @new_password_len: Length of new_password - * @old_password: 0-to-256-unicode-char OldPassword (IN; ASCII) - * @old_password_len: Length of old_password - * @encrypted_pw_block: 516-octet EncryptedPwBlock (OUT) - * Returns: 0 on success, -1 on failure - */ -int new_password_encrypted_with_old_nt_password_hash( - const u8 *new_password, size_t new_password_len, - const u8 *old_password, size_t old_password_len, - u8 *encrypted_pw_block) -{ - u8 password_hash[16]; - - if (nt_password_hash(old_password, old_password_len, password_hash)) - return -1; - if (encrypt_pw_block_with_password_hash(new_password, new_password_len, - password_hash, - encrypted_pw_block)) - return -1; - return 0; -} - - -/** - * nt_password_hash_encrypted_with_block - NtPasswordHashEncryptedWithBlock() - RFC 2759, Sect 8.13 - * @password_hash: 16-octer PasswordHash (IN) - * @block: 16-octet Block (IN) - * @cypher: 16-octer Cypher (OUT) - */ -void nt_password_hash_encrypted_with_block(const u8 *password_hash, - const u8 *block, u8 *cypher) -{ - des_encrypt(password_hash, block, cypher); - des_encrypt(password_hash + 8, block + 7, cypher + 8); -} - - -/** - * old_nt_password_hash_encrypted_with_new_nt_password_hash - OldNtPasswordHashEncryptedWithNewNtPasswordHash() - RFC 2759, Sect. 8.12 - * @new_password: 0-to-256-unicode-char NewPassword (IN; ASCII) - * @new_password_len: Length of new_password - * @old_password: 0-to-256-unicode-char OldPassword (IN; ASCII) - * @old_password_len: Length of old_password - * @encrypted_password_hash: 16-octet EncryptedPasswordHash (OUT) - * Returns: 0 on success, -1 on failure - */ -int old_nt_password_hash_encrypted_with_new_nt_password_hash( - const u8 *new_password, size_t new_password_len, - const u8 *old_password, size_t old_password_len, - u8 *encrypted_password_hash) -{ - u8 old_password_hash[16], new_password_hash[16]; - - if (nt_password_hash(old_password, old_password_len, - old_password_hash) || - nt_password_hash(new_password, new_password_len, - new_password_hash)) - return -1; - nt_password_hash_encrypted_with_block(old_password_hash, - new_password_hash, - encrypted_password_hash); - return 0; -} diff --git a/hostapd-0.8/src/crypto/ms_funcs.h b/hostapd-0.8/src/crypto/ms_funcs.h deleted file mode 100644 index 298dbcf..0000000 --- a/hostapd-0.8/src/crypto/ms_funcs.h +++ /dev/null @@ -1,64 +0,0 @@ -/* - * WPA Supplicant / shared MSCHAPV2 helper functions / RFC 2433 / RFC 2759 - * Copyright (c) 2004-2009, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#ifndef MS_FUNCS_H -#define MS_FUNCS_H - -int generate_nt_response(const u8 *auth_challenge, const u8 *peer_challenge, - const u8 *username, size_t username_len, - const u8 *password, size_t password_len, - u8 *response); -int generate_nt_response_pwhash(const u8 *auth_challenge, - const u8 *peer_challenge, - const u8 *username, size_t username_len, - const u8 *password_hash, - u8 *response); -int generate_authenticator_response(const u8 *password, size_t password_len, - const u8 *peer_challenge, - const u8 *auth_challenge, - const u8 *username, size_t username_len, - const u8 *nt_response, u8 *response); -int generate_authenticator_response_pwhash( - const u8 *password_hash, - const u8 *peer_challenge, const u8 *auth_challenge, - const u8 *username, size_t username_len, - const u8 *nt_response, u8 *response); -int nt_challenge_response(const u8 *challenge, const u8 *password, - size_t password_len, u8 *response); - -void challenge_response(const u8 *challenge, const u8 *password_hash, - u8 *response); -int nt_password_hash(const u8 *password, size_t password_len, - u8 *password_hash); -int hash_nt_password_hash(const u8 *password_hash, u8 *password_hash_hash); -int get_master_key(const u8 *password_hash_hash, const u8 *nt_response, - u8 *master_key); -int get_asymetric_start_key(const u8 *master_key, u8 *session_key, - size_t session_key_len, int is_send, - int is_server); -int __must_check encrypt_pw_block_with_password_hash( - const u8 *password, size_t password_len, - const u8 *password_hash, u8 *pw_block); -int __must_check new_password_encrypted_with_old_nt_password_hash( - const u8 *new_password, size_t new_password_len, - const u8 *old_password, size_t old_password_len, - u8 *encrypted_pw_block); -void nt_password_hash_encrypted_with_block(const u8 *password_hash, - const u8 *block, u8 *cypher); -int old_nt_password_hash_encrypted_with_new_nt_password_hash( - const u8 *new_password, size_t new_password_len, - const u8 *old_password, size_t old_password_len, - u8 *encrypted_password_hash); - -#endif /* MS_FUNCS_H */ diff --git a/hostapd-0.8/src/crypto/random.c b/hostapd-0.8/src/crypto/random.c deleted file mode 100644 index a30afde..0000000 --- a/hostapd-0.8/src/crypto/random.c +++ /dev/null @@ -1,337 +0,0 @@ -/* - * Random number generator - * Copyright (c) 2010-2011, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - * - * This random number generator is used to provide additional entropy to the - * one provided by the operating system (os_get_random()) for session key - * generation. The os_get_random() output is expected to be secure and the - * implementation here is expected to provide only limited protection against - * cases where os_get_random() cannot provide strong randomness. This - * implementation shall not be assumed to be secure as the sole source of - * randomness. The random_get_bytes() function mixes in randomness from - * os_get_random() and as such, calls to os_get_random() can be replaced with - * calls to random_get_bytes() without reducing security. - * - * The design here follows partially the design used in the Linux - * drivers/char/random.c, but the implementation here is simpler and not as - * strong. This is a compromise to reduce duplicated CPU effort and to avoid - * extra code/memory size. As pointed out above, os_get_random() needs to be - * guaranteed to be secure for any of the security assumptions to hold. - */ - -#include "utils/includes.h" -#ifdef __linux__ -#include -#endif /* __linux__ */ - -#include "utils/common.h" -#include "utils/eloop.h" -#include "sha1.h" -#include "random.h" - -#define POOL_WORDS 32 -#define POOL_WORDS_MASK (POOL_WORDS - 1) -#define POOL_TAP1 26 -#define POOL_TAP2 20 -#define POOL_TAP3 14 -#define POOL_TAP4 7 -#define POOL_TAP5 1 -#define EXTRACT_LEN 16 -#define MIN_READY_MARK 2 - -static u32 pool[POOL_WORDS]; -static unsigned int input_rotate = 0; -static unsigned int pool_pos = 0; -static u8 dummy_key[20]; -#ifdef __linux__ -static size_t dummy_key_avail = 0; -static int random_fd = -1; -#endif /* __linux__ */ -static unsigned int own_pool_ready = 0; - -#define MIN_COLLECT_ENTROPY 1000 -static unsigned int entropy = 0; -static unsigned int total_collected = 0; - - -static u32 __ROL32(u32 x, u32 y) -{ - return (x << (y & 31)) | (x >> (32 - (y & 31))); -} - - -static void random_mix_pool(const void *buf, size_t len) -{ - static const u32 twist[8] = { - 0x00000000, 0x3b6e20c8, 0x76dc4190, 0x4db26158, - 0xedb88320, 0xd6d6a3e8, 0x9b64c2b0, 0xa00ae278 - }; - const u8 *pos = buf; - u32 w; - - wpa_hexdump_key(MSG_EXCESSIVE, "random_mix_pool", buf, len); - - while (len--) { - w = __ROL32(*pos++, input_rotate & 31); - input_rotate += pool_pos ? 7 : 14; - pool_pos = (pool_pos - 1) & POOL_WORDS_MASK; - w ^= pool[pool_pos]; - w ^= pool[(pool_pos + POOL_TAP1) & POOL_WORDS_MASK]; - w ^= pool[(pool_pos + POOL_TAP2) & POOL_WORDS_MASK]; - w ^= pool[(pool_pos + POOL_TAP3) & POOL_WORDS_MASK]; - w ^= pool[(pool_pos + POOL_TAP4) & POOL_WORDS_MASK]; - w ^= pool[(pool_pos + POOL_TAP5) & POOL_WORDS_MASK]; - pool[pool_pos] = (w >> 3) ^ twist[w & 7]; - } -} - - -static void random_extract(u8 *out) -{ - unsigned int i; - u8 hash[SHA1_MAC_LEN]; - u32 *hash_ptr; - u32 buf[POOL_WORDS / 2]; - - /* First, add hash back to pool to make backtracking more difficult. */ - hmac_sha1(dummy_key, sizeof(dummy_key), (const u8 *) pool, - sizeof(pool), hash); - random_mix_pool(hash, sizeof(hash)); - /* Hash half the pool to extra data */ - for (i = 0; i < POOL_WORDS / 2; i++) - buf[i] = pool[(pool_pos - i) & POOL_WORDS_MASK]; - hmac_sha1(dummy_key, sizeof(dummy_key), (const u8 *) buf, - sizeof(buf), hash); - /* - * Fold the hash to further reduce any potential output pattern. - * Though, compromise this to reduce CPU use for the most common output - * length (32) and return 16 bytes from instead of only half. - */ - hash_ptr = (u32 *) hash; - hash_ptr[0] ^= hash_ptr[4]; - os_memcpy(out, hash, EXTRACT_LEN); -} - - -void random_add_randomness(const void *buf, size_t len) -{ - struct os_time t; - static unsigned int count = 0; - - count++; - wpa_printf(MSG_MSGDUMP, "Add randomness: count=%u entropy=%u", - count, entropy); - if (entropy > MIN_COLLECT_ENTROPY && (count & 0x3ff) != 0) { - /* - * No need to add more entropy at this point, so save CPU and - * skip the update. - */ - return; - } - - os_get_time(&t); - wpa_hexdump_key(MSG_EXCESSIVE, "random pool", - (const u8 *) pool, sizeof(pool)); - random_mix_pool(&t, sizeof(t)); - random_mix_pool(buf, len); - wpa_hexdump_key(MSG_EXCESSIVE, "random pool", - (const u8 *) pool, sizeof(pool)); - entropy++; - total_collected++; -} - - -int random_get_bytes(void *buf, size_t len) -{ - int ret; - u8 *bytes = buf; - size_t left; - - wpa_printf(MSG_MSGDUMP, "Get randomness: len=%u entropy=%u", - (unsigned int) len, entropy); - - /* Start with assumed strong randomness from OS */ - ret = os_get_random(buf, len); - wpa_hexdump_key(MSG_EXCESSIVE, "random from os_get_random", - buf, len); - - /* Mix in additional entropy extracted from the internal pool */ - left = len; - while (left) { - size_t siz, i; - u8 tmp[EXTRACT_LEN]; - random_extract(tmp); - wpa_hexdump_key(MSG_EXCESSIVE, "random from internal pool", - tmp, sizeof(tmp)); - siz = left > EXTRACT_LEN ? EXTRACT_LEN : left; - for (i = 0; i < siz; i++) - *bytes++ ^= tmp[i]; - left -= siz; - } - wpa_hexdump_key(MSG_EXCESSIVE, "mixed random", buf, len); - - if (entropy < len) - entropy = 0; - else - entropy -= len; - - return ret; -} - - -int random_pool_ready(void) -{ -#ifdef __linux__ - int fd; - ssize_t res; - - /* - * Make sure that there is reasonable entropy available before allowing - * some key derivation operations to proceed. - */ - - if (dummy_key_avail == sizeof(dummy_key)) - return 1; /* Already initialized - good to continue */ - - /* - * Try to fetch some more data from the kernel high quality - * /dev/random. There may not be enough data available at this point, - * so use non-blocking read to avoid blocking the application - * completely. - */ - fd = open("/dev/random", O_RDONLY | O_NONBLOCK); - if (fd < 0) { -#ifndef CONFIG_NO_STDOUT_DEBUG - int error = errno; - perror("open(/dev/random)"); - wpa_printf(MSG_ERROR, "random: Cannot open /dev/random: %s", - strerror(error)); -#endif /* CONFIG_NO_STDOUT_DEBUG */ - return -1; - } - - res = read(fd, dummy_key + dummy_key_avail, - sizeof(dummy_key) - dummy_key_avail); - if (res < 0) { - wpa_printf(MSG_ERROR, "random: Cannot read from /dev/random: " - "%s", strerror(errno)); - res = 0; - } - wpa_printf(MSG_DEBUG, "random: Got %u/%u bytes from " - "/dev/random", (unsigned) res, - (unsigned) (sizeof(dummy_key) - dummy_key_avail)); - dummy_key_avail += res; - close(fd); - - if (dummy_key_avail == sizeof(dummy_key)) - return 1; - - wpa_printf(MSG_INFO, "random: Only %u/%u bytes of strong " - "random data available from /dev/random", - (unsigned) dummy_key_avail, (unsigned) sizeof(dummy_key)); - - if (own_pool_ready >= MIN_READY_MARK || - total_collected + 10 * own_pool_ready > MIN_COLLECT_ENTROPY) { - wpa_printf(MSG_INFO, "random: Allow operation to proceed " - "based on internal entropy"); - return 1; - } - - wpa_printf(MSG_INFO, "random: Not enough entropy pool available for " - "secure operations"); - return 0; -#else /* __linux__ */ - /* TODO: could do similar checks on non-Linux platforms */ - return 1; -#endif /* __linux__ */ -} - - -void random_mark_pool_ready(void) -{ - own_pool_ready++; - wpa_printf(MSG_DEBUG, "random: Mark internal entropy pool to be " - "ready (count=%u/%u)", own_pool_ready, MIN_READY_MARK); -} - - -#ifdef __linux__ - -static void random_close_fd(void) -{ - if (random_fd >= 0) { - eloop_unregister_read_sock(random_fd); - close(random_fd); - random_fd = -1; - } -} - - -static void random_read_fd(int sock, void *eloop_ctx, void *sock_ctx) -{ - ssize_t res; - - if (dummy_key_avail == sizeof(dummy_key)) { - random_close_fd(); - return; - } - - res = read(sock, dummy_key + dummy_key_avail, - sizeof(dummy_key) - dummy_key_avail); - if (res < 0) { - wpa_printf(MSG_ERROR, "random: Cannot read from /dev/random: " - "%s", strerror(errno)); - return; - } - - wpa_printf(MSG_DEBUG, "random: Got %u/%u bytes from /dev/random", - (unsigned) res, - (unsigned) (sizeof(dummy_key) - dummy_key_avail)); - dummy_key_avail += res; - - if (dummy_key_avail == sizeof(dummy_key)) - random_close_fd(); -} - -#endif /* __linux__ */ - - -void random_init(void) -{ -#ifdef __linux__ - if (random_fd >= 0) - return; - - random_fd = open("/dev/random", O_RDONLY | O_NONBLOCK); - if (random_fd < 0) { -#ifndef CONFIG_NO_STDOUT_DEBUG - int error = errno; - perror("open(/dev/random)"); - wpa_printf(MSG_ERROR, "random: Cannot open /dev/random: %s", - strerror(error)); -#endif /* CONFIG_NO_STDOUT_DEBUG */ - return; - } - wpa_printf(MSG_DEBUG, "random: Trying to read entropy from " - "/dev/random"); - - eloop_register_read_sock(random_fd, random_read_fd, NULL, NULL); -#endif /* __linux__ */ -} - - -void random_deinit(void) -{ -#ifdef __linux__ - random_close_fd(); -#endif /* __linux__ */ -} diff --git a/hostapd-0.8/src/crypto/random.h b/hostapd-0.8/src/crypto/random.h deleted file mode 100644 index 5dabd2b..0000000 --- a/hostapd-0.8/src/crypto/random.h +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Random number generator - * Copyright (c) 2010-2011, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#ifndef RANDOM_H -#define RANDOM_H - -#ifdef CONFIG_NO_RANDOM_POOL -#define random_init() do { } while (0) -#define random_deinit() do { } while (0) -#define random_add_randomness(b, l) do { } while (0) -#define random_get_bytes(b, l) os_get_random((b), (l)) -#define random_pool_ready() 1 -#define random_mark_pool_ready() do { } while (0) -#else /* CONFIG_NO_RANDOM_POOL */ -void random_init(void); -void random_deinit(void); -void random_add_randomness(const void *buf, size_t len); -int random_get_bytes(void *buf, size_t len); -int random_pool_ready(void); -void random_mark_pool_ready(void); -#endif /* CONFIG_NO_RANDOM_POOL */ - -#endif /* RANDOM_H */ diff --git a/hostapd-0.8/src/crypto/rc4.c b/hostapd-0.8/src/crypto/rc4.c deleted file mode 100644 index 5ab1be1..0000000 --- a/hostapd-0.8/src/crypto/rc4.c +++ /dev/null @@ -1,60 +0,0 @@ -/* - * RC4 stream cipher - * Copyright (c) 2002-2005, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#include "includes.h" - -#include "common.h" -#include "crypto.h" - -#define S_SWAP(a,b) do { u8 t = S[a]; S[a] = S[b]; S[b] = t; } while(0) - -int rc4_skip(const u8 *key, size_t keylen, size_t skip, - u8 *data, size_t data_len) -{ - u32 i, j, k; - u8 S[256], *pos; - size_t kpos; - - /* Setup RC4 state */ - for (i = 0; i < 256; i++) - S[i] = i; - j = 0; - kpos = 0; - for (i = 0; i < 256; i++) { - j = (j + S[i] + key[kpos]) & 0xff; - kpos++; - if (kpos >= keylen) - kpos = 0; - S_SWAP(i, j); - } - - /* Skip the start of the stream */ - i = j = 0; - for (k = 0; k < skip; k++) { - i = (i + 1) & 0xff; - j = (j + S[i]) & 0xff; - S_SWAP(i, j); - } - - /* Apply RC4 to data */ - pos = data; - for (k = 0; k < data_len; k++) { - i = (i + 1) & 0xff; - j = (j + S[i]) & 0xff; - S_SWAP(i, j); - *pos++ ^= S[(S[i] + S[j]) & 0xff]; - } - - return 0; -} diff --git a/hostapd-0.8/src/crypto/sha1-internal.c b/hostapd-0.8/src/crypto/sha1-internal.c deleted file mode 100644 index 3f05ca1..0000000 --- a/hostapd-0.8/src/crypto/sha1-internal.c +++ /dev/null @@ -1,308 +0,0 @@ -/* - * SHA1 hash implementation and interface functions - * Copyright (c) 2003-2005, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#include "includes.h" - -#include "common.h" -#include "sha1.h" -#include "sha1_i.h" -#include "md5.h" -#include "crypto.h" - -typedef struct SHA1Context SHA1_CTX; - -void SHA1Transform(u32 state[5], const unsigned char buffer[64]); - - -/** - * sha1_vector - SHA-1 hash for data vector - * @num_elem: Number of elements in the data vector - * @addr: Pointers to the data areas - * @len: Lengths of the data blocks - * @mac: Buffer for the hash - * Returns: 0 on success, -1 of failure - */ -int sha1_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac) -{ - SHA1_CTX ctx; - size_t i; - - SHA1Init(&ctx); - for (i = 0; i < num_elem; i++) - SHA1Update(&ctx, addr[i], len[i]); - SHA1Final(mac, &ctx); - return 0; -} - - -/* ===== start - public domain SHA1 implementation ===== */ - -/* -SHA-1 in C -By Steve Reid -100% Public Domain - ------------------ -Modified 7/98 -By James H. Brown -Still 100% Public Domain - -Corrected a problem which generated improper hash values on 16 bit machines -Routine SHA1Update changed from - void SHA1Update(SHA1_CTX* context, unsigned char* data, unsigned int -len) -to - void SHA1Update(SHA1_CTX* context, unsigned char* data, unsigned -long len) - -The 'len' parameter was declared an int which works fine on 32 bit machines. -However, on 16 bit machines an int is too small for the shifts being done -against -it. This caused the hash function to generate incorrect values if len was -greater than 8191 (8K - 1) due to the 'len << 3' on line 3 of SHA1Update(). - -Since the file IO in main() reads 16K at a time, any file 8K or larger would -be guaranteed to generate the wrong hash (e.g. Test Vector #3, a million -"a"s). - -I also changed the declaration of variables i & j in SHA1Update to -unsigned long from unsigned int for the same reason. - -These changes should make no difference to any 32 bit implementations since -an -int and a long are the same size in those environments. - --- -I also corrected a few compiler warnings generated by Borland C. -1. Added #include for exit() prototype -2. Removed unused variable 'j' in SHA1Final -3. Changed exit(0) to return(0) at end of main. - -ALL changes I made can be located by searching for comments containing 'JHB' ------------------ -Modified 8/98 -By Steve Reid -Still 100% public domain - -1- Removed #include and used return() instead of exit() -2- Fixed overwriting of finalcount in SHA1Final() (discovered by Chris Hall) -3- Changed email address from steve@edmweb.com to sreid@sea-to-sky.net - ------------------ -Modified 4/01 -By Saul Kravitz -Still 100% PD -Modified to run on Compaq Alpha hardware. - ------------------ -Modified 4/01 -By Jouni Malinen -Minor changes to match the coding style used in Dynamics. - -Modified September 24, 2004 -By Jouni Malinen -Fixed alignment issue in SHA1Transform when SHA1HANDSOFF is defined. - -*/ - -/* -Test Vectors (from FIPS PUB 180-1) -"abc" - A9993E36 4706816A BA3E2571 7850C26C 9CD0D89D -"abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq" - 84983E44 1C3BD26E BAAE4AA1 F95129E5 E54670F1 -A million repetitions of "a" - 34AA973C D4C4DAA4 F61EEB2B DBAD2731 6534016F -*/ - -#define SHA1HANDSOFF - -#define rol(value, bits) (((value) << (bits)) | ((value) >> (32 - (bits)))) - -/* blk0() and blk() perform the initial expand. */ -/* I got the idea of expanding during the round function from SSLeay */ -#ifndef WORDS_BIGENDIAN -#define blk0(i) (block->l[i] = (rol(block->l[i], 24) & 0xFF00FF00) | \ - (rol(block->l[i], 8) & 0x00FF00FF)) -#else -#define blk0(i) block->l[i] -#endif -#define blk(i) (block->l[i & 15] = rol(block->l[(i + 13) & 15] ^ \ - block->l[(i + 8) & 15] ^ block->l[(i + 2) & 15] ^ block->l[i & 15], 1)) - -/* (R0+R1), R2, R3, R4 are the different operations used in SHA1 */ -#define R0(v,w,x,y,z,i) \ - z += ((w & (x ^ y)) ^ y) + blk0(i) + 0x5A827999 + rol(v, 5); \ - w = rol(w, 30); -#define R1(v,w,x,y,z,i) \ - z += ((w & (x ^ y)) ^ y) + blk(i) + 0x5A827999 + rol(v, 5); \ - w = rol(w, 30); -#define R2(v,w,x,y,z,i) \ - z += (w ^ x ^ y) + blk(i) + 0x6ED9EBA1 + rol(v, 5); w = rol(w, 30); -#define R3(v,w,x,y,z,i) \ - z += (((w | x) & y) | (w & x)) + blk(i) + 0x8F1BBCDC + rol(v, 5); \ - w = rol(w, 30); -#define R4(v,w,x,y,z,i) \ - z += (w ^ x ^ y) + blk(i) + 0xCA62C1D6 + rol(v, 5); \ - w=rol(w, 30); - - -#ifdef VERBOSE /* SAK */ -void SHAPrintContext(SHA1_CTX *context, char *msg) -{ - printf("%s (%d,%d) %x %x %x %x %x\n", - msg, - context->count[0], context->count[1], - context->state[0], - context->state[1], - context->state[2], - context->state[3], - context->state[4]); -} -#endif - -/* Hash a single 512-bit block. This is the core of the algorithm. */ - -void SHA1Transform(u32 state[5], const unsigned char buffer[64]) -{ - u32 a, b, c, d, e; - typedef union { - unsigned char c[64]; - u32 l[16]; - } CHAR64LONG16; - CHAR64LONG16* block; -#ifdef SHA1HANDSOFF - CHAR64LONG16 workspace; - block = &workspace; - os_memcpy(block, buffer, 64); -#else - block = (CHAR64LONG16 *) buffer; -#endif - /* Copy context->state[] to working vars */ - a = state[0]; - b = state[1]; - c = state[2]; - d = state[3]; - e = state[4]; - /* 4 rounds of 20 operations each. Loop unrolled. */ - R0(a,b,c,d,e, 0); R0(e,a,b,c,d, 1); R0(d,e,a,b,c, 2); R0(c,d,e,a,b, 3); - R0(b,c,d,e,a, 4); R0(a,b,c,d,e, 5); R0(e,a,b,c,d, 6); R0(d,e,a,b,c, 7); - R0(c,d,e,a,b, 8); R0(b,c,d,e,a, 9); R0(a,b,c,d,e,10); R0(e,a,b,c,d,11); - R0(d,e,a,b,c,12); R0(c,d,e,a,b,13); R0(b,c,d,e,a,14); R0(a,b,c,d,e,15); - R1(e,a,b,c,d,16); R1(d,e,a,b,c,17); R1(c,d,e,a,b,18); R1(b,c,d,e,a,19); - R2(a,b,c,d,e,20); R2(e,a,b,c,d,21); R2(d,e,a,b,c,22); R2(c,d,e,a,b,23); - R2(b,c,d,e,a,24); R2(a,b,c,d,e,25); R2(e,a,b,c,d,26); R2(d,e,a,b,c,27); - R2(c,d,e,a,b,28); R2(b,c,d,e,a,29); R2(a,b,c,d,e,30); R2(e,a,b,c,d,31); - R2(d,e,a,b,c,32); R2(c,d,e,a,b,33); R2(b,c,d,e,a,34); R2(a,b,c,d,e,35); - R2(e,a,b,c,d,36); R2(d,e,a,b,c,37); R2(c,d,e,a,b,38); R2(b,c,d,e,a,39); - R3(a,b,c,d,e,40); R3(e,a,b,c,d,41); R3(d,e,a,b,c,42); R3(c,d,e,a,b,43); - R3(b,c,d,e,a,44); R3(a,b,c,d,e,45); R3(e,a,b,c,d,46); R3(d,e,a,b,c,47); - R3(c,d,e,a,b,48); R3(b,c,d,e,a,49); R3(a,b,c,d,e,50); R3(e,a,b,c,d,51); - R3(d,e,a,b,c,52); R3(c,d,e,a,b,53); R3(b,c,d,e,a,54); R3(a,b,c,d,e,55); - R3(e,a,b,c,d,56); R3(d,e,a,b,c,57); R3(c,d,e,a,b,58); R3(b,c,d,e,a,59); - R4(a,b,c,d,e,60); R4(e,a,b,c,d,61); R4(d,e,a,b,c,62); R4(c,d,e,a,b,63); - R4(b,c,d,e,a,64); R4(a,b,c,d,e,65); R4(e,a,b,c,d,66); R4(d,e,a,b,c,67); - R4(c,d,e,a,b,68); R4(b,c,d,e,a,69); R4(a,b,c,d,e,70); R4(e,a,b,c,d,71); - R4(d,e,a,b,c,72); R4(c,d,e,a,b,73); R4(b,c,d,e,a,74); R4(a,b,c,d,e,75); - R4(e,a,b,c,d,76); R4(d,e,a,b,c,77); R4(c,d,e,a,b,78); R4(b,c,d,e,a,79); - /* Add the working vars back into context.state[] */ - state[0] += a; - state[1] += b; - state[2] += c; - state[3] += d; - state[4] += e; - /* Wipe variables */ - a = b = c = d = e = 0; -#ifdef SHA1HANDSOFF - os_memset(block, 0, 64); -#endif -} - - -/* SHA1Init - Initialize new context */ - -void SHA1Init(SHA1_CTX* context) -{ - /* SHA1 initialization constants */ - context->state[0] = 0x67452301; - context->state[1] = 0xEFCDAB89; - context->state[2] = 0x98BADCFE; - context->state[3] = 0x10325476; - context->state[4] = 0xC3D2E1F0; - context->count[0] = context->count[1] = 0; -} - - -/* Run your data through this. */ - -void SHA1Update(SHA1_CTX* context, const void *_data, u32 len) -{ - u32 i, j; - const unsigned char *data = _data; - -#ifdef VERBOSE - SHAPrintContext(context, "before"); -#endif - j = (context->count[0] >> 3) & 63; - if ((context->count[0] += len << 3) < (len << 3)) - context->count[1]++; - context->count[1] += (len >> 29); - if ((j + len) > 63) { - os_memcpy(&context->buffer[j], data, (i = 64-j)); - SHA1Transform(context->state, context->buffer); - for ( ; i + 63 < len; i += 64) { - SHA1Transform(context->state, &data[i]); - } - j = 0; - } - else i = 0; - os_memcpy(&context->buffer[j], &data[i], len - i); -#ifdef VERBOSE - SHAPrintContext(context, "after "); -#endif -} - - -/* Add padding and return the message digest. */ - -void SHA1Final(unsigned char digest[20], SHA1_CTX* context) -{ - u32 i; - unsigned char finalcount[8]; - - for (i = 0; i < 8; i++) { - finalcount[i] = (unsigned char) - ((context->count[(i >= 4 ? 0 : 1)] >> - ((3-(i & 3)) * 8) ) & 255); /* Endian independent */ - } - SHA1Update(context, (unsigned char *) "\200", 1); - while ((context->count[0] & 504) != 448) { - SHA1Update(context, (unsigned char *) "\0", 1); - } - SHA1Update(context, finalcount, 8); /* Should cause a SHA1Transform() - */ - for (i = 0; i < 20; i++) { - digest[i] = (unsigned char) - ((context->state[i >> 2] >> ((3 - (i & 3)) * 8)) & - 255); - } - /* Wipe variables */ - i = 0; - os_memset(context->buffer, 0, 64); - os_memset(context->state, 0, 20); - os_memset(context->count, 0, 8); - os_memset(finalcount, 0, 8); -} - -/* ===== end - public domain SHA1 implementation ===== */ diff --git a/hostapd-0.8/src/crypto/sha1-pbkdf2.c b/hostapd-0.8/src/crypto/sha1-pbkdf2.c deleted file mode 100644 index 11323de..0000000 --- a/hostapd-0.8/src/crypto/sha1-pbkdf2.c +++ /dev/null @@ -1,100 +0,0 @@ -/* - * SHA1-based key derivation function (PBKDF2) for IEEE 802.11i - * Copyright (c) 2003-2005, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#include "includes.h" - -#include "common.h" -#include "sha1.h" -#include "md5.h" -#include "crypto.h" - -static int pbkdf2_sha1_f(const char *passphrase, const char *ssid, - size_t ssid_len, int iterations, unsigned int count, - u8 *digest) -{ - unsigned char tmp[SHA1_MAC_LEN], tmp2[SHA1_MAC_LEN]; - int i, j; - unsigned char count_buf[4]; - const u8 *addr[2]; - size_t len[2]; - size_t passphrase_len = os_strlen(passphrase); - - addr[0] = (u8 *) ssid; - len[0] = ssid_len; - addr[1] = count_buf; - len[1] = 4; - - /* F(P, S, c, i) = U1 xor U2 xor ... Uc - * U1 = PRF(P, S || i) - * U2 = PRF(P, U1) - * Uc = PRF(P, Uc-1) - */ - - count_buf[0] = (count >> 24) & 0xff; - count_buf[1] = (count >> 16) & 0xff; - count_buf[2] = (count >> 8) & 0xff; - count_buf[3] = count & 0xff; - if (hmac_sha1_vector((u8 *) passphrase, passphrase_len, 2, addr, len, - tmp)) - return -1; - os_memcpy(digest, tmp, SHA1_MAC_LEN); - - for (i = 1; i < iterations; i++) { - if (hmac_sha1((u8 *) passphrase, passphrase_len, tmp, - SHA1_MAC_LEN, tmp2)) - return -1; - os_memcpy(tmp, tmp2, SHA1_MAC_LEN); - for (j = 0; j < SHA1_MAC_LEN; j++) - digest[j] ^= tmp2[j]; - } - - return 0; -} - - -/** - * pbkdf2_sha1 - SHA1-based key derivation function (PBKDF2) for IEEE 802.11i - * @passphrase: ASCII passphrase - * @ssid: SSID - * @ssid_len: SSID length in bytes - * @iterations: Number of iterations to run - * @buf: Buffer for the generated key - * @buflen: Length of the buffer in bytes - * Returns: 0 on success, -1 of failure - * - * This function is used to derive PSK for WPA-PSK. For this protocol, - * iterations is set to 4096 and buflen to 32. This function is described in - * IEEE Std 802.11-2004, Clause H.4. The main construction is from PKCS#5 v2.0. - */ -int pbkdf2_sha1(const char *passphrase, const char *ssid, size_t ssid_len, - int iterations, u8 *buf, size_t buflen) -{ - unsigned int count = 0; - unsigned char *pos = buf; - size_t left = buflen, plen; - unsigned char digest[SHA1_MAC_LEN]; - - while (left > 0) { - count++; - if (pbkdf2_sha1_f(passphrase, ssid, ssid_len, iterations, - count, digest)) - return -1; - plen = left > SHA1_MAC_LEN ? SHA1_MAC_LEN : left; - os_memcpy(pos, digest, plen); - pos += plen; - left -= plen; - } - - return 0; -} diff --git a/hostapd-0.8/src/crypto/sha1-tlsprf.c b/hostapd-0.8/src/crypto/sha1-tlsprf.c deleted file mode 100644 index 2c8c029..0000000 --- a/hostapd-0.8/src/crypto/sha1-tlsprf.c +++ /dev/null @@ -1,109 +0,0 @@ -/* - * TLS PRF (SHA1 + MD5) - * Copyright (c) 2003-2005, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#include "includes.h" - -#include "common.h" -#include "sha1.h" -#include "md5.h" -#include "crypto.h" - - -/** - * tls_prf - Pseudo-Random Function for TLS (TLS-PRF, RFC 2246) - * @secret: Key for PRF - * @secret_len: Length of the key in bytes - * @label: A unique label for each purpose of the PRF - * @seed: Seed value to bind into the key - * @seed_len: Length of the seed - * @out: Buffer for the generated pseudo-random key - * @outlen: Number of bytes of key to generate - * Returns: 0 on success, -1 on failure. - * - * This function is used to derive new, cryptographically separate keys from a - * given key in TLS. This PRF is defined in RFC 2246, Chapter 5. - */ -int tls_prf(const u8 *secret, size_t secret_len, const char *label, - const u8 *seed, size_t seed_len, u8 *out, size_t outlen) -{ - size_t L_S1, L_S2, i; - const u8 *S1, *S2; - u8 A_MD5[MD5_MAC_LEN], A_SHA1[SHA1_MAC_LEN]; - u8 P_MD5[MD5_MAC_LEN], P_SHA1[SHA1_MAC_LEN]; - int MD5_pos, SHA1_pos; - const u8 *MD5_addr[3]; - size_t MD5_len[3]; - const unsigned char *SHA1_addr[3]; - size_t SHA1_len[3]; - - if (secret_len & 1) - return -1; - - MD5_addr[0] = A_MD5; - MD5_len[0] = MD5_MAC_LEN; - MD5_addr[1] = (unsigned char *) label; - MD5_len[1] = os_strlen(label); - MD5_addr[2] = seed; - MD5_len[2] = seed_len; - - SHA1_addr[0] = A_SHA1; - SHA1_len[0] = SHA1_MAC_LEN; - SHA1_addr[1] = (unsigned char *) label; - SHA1_len[1] = os_strlen(label); - SHA1_addr[2] = seed; - SHA1_len[2] = seed_len; - - /* RFC 2246, Chapter 5 - * A(0) = seed, A(i) = HMAC(secret, A(i-1)) - * P_hash = HMAC(secret, A(1) + seed) + HMAC(secret, A(2) + seed) + .. - * PRF = P_MD5(S1, label + seed) XOR P_SHA-1(S2, label + seed) - */ - - L_S1 = L_S2 = (secret_len + 1) / 2; - S1 = secret; - S2 = secret + L_S1; - if (secret_len & 1) { - /* The last byte of S1 will be shared with S2 */ - S2--; - } - - hmac_md5_vector_non_fips_allow(S1, L_S1, 2, &MD5_addr[1], &MD5_len[1], - A_MD5); - hmac_sha1_vector(S2, L_S2, 2, &SHA1_addr[1], &SHA1_len[1], A_SHA1); - - MD5_pos = MD5_MAC_LEN; - SHA1_pos = SHA1_MAC_LEN; - for (i = 0; i < outlen; i++) { - if (MD5_pos == MD5_MAC_LEN) { - hmac_md5_vector_non_fips_allow(S1, L_S1, 3, MD5_addr, - MD5_len, P_MD5); - MD5_pos = 0; - hmac_md5_non_fips_allow(S1, L_S1, A_MD5, MD5_MAC_LEN, - A_MD5); - } - if (SHA1_pos == SHA1_MAC_LEN) { - hmac_sha1_vector(S2, L_S2, 3, SHA1_addr, SHA1_len, - P_SHA1); - SHA1_pos = 0; - hmac_sha1(S2, L_S2, A_SHA1, SHA1_MAC_LEN, A_SHA1); - } - - out[i] = P_MD5[MD5_pos] ^ P_SHA1[SHA1_pos]; - - MD5_pos++; - SHA1_pos++; - } - - return 0; -} diff --git a/hostapd-0.8/src/crypto/sha1-tprf.c b/hostapd-0.8/src/crypto/sha1-tprf.c deleted file mode 100644 index 4a80e96..0000000 --- a/hostapd-0.8/src/crypto/sha1-tprf.c +++ /dev/null @@ -1,76 +0,0 @@ -/* - * SHA1 T-PRF for EAP-FAST - * Copyright (c) 2003-2005, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#include "includes.h" - -#include "common.h" -#include "sha1.h" -#include "crypto.h" - -/** - * sha1_t_prf - EAP-FAST Pseudo-Random Function (T-PRF) - * @key: Key for PRF - * @key_len: Length of the key in bytes - * @label: A unique label for each purpose of the PRF - * @seed: Seed value to bind into the key - * @seed_len: Length of the seed - * @buf: Buffer for the generated pseudo-random key - * @buf_len: Number of bytes of key to generate - * Returns: 0 on success, -1 of failure - * - * This function is used to derive new, cryptographically separate keys from a - * given key for EAP-FAST. T-PRF is defined in RFC 4851, Section 5.5. - */ -int sha1_t_prf(const u8 *key, size_t key_len, const char *label, - const u8 *seed, size_t seed_len, u8 *buf, size_t buf_len) -{ - unsigned char counter = 0; - size_t pos, plen; - u8 hash[SHA1_MAC_LEN]; - size_t label_len = os_strlen(label); - u8 output_len[2]; - const unsigned char *addr[5]; - size_t len[5]; - - addr[0] = hash; - len[0] = 0; - addr[1] = (unsigned char *) label; - len[1] = label_len + 1; - addr[2] = seed; - len[2] = seed_len; - addr[3] = output_len; - len[3] = 2; - addr[4] = &counter; - len[4] = 1; - - output_len[0] = (buf_len >> 8) & 0xff; - output_len[1] = buf_len & 0xff; - pos = 0; - while (pos < buf_len) { - counter++; - plen = buf_len - pos; - if (hmac_sha1_vector(key, key_len, 5, addr, len, hash)) - return -1; - if (plen >= SHA1_MAC_LEN) { - os_memcpy(&buf[pos], hash, SHA1_MAC_LEN); - pos += SHA1_MAC_LEN; - } else { - os_memcpy(&buf[pos], hash, plen); - break; - } - len[0] = SHA1_MAC_LEN; - } - - return 0; -} diff --git a/hostapd-0.8/src/crypto/sha1.c b/hostapd-0.8/src/crypto/sha1.c deleted file mode 100644 index fe00bdb..0000000 --- a/hostapd-0.8/src/crypto/sha1.c +++ /dev/null @@ -1,163 +0,0 @@ -/* - * SHA1 hash implementation and interface functions - * Copyright (c) 2003-2005, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#include "includes.h" - -#include "common.h" -#include "sha1.h" -#include "crypto.h" - - -/** - * hmac_sha1_vector - HMAC-SHA1 over data vector (RFC 2104) - * @key: Key for HMAC operations - * @key_len: Length of the key in bytes - * @num_elem: Number of elements in the data vector - * @addr: Pointers to the data areas - * @len: Lengths of the data blocks - * @mac: Buffer for the hash (20 bytes) - * Returns: 0 on success, -1 on failure - */ -int hmac_sha1_vector(const u8 *key, size_t key_len, size_t num_elem, - const u8 *addr[], const size_t *len, u8 *mac) -{ - unsigned char k_pad[64]; /* padding - key XORd with ipad/opad */ - unsigned char tk[20]; - const u8 *_addr[6]; - size_t _len[6], i; - - if (num_elem > 5) { - /* - * Fixed limit on the number of fragments to avoid having to - * allocate memory (which could fail). - */ - return -1; - } - - /* if key is longer than 64 bytes reset it to key = SHA1(key) */ - if (key_len > 64) { - if (sha1_vector(1, &key, &key_len, tk)) - return -1; - key = tk; - key_len = 20; - } - - /* the HMAC_SHA1 transform looks like: - * - * SHA1(K XOR opad, SHA1(K XOR ipad, text)) - * - * where K is an n byte key - * ipad is the byte 0x36 repeated 64 times - * opad is the byte 0x5c repeated 64 times - * and text is the data being protected */ - - /* start out by storing key in ipad */ - os_memset(k_pad, 0, sizeof(k_pad)); - os_memcpy(k_pad, key, key_len); - /* XOR key with ipad values */ - for (i = 0; i < 64; i++) - k_pad[i] ^= 0x36; - - /* perform inner SHA1 */ - _addr[0] = k_pad; - _len[0] = 64; - for (i = 0; i < num_elem; i++) { - _addr[i + 1] = addr[i]; - _len[i + 1] = len[i]; - } - if (sha1_vector(1 + num_elem, _addr, _len, mac)) - return -1; - - os_memset(k_pad, 0, sizeof(k_pad)); - os_memcpy(k_pad, key, key_len); - /* XOR key with opad values */ - for (i = 0; i < 64; i++) - k_pad[i] ^= 0x5c; - - /* perform outer SHA1 */ - _addr[0] = k_pad; - _len[0] = 64; - _addr[1] = mac; - _len[1] = SHA1_MAC_LEN; - return sha1_vector(2, _addr, _len, mac); -} - - -/** - * hmac_sha1 - HMAC-SHA1 over data buffer (RFC 2104) - * @key: Key for HMAC operations - * @key_len: Length of the key in bytes - * @data: Pointers to the data area - * @data_len: Length of the data area - * @mac: Buffer for the hash (20 bytes) - * Returns: 0 on success, -1 of failure - */ -int hmac_sha1(const u8 *key, size_t key_len, const u8 *data, size_t data_len, - u8 *mac) -{ - return hmac_sha1_vector(key, key_len, 1, &data, &data_len, mac); -} - - -/** - * sha1_prf - SHA1-based Pseudo-Random Function (PRF) (IEEE 802.11i, 8.5.1.1) - * @key: Key for PRF - * @key_len: Length of the key in bytes - * @label: A unique label for each purpose of the PRF - * @data: Extra data to bind into the key - * @data_len: Length of the data - * @buf: Buffer for the generated pseudo-random key - * @buf_len: Number of bytes of key to generate - * Returns: 0 on success, -1 of failure - * - * This function is used to derive new, cryptographically separate keys from a - * given key (e.g., PMK in IEEE 802.11i). - */ -int sha1_prf(const u8 *key, size_t key_len, const char *label, - const u8 *data, size_t data_len, u8 *buf, size_t buf_len) -{ - u8 counter = 0; - size_t pos, plen; - u8 hash[SHA1_MAC_LEN]; - size_t label_len = os_strlen(label) + 1; - const unsigned char *addr[3]; - size_t len[3]; - - addr[0] = (u8 *) label; - len[0] = label_len; - addr[1] = data; - len[1] = data_len; - addr[2] = &counter; - len[2] = 1; - - pos = 0; - while (pos < buf_len) { - plen = buf_len - pos; - if (plen >= SHA1_MAC_LEN) { - if (hmac_sha1_vector(key, key_len, 3, addr, len, - &buf[pos])) - return -1; - pos += SHA1_MAC_LEN; - } else { - if (hmac_sha1_vector(key, key_len, 3, addr, len, - hash)) - return -1; - os_memcpy(&buf[pos], hash, plen); - break; - } - counter++; - } - - return 0; -} diff --git a/hostapd-0.8/src/crypto/sha1.h b/hostapd-0.8/src/crypto/sha1.h deleted file mode 100644 index c1a6233..0000000 --- a/hostapd-0.8/src/crypto/sha1.h +++ /dev/null @@ -1,33 +0,0 @@ -/* - * SHA1 hash implementation and interface functions - * Copyright (c) 2003-2009, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#ifndef SHA1_H -#define SHA1_H - -#define SHA1_MAC_LEN 20 - -int hmac_sha1_vector(const u8 *key, size_t key_len, size_t num_elem, - const u8 *addr[], const size_t *len, u8 *mac); -int hmac_sha1(const u8 *key, size_t key_len, const u8 *data, size_t data_len, - u8 *mac); -int sha1_prf(const u8 *key, size_t key_len, const char *label, - const u8 *data, size_t data_len, u8 *buf, size_t buf_len); -int sha1_t_prf(const u8 *key, size_t key_len, const char *label, - const u8 *seed, size_t seed_len, u8 *buf, size_t buf_len); -int __must_check tls_prf(const u8 *secret, size_t secret_len, - const char *label, const u8 *seed, size_t seed_len, - u8 *out, size_t outlen); -int pbkdf2_sha1(const char *passphrase, const char *ssid, size_t ssid_len, - int iterations, u8 *buf, size_t buflen); -#endif /* SHA1_H */ diff --git a/hostapd-0.8/src/crypto/sha1_i.h b/hostapd-0.8/src/crypto/sha1_i.h deleted file mode 100644 index ec2f82f..0000000 --- a/hostapd-0.8/src/crypto/sha1_i.h +++ /dev/null @@ -1,29 +0,0 @@ -/* - * SHA1 internal definitions - * Copyright (c) 2003-2005, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#ifndef SHA1_I_H -#define SHA1_I_H - -struct SHA1Context { - u32 state[5]; - u32 count[2]; - unsigned char buffer[64]; -}; - -void SHA1Init(struct SHA1Context *context); -void SHA1Update(struct SHA1Context *context, const void *data, u32 len); -void SHA1Final(unsigned char digest[20], struct SHA1Context *context); -void SHA1Transform(u32 state[5], const unsigned char buffer[64]); - -#endif /* SHA1_I_H */ diff --git a/hostapd-0.8/src/crypto/sha256-internal.c b/hostapd-0.8/src/crypto/sha256-internal.c deleted file mode 100644 index b061373..0000000 --- a/hostapd-0.8/src/crypto/sha256-internal.c +++ /dev/null @@ -1,243 +0,0 @@ -/* - * SHA-256 hash implementation and interface functions - * Copyright (c) 2003-2007, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#include "includes.h" - -#include "common.h" -#include "sha256.h" -#include "crypto.h" - -struct sha256_state { - u64 length; - u32 state[8], curlen; - u8 buf[64]; -}; - -static void sha256_init(struct sha256_state *md); -static int sha256_process(struct sha256_state *md, const unsigned char *in, - unsigned long inlen); -static int sha256_done(struct sha256_state *md, unsigned char *out); - - -/** - * sha256_vector - SHA256 hash for data vector - * @num_elem: Number of elements in the data vector - * @addr: Pointers to the data areas - * @len: Lengths of the data blocks - * @mac: Buffer for the hash - * Returns: 0 on success, -1 of failure - */ -int sha256_vector(size_t num_elem, const u8 *addr[], const size_t *len, - u8 *mac) -{ - struct sha256_state ctx; - size_t i; - - sha256_init(&ctx); - for (i = 0; i < num_elem; i++) - if (sha256_process(&ctx, addr[i], len[i])) - return -1; - if (sha256_done(&ctx, mac)) - return -1; - return 0; -} - - -/* ===== start - public domain SHA256 implementation ===== */ - -/* This is based on SHA256 implementation in LibTomCrypt that was released into - * public domain by Tom St Denis. */ - -/* the K array */ -static const unsigned long K[64] = { - 0x428a2f98UL, 0x71374491UL, 0xb5c0fbcfUL, 0xe9b5dba5UL, 0x3956c25bUL, - 0x59f111f1UL, 0x923f82a4UL, 0xab1c5ed5UL, 0xd807aa98UL, 0x12835b01UL, - 0x243185beUL, 0x550c7dc3UL, 0x72be5d74UL, 0x80deb1feUL, 0x9bdc06a7UL, - 0xc19bf174UL, 0xe49b69c1UL, 0xefbe4786UL, 0x0fc19dc6UL, 0x240ca1ccUL, - 0x2de92c6fUL, 0x4a7484aaUL, 0x5cb0a9dcUL, 0x76f988daUL, 0x983e5152UL, - 0xa831c66dUL, 0xb00327c8UL, 0xbf597fc7UL, 0xc6e00bf3UL, 0xd5a79147UL, - 0x06ca6351UL, 0x14292967UL, 0x27b70a85UL, 0x2e1b2138UL, 0x4d2c6dfcUL, - 0x53380d13UL, 0x650a7354UL, 0x766a0abbUL, 0x81c2c92eUL, 0x92722c85UL, - 0xa2bfe8a1UL, 0xa81a664bUL, 0xc24b8b70UL, 0xc76c51a3UL, 0xd192e819UL, - 0xd6990624UL, 0xf40e3585UL, 0x106aa070UL, 0x19a4c116UL, 0x1e376c08UL, - 0x2748774cUL, 0x34b0bcb5UL, 0x391c0cb3UL, 0x4ed8aa4aUL, 0x5b9cca4fUL, - 0x682e6ff3UL, 0x748f82eeUL, 0x78a5636fUL, 0x84c87814UL, 0x8cc70208UL, - 0x90befffaUL, 0xa4506cebUL, 0xbef9a3f7UL, 0xc67178f2UL -}; - - -/* Various logical functions */ -#define RORc(x, y) \ -( ((((unsigned long) (x) & 0xFFFFFFFFUL) >> (unsigned long) ((y) & 31)) | \ - ((unsigned long) (x) << (unsigned long) (32 - ((y) & 31)))) & 0xFFFFFFFFUL) -#define Ch(x,y,z) (z ^ (x & (y ^ z))) -#define Maj(x,y,z) (((x | y) & z) | (x & y)) -#define S(x, n) RORc((x), (n)) -#define R(x, n) (((x)&0xFFFFFFFFUL)>>(n)) -#define Sigma0(x) (S(x, 2) ^ S(x, 13) ^ S(x, 22)) -#define Sigma1(x) (S(x, 6) ^ S(x, 11) ^ S(x, 25)) -#define Gamma0(x) (S(x, 7) ^ S(x, 18) ^ R(x, 3)) -#define Gamma1(x) (S(x, 17) ^ S(x, 19) ^ R(x, 10)) -#ifndef MIN -#define MIN(x, y) (((x) < (y)) ? (x) : (y)) -#endif - -/* compress 512-bits */ -static int sha256_compress(struct sha256_state *md, unsigned char *buf) -{ - u32 S[8], W[64], t0, t1; - u32 t; - int i; - - /* copy state into S */ - for (i = 0; i < 8; i++) { - S[i] = md->state[i]; - } - - /* copy the state into 512-bits into W[0..15] */ - for (i = 0; i < 16; i++) - W[i] = WPA_GET_BE32(buf + (4 * i)); - - /* fill W[16..63] */ - for (i = 16; i < 64; i++) { - W[i] = Gamma1(W[i - 2]) + W[i - 7] + Gamma0(W[i - 15]) + - W[i - 16]; - } - - /* Compress */ -#define RND(a,b,c,d,e,f,g,h,i) \ - t0 = h + Sigma1(e) + Ch(e, f, g) + K[i] + W[i]; \ - t1 = Sigma0(a) + Maj(a, b, c); \ - d += t0; \ - h = t0 + t1; - - for (i = 0; i < 64; ++i) { - RND(S[0], S[1], S[2], S[3], S[4], S[5], S[6], S[7], i); - t = S[7]; S[7] = S[6]; S[6] = S[5]; S[5] = S[4]; - S[4] = S[3]; S[3] = S[2]; S[2] = S[1]; S[1] = S[0]; S[0] = t; - } - - /* feedback */ - for (i = 0; i < 8; i++) { - md->state[i] = md->state[i] + S[i]; - } - return 0; -} - - -/* Initialize the hash state */ -static void sha256_init(struct sha256_state *md) -{ - md->curlen = 0; - md->length = 0; - md->state[0] = 0x6A09E667UL; - md->state[1] = 0xBB67AE85UL; - md->state[2] = 0x3C6EF372UL; - md->state[3] = 0xA54FF53AUL; - md->state[4] = 0x510E527FUL; - md->state[5] = 0x9B05688CUL; - md->state[6] = 0x1F83D9ABUL; - md->state[7] = 0x5BE0CD19UL; -} - -/** - Process a block of memory though the hash - @param md The hash state - @param in The data to hash - @param inlen The length of the data (octets) - @return CRYPT_OK if successful -*/ -static int sha256_process(struct sha256_state *md, const unsigned char *in, - unsigned long inlen) -{ - unsigned long n; -#define block_size 64 - - if (md->curlen > sizeof(md->buf)) - return -1; - - while (inlen > 0) { - if (md->curlen == 0 && inlen >= block_size) { - if (sha256_compress(md, (unsigned char *) in) < 0) - return -1; - md->length += block_size * 8; - in += block_size; - inlen -= block_size; - } else { - n = MIN(inlen, (block_size - md->curlen)); - os_memcpy(md->buf + md->curlen, in, n); - md->curlen += n; - in += n; - inlen -= n; - if (md->curlen == block_size) { - if (sha256_compress(md, md->buf) < 0) - return -1; - md->length += 8 * block_size; - md->curlen = 0; - } - } - } - - return 0; -} - - -/** - Terminate the hash to get the digest - @param md The hash state - @param out [out] The destination of the hash (32 bytes) - @return CRYPT_OK if successful -*/ -static int sha256_done(struct sha256_state *md, unsigned char *out) -{ - int i; - - if (md->curlen >= sizeof(md->buf)) - return -1; - - /* increase the length of the message */ - md->length += md->curlen * 8; - - /* append the '1' bit */ - md->buf[md->curlen++] = (unsigned char) 0x80; - - /* if the length is currently above 56 bytes we append zeros - * then compress. Then we can fall back to padding zeros and length - * encoding like normal. - */ - if (md->curlen > 56) { - while (md->curlen < 64) { - md->buf[md->curlen++] = (unsigned char) 0; - } - sha256_compress(md, md->buf); - md->curlen = 0; - } - - /* pad upto 56 bytes of zeroes */ - while (md->curlen < 56) { - md->buf[md->curlen++] = (unsigned char) 0; - } - - /* store length */ - WPA_PUT_BE64(md->buf + 56, md->length); - sha256_compress(md, md->buf); - - /* copy output */ - for (i = 0; i < 8; i++) - WPA_PUT_BE32(out + (4 * i), md->state[i]); - - return 0; -} - -/* ===== end - public domain SHA256 implementation ===== */ diff --git a/hostapd-0.8/src/crypto/sha256.c b/hostapd-0.8/src/crypto/sha256.c deleted file mode 100644 index 7f320f9..0000000 --- a/hostapd-0.8/src/crypto/sha256.c +++ /dev/null @@ -1,157 +0,0 @@ -/* - * SHA-256 hash implementation and interface functions - * Copyright (c) 2003-2007, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#include "includes.h" - -#include "common.h" -#include "sha256.h" -#include "crypto.h" - - -/** - * hmac_sha256_vector - HMAC-SHA256 over data vector (RFC 2104) - * @key: Key for HMAC operations - * @key_len: Length of the key in bytes - * @num_elem: Number of elements in the data vector - * @addr: Pointers to the data areas - * @len: Lengths of the data blocks - * @mac: Buffer for the hash (32 bytes) - */ -void hmac_sha256_vector(const u8 *key, size_t key_len, size_t num_elem, - const u8 *addr[], const size_t *len, u8 *mac) -{ - unsigned char k_pad[64]; /* padding - key XORd with ipad/opad */ - unsigned char tk[32]; - const u8 *_addr[6]; - size_t _len[6], i; - - if (num_elem > 5) { - /* - * Fixed limit on the number of fragments to avoid having to - * allocate memory (which could fail). - */ - return; - } - - /* if key is longer than 64 bytes reset it to key = SHA256(key) */ - if (key_len > 64) { - sha256_vector(1, &key, &key_len, tk); - key = tk; - key_len = 32; - } - - /* the HMAC_SHA256 transform looks like: - * - * SHA256(K XOR opad, SHA256(K XOR ipad, text)) - * - * where K is an n byte key - * ipad is the byte 0x36 repeated 64 times - * opad is the byte 0x5c repeated 64 times - * and text is the data being protected */ - - /* start out by storing key in ipad */ - os_memset(k_pad, 0, sizeof(k_pad)); - os_memcpy(k_pad, key, key_len); - /* XOR key with ipad values */ - for (i = 0; i < 64; i++) - k_pad[i] ^= 0x36; - - /* perform inner SHA256 */ - _addr[0] = k_pad; - _len[0] = 64; - for (i = 0; i < num_elem; i++) { - _addr[i + 1] = addr[i]; - _len[i + 1] = len[i]; - } - sha256_vector(1 + num_elem, _addr, _len, mac); - - os_memset(k_pad, 0, sizeof(k_pad)); - os_memcpy(k_pad, key, key_len); - /* XOR key with opad values */ - for (i = 0; i < 64; i++) - k_pad[i] ^= 0x5c; - - /* perform outer SHA256 */ - _addr[0] = k_pad; - _len[0] = 64; - _addr[1] = mac; - _len[1] = SHA256_MAC_LEN; - sha256_vector(2, _addr, _len, mac); -} - - -/** - * hmac_sha256 - HMAC-SHA256 over data buffer (RFC 2104) - * @key: Key for HMAC operations - * @key_len: Length of the key in bytes - * @data: Pointers to the data area - * @data_len: Length of the data area - * @mac: Buffer for the hash (20 bytes) - */ -void hmac_sha256(const u8 *key, size_t key_len, const u8 *data, - size_t data_len, u8 *mac) -{ - hmac_sha256_vector(key, key_len, 1, &data, &data_len, mac); -} - - -/** - * sha256_prf - SHA256-based Pseudo-Random Function (IEEE 802.11r, 8.5.1.5.2) - * @key: Key for PRF - * @key_len: Length of the key in bytes - * @label: A unique label for each purpose of the PRF - * @data: Extra data to bind into the key - * @data_len: Length of the data - * @buf: Buffer for the generated pseudo-random key - * @buf_len: Number of bytes of key to generate - * - * This function is used to derive new, cryptographically separate keys from a - * given key. - */ -void sha256_prf(const u8 *key, size_t key_len, const char *label, - const u8 *data, size_t data_len, u8 *buf, size_t buf_len) -{ - u16 counter = 1; - size_t pos, plen; - u8 hash[SHA256_MAC_LEN]; - const u8 *addr[4]; - size_t len[4]; - u8 counter_le[2], length_le[2]; - - addr[0] = counter_le; - len[0] = 2; - addr[1] = (u8 *) label; - len[1] = os_strlen(label); - addr[2] = data; - len[2] = data_len; - addr[3] = length_le; - len[3] = sizeof(length_le); - - WPA_PUT_LE16(length_le, buf_len * 8); - pos = 0; - while (pos < buf_len) { - plen = buf_len - pos; - WPA_PUT_LE16(counter_le, counter); - if (plen >= SHA256_MAC_LEN) { - hmac_sha256_vector(key, key_len, 4, addr, len, - &buf[pos]); - pos += SHA256_MAC_LEN; - } else { - hmac_sha256_vector(key, key_len, 4, addr, len, hash); - os_memcpy(&buf[pos], hash, plen); - break; - } - counter++; - } -} diff --git a/hostapd-0.8/src/crypto/sha256.h b/hostapd-0.8/src/crypto/sha256.h deleted file mode 100644 index dc597f0..0000000 --- a/hostapd-0.8/src/crypto/sha256.h +++ /dev/null @@ -1,27 +0,0 @@ -/* - * SHA256 hash implementation and interface functions - * Copyright (c) 2003-2006, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#ifndef SHA256_H -#define SHA256_H - -#define SHA256_MAC_LEN 32 - -void hmac_sha256_vector(const u8 *key, size_t key_len, size_t num_elem, - const u8 *addr[], const size_t *len, u8 *mac); -void hmac_sha256(const u8 *key, size_t key_len, const u8 *data, - size_t data_len, u8 *mac); -void sha256_prf(const u8 *key, size_t key_len, const char *label, - const u8 *data, size_t data_len, u8 *buf, size_t buf_len); - -#endif /* SHA256_H */ diff --git a/hostapd-0.8/src/crypto/tls.h b/hostapd-0.8/src/crypto/tls.h deleted file mode 100644 index 0928b5b..0000000 --- a/hostapd-0.8/src/crypto/tls.h +++ /dev/null @@ -1,569 +0,0 @@ -/* - * SSL/TLS interface definition - * Copyright (c) 2004-2010, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#ifndef TLS_H -#define TLS_H - -struct tls_connection; - -struct tls_keys { - const u8 *master_key; /* TLS master secret */ - size_t master_key_len; - const u8 *client_random; - size_t client_random_len; - const u8 *server_random; - size_t server_random_len; - const u8 *inner_secret; /* TLS/IA inner secret */ - size_t inner_secret_len; -}; - -enum tls_event { - TLS_CERT_CHAIN_FAILURE, - TLS_PEER_CERTIFICATE -}; - -/* - * Note: These are used as identifier with external programs and as such, the - * values must not be changed. - */ -enum tls_fail_reason { - TLS_FAIL_UNSPECIFIED = 0, - TLS_FAIL_UNTRUSTED = 1, - TLS_FAIL_REVOKED = 2, - TLS_FAIL_NOT_YET_VALID = 3, - TLS_FAIL_EXPIRED = 4, - TLS_FAIL_SUBJECT_MISMATCH = 5, - TLS_FAIL_ALTSUBJECT_MISMATCH = 6, - TLS_FAIL_BAD_CERTIFICATE = 7, - TLS_FAIL_SERVER_CHAIN_PROBE = 8 -}; - -union tls_event_data { - struct { - int depth; - const char *subject; - enum tls_fail_reason reason; - const char *reason_txt; - const struct wpabuf *cert; - } cert_fail; - - struct { - int depth; - const char *subject; - const struct wpabuf *cert; - const u8 *hash; - size_t hash_len; - } peer_cert; -}; - -struct tls_config { - const char *opensc_engine_path; - const char *pkcs11_engine_path; - const char *pkcs11_module_path; - int fips_mode; - - void (*event_cb)(void *ctx, enum tls_event ev, - union tls_event_data *data); - void *cb_ctx; -}; - -#define TLS_CONN_ALLOW_SIGN_RSA_MD5 BIT(0) -#define TLS_CONN_DISABLE_TIME_CHECKS BIT(1) - -/** - * struct tls_connection_params - Parameters for TLS connection - * @ca_cert: File or reference name for CA X.509 certificate in PEM or DER - * format - * @ca_cert_blob: ca_cert as inlined data or %NULL if not used - * @ca_cert_blob_len: ca_cert_blob length - * @ca_path: Path to CA certificates (OpenSSL specific) - * @subject_match: String to match in the subject of the peer certificate or - * %NULL to allow all subjects - * @altsubject_match: String to match in the alternative subject of the peer - * certificate or %NULL to allow all alternative subjects - * @client_cert: File or reference name for client X.509 certificate in PEM or - * DER format - * @client_cert_blob: client_cert as inlined data or %NULL if not used - * @client_cert_blob_len: client_cert_blob length - * @private_key: File or reference name for client private key in PEM or DER - * format (traditional format (RSA PRIVATE KEY) or PKCS#8 (PRIVATE KEY) - * @private_key_blob: private_key as inlined data or %NULL if not used - * @private_key_blob_len: private_key_blob length - * @private_key_passwd: Passphrase for decrypted private key, %NULL if no - * passphrase is used. - * @dh_file: File name for DH/DSA data in PEM format, or %NULL if not used - * @dh_blob: dh_file as inlined data or %NULL if not used - * @dh_blob_len: dh_blob length - * @engine: 1 = use engine (e.g., a smartcard) for private key operations - * (this is OpenSSL specific for now) - * @engine_id: engine id string (this is OpenSSL specific for now) - * @ppin: pointer to the pin variable in the configuration - * (this is OpenSSL specific for now) - * @key_id: the private key's id when using engine (this is OpenSSL - * specific for now) - * @cert_id: the certificate's id when using engine - * @ca_cert_id: the CA certificate's id when using engine - * @tls_ia: Whether to enable TLS/IA (for EAP-TTLSv1) - * @flags: Parameter options (TLS_CONN_*) - * - * TLS connection parameters to be configured with tls_connection_set_params() - * and tls_global_set_params(). - * - * Certificates and private key can be configured either as a reference name - * (file path or reference to certificate store) or by providing the same data - * as a pointer to the data in memory. Only one option will be used for each - * field. - */ -struct tls_connection_params { - const char *ca_cert; - const u8 *ca_cert_blob; - size_t ca_cert_blob_len; - const char *ca_path; - const char *subject_match; - const char *altsubject_match; - const char *client_cert; - const u8 *client_cert_blob; - size_t client_cert_blob_len; - const char *private_key; - const u8 *private_key_blob; - size_t private_key_blob_len; - const char *private_key_passwd; - const char *dh_file; - const u8 *dh_blob; - size_t dh_blob_len; - int tls_ia; - - /* OpenSSL specific variables */ - int engine; - const char *engine_id; - const char *pin; - const char *key_id; - const char *cert_id; - const char *ca_cert_id; - - unsigned int flags; -}; - - -/** - * tls_init - Initialize TLS library - * @conf: Configuration data for TLS library - * Returns: Context data to be used as tls_ctx in calls to other functions, - * or %NULL on failure. - * - * Called once during program startup and once for each RSN pre-authentication - * session. In other words, there can be two concurrent TLS contexts. If global - * library initialization is needed (i.e., one that is shared between both - * authentication types), the TLS library wrapper should maintain a reference - * counter and do global initialization only when moving from 0 to 1 reference. - */ -void * tls_init(const struct tls_config *conf); - -/** - * tls_deinit - Deinitialize TLS library - * @tls_ctx: TLS context data from tls_init() - * - * Called once during program shutdown and once for each RSN pre-authentication - * session. If global library deinitialization is needed (i.e., one that is - * shared between both authentication types), the TLS library wrapper should - * maintain a reference counter and do global deinitialization only when moving - * from 1 to 0 references. - */ -void tls_deinit(void *tls_ctx); - -/** - * tls_get_errors - Process pending errors - * @tls_ctx: TLS context data from tls_init() - * Returns: Number of found error, 0 if no errors detected. - * - * Process all pending TLS errors. - */ -int tls_get_errors(void *tls_ctx); - -/** - * tls_connection_init - Initialize a new TLS connection - * @tls_ctx: TLS context data from tls_init() - * Returns: Connection context data, conn for other function calls - */ -struct tls_connection * tls_connection_init(void *tls_ctx); - -/** - * tls_connection_deinit - Free TLS connection data - * @tls_ctx: TLS context data from tls_init() - * @conn: Connection context data from tls_connection_init() - * - * Release all resources allocated for TLS connection. - */ -void tls_connection_deinit(void *tls_ctx, struct tls_connection *conn); - -/** - * tls_connection_established - Has the TLS connection been completed? - * @tls_ctx: TLS context data from tls_init() - * @conn: Connection context data from tls_connection_init() - * Returns: 1 if TLS connection has been completed, 0 if not. - */ -int tls_connection_established(void *tls_ctx, struct tls_connection *conn); - -/** - * tls_connection_shutdown - Shutdown TLS connection - * @tls_ctx: TLS context data from tls_init() - * @conn: Connection context data from tls_connection_init() - * Returns: 0 on success, -1 on failure - * - * Shutdown current TLS connection without releasing all resources. New - * connection can be started by using the same conn without having to call - * tls_connection_init() or setting certificates etc. again. The new - * connection should try to use session resumption. - */ -int tls_connection_shutdown(void *tls_ctx, struct tls_connection *conn); - -enum { - TLS_SET_PARAMS_ENGINE_PRV_VERIFY_FAILED = -3, - TLS_SET_PARAMS_ENGINE_PRV_INIT_FAILED = -2 -}; - -/** - * tls_connection_set_params - Set TLS connection parameters - * @tls_ctx: TLS context data from tls_init() - * @conn: Connection context data from tls_connection_init() - * @params: Connection parameters - * Returns: 0 on success, -1 on failure, - * TLS_SET_PARAMS_ENGINE_PRV_INIT_FAILED (-2) on possible PIN error causing - * PKCS#11 engine failure, or - * TLS_SET_PARAMS_ENGINE_PRV_VERIFY_FAILED (-3) on failure to verify the - * PKCS#11 engine private key. - */ -int __must_check -tls_connection_set_params(void *tls_ctx, struct tls_connection *conn, - const struct tls_connection_params *params); - -/** - * tls_global_set_params - Set TLS parameters for all TLS connection - * @tls_ctx: TLS context data from tls_init() - * @params: Global TLS parameters - * Returns: 0 on success, -1 on failure, - * TLS_SET_PARAMS_ENGINE_PRV_INIT_FAILED (-2) on possible PIN error causing - * PKCS#11 engine failure, or - * TLS_SET_PARAMS_ENGINE_PRV_VERIFY_FAILED (-3) on failure to verify the - * PKCS#11 engine private key. - */ -int __must_check tls_global_set_params( - void *tls_ctx, const struct tls_connection_params *params); - -/** - * tls_global_set_verify - Set global certificate verification options - * @tls_ctx: TLS context data from tls_init() - * @check_crl: 0 = do not verify CRLs, 1 = verify CRL for the user certificate, - * 2 = verify CRL for all certificates - * Returns: 0 on success, -1 on failure - */ -int __must_check tls_global_set_verify(void *tls_ctx, int check_crl); - -/** - * tls_connection_set_verify - Set certificate verification options - * @tls_ctx: TLS context data from tls_init() - * @conn: Connection context data from tls_connection_init() - * @verify_peer: 1 = verify peer certificate - * Returns: 0 on success, -1 on failure - */ -int __must_check tls_connection_set_verify(void *tls_ctx, - struct tls_connection *conn, - int verify_peer); - -/** - * tls_connection_set_ia - Set TLS/IA parameters - * @tls_ctx: TLS context data from tls_init() - * @conn: Connection context data from tls_connection_init() - * @tls_ia: 1 = enable TLS/IA - * Returns: 0 on success, -1 on failure - * - * This function is used to configure TLS/IA in server mode where - * tls_connection_set_params() is not used. - */ -int __must_check tls_connection_set_ia(void *tls_ctx, - struct tls_connection *conn, - int tls_ia); - -/** - * tls_connection_get_keys - Get master key and random data from TLS connection - * @tls_ctx: TLS context data from tls_init() - * @conn: Connection context data from tls_connection_init() - * @keys: Structure of key/random data (filled on success) - * Returns: 0 on success, -1 on failure - */ -int __must_check tls_connection_get_keys(void *tls_ctx, - struct tls_connection *conn, - struct tls_keys *keys); - -/** - * tls_connection_prf - Use TLS-PRF to derive keying material - * @tls_ctx: TLS context data from tls_init() - * @conn: Connection context data from tls_connection_init() - * @label: Label (e.g., description of the key) for PRF - * @server_random_first: seed is 0 = client_random|server_random, - * 1 = server_random|client_random - * @out: Buffer for output data from TLS-PRF - * @out_len: Length of the output buffer - * Returns: 0 on success, -1 on failure - * - * This function is optional to implement if tls_connection_get_keys() provides - * access to master secret and server/client random values. If these values are - * not exported from the TLS library, tls_connection_prf() is required so that - * further keying material can be derived from the master secret. If not - * implemented, the function will still need to be defined, but it can just - * return -1. Example implementation of this function is in tls_prf() function - * when it is called with seed set to client_random|server_random (or - * server_random|client_random). - */ -int __must_check tls_connection_prf(void *tls_ctx, - struct tls_connection *conn, - const char *label, - int server_random_first, - u8 *out, size_t out_len); - -/** - * tls_connection_handshake - Process TLS handshake (client side) - * @tls_ctx: TLS context data from tls_init() - * @conn: Connection context data from tls_connection_init() - * @in_data: Input data from TLS server - * @appl_data: Pointer to application data pointer, or %NULL if dropped - * Returns: Output data, %NULL on failure - * - * The caller is responsible for freeing the returned output data. If the final - * handshake message includes application data, this is decrypted and - * appl_data (if not %NULL) is set to point this data. The caller is - * responsible for freeing appl_data. - * - * This function is used during TLS handshake. The first call is done with - * in_data == %NULL and the library is expected to return ClientHello packet. - * This packet is then send to the server and a response from server is given - * to TLS library by calling this function again with in_data pointing to the - * TLS message from the server. - * - * If the TLS handshake fails, this function may return %NULL. However, if the - * TLS library has a TLS alert to send out, that should be returned as the - * output data. In this case, tls_connection_get_failed() must return failure - * (> 0). - * - * tls_connection_established() should return 1 once the TLS handshake has been - * completed successfully. - */ -struct wpabuf * tls_connection_handshake(void *tls_ctx, - struct tls_connection *conn, - const struct wpabuf *in_data, - struct wpabuf **appl_data); - -/** - * tls_connection_server_handshake - Process TLS handshake (server side) - * @tls_ctx: TLS context data from tls_init() - * @conn: Connection context data from tls_connection_init() - * @in_data: Input data from TLS peer - * @appl_data: Pointer to application data pointer, or %NULL if dropped - * Returns: Output data, %NULL on failure - * - * The caller is responsible for freeing the returned output data. - */ -struct wpabuf * tls_connection_server_handshake(void *tls_ctx, - struct tls_connection *conn, - const struct wpabuf *in_data, - struct wpabuf **appl_data); - -/** - * tls_connection_encrypt - Encrypt data into TLS tunnel - * @tls_ctx: TLS context data from tls_init() - * @conn: Connection context data from tls_connection_init() - * @in_data: Plaintext data to be encrypted - * Returns: Encrypted TLS data or %NULL on failure - * - * This function is used after TLS handshake has been completed successfully to - * send data in the encrypted tunnel. The caller is responsible for freeing the - * returned output data. - */ -struct wpabuf * tls_connection_encrypt(void *tls_ctx, - struct tls_connection *conn, - const struct wpabuf *in_data); - -/** - * tls_connection_decrypt - Decrypt data from TLS tunnel - * @tls_ctx: TLS context data from tls_init() - * @conn: Connection context data from tls_connection_init() - * @in_data: Encrypted TLS data - * Returns: Decrypted TLS data or %NULL on failure - * - * This function is used after TLS handshake has been completed successfully to - * receive data from the encrypted tunnel. The caller is responsible for - * freeing the returned output data. - */ -struct wpabuf * tls_connection_decrypt(void *tls_ctx, - struct tls_connection *conn, - const struct wpabuf *in_data); - -/** - * tls_connection_resumed - Was session resumption used - * @tls_ctx: TLS context data from tls_init() - * @conn: Connection context data from tls_connection_init() - * Returns: 1 if current session used session resumption, 0 if not - */ -int tls_connection_resumed(void *tls_ctx, struct tls_connection *conn); - -enum { - TLS_CIPHER_NONE, - TLS_CIPHER_RC4_SHA /* 0x0005 */, - TLS_CIPHER_AES128_SHA /* 0x002f */, - TLS_CIPHER_RSA_DHE_AES128_SHA /* 0x0031 */, - TLS_CIPHER_ANON_DH_AES128_SHA /* 0x0034 */ -}; - -/** - * tls_connection_set_cipher_list - Configure acceptable cipher suites - * @tls_ctx: TLS context data from tls_init() - * @conn: Connection context data from tls_connection_init() - * @ciphers: Zero (TLS_CIPHER_NONE) terminated list of allowed ciphers - * (TLS_CIPHER_*). - * Returns: 0 on success, -1 on failure - */ -int __must_check tls_connection_set_cipher_list(void *tls_ctx, - struct tls_connection *conn, - u8 *ciphers); - -/** - * tls_get_cipher - Get current cipher name - * @tls_ctx: TLS context data from tls_init() - * @conn: Connection context data from tls_connection_init() - * @buf: Buffer for the cipher name - * @buflen: buf size - * Returns: 0 on success, -1 on failure - * - * Get the name of the currently used cipher. - */ -int __must_check tls_get_cipher(void *tls_ctx, struct tls_connection *conn, - char *buf, size_t buflen); - -/** - * tls_connection_enable_workaround - Enable TLS workaround options - * @tls_ctx: TLS context data from tls_init() - * @conn: Connection context data from tls_connection_init() - * Returns: 0 on success, -1 on failure - * - * This function is used to enable connection-specific workaround options for - * buffer SSL/TLS implementations. - */ -int __must_check tls_connection_enable_workaround(void *tls_ctx, - struct tls_connection *conn); - -/** - * tls_connection_client_hello_ext - Set TLS extension for ClientHello - * @tls_ctx: TLS context data from tls_init() - * @conn: Connection context data from tls_connection_init() - * @ext_type: Extension type - * @data: Extension payload (%NULL to remove extension) - * @data_len: Extension payload length - * Returns: 0 on success, -1 on failure - */ -int __must_check tls_connection_client_hello_ext(void *tls_ctx, - struct tls_connection *conn, - int ext_type, const u8 *data, - size_t data_len); - -/** - * tls_connection_get_failed - Get connection failure status - * @tls_ctx: TLS context data from tls_init() - * @conn: Connection context data from tls_connection_init() - * - * Returns >0 if connection has failed, 0 if not. - */ -int tls_connection_get_failed(void *tls_ctx, struct tls_connection *conn); - -/** - * tls_connection_get_read_alerts - Get connection read alert status - * @tls_ctx: TLS context data from tls_init() - * @conn: Connection context data from tls_connection_init() - * Returns: Number of times a fatal read (remote end reported error) has - * happened during this connection. - */ -int tls_connection_get_read_alerts(void *tls_ctx, struct tls_connection *conn); - -/** - * tls_connection_get_write_alerts - Get connection write alert status - * @tls_ctx: TLS context data from tls_init() - * @conn: Connection context data from tls_connection_init() - * Returns: Number of times a fatal write (locally detected error) has happened - * during this connection. - */ -int tls_connection_get_write_alerts(void *tls_ctx, - struct tls_connection *conn); - -/** - * tls_connection_get_keyblock_size - Get TLS key_block size - * @tls_ctx: TLS context data from tls_init() - * @conn: Connection context data from tls_connection_init() - * Returns: Size of the key_block for the negotiated cipher suite or -1 on - * failure - */ -int tls_connection_get_keyblock_size(void *tls_ctx, - struct tls_connection *conn); - -#define TLS_CAPABILITY_IA 0x0001 /* TLS Inner Application (TLS/IA) */ -/** - * tls_capabilities - Get supported TLS capabilities - * @tls_ctx: TLS context data from tls_init() - * Returns: Bit field of supported TLS capabilities (TLS_CAPABILITY_*) - */ -unsigned int tls_capabilities(void *tls_ctx); - -/** - * tls_connection_ia_send_phase_finished - Send a TLS/IA PhaseFinished message - * @tls_ctx: TLS context data from tls_init() - * @conn: Connection context data from tls_connection_init() - * @final: 1 = FinalPhaseFinished, 0 = IntermediatePhaseFinished - * Returns: Encrypted TLS/IA data, %NULL on failure - * - * This function is used to send the TLS/IA end phase message, e.g., when the - * EAP server completes EAP-TTLSv1. - */ -struct wpabuf * tls_connection_ia_send_phase_finished( - void *tls_ctx, struct tls_connection *conn, int final); - -/** - * tls_connection_ia_final_phase_finished - Has final phase been completed - * @tls_ctx: TLS context data from tls_init() - * @conn: Connection context data from tls_connection_init() - * Returns: 1 if valid FinalPhaseFinished has been received, 0 if not, or -1 - * on failure - */ -int __must_check tls_connection_ia_final_phase_finished( - void *tls_ctx, struct tls_connection *conn); - -/** - * tls_connection_ia_permute_inner_secret - Permute TLS/IA inner secret - * @tls_ctx: TLS context data from tls_init() - * @conn: Connection context data from tls_connection_init() - * @key: Session key material (session_key vectors with 2-octet length), or - * %NULL if no session key was generating in the current phase - * @key_len: Length of session key material - * Returns: 0 on success, -1 on failure - */ -int __must_check tls_connection_ia_permute_inner_secret( - void *tls_ctx, struct tls_connection *conn, - const u8 *key, size_t key_len); - -typedef int (*tls_session_ticket_cb) -(void *ctx, const u8 *ticket, size_t len, const u8 *client_random, - const u8 *server_random, u8 *master_secret); - -int __must_check tls_connection_set_session_ticket_cb( - void *tls_ctx, struct tls_connection *conn, - tls_session_ticket_cb cb, void *ctx); - -#endif /* TLS_H */ diff --git a/hostapd-0.8/src/crypto/tls_gnutls.c b/hostapd-0.8/src/crypto/tls_gnutls.c deleted file mode 100644 index c3a7358..0000000 --- a/hostapd-0.8/src/crypto/tls_gnutls.c +++ /dev/null @@ -1,1457 +0,0 @@ -/* - * SSL/TLS interface functions for GnuTLS - * Copyright (c) 2004-2009, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#include "includes.h" -#include -#include -#ifdef PKCS12_FUNCS -#include -#endif /* PKCS12_FUNCS */ - -#ifdef CONFIG_GNUTLS_EXTRA -#if LIBGNUTLS_VERSION_NUMBER >= 0x010302 -#define GNUTLS_IA -#include -#if LIBGNUTLS_VERSION_NUMBER == 0x010302 -/* This function is not included in the current gnutls/extra.h even though it - * should be, so define it here as a workaround for the time being. */ -int gnutls_ia_verify_endphase(gnutls_session_t session, char *checksum); -#endif /* LIBGNUTLS_VERSION_NUMBER == 0x010302 */ -#endif /* LIBGNUTLS_VERSION_NUMBER >= 0x010302 */ -#endif /* CONFIG_GNUTLS_EXTRA */ - -#include "common.h" -#include "tls.h" - - -#ifndef TLS_RANDOM_SIZE -#define TLS_RANDOM_SIZE 32 -#endif -#ifndef TLS_MASTER_SIZE -#define TLS_MASTER_SIZE 48 -#endif - - -#if LIBGNUTLS_VERSION_NUMBER < 0x010302 -/* GnuTLS 1.3.2 added functions for using master secret. Older versions require - * use of internal structures to get the master_secret and - * {server,client}_random. - */ -#define GNUTLS_INTERNAL_STRUCTURE_HACK -#endif /* LIBGNUTLS_VERSION_NUMBER < 0x010302 */ - - -#ifdef GNUTLS_INTERNAL_STRUCTURE_HACK -/* - * It looks like gnutls does not provide access to client/server_random and - * master_key. This is somewhat unfortunate since these are needed for key - * derivation in EAP-{TLS,TTLS,PEAP,FAST}. Workaround for now is a horrible - * hack that copies the gnutls_session_int definition from gnutls_int.h so that - * we can get the needed information. - */ - -typedef u8 uint8; -typedef unsigned char opaque; -typedef struct { - uint8 suite[2]; -} cipher_suite_st; - -typedef struct { - gnutls_connection_end_t entity; - gnutls_kx_algorithm_t kx_algorithm; - gnutls_cipher_algorithm_t read_bulk_cipher_algorithm; - gnutls_mac_algorithm_t read_mac_algorithm; - gnutls_compression_method_t read_compression_algorithm; - gnutls_cipher_algorithm_t write_bulk_cipher_algorithm; - gnutls_mac_algorithm_t write_mac_algorithm; - gnutls_compression_method_t write_compression_algorithm; - cipher_suite_st current_cipher_suite; - opaque master_secret[TLS_MASTER_SIZE]; - opaque client_random[TLS_RANDOM_SIZE]; - opaque server_random[TLS_RANDOM_SIZE]; - /* followed by stuff we are not interested in */ -} security_parameters_st; - -struct gnutls_session_int { - security_parameters_st security_parameters; - /* followed by things we are not interested in */ -}; -#endif /* LIBGNUTLS_VERSION_NUMBER < 0x010302 */ - -static int tls_gnutls_ref_count = 0; - -struct tls_global { - /* Data for session resumption */ - void *session_data; - size_t session_data_size; - - int server; - - int params_set; - gnutls_certificate_credentials_t xcred; -}; - -struct tls_connection { - gnutls_session session; - char *subject_match, *altsubject_match; - int read_alerts, write_alerts, failed; - - u8 *pre_shared_secret; - size_t pre_shared_secret_len; - int established; - int verify_peer; - - struct wpabuf *push_buf; - struct wpabuf *pull_buf; - const u8 *pull_buf_offset; - - int params_set; - gnutls_certificate_credentials_t xcred; - - int tls_ia; - int final_phase_finished; - -#ifdef GNUTLS_IA - gnutls_ia_server_credentials_t iacred_srv; - gnutls_ia_client_credentials_t iacred_cli; - - /* Session keys generated in the current phase for inner secret - * permutation before generating/verifying PhaseFinished. */ - u8 *session_keys; - size_t session_keys_len; - - u8 inner_secret[TLS_MASTER_SIZE]; -#endif /* GNUTLS_IA */ -}; - - -static void tls_log_func(int level, const char *msg) -{ - char *s, *pos; - if (level == 6 || level == 7) { - /* These levels seem to be mostly I/O debug and msg dumps */ - return; - } - - s = os_strdup(msg); - if (s == NULL) - return; - - pos = s; - while (*pos != '\0') { - if (*pos == '\n') { - *pos = '\0'; - break; - } - pos++; - } - wpa_printf(level > 3 ? MSG_MSGDUMP : MSG_DEBUG, - "gnutls<%d> %s", level, s); - os_free(s); -} - - -extern int wpa_debug_show_keys; - -void * tls_init(const struct tls_config *conf) -{ - struct tls_global *global; - -#ifdef GNUTLS_INTERNAL_STRUCTURE_HACK - /* Because of the horrible hack to get master_secret and client/server - * random, we need to make sure that the gnutls version is something - * that is expected to have same structure definition for the session - * data.. */ - const char *ver; - const char *ok_ver[] = { "1.2.3", "1.2.4", "1.2.5", "1.2.6", "1.2.9", - "1.3.2", - NULL }; - int i; -#endif /* GNUTLS_INTERNAL_STRUCTURE_HACK */ - - global = os_zalloc(sizeof(*global)); - if (global == NULL) - return NULL; - - if (tls_gnutls_ref_count == 0 && gnutls_global_init() < 0) { - os_free(global); - return NULL; - } - tls_gnutls_ref_count++; - -#ifdef GNUTLS_INTERNAL_STRUCTURE_HACK - ver = gnutls_check_version(NULL); - if (ver == NULL) { - tls_deinit(global); - return NULL; - } - wpa_printf(MSG_DEBUG, "%s - gnutls version %s", __func__, ver); - for (i = 0; ok_ver[i]; i++) { - if (strcmp(ok_ver[i], ver) == 0) - break; - } - if (ok_ver[i] == NULL) { - wpa_printf(MSG_INFO, "Untested gnutls version %s - this needs " - "to be tested and enabled in tls_gnutls.c", ver); - tls_deinit(global); - return NULL; - } -#endif /* GNUTLS_INTERNAL_STRUCTURE_HACK */ - - gnutls_global_set_log_function(tls_log_func); - if (wpa_debug_show_keys) - gnutls_global_set_log_level(11); - return global; -} - - -void tls_deinit(void *ssl_ctx) -{ - struct tls_global *global = ssl_ctx; - if (global) { - if (global->params_set) - gnutls_certificate_free_credentials(global->xcred); - os_free(global->session_data); - os_free(global); - } - - tls_gnutls_ref_count--; - if (tls_gnutls_ref_count == 0) - gnutls_global_deinit(); -} - - -int tls_get_errors(void *ssl_ctx) -{ - return 0; -} - - -static ssize_t tls_pull_func(gnutls_transport_ptr ptr, void *buf, - size_t len) -{ - struct tls_connection *conn = (struct tls_connection *) ptr; - const u8 *end; - if (conn->pull_buf == NULL) { - errno = EWOULDBLOCK; - return -1; - } - - end = wpabuf_head_u8(conn->pull_buf) + wpabuf_len(conn->pull_buf); - if ((size_t) (end - conn->pull_buf_offset) < len) - len = end - conn->pull_buf_offset; - os_memcpy(buf, conn->pull_buf_offset, len); - conn->pull_buf_offset += len; - if (conn->pull_buf_offset == end) { - wpa_printf(MSG_DEBUG, "%s - pull_buf consumed", __func__); - wpabuf_free(conn->pull_buf); - conn->pull_buf = NULL; - conn->pull_buf_offset = NULL; - } else { - wpa_printf(MSG_DEBUG, "%s - %lu bytes remaining in pull_buf", - __func__, - (unsigned long) (end - conn->pull_buf_offset)); - } - return len; -} - - -static ssize_t tls_push_func(gnutls_transport_ptr ptr, const void *buf, - size_t len) -{ - struct tls_connection *conn = (struct tls_connection *) ptr; - - if (wpabuf_resize(&conn->push_buf, len) < 0) { - errno = ENOMEM; - return -1; - } - wpabuf_put_data(conn->push_buf, buf, len); - - return len; -} - - -static int tls_gnutls_init_session(struct tls_global *global, - struct tls_connection *conn) -{ - const int cert_types[2] = { GNUTLS_CRT_X509, 0 }; - const int protos[2] = { GNUTLS_TLS1, 0 }; - int ret; - - ret = gnutls_init(&conn->session, - global->server ? GNUTLS_SERVER : GNUTLS_CLIENT); - if (ret < 0) { - wpa_printf(MSG_INFO, "TLS: Failed to initialize new TLS " - "connection: %s", gnutls_strerror(ret)); - return -1; - } - - ret = gnutls_set_default_priority(conn->session); - if (ret < 0) - goto fail; - - ret = gnutls_certificate_type_set_priority(conn->session, cert_types); - if (ret < 0) - goto fail; - - ret = gnutls_protocol_set_priority(conn->session, protos); - if (ret < 0) - goto fail; - - gnutls_transport_set_pull_function(conn->session, tls_pull_func); - gnutls_transport_set_push_function(conn->session, tls_push_func); - gnutls_transport_set_ptr(conn->session, (gnutls_transport_ptr) conn); - - return 0; - -fail: - wpa_printf(MSG_INFO, "TLS: Failed to setup new TLS connection: %s", - gnutls_strerror(ret)); - gnutls_deinit(conn->session); - return -1; -} - - -struct tls_connection * tls_connection_init(void *ssl_ctx) -{ - struct tls_global *global = ssl_ctx; - struct tls_connection *conn; - int ret; - - conn = os_zalloc(sizeof(*conn)); - if (conn == NULL) - return NULL; - - if (tls_gnutls_init_session(global, conn)) { - os_free(conn); - return NULL; - } - - if (global->params_set) { - ret = gnutls_credentials_set(conn->session, - GNUTLS_CRD_CERTIFICATE, - global->xcred); - if (ret < 0) { - wpa_printf(MSG_INFO, "Failed to configure " - "credentials: %s", gnutls_strerror(ret)); - os_free(conn); - return NULL; - } - } - - if (gnutls_certificate_allocate_credentials(&conn->xcred)) { - os_free(conn); - return NULL; - } - - return conn; -} - - -void tls_connection_deinit(void *ssl_ctx, struct tls_connection *conn) -{ - if (conn == NULL) - return; - -#ifdef GNUTLS_IA - if (conn->iacred_srv) - gnutls_ia_free_server_credentials(conn->iacred_srv); - if (conn->iacred_cli) - gnutls_ia_free_client_credentials(conn->iacred_cli); - if (conn->session_keys) { - os_memset(conn->session_keys, 0, conn->session_keys_len); - os_free(conn->session_keys); - } -#endif /* GNUTLS_IA */ - - gnutls_certificate_free_credentials(conn->xcred); - gnutls_deinit(conn->session); - os_free(conn->pre_shared_secret); - os_free(conn->subject_match); - os_free(conn->altsubject_match); - wpabuf_free(conn->push_buf); - wpabuf_free(conn->pull_buf); - os_free(conn); -} - - -int tls_connection_established(void *ssl_ctx, struct tls_connection *conn) -{ - return conn ? conn->established : 0; -} - - -int tls_connection_shutdown(void *ssl_ctx, struct tls_connection *conn) -{ - struct tls_global *global = ssl_ctx; - int ret; - - if (conn == NULL) - return -1; - - /* Shutdown previous TLS connection without notifying the peer - * because the connection was already terminated in practice - * and "close notify" shutdown alert would confuse AS. */ - gnutls_bye(conn->session, GNUTLS_SHUT_RDWR); - wpabuf_free(conn->push_buf); - conn->push_buf = NULL; - conn->established = 0; - conn->final_phase_finished = 0; -#ifdef GNUTLS_IA - if (conn->session_keys) { - os_memset(conn->session_keys, 0, conn->session_keys_len); - os_free(conn->session_keys); - } - conn->session_keys_len = 0; -#endif /* GNUTLS_IA */ - - gnutls_deinit(conn->session); - if (tls_gnutls_init_session(global, conn)) { - wpa_printf(MSG_INFO, "GnuTLS: Failed to preparare new session " - "for session resumption use"); - return -1; - } - - ret = gnutls_credentials_set(conn->session, GNUTLS_CRD_CERTIFICATE, - conn->params_set ? conn->xcred : - global->xcred); - if (ret < 0) { - wpa_printf(MSG_INFO, "GnuTLS: Failed to configure credentials " - "for session resumption: %s", gnutls_strerror(ret)); - return -1; - } - - if (global->session_data) { - ret = gnutls_session_set_data(conn->session, - global->session_data, - global->session_data_size); - if (ret < 0) { - wpa_printf(MSG_INFO, "GnuTLS: Failed to set session " - "data: %s", gnutls_strerror(ret)); - return -1; - } - } - - return 0; -} - - -#if 0 -static int tls_match_altsubject(X509 *cert, const char *match) -{ - GENERAL_NAME *gen; - char *field, *tmp; - void *ext; - int i, found = 0; - size_t len; - - ext = X509_get_ext_d2i(cert, NID_subject_alt_name, NULL, NULL); - - for (i = 0; ext && i < sk_GENERAL_NAME_num(ext); i++) { - gen = sk_GENERAL_NAME_value(ext, i); - switch (gen->type) { - case GEN_EMAIL: - field = "EMAIL"; - break; - case GEN_DNS: - field = "DNS"; - break; - case GEN_URI: - field = "URI"; - break; - default: - field = NULL; - wpa_printf(MSG_DEBUG, "TLS: altSubjectName: " - "unsupported type=%d", gen->type); - break; - } - - if (!field) - continue; - - wpa_printf(MSG_DEBUG, "TLS: altSubjectName: %s:%s", - field, gen->d.ia5->data); - len = os_strlen(field) + 1 + - strlen((char *) gen->d.ia5->data) + 1; - tmp = os_malloc(len); - if (tmp == NULL) - continue; - snprintf(tmp, len, "%s:%s", field, gen->d.ia5->data); - if (strstr(tmp, match)) - found++; - os_free(tmp); - } - - return found; -} -#endif - - -#if 0 -static int tls_verify_cb(int preverify_ok, X509_STORE_CTX *x509_ctx) -{ - char buf[256]; - X509 *err_cert; - int err, depth; - SSL *ssl; - struct tls_connection *conn; - char *match, *altmatch; - - err_cert = X509_STORE_CTX_get_current_cert(x509_ctx); - err = X509_STORE_CTX_get_error(x509_ctx); - depth = X509_STORE_CTX_get_error_depth(x509_ctx); - ssl = X509_STORE_CTX_get_ex_data(x509_ctx, - SSL_get_ex_data_X509_STORE_CTX_idx()); - X509_NAME_oneline(X509_get_subject_name(err_cert), buf, sizeof(buf)); - - conn = SSL_get_app_data(ssl); - match = conn ? conn->subject_match : NULL; - altmatch = conn ? conn->altsubject_match : NULL; - - if (!preverify_ok) { - wpa_printf(MSG_WARNING, "TLS: Certificate verification failed," - " error %d (%s) depth %d for '%s'", err, - X509_verify_cert_error_string(err), depth, buf); - } else { - wpa_printf(MSG_DEBUG, "TLS: tls_verify_cb - " - "preverify_ok=%d err=%d (%s) depth=%d buf='%s'", - preverify_ok, err, - X509_verify_cert_error_string(err), depth, buf); - if (depth == 0 && match && strstr(buf, match) == NULL) { - wpa_printf(MSG_WARNING, "TLS: Subject '%s' did not " - "match with '%s'", buf, match); - preverify_ok = 0; - } else if (depth == 0 && altmatch && - !tls_match_altsubject(err_cert, altmatch)) { - wpa_printf(MSG_WARNING, "TLS: altSubjectName match " - "'%s' not found", altmatch); - preverify_ok = 0; - } - } - - return preverify_ok; -} -#endif - - -int tls_connection_set_params(void *tls_ctx, struct tls_connection *conn, - const struct tls_connection_params *params) -{ - int ret; - - if (conn == NULL || params == NULL) - return -1; - - os_free(conn->subject_match); - conn->subject_match = NULL; - if (params->subject_match) { - conn->subject_match = os_strdup(params->subject_match); - if (conn->subject_match == NULL) - return -1; - } - - os_free(conn->altsubject_match); - conn->altsubject_match = NULL; - if (params->altsubject_match) { - conn->altsubject_match = os_strdup(params->altsubject_match); - if (conn->altsubject_match == NULL) - return -1; - } - - /* TODO: gnutls_certificate_set_verify_flags(xcred, flags); - * to force peer validation(?) */ - - if (params->ca_cert) { - conn->verify_peer = 1; - ret = gnutls_certificate_set_x509_trust_file( - conn->xcred, params->ca_cert, GNUTLS_X509_FMT_PEM); - if (ret < 0) { - wpa_printf(MSG_DEBUG, "Failed to read CA cert '%s' " - "in PEM format: %s", params->ca_cert, - gnutls_strerror(ret)); - ret = gnutls_certificate_set_x509_trust_file( - conn->xcred, params->ca_cert, - GNUTLS_X509_FMT_DER); - if (ret < 0) { - wpa_printf(MSG_DEBUG, "Failed to read CA cert " - "'%s' in DER format: %s", - params->ca_cert, - gnutls_strerror(ret)); - return -1; - } - } - - if (params->flags & TLS_CONN_ALLOW_SIGN_RSA_MD5) { - gnutls_certificate_set_verify_flags( - conn->xcred, GNUTLS_VERIFY_ALLOW_SIGN_RSA_MD5); - } - - if (params->flags & TLS_CONN_DISABLE_TIME_CHECKS) { - gnutls_certificate_set_verify_flags( - conn->xcred, - GNUTLS_VERIFY_DISABLE_TIME_CHECKS); - } - } - - if (params->client_cert && params->private_key) { - /* TODO: private_key_passwd? */ - ret = gnutls_certificate_set_x509_key_file( - conn->xcred, params->client_cert, params->private_key, - GNUTLS_X509_FMT_PEM); - if (ret < 0) { - wpa_printf(MSG_DEBUG, "Failed to read client cert/key " - "in PEM format: %s", gnutls_strerror(ret)); - ret = gnutls_certificate_set_x509_key_file( - conn->xcred, params->client_cert, - params->private_key, GNUTLS_X509_FMT_DER); - if (ret < 0) { - wpa_printf(MSG_DEBUG, "Failed to read client " - "cert/key in DER format: %s", - gnutls_strerror(ret)); - return ret; - } - } - } else if (params->private_key) { - int pkcs12_ok = 0; -#ifdef PKCS12_FUNCS - /* Try to load in PKCS#12 format */ -#if LIBGNUTLS_VERSION_NUMBER >= 0x010302 - ret = gnutls_certificate_set_x509_simple_pkcs12_file( - conn->xcred, params->private_key, GNUTLS_X509_FMT_DER, - params->private_key_passwd); - if (ret != 0) { - wpa_printf(MSG_DEBUG, "Failed to load private_key in " - "PKCS#12 format: %s", gnutls_strerror(ret)); - return -1; - } else - pkcs12_ok = 1; -#endif /* LIBGNUTLS_VERSION_NUMBER >= 0x010302 */ -#endif /* PKCS12_FUNCS */ - - if (!pkcs12_ok) { - wpa_printf(MSG_DEBUG, "GnuTLS: PKCS#12 support not " - "included"); - return -1; - } - } - - conn->tls_ia = params->tls_ia; - conn->params_set = 1; - - ret = gnutls_credentials_set(conn->session, GNUTLS_CRD_CERTIFICATE, - conn->xcred); - if (ret < 0) { - wpa_printf(MSG_INFO, "Failed to configure credentials: %s", - gnutls_strerror(ret)); - } - -#ifdef GNUTLS_IA - if (conn->iacred_cli) - gnutls_ia_free_client_credentials(conn->iacred_cli); - - ret = gnutls_ia_allocate_client_credentials(&conn->iacred_cli); - if (ret) { - wpa_printf(MSG_DEBUG, "Failed to allocate IA credentials: %s", - gnutls_strerror(ret)); - return -1; - } - - ret = gnutls_credentials_set(conn->session, GNUTLS_CRD_IA, - conn->iacred_cli); - if (ret) { - wpa_printf(MSG_DEBUG, "Failed to configure IA credentials: %s", - gnutls_strerror(ret)); - gnutls_ia_free_client_credentials(conn->iacred_cli); - conn->iacred_cli = NULL; - return -1; - } -#endif /* GNUTLS_IE */ - - return ret; -} - - -int tls_global_set_params(void *tls_ctx, - const struct tls_connection_params *params) -{ - struct tls_global *global = tls_ctx; - int ret; - - /* Currently, global parameters are only set when running in server - * mode. */ - global->server = 1; - - if (global->params_set) { - gnutls_certificate_free_credentials(global->xcred); - global->params_set = 0; - } - - ret = gnutls_certificate_allocate_credentials(&global->xcred); - if (ret) { - wpa_printf(MSG_DEBUG, "Failed to allocate global credentials " - "%s", gnutls_strerror(ret)); - return -1; - } - - if (params->ca_cert) { - ret = gnutls_certificate_set_x509_trust_file( - global->xcred, params->ca_cert, GNUTLS_X509_FMT_PEM); - if (ret < 0) { - wpa_printf(MSG_DEBUG, "Failed to read CA cert '%s' " - "in PEM format: %s", params->ca_cert, - gnutls_strerror(ret)); - ret = gnutls_certificate_set_x509_trust_file( - global->xcred, params->ca_cert, - GNUTLS_X509_FMT_DER); - if (ret < 0) { - wpa_printf(MSG_DEBUG, "Failed to read CA cert " - "'%s' in DER format: %s", - params->ca_cert, - gnutls_strerror(ret)); - goto fail; - } - } - - if (params->flags & TLS_CONN_ALLOW_SIGN_RSA_MD5) { - gnutls_certificate_set_verify_flags( - global->xcred, - GNUTLS_VERIFY_ALLOW_SIGN_RSA_MD5); - } - - if (params->flags & TLS_CONN_DISABLE_TIME_CHECKS) { - gnutls_certificate_set_verify_flags( - global->xcred, - GNUTLS_VERIFY_DISABLE_TIME_CHECKS); - } - } - - if (params->client_cert && params->private_key) { - /* TODO: private_key_passwd? */ - ret = gnutls_certificate_set_x509_key_file( - global->xcred, params->client_cert, - params->private_key, GNUTLS_X509_FMT_PEM); - if (ret < 0) { - wpa_printf(MSG_DEBUG, "Failed to read client cert/key " - "in PEM format: %s", gnutls_strerror(ret)); - ret = gnutls_certificate_set_x509_key_file( - global->xcred, params->client_cert, - params->private_key, GNUTLS_X509_FMT_DER); - if (ret < 0) { - wpa_printf(MSG_DEBUG, "Failed to read client " - "cert/key in DER format: %s", - gnutls_strerror(ret)); - goto fail; - } - } - } else if (params->private_key) { - int pkcs12_ok = 0; -#ifdef PKCS12_FUNCS - /* Try to load in PKCS#12 format */ -#if LIBGNUTLS_VERSION_NUMBER >= 0x010302 - ret = gnutls_certificate_set_x509_simple_pkcs12_file( - global->xcred, params->private_key, - GNUTLS_X509_FMT_DER, params->private_key_passwd); - if (ret != 0) { - wpa_printf(MSG_DEBUG, "Failed to load private_key in " - "PKCS#12 format: %s", gnutls_strerror(ret)); - goto fail; - } else - pkcs12_ok = 1; -#endif /* LIBGNUTLS_VERSION_NUMBER >= 0x010302 */ -#endif /* PKCS12_FUNCS */ - - if (!pkcs12_ok) { - wpa_printf(MSG_DEBUG, "GnuTLS: PKCS#12 support not " - "included"); - goto fail; - } - } - - global->params_set = 1; - - return 0; - -fail: - gnutls_certificate_free_credentials(global->xcred); - return -1; -} - - -int tls_global_set_verify(void *ssl_ctx, int check_crl) -{ - /* TODO */ - return 0; -} - - -int tls_connection_set_verify(void *ssl_ctx, struct tls_connection *conn, - int verify_peer) -{ - if (conn == NULL || conn->session == NULL) - return -1; - - conn->verify_peer = verify_peer; - gnutls_certificate_server_set_request(conn->session, - verify_peer ? GNUTLS_CERT_REQUIRE - : GNUTLS_CERT_REQUEST); - - return 0; -} - - -int tls_connection_get_keys(void *ssl_ctx, struct tls_connection *conn, - struct tls_keys *keys) -{ -#ifdef GNUTLS_INTERNAL_STRUCTURE_HACK - security_parameters_st *sec; -#endif /* GNUTLS_INTERNAL_STRUCTURE_HACK */ - - if (conn == NULL || conn->session == NULL || keys == NULL) - return -1; - - os_memset(keys, 0, sizeof(*keys)); - -#ifdef GNUTLS_INTERNAL_STRUCTURE_HACK - sec = &conn->session->security_parameters; - keys->master_key = sec->master_secret; - keys->master_key_len = TLS_MASTER_SIZE; - keys->client_random = sec->client_random; - keys->server_random = sec->server_random; -#else /* GNUTLS_INTERNAL_STRUCTURE_HACK */ - keys->client_random = - (u8 *) gnutls_session_get_client_random(conn->session); - keys->server_random = - (u8 *) gnutls_session_get_server_random(conn->session); - /* No access to master_secret */ -#endif /* GNUTLS_INTERNAL_STRUCTURE_HACK */ - -#ifdef GNUTLS_IA - gnutls_ia_extract_inner_secret(conn->session, - (char *) conn->inner_secret); - keys->inner_secret = conn->inner_secret; - keys->inner_secret_len = TLS_MASTER_SIZE; -#endif /* GNUTLS_IA */ - - keys->client_random_len = TLS_RANDOM_SIZE; - keys->server_random_len = TLS_RANDOM_SIZE; - - return 0; -} - - -int tls_connection_prf(void *tls_ctx, struct tls_connection *conn, - const char *label, int server_random_first, - u8 *out, size_t out_len) -{ -#if LIBGNUTLS_VERSION_NUMBER >= 0x010302 - if (conn == NULL || conn->session == NULL) - return -1; - - return gnutls_prf(conn->session, os_strlen(label), label, - server_random_first, 0, NULL, out_len, (char *) out); -#else /* LIBGNUTLS_VERSION_NUMBER >= 0x010302 */ - return -1; -#endif /* LIBGNUTLS_VERSION_NUMBER >= 0x010302 */ -} - - -static int tls_connection_verify_peer(struct tls_connection *conn, - gnutls_alert_description_t *err) -{ - unsigned int status, num_certs, i; - struct os_time now; - const gnutls_datum_t *certs; - gnutls_x509_crt_t cert; - - if (gnutls_certificate_verify_peers2(conn->session, &status) < 0) { - wpa_printf(MSG_INFO, "TLS: Failed to verify peer " - "certificate chain"); - *err = GNUTLS_A_INTERNAL_ERROR; - return -1; - } - - if (conn->verify_peer && (status & GNUTLS_CERT_INVALID)) { - wpa_printf(MSG_INFO, "TLS: Peer certificate not trusted"); - if (status & GNUTLS_CERT_INSECURE_ALGORITHM) { - wpa_printf(MSG_INFO, "TLS: Certificate uses insecure " - "algorithm"); - *err = GNUTLS_A_INSUFFICIENT_SECURITY; - } - if (status & GNUTLS_CERT_NOT_ACTIVATED) { - wpa_printf(MSG_INFO, "TLS: Certificate not yet " - "activated"); - *err = GNUTLS_A_CERTIFICATE_EXPIRED; - } - if (status & GNUTLS_CERT_EXPIRED) { - wpa_printf(MSG_INFO, "TLS: Certificate expired"); - *err = GNUTLS_A_CERTIFICATE_EXPIRED; - } - return -1; - } - - if (status & GNUTLS_CERT_SIGNER_NOT_FOUND) { - wpa_printf(MSG_INFO, "TLS: Peer certificate does not have a " - "known issuer"); - *err = GNUTLS_A_UNKNOWN_CA; - return -1; - } - - if (status & GNUTLS_CERT_REVOKED) { - wpa_printf(MSG_INFO, "TLS: Peer certificate has been revoked"); - *err = GNUTLS_A_CERTIFICATE_REVOKED; - return -1; - } - - os_get_time(&now); - - certs = gnutls_certificate_get_peers(conn->session, &num_certs); - if (certs == NULL) { - wpa_printf(MSG_INFO, "TLS: No peer certificate chain " - "received"); - *err = GNUTLS_A_UNKNOWN_CA; - return -1; - } - - for (i = 0; i < num_certs; i++) { - char *buf; - size_t len; - if (gnutls_x509_crt_init(&cert) < 0) { - wpa_printf(MSG_INFO, "TLS: Certificate initialization " - "failed"); - *err = GNUTLS_A_BAD_CERTIFICATE; - return -1; - } - - if (gnutls_x509_crt_import(cert, &certs[i], - GNUTLS_X509_FMT_DER) < 0) { - wpa_printf(MSG_INFO, "TLS: Could not parse peer " - "certificate %d/%d", i + 1, num_certs); - gnutls_x509_crt_deinit(cert); - *err = GNUTLS_A_BAD_CERTIFICATE; - return -1; - } - - gnutls_x509_crt_get_dn(cert, NULL, &len); - len++; - buf = os_malloc(len + 1); - if (buf) { - buf[0] = buf[len] = '\0'; - gnutls_x509_crt_get_dn(cert, buf, &len); - } - wpa_printf(MSG_DEBUG, "TLS: Peer cert chain %d/%d: %s", - i + 1, num_certs, buf); - - if (i == 0) { - /* TODO: validate subject_match and altsubject_match */ - } - - os_free(buf); - - if (gnutls_x509_crt_get_expiration_time(cert) < now.sec || - gnutls_x509_crt_get_activation_time(cert) > now.sec) { - wpa_printf(MSG_INFO, "TLS: Peer certificate %d/%d is " - "not valid at this time", - i + 1, num_certs); - gnutls_x509_crt_deinit(cert); - *err = GNUTLS_A_CERTIFICATE_EXPIRED; - return -1; - } - - gnutls_x509_crt_deinit(cert); - } - - return 0; -} - - -static struct wpabuf * gnutls_get_appl_data(struct tls_connection *conn) -{ - int res; - struct wpabuf *ad; - wpa_printf(MSG_DEBUG, "GnuTLS: Check for possible Application Data"); - ad = wpabuf_alloc((wpabuf_len(conn->pull_buf) + 500) * 3); - if (ad == NULL) - return NULL; - - res = gnutls_record_recv(conn->session, wpabuf_mhead(ad), - wpabuf_size(ad)); - wpa_printf(MSG_DEBUG, "GnuTLS: gnutls_record_recv: %d", res); - if (res < 0) { - wpa_printf(MSG_DEBUG, "%s - gnutls_ia_recv failed: %d " - "(%s)", __func__, (int) res, - gnutls_strerror(res)); - wpabuf_free(ad); - return NULL; - } - - wpabuf_put(ad, res); - wpa_printf(MSG_DEBUG, "GnuTLS: Received %d bytes of Application Data", - res); - return ad; -} - - -struct wpabuf * tls_connection_handshake(void *tls_ctx, - struct tls_connection *conn, - const struct wpabuf *in_data, - struct wpabuf **appl_data) -{ - struct tls_global *global = tls_ctx; - struct wpabuf *out_data; - int ret; - - if (appl_data) - *appl_data = NULL; - - if (in_data && wpabuf_len(in_data) > 0) { - if (conn->pull_buf) { - wpa_printf(MSG_DEBUG, "%s - %lu bytes remaining in " - "pull_buf", __func__, - (unsigned long) wpabuf_len(conn->pull_buf)); - wpabuf_free(conn->pull_buf); - } - conn->pull_buf = wpabuf_dup(in_data); - if (conn->pull_buf == NULL) - return NULL; - conn->pull_buf_offset = wpabuf_head(conn->pull_buf); - } - - ret = gnutls_handshake(conn->session); - if (ret < 0) { - switch (ret) { - case GNUTLS_E_AGAIN: - if (global->server && conn->established && - conn->push_buf == NULL) { - /* Need to return something to trigger - * completion of EAP-TLS. */ - conn->push_buf = wpabuf_alloc(0); - } - break; - case GNUTLS_E_FATAL_ALERT_RECEIVED: - wpa_printf(MSG_DEBUG, "%s - received fatal '%s' alert", - __func__, gnutls_alert_get_name( - gnutls_alert_get(conn->session))); - conn->read_alerts++; - /* continue */ - default: - wpa_printf(MSG_DEBUG, "%s - gnutls_handshake failed " - "-> %s", __func__, gnutls_strerror(ret)); - conn->failed++; - } - } else { - size_t size; - gnutls_alert_description_t err; - - if (conn->verify_peer && - tls_connection_verify_peer(conn, &err)) { - wpa_printf(MSG_INFO, "TLS: Peer certificate chain " - "failed validation"); - conn->failed++; - gnutls_alert_send(conn->session, GNUTLS_AL_FATAL, err); - goto out; - } - -#ifdef CONFIG_GNUTLS_EXTRA - if (conn->tls_ia && !gnutls_ia_handshake_p(conn->session)) { - wpa_printf(MSG_INFO, "TLS: No TLS/IA negotiation"); - conn->failed++; - return NULL; - } -#endif /* CONFIG_GNUTLS_EXTRA */ - - if (conn->tls_ia) - wpa_printf(MSG_DEBUG, "TLS: Start TLS/IA handshake"); - else { - wpa_printf(MSG_DEBUG, "TLS: Handshake completed " - "successfully"); - } - conn->established = 1; - if (conn->push_buf == NULL) { - /* Need to return something to get final TLS ACK. */ - conn->push_buf = wpabuf_alloc(0); - } - - gnutls_session_get_data(conn->session, NULL, &size); - if (global->session_data == NULL || - global->session_data_size < size) { - os_free(global->session_data); - global->session_data = os_malloc(size); - } - if (global->session_data) { - global->session_data_size = size; - gnutls_session_get_data(conn->session, - global->session_data, - &global->session_data_size); - } - - if (conn->pull_buf && appl_data) - *appl_data = gnutls_get_appl_data(conn); - } - -out: - out_data = conn->push_buf; - conn->push_buf = NULL; - return out_data; -} - - -struct wpabuf * tls_connection_server_handshake(void *tls_ctx, - struct tls_connection *conn, - const struct wpabuf *in_data, - struct wpabuf **appl_data) -{ - return tls_connection_handshake(tls_ctx, conn, in_data, appl_data); -} - - -struct wpabuf * tls_connection_encrypt(void *tls_ctx, - struct tls_connection *conn, - const struct wpabuf *in_data) -{ - ssize_t res; - struct wpabuf *buf; - -#ifdef GNUTLS_IA - if (conn->tls_ia) - res = gnutls_ia_send(conn->session, wpabuf_head(in_data), - wpabuf_len(in_data)); - else -#endif /* GNUTLS_IA */ - res = gnutls_record_send(conn->session, wpabuf_head(in_data), - wpabuf_len(in_data)); - if (res < 0) { - wpa_printf(MSG_INFO, "%s: Encryption failed: %s", - __func__, gnutls_strerror(res)); - return NULL; - } - - buf = conn->push_buf; - conn->push_buf = NULL; - return buf; -} - - -struct wpabuf * tls_connection_decrypt(void *tls_ctx, - struct tls_connection *conn, - const struct wpabuf *in_data) -{ - ssize_t res; - struct wpabuf *out; - - if (conn->pull_buf) { - wpa_printf(MSG_DEBUG, "%s - %lu bytes remaining in " - "pull_buf", __func__, - (unsigned long) wpabuf_len(conn->pull_buf)); - wpabuf_free(conn->pull_buf); - } - conn->pull_buf = wpabuf_dup(in_data); - if (conn->pull_buf == NULL) - return NULL; - conn->pull_buf_offset = wpabuf_head(conn->pull_buf); - - /* - * Even though we try to disable TLS compression, it is possible that - * this cannot be done with all TLS libraries. Add extra buffer space - * to handle the possibility of the decrypted data being longer than - * input data. - */ - out = wpabuf_alloc((wpabuf_len(in_data) + 500) * 3); - if (out == NULL) - return NULL; - -#ifdef GNUTLS_IA - if (conn->tls_ia) { - res = gnutls_ia_recv(conn->session, wpabuf_mhead(out), - wpabuf_size(out)); - if (res == GNUTLS_E_WARNING_IA_IPHF_RECEIVED || - res == GNUTLS_E_WARNING_IA_FPHF_RECEIVED) { - int final = res == GNUTLS_E_WARNING_IA_FPHF_RECEIVED; - wpa_printf(MSG_DEBUG, "%s: Received %sPhaseFinished", - __func__, final ? "Final" : "Intermediate"); - - res = gnutls_ia_permute_inner_secret( - conn->session, conn->session_keys_len, - (char *) conn->session_keys); - if (conn->session_keys) { - os_memset(conn->session_keys, 0, - conn->session_keys_len); - os_free(conn->session_keys); - } - conn->session_keys = NULL; - conn->session_keys_len = 0; - if (res) { - wpa_printf(MSG_DEBUG, "%s: Failed to permute " - "inner secret: %s", - __func__, gnutls_strerror(res)); - wpabuf_free(out); - return NULL; - } - - res = gnutls_ia_verify_endphase(conn->session, - wpabuf_head(out)); - if (res == 0) { - wpa_printf(MSG_DEBUG, "%s: Correct endphase " - "checksum", __func__); - } else { - wpa_printf(MSG_INFO, "%s: Endphase " - "verification failed: %s", - __func__, gnutls_strerror(res)); - wpabuf_free(out); - return NULL; - } - - if (final) - conn->final_phase_finished = 1; - - return out; - } - - if (res < 0) { - wpa_printf(MSG_DEBUG, "%s - gnutls_ia_recv failed: %d " - "(%s)", __func__, (int) res, - gnutls_strerror(res)); - wpabuf_free(out); - return NULL; - } - wpabuf_put(out, res); - return out; - } -#endif /* GNUTLS_IA */ - - res = gnutls_record_recv(conn->session, wpabuf_mhead(out), - wpabuf_size(out)); - if (res < 0) { - wpa_printf(MSG_DEBUG, "%s - gnutls_record_recv failed: %d " - "(%s)", __func__, (int) res, gnutls_strerror(res)); - wpabuf_free(out); - return NULL; - } - wpabuf_put(out, res); - - return out; -} - - -int tls_connection_resumed(void *ssl_ctx, struct tls_connection *conn) -{ - if (conn == NULL) - return 0; - return gnutls_session_is_resumed(conn->session); -} - - -int tls_connection_set_cipher_list(void *tls_ctx, struct tls_connection *conn, - u8 *ciphers) -{ - /* TODO */ - return -1; -} - - -int tls_get_cipher(void *ssl_ctx, struct tls_connection *conn, - char *buf, size_t buflen) -{ - /* TODO */ - buf[0] = '\0'; - return 0; -} - - -int tls_connection_enable_workaround(void *ssl_ctx, - struct tls_connection *conn) -{ - gnutls_record_disable_padding(conn->session); - return 0; -} - - -int tls_connection_client_hello_ext(void *ssl_ctx, struct tls_connection *conn, - int ext_type, const u8 *data, - size_t data_len) -{ - /* TODO */ - return -1; -} - - -int tls_connection_get_failed(void *ssl_ctx, struct tls_connection *conn) -{ - if (conn == NULL) - return -1; - return conn->failed; -} - - -int tls_connection_get_read_alerts(void *ssl_ctx, struct tls_connection *conn) -{ - if (conn == NULL) - return -1; - return conn->read_alerts; -} - - -int tls_connection_get_write_alerts(void *ssl_ctx, struct tls_connection *conn) -{ - if (conn == NULL) - return -1; - return conn->write_alerts; -} - - -int tls_connection_get_keyblock_size(void *tls_ctx, - struct tls_connection *conn) -{ - /* TODO */ - return -1; -} - - -unsigned int tls_capabilities(void *tls_ctx) -{ - unsigned int capa = 0; - -#ifdef GNUTLS_IA - capa |= TLS_CAPABILITY_IA; -#endif /* GNUTLS_IA */ - - return capa; -} - - -int tls_connection_set_ia(void *tls_ctx, struct tls_connection *conn, - int tls_ia) -{ -#ifdef GNUTLS_IA - int ret; - - if (conn == NULL) - return -1; - - conn->tls_ia = tls_ia; - if (!tls_ia) - return 0; - - ret = gnutls_ia_allocate_server_credentials(&conn->iacred_srv); - if (ret) { - wpa_printf(MSG_DEBUG, "Failed to allocate IA credentials: %s", - gnutls_strerror(ret)); - return -1; - } - - ret = gnutls_credentials_set(conn->session, GNUTLS_CRD_IA, - conn->iacred_srv); - if (ret) { - wpa_printf(MSG_DEBUG, "Failed to configure IA credentials: %s", - gnutls_strerror(ret)); - gnutls_ia_free_server_credentials(conn->iacred_srv); - conn->iacred_srv = NULL; - return -1; - } - - return 0; -#else /* GNUTLS_IA */ - return -1; -#endif /* GNUTLS_IA */ -} - - -struct wpabuf * tls_connection_ia_send_phase_finished( - void *tls_ctx, struct tls_connection *conn, int final) -{ -#ifdef GNUTLS_IA - int ret; - struct wpabuf *buf; - - if (conn == NULL || conn->session == NULL || !conn->tls_ia) - return NULL; - - ret = gnutls_ia_permute_inner_secret(conn->session, - conn->session_keys_len, - (char *) conn->session_keys); - if (conn->session_keys) { - os_memset(conn->session_keys, 0, conn->session_keys_len); - os_free(conn->session_keys); - } - conn->session_keys = NULL; - conn->session_keys_len = 0; - if (ret) { - wpa_printf(MSG_DEBUG, "%s: Failed to permute inner secret: %s", - __func__, gnutls_strerror(ret)); - return NULL; - } - - ret = gnutls_ia_endphase_send(conn->session, final); - if (ret) { - wpa_printf(MSG_DEBUG, "%s: Failed to send endphase: %s", - __func__, gnutls_strerror(ret)); - return NULL; - } - - buf = conn->push_buf; - conn->push_buf = NULL; - return buf; -#else /* GNUTLS_IA */ - return NULL; -#endif /* GNUTLS_IA */ -} - - -int tls_connection_ia_final_phase_finished(void *tls_ctx, - struct tls_connection *conn) -{ - if (conn == NULL) - return -1; - - return conn->final_phase_finished; -} - - -int tls_connection_ia_permute_inner_secret(void *tls_ctx, - struct tls_connection *conn, - const u8 *key, size_t key_len) -{ -#ifdef GNUTLS_IA - if (conn == NULL || !conn->tls_ia) - return -1; - - if (conn->session_keys) { - os_memset(conn->session_keys, 0, conn->session_keys_len); - os_free(conn->session_keys); - } - conn->session_keys_len = 0; - - if (key) { - conn->session_keys = os_malloc(key_len); - if (conn->session_keys == NULL) - return -1; - os_memcpy(conn->session_keys, key, key_len); - conn->session_keys_len = key_len; - } else { - conn->session_keys = NULL; - conn->session_keys_len = 0; - } - - return 0; -#else /* GNUTLS_IA */ - return -1; -#endif /* GNUTLS_IA */ -} - - -int tls_connection_set_session_ticket_cb(void *tls_ctx, - struct tls_connection *conn, - tls_session_ticket_cb cb, void *ctx) -{ - return -1; -} diff --git a/hostapd-0.8/src/crypto/tls_internal.c b/hostapd-0.8/src/crypto/tls_internal.c deleted file mode 100644 index 64124d8..0000000 --- a/hostapd-0.8/src/crypto/tls_internal.c +++ /dev/null @@ -1,651 +0,0 @@ -/* - * TLS interface functions and an internal TLS implementation - * Copyright (c) 2004-2009, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - * - * This file interface functions for hostapd/wpa_supplicant to use the - * integrated TLSv1 implementation. - */ - -#include "includes.h" - -#include "common.h" -#include "tls.h" -#include "tls/tlsv1_client.h" -#include "tls/tlsv1_server.h" - - -static int tls_ref_count = 0; - -struct tls_global { - int server; - struct tlsv1_credentials *server_cred; - int check_crl; -}; - -struct tls_connection { - struct tlsv1_client *client; - struct tlsv1_server *server; -}; - - -void * tls_init(const struct tls_config *conf) -{ - struct tls_global *global; - - if (tls_ref_count == 0) { -#ifdef CONFIG_TLS_INTERNAL_CLIENT - if (tlsv1_client_global_init()) - return NULL; -#endif /* CONFIG_TLS_INTERNAL_CLIENT */ -#ifdef CONFIG_TLS_INTERNAL_SERVER - if (tlsv1_server_global_init()) - return NULL; -#endif /* CONFIG_TLS_INTERNAL_SERVER */ - } - tls_ref_count++; - - global = os_zalloc(sizeof(*global)); - if (global == NULL) - return NULL; - - return global; -} - -void tls_deinit(void *ssl_ctx) -{ - struct tls_global *global = ssl_ctx; - tls_ref_count--; - if (tls_ref_count == 0) { -#ifdef CONFIG_TLS_INTERNAL_CLIENT - tlsv1_client_global_deinit(); -#endif /* CONFIG_TLS_INTERNAL_CLIENT */ -#ifdef CONFIG_TLS_INTERNAL_SERVER - tlsv1_cred_free(global->server_cred); - tlsv1_server_global_deinit(); -#endif /* CONFIG_TLS_INTERNAL_SERVER */ - } - os_free(global); -} - - -int tls_get_errors(void *tls_ctx) -{ - return 0; -} - - -struct tls_connection * tls_connection_init(void *tls_ctx) -{ - struct tls_connection *conn; - struct tls_global *global = tls_ctx; - - conn = os_zalloc(sizeof(*conn)); - if (conn == NULL) - return NULL; - -#ifdef CONFIG_TLS_INTERNAL_CLIENT - if (!global->server) { - conn->client = tlsv1_client_init(); - if (conn->client == NULL) { - os_free(conn); - return NULL; - } - } -#endif /* CONFIG_TLS_INTERNAL_CLIENT */ -#ifdef CONFIG_TLS_INTERNAL_SERVER - if (global->server) { - conn->server = tlsv1_server_init(global->server_cred); - if (conn->server == NULL) { - os_free(conn); - return NULL; - } - } -#endif /* CONFIG_TLS_INTERNAL_SERVER */ - - return conn; -} - - -void tls_connection_deinit(void *tls_ctx, struct tls_connection *conn) -{ - if (conn == NULL) - return; -#ifdef CONFIG_TLS_INTERNAL_CLIENT - if (conn->client) - tlsv1_client_deinit(conn->client); -#endif /* CONFIG_TLS_INTERNAL_CLIENT */ -#ifdef CONFIG_TLS_INTERNAL_SERVER - if (conn->server) - tlsv1_server_deinit(conn->server); -#endif /* CONFIG_TLS_INTERNAL_SERVER */ - os_free(conn); -} - - -int tls_connection_established(void *tls_ctx, struct tls_connection *conn) -{ -#ifdef CONFIG_TLS_INTERNAL_CLIENT - if (conn->client) - return tlsv1_client_established(conn->client); -#endif /* CONFIG_TLS_INTERNAL_CLIENT */ -#ifdef CONFIG_TLS_INTERNAL_SERVER - if (conn->server) - return tlsv1_server_established(conn->server); -#endif /* CONFIG_TLS_INTERNAL_SERVER */ - return 0; -} - - -int tls_connection_shutdown(void *tls_ctx, struct tls_connection *conn) -{ -#ifdef CONFIG_TLS_INTERNAL_CLIENT - if (conn->client) - return tlsv1_client_shutdown(conn->client); -#endif /* CONFIG_TLS_INTERNAL_CLIENT */ -#ifdef CONFIG_TLS_INTERNAL_SERVER - if (conn->server) - return tlsv1_server_shutdown(conn->server); -#endif /* CONFIG_TLS_INTERNAL_SERVER */ - return -1; -} - - -int tls_connection_set_params(void *tls_ctx, struct tls_connection *conn, - const struct tls_connection_params *params) -{ -#ifdef CONFIG_TLS_INTERNAL_CLIENT - struct tlsv1_credentials *cred; - - if (conn->client == NULL) - return -1; - - cred = tlsv1_cred_alloc(); - if (cred == NULL) - return -1; - - if (tlsv1_set_ca_cert(cred, params->ca_cert, - params->ca_cert_blob, params->ca_cert_blob_len, - params->ca_path)) { - wpa_printf(MSG_INFO, "TLS: Failed to configure trusted CA " - "certificates"); - tlsv1_cred_free(cred); - return -1; - } - - if (tlsv1_set_cert(cred, params->client_cert, - params->client_cert_blob, - params->client_cert_blob_len)) { - wpa_printf(MSG_INFO, "TLS: Failed to configure client " - "certificate"); - tlsv1_cred_free(cred); - return -1; - } - - if (tlsv1_set_private_key(cred, params->private_key, - params->private_key_passwd, - params->private_key_blob, - params->private_key_blob_len)) { - wpa_printf(MSG_INFO, "TLS: Failed to load private key"); - tlsv1_cred_free(cred); - return -1; - } - - if (tlsv1_set_dhparams(cred, params->dh_file, params->dh_blob, - params->dh_blob_len)) { - wpa_printf(MSG_INFO, "TLS: Failed to load DH parameters"); - tlsv1_cred_free(cred); - return -1; - } - - if (tlsv1_client_set_cred(conn->client, cred) < 0) { - tlsv1_cred_free(cred); - return -1; - } - - return 0; -#else /* CONFIG_TLS_INTERNAL_CLIENT */ - return -1; -#endif /* CONFIG_TLS_INTERNAL_CLIENT */ -} - - -int tls_global_set_params(void *tls_ctx, - const struct tls_connection_params *params) -{ -#ifdef CONFIG_TLS_INTERNAL_SERVER - struct tls_global *global = tls_ctx; - struct tlsv1_credentials *cred; - - /* Currently, global parameters are only set when running in server - * mode. */ - global->server = 1; - tlsv1_cred_free(global->server_cred); - global->server_cred = cred = tlsv1_cred_alloc(); - if (cred == NULL) - return -1; - - if (tlsv1_set_ca_cert(cred, params->ca_cert, params->ca_cert_blob, - params->ca_cert_blob_len, params->ca_path)) { - wpa_printf(MSG_INFO, "TLS: Failed to configure trusted CA " - "certificates"); - return -1; - } - - if (tlsv1_set_cert(cred, params->client_cert, params->client_cert_blob, - params->client_cert_blob_len)) { - wpa_printf(MSG_INFO, "TLS: Failed to configure server " - "certificate"); - return -1; - } - - if (tlsv1_set_private_key(cred, params->private_key, - params->private_key_passwd, - params->private_key_blob, - params->private_key_blob_len)) { - wpa_printf(MSG_INFO, "TLS: Failed to load private key"); - return -1; - } - - if (tlsv1_set_dhparams(cred, params->dh_file, params->dh_blob, - params->dh_blob_len)) { - wpa_printf(MSG_INFO, "TLS: Failed to load DH parameters"); - return -1; - } - - return 0; -#else /* CONFIG_TLS_INTERNAL_SERVER */ - return -1; -#endif /* CONFIG_TLS_INTERNAL_SERVER */ -} - - -int tls_global_set_verify(void *tls_ctx, int check_crl) -{ - struct tls_global *global = tls_ctx; - global->check_crl = check_crl; - return 0; -} - - -int tls_connection_set_verify(void *tls_ctx, struct tls_connection *conn, - int verify_peer) -{ -#ifdef CONFIG_TLS_INTERNAL_SERVER - if (conn->server) - return tlsv1_server_set_verify(conn->server, verify_peer); -#endif /* CONFIG_TLS_INTERNAL_SERVER */ - return -1; -} - - -int tls_connection_set_ia(void *tls_ctx, struct tls_connection *conn, - int tls_ia) -{ - return -1; -} - - -int tls_connection_get_keys(void *tls_ctx, struct tls_connection *conn, - struct tls_keys *keys) -{ -#ifdef CONFIG_TLS_INTERNAL_CLIENT - if (conn->client) - return tlsv1_client_get_keys(conn->client, keys); -#endif /* CONFIG_TLS_INTERNAL_CLIENT */ -#ifdef CONFIG_TLS_INTERNAL_SERVER - if (conn->server) - return tlsv1_server_get_keys(conn->server, keys); -#endif /* CONFIG_TLS_INTERNAL_SERVER */ - return -1; -} - - -int tls_connection_prf(void *tls_ctx, struct tls_connection *conn, - const char *label, int server_random_first, - u8 *out, size_t out_len) -{ -#ifdef CONFIG_TLS_INTERNAL_CLIENT - if (conn->client) { - return tlsv1_client_prf(conn->client, label, - server_random_first, - out, out_len); - } -#endif /* CONFIG_TLS_INTERNAL_CLIENT */ -#ifdef CONFIG_TLS_INTERNAL_SERVER - if (conn->server) { - return tlsv1_server_prf(conn->server, label, - server_random_first, - out, out_len); - } -#endif /* CONFIG_TLS_INTERNAL_SERVER */ - return -1; -} - - -struct wpabuf * tls_connection_handshake(void *tls_ctx, - struct tls_connection *conn, - const struct wpabuf *in_data, - struct wpabuf **appl_data) -{ -#ifdef CONFIG_TLS_INTERNAL_CLIENT - u8 *res, *ad; - size_t res_len, ad_len; - struct wpabuf *out; - - if (conn->client == NULL) - return NULL; - - ad = NULL; - res = tlsv1_client_handshake(conn->client, - in_data ? wpabuf_head(in_data) : NULL, - in_data ? wpabuf_len(in_data) : 0, - &res_len, &ad, &ad_len); - if (res == NULL) - return NULL; - out = wpabuf_alloc_ext_data(res, res_len); - if (out == NULL) { - os_free(res); - os_free(ad); - return NULL; - } - if (appl_data) { - if (ad) { - *appl_data = wpabuf_alloc_ext_data(ad, ad_len); - if (*appl_data == NULL) - os_free(ad); - } else - *appl_data = NULL; - } else - os_free(ad); - - return out; -#else /* CONFIG_TLS_INTERNAL_CLIENT */ - return NULL; -#endif /* CONFIG_TLS_INTERNAL_CLIENT */ -} - - -struct wpabuf * tls_connection_server_handshake(void *tls_ctx, - struct tls_connection *conn, - const struct wpabuf *in_data, - struct wpabuf **appl_data) -{ -#ifdef CONFIG_TLS_INTERNAL_SERVER - u8 *res; - size_t res_len; - struct wpabuf *out; - - if (conn->server == NULL) - return NULL; - - if (appl_data) - *appl_data = NULL; - - res = tlsv1_server_handshake(conn->server, wpabuf_head(in_data), - wpabuf_len(in_data), &res_len); - if (res == NULL && tlsv1_server_established(conn->server)) - return wpabuf_alloc(0); - if (res == NULL) - return NULL; - out = wpabuf_alloc_ext_data(res, res_len); - if (out == NULL) { - os_free(res); - return NULL; - } - - return out; -#else /* CONFIG_TLS_INTERNAL_SERVER */ - return NULL; -#endif /* CONFIG_TLS_INTERNAL_SERVER */ -} - - -struct wpabuf * tls_connection_encrypt(void *tls_ctx, - struct tls_connection *conn, - const struct wpabuf *in_data) -{ -#ifdef CONFIG_TLS_INTERNAL_CLIENT - if (conn->client) { - struct wpabuf *buf; - int res; - buf = wpabuf_alloc(wpabuf_len(in_data) + 300); - if (buf == NULL) - return NULL; - res = tlsv1_client_encrypt(conn->client, wpabuf_head(in_data), - wpabuf_len(in_data), - wpabuf_mhead(buf), - wpabuf_size(buf)); - if (res < 0) { - wpabuf_free(buf); - return NULL; - } - wpabuf_put(buf, res); - return buf; - } -#endif /* CONFIG_TLS_INTERNAL_CLIENT */ -#ifdef CONFIG_TLS_INTERNAL_SERVER - if (conn->server) { - struct wpabuf *buf; - int res; - buf = wpabuf_alloc(wpabuf_len(in_data) + 300); - if (buf == NULL) - return NULL; - res = tlsv1_server_encrypt(conn->server, wpabuf_head(in_data), - wpabuf_len(in_data), - wpabuf_mhead(buf), - wpabuf_size(buf)); - if (res < 0) { - wpabuf_free(buf); - return NULL; - } - wpabuf_put(buf, res); - return buf; - } -#endif /* CONFIG_TLS_INTERNAL_SERVER */ - return NULL; -} - - -struct wpabuf * tls_connection_decrypt(void *tls_ctx, - struct tls_connection *conn, - const struct wpabuf *in_data) -{ -#ifdef CONFIG_TLS_INTERNAL_CLIENT - if (conn->client) { - struct wpabuf *buf; - int res; - buf = wpabuf_alloc((wpabuf_len(in_data) + 500) * 3); - if (buf == NULL) - return NULL; - res = tlsv1_client_decrypt(conn->client, wpabuf_head(in_data), - wpabuf_len(in_data), - wpabuf_mhead(buf), - wpabuf_size(buf)); - if (res < 0) { - wpabuf_free(buf); - return NULL; - } - wpabuf_put(buf, res); - return buf; - } -#endif /* CONFIG_TLS_INTERNAL_CLIENT */ -#ifdef CONFIG_TLS_INTERNAL_SERVER - if (conn->server) { - struct wpabuf *buf; - int res; - buf = wpabuf_alloc((wpabuf_len(in_data) + 500) * 3); - if (buf == NULL) - return NULL; - res = tlsv1_server_decrypt(conn->server, wpabuf_head(in_data), - wpabuf_len(in_data), - wpabuf_mhead(buf), - wpabuf_size(buf)); - if (res < 0) { - wpabuf_free(buf); - return NULL; - } - wpabuf_put(buf, res); - return buf; - } -#endif /* CONFIG_TLS_INTERNAL_SERVER */ - return NULL; -} - - -int tls_connection_resumed(void *tls_ctx, struct tls_connection *conn) -{ -#ifdef CONFIG_TLS_INTERNAL_CLIENT - if (conn->client) - return tlsv1_client_resumed(conn->client); -#endif /* CONFIG_TLS_INTERNAL_CLIENT */ -#ifdef CONFIG_TLS_INTERNAL_SERVER - if (conn->server) - return tlsv1_server_resumed(conn->server); -#endif /* CONFIG_TLS_INTERNAL_SERVER */ - return -1; -} - - -int tls_connection_set_cipher_list(void *tls_ctx, struct tls_connection *conn, - u8 *ciphers) -{ -#ifdef CONFIG_TLS_INTERNAL_CLIENT - if (conn->client) - return tlsv1_client_set_cipher_list(conn->client, ciphers); -#endif /* CONFIG_TLS_INTERNAL_CLIENT */ -#ifdef CONFIG_TLS_INTERNAL_SERVER - if (conn->server) - return tlsv1_server_set_cipher_list(conn->server, ciphers); -#endif /* CONFIG_TLS_INTERNAL_SERVER */ - return -1; -} - - -int tls_get_cipher(void *tls_ctx, struct tls_connection *conn, - char *buf, size_t buflen) -{ - if (conn == NULL) - return -1; -#ifdef CONFIG_TLS_INTERNAL_CLIENT - if (conn->client) - return tlsv1_client_get_cipher(conn->client, buf, buflen); -#endif /* CONFIG_TLS_INTERNAL_CLIENT */ -#ifdef CONFIG_TLS_INTERNAL_SERVER - if (conn->server) - return tlsv1_server_get_cipher(conn->server, buf, buflen); -#endif /* CONFIG_TLS_INTERNAL_SERVER */ - return -1; -} - - -int tls_connection_enable_workaround(void *tls_ctx, - struct tls_connection *conn) -{ - return -1; -} - - -int tls_connection_client_hello_ext(void *tls_ctx, struct tls_connection *conn, - int ext_type, const u8 *data, - size_t data_len) -{ -#ifdef CONFIG_TLS_INTERNAL_CLIENT - if (conn->client) { - return tlsv1_client_hello_ext(conn->client, ext_type, - data, data_len); - } -#endif /* CONFIG_TLS_INTERNAL_CLIENT */ - return -1; -} - - -int tls_connection_get_failed(void *tls_ctx, struct tls_connection *conn) -{ - return 0; -} - - -int tls_connection_get_read_alerts(void *tls_ctx, struct tls_connection *conn) -{ - return 0; -} - - -int tls_connection_get_write_alerts(void *tls_ctx, - struct tls_connection *conn) -{ - return 0; -} - - -int tls_connection_get_keyblock_size(void *tls_ctx, - struct tls_connection *conn) -{ -#ifdef CONFIG_TLS_INTERNAL_CLIENT - if (conn->client) - return tlsv1_client_get_keyblock_size(conn->client); -#endif /* CONFIG_TLS_INTERNAL_CLIENT */ -#ifdef CONFIG_TLS_INTERNAL_SERVER - if (conn->server) - return tlsv1_server_get_keyblock_size(conn->server); -#endif /* CONFIG_TLS_INTERNAL_SERVER */ - return -1; -} - - -unsigned int tls_capabilities(void *tls_ctx) -{ - return 0; -} - - -struct wpabuf * tls_connection_ia_send_phase_finished( - void *tls_ctx, struct tls_connection *conn, int final) -{ - return NULL; -} - - -int tls_connection_ia_final_phase_finished(void *tls_ctx, - struct tls_connection *conn) -{ - return -1; -} - - -int tls_connection_ia_permute_inner_secret(void *tls_ctx, - struct tls_connection *conn, - const u8 *key, size_t key_len) -{ - return -1; -} - - -int tls_connection_set_session_ticket_cb(void *tls_ctx, - struct tls_connection *conn, - tls_session_ticket_cb cb, - void *ctx) -{ -#ifdef CONFIG_TLS_INTERNAL_CLIENT - if (conn->client) { - tlsv1_client_set_session_ticket_cb(conn->client, cb, ctx); - return 0; - } -#endif /* CONFIG_TLS_INTERNAL_CLIENT */ -#ifdef CONFIG_TLS_INTERNAL_SERVER - if (conn->server) { - tlsv1_server_set_session_ticket_cb(conn->server, cb, ctx); - return 0; - } -#endif /* CONFIG_TLS_INTERNAL_SERVER */ - return -1; -} diff --git a/hostapd-0.8/src/crypto/tls_none.c b/hostapd-0.8/src/crypto/tls_none.c deleted file mode 100644 index 0c836bb..0000000 --- a/hostapd-0.8/src/crypto/tls_none.c +++ /dev/null @@ -1,229 +0,0 @@ -/* - * SSL/TLS interface functions for no TLS case - * Copyright (c) 2004-2009, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#include "includes.h" - -#include "common.h" -#include "tls.h" - -void * tls_init(const struct tls_config *conf) -{ - return (void *) 1; -} - - -void tls_deinit(void *ssl_ctx) -{ -} - - -int tls_get_errors(void *tls_ctx) -{ - return 0; -} - - -struct tls_connection * tls_connection_init(void *tls_ctx) -{ - return NULL; -} - - -void tls_connection_deinit(void *tls_ctx, struct tls_connection *conn) -{ -} - - -int tls_connection_established(void *tls_ctx, struct tls_connection *conn) -{ - return -1; -} - - -int tls_connection_shutdown(void *tls_ctx, struct tls_connection *conn) -{ - return -1; -} - - -int tls_connection_set_params(void *tls_ctx, struct tls_connection *conn, - const struct tls_connection_params *params) -{ - return -1; -} - - -int tls_global_set_params(void *tls_ctx, - const struct tls_connection_params *params) -{ - return -1; -} - - -int tls_global_set_verify(void *tls_ctx, int check_crl) -{ - return -1; -} - - -int tls_connection_set_verify(void *tls_ctx, struct tls_connection *conn, - int verify_peer) -{ - return -1; -} - - -int tls_connection_set_ia(void *tls_ctx, struct tls_connection *conn, - int tls_ia) -{ - return -1; -} - - -int tls_connection_get_keys(void *tls_ctx, struct tls_connection *conn, - struct tls_keys *keys) -{ - return -1; -} - - -int tls_connection_prf(void *tls_ctx, struct tls_connection *conn, - const char *label, int server_random_first, - u8 *out, size_t out_len) -{ - return -1; -} - - -struct wpabuf * tls_connection_handshake(void *tls_ctx, - struct tls_connection *conn, - const struct wpabuf *in_data, - struct wpabuf **appl_data) -{ - return NULL; -} - - -struct wpabuf * tls_connection_server_handshake(void *tls_ctx, - struct tls_connection *conn, - const struct wpabuf *in_data, - struct wpabuf **appl_data) -{ - return NULL; -} - - -struct wpabuf * tls_connection_encrypt(void *tls_ctx, - struct tls_connection *conn, - const struct wpabuf *in_data) -{ - return NULL; -} - - -struct wpabuf * tls_connection_decrypt(void *tls_ctx, - struct tls_connection *conn, - const struct wpabuf *in_data) -{ - return NULL; -} - - -int tls_connection_resumed(void *tls_ctx, struct tls_connection *conn) -{ - return 0; -} - - -int tls_connection_set_cipher_list(void *tls_ctx, struct tls_connection *conn, - u8 *ciphers) -{ - return -1; -} - - -int tls_get_cipher(void *tls_ctx, struct tls_connection *conn, - char *buf, size_t buflen) -{ - return -1; -} - - -int tls_connection_enable_workaround(void *tls_ctx, - struct tls_connection *conn) -{ - return -1; -} - - -int tls_connection_client_hello_ext(void *tls_ctx, struct tls_connection *conn, - int ext_type, const u8 *data, - size_t data_len) -{ - return -1; -} - - -int tls_connection_get_failed(void *tls_ctx, struct tls_connection *conn) -{ - return 0; -} - - -int tls_connection_get_read_alerts(void *tls_ctx, struct tls_connection *conn) -{ - return 0; -} - - -int tls_connection_get_write_alerts(void *tls_ctx, - struct tls_connection *conn) -{ - return 0; -} - - -int tls_connection_get_keyblock_size(void *tls_ctx, - struct tls_connection *conn) -{ - return -1; -} - - -unsigned int tls_capabilities(void *tls_ctx) -{ - return 0; -} - - -struct wpabuf * tls_connection_ia_send_phase_finished( - void *tls_ctx, struct tls_connection *conn, int final) -{ - return NULL; -} - - -int tls_connection_ia_final_phase_finished(void *tls_ctx, - struct tls_connection *conn) -{ - return -1; -} - - -int tls_connection_ia_permute_inner_secret(void *tls_ctx, - struct tls_connection *conn, - const u8 *key, size_t key_len) -{ - return -1; -} diff --git a/hostapd-0.8/src/crypto/tls_nss.c b/hostapd-0.8/src/crypto/tls_nss.c deleted file mode 100644 index ad834b6..0000000 --- a/hostapd-0.8/src/crypto/tls_nss.c +++ /dev/null @@ -1,680 +0,0 @@ -/* - * SSL/TLS interface functions for NSS - * Copyright (c) 2009, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#include "includes.h" -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "common.h" -#include "tls.h" - -static int tls_nss_ref_count = 0; - -static PRDescIdentity nss_layer_id; - - -struct tls_connection { - PRFileDesc *fd; - - int established; - int verify_peer; - u8 *push_buf, *pull_buf, *pull_buf_offset; - size_t push_buf_len, pull_buf_len; -}; - - -static PRStatus nss_io_close(PRFileDesc *fd) -{ - wpa_printf(MSG_DEBUG, "NSS: I/O close"); - return PR_SUCCESS; -} - - -static PRInt32 nss_io_read(PRFileDesc *fd, void *buf, PRInt32 amount) -{ - wpa_printf(MSG_DEBUG, "NSS: I/O read(%d)", amount); - return PR_FAILURE; -} - - -static PRInt32 nss_io_write(PRFileDesc *fd, const void *buf, PRInt32 amount) -{ - wpa_printf(MSG_DEBUG, "NSS: I/O write(%d)", amount); - return PR_FAILURE; -} - - -static PRInt32 nss_io_writev(PRFileDesc *fd, const PRIOVec *iov, - PRInt32 iov_size, PRIntervalTime timeout) -{ - wpa_printf(MSG_DEBUG, "NSS: I/O writev(%d)", iov_size); - return PR_FAILURE; -} - - -static PRInt32 nss_io_recv(PRFileDesc *fd, void *buf, PRInt32 amount, - PRIntn flags, PRIntervalTime timeout) -{ - struct tls_connection *conn = (struct tls_connection *) fd->secret; - u8 *end; - - wpa_printf(MSG_DEBUG, "NSS: I/O recv(%d)", amount); - - if (conn->pull_buf == NULL) { - wpa_printf(MSG_DEBUG, "NSS: No data available to be read yet"); - return PR_FAILURE; - } - - end = conn->pull_buf + conn->pull_buf_len; - if (end - conn->pull_buf_offset < amount) - amount = end - conn->pull_buf_offset; - os_memcpy(buf, conn->pull_buf_offset, amount); - conn->pull_buf_offset += amount; - if (conn->pull_buf_offset == end) { - wpa_printf(MSG_DEBUG, "%s - pull_buf consumed", __func__); - os_free(conn->pull_buf); - conn->pull_buf = conn->pull_buf_offset = NULL; - conn->pull_buf_len = 0; - } else { - wpa_printf(MSG_DEBUG, "%s - %lu bytes remaining in pull_buf", - __func__, - (unsigned long) (end - conn->pull_buf_offset)); - } - return amount; -} - - -static PRInt32 nss_io_send(PRFileDesc *fd, const void *buf, PRInt32 amount, - PRIntn flags, PRIntervalTime timeout) -{ - struct tls_connection *conn = (struct tls_connection *) fd->secret; - u8 *nbuf; - - wpa_printf(MSG_DEBUG, "NSS: I/O %s", __func__); - wpa_hexdump(MSG_MSGDUMP, "NSS: I/O send data", buf, amount); - - nbuf = os_realloc(conn->push_buf, conn->push_buf_len + amount); - if (nbuf == NULL) { - wpa_printf(MSG_ERROR, "NSS: Failed to allocate memory for the " - "data to be sent"); - return PR_FAILURE; - } - os_memcpy(nbuf + conn->push_buf_len, buf, amount); - conn->push_buf = nbuf; - conn->push_buf_len += amount; - - return amount; -} - - -static PRInt32 nss_io_recvfrom(PRFileDesc *fd, void *buf, PRInt32 amount, - PRIntn flags, PRNetAddr *addr, - PRIntervalTime timeout) -{ - wpa_printf(MSG_DEBUG, "NSS: I/O %s", __func__); - return PR_FAILURE; -} - - -static PRInt32 nss_io_sendto(PRFileDesc *fd, const void *buf, PRInt32 amount, - PRIntn flags, const PRNetAddr *addr, - PRIntervalTime timeout) -{ - wpa_printf(MSG_DEBUG, "NSS: I/O %s", __func__); - return PR_FAILURE; -} - - -static PRStatus nss_io_getpeername(PRFileDesc *fd, PRNetAddr *addr) -{ - wpa_printf(MSG_DEBUG, "NSS: I/O getpeername"); - - /* - * It Looks like NSS only supports IPv4 and IPv6 TCP sockets. Provide a - * fake IPv4 address to work around this even though we are not really - * using TCP. - */ - os_memset(addr, 0, sizeof(*addr)); - addr->inet.family = PR_AF_INET; - - return PR_SUCCESS; -} - - -static PRStatus nss_io_getsocketoption(PRFileDesc *fd, - PRSocketOptionData *data) -{ - switch (data->option) { - case PR_SockOpt_Nonblocking: - wpa_printf(MSG_DEBUG, "NSS: I/O getsocketoption(Nonblocking)"); - data->value.non_blocking = PR_TRUE; - return PR_SUCCESS; - default: - wpa_printf(MSG_DEBUG, "NSS: I/O getsocketoption(%d)", - data->option); - return PR_FAILURE; - } -} - - -static const PRIOMethods nss_io = { - PR_DESC_LAYERED, - nss_io_close, - nss_io_read, - nss_io_write, - NULL /* available */, - NULL /* available64 */, - NULL /* fsync */, - NULL /* fseek */, - NULL /* fseek64 */, - NULL /* fileinfo */, - NULL /* fileinfo64 */, - nss_io_writev, - NULL /* connect */, - NULL /* accept */, - NULL /* bind */, - NULL /* listen */, - NULL /* shutdown */, - nss_io_recv, - nss_io_send, - nss_io_recvfrom, - nss_io_sendto, - NULL /* poll */, - NULL /* acceptread */, - NULL /* transmitfile */, - NULL /* getsockname */, - nss_io_getpeername, - NULL /* reserved_fn_6 */, - NULL /* reserved_fn_5 */, - nss_io_getsocketoption, - NULL /* setsocketoption */, - NULL /* sendfile */, - NULL /* connectcontinue */, - NULL /* reserved_fn_3 */, - NULL /* reserved_fn_2 */, - NULL /* reserved_fn_1 */, - NULL /* reserved_fn_0 */ -}; - - -static char * nss_password_cb(PK11SlotInfo *slot, PRBool retry, void *arg) -{ - wpa_printf(MSG_ERROR, "NSS: TODO - %s", __func__); - return NULL; -} - - -void * tls_init(const struct tls_config *conf) -{ - char *dir; - - tls_nss_ref_count++; - if (tls_nss_ref_count > 1) - return (void *) 1; - - PR_Init(PR_SYSTEM_THREAD, PR_PRIORITY_NORMAL, 1); - - nss_layer_id = PR_GetUniqueIdentity("wpa_supplicant"); - - PK11_SetPasswordFunc(nss_password_cb); - - dir = getenv("SSL_DIR"); - if (dir) { - if (NSS_Init(dir) != SECSuccess) { - wpa_printf(MSG_ERROR, "NSS: NSS_Init(cert_dir=%s) " - "failed", dir); - return NULL; - } - } else { - if (NSS_NoDB_Init(NULL) != SECSuccess) { - wpa_printf(MSG_ERROR, "NSS: NSS_NoDB_Init(NULL) " - "failed"); - return NULL; - } - } - - if (SSL_OptionSetDefault(SSL_V2_COMPATIBLE_HELLO, PR_FALSE) != - SECSuccess || - SSL_OptionSetDefault(SSL_ENABLE_SSL3, PR_FALSE) != SECSuccess || - SSL_OptionSetDefault(SSL_ENABLE_SSL2, PR_FALSE) != SECSuccess || - SSL_OptionSetDefault(SSL_ENABLE_TLS, PR_TRUE) != SECSuccess) { - wpa_printf(MSG_ERROR, "NSS: SSL_OptionSetDefault failed"); - return NULL; - } - - if (NSS_SetDomesticPolicy() != SECSuccess) { - wpa_printf(MSG_ERROR, "NSS: NSS_SetDomesticPolicy() failed"); - return NULL; - } - - return (void *) 1; -} - -void tls_deinit(void *ssl_ctx) -{ - tls_nss_ref_count--; - if (tls_nss_ref_count == 0) { - if (NSS_Shutdown() != SECSuccess) - wpa_printf(MSG_ERROR, "NSS: NSS_Shutdown() failed"); - } -} - - -int tls_get_errors(void *tls_ctx) -{ - return 0; -} - - -static SECStatus nss_bad_cert_cb(void *arg, PRFileDesc *fd) -{ - struct tls_connection *conn = arg; - SECStatus res = SECSuccess; - PRErrorCode err; - CERTCertificate *cert; - char *subject, *issuer; - - err = PR_GetError(); - if (IS_SEC_ERROR(err)) - wpa_printf(MSG_DEBUG, "NSS: Bad Server Certificate (sec err " - "%d)", err - SEC_ERROR_BASE); - else - wpa_printf(MSG_DEBUG, "NSS: Bad Server Certificate (err %d)", - err); - cert = SSL_PeerCertificate(fd); - subject = CERT_NameToAscii(&cert->subject); - issuer = CERT_NameToAscii(&cert->issuer); - wpa_printf(MSG_DEBUG, "NSS: Peer certificate subject='%s' issuer='%s'", - subject, issuer); - CERT_DestroyCertificate(cert); - PR_Free(subject); - PR_Free(issuer); - if (conn->verify_peer) - res = SECFailure; - - return res; -} - - -static void nss_handshake_cb(PRFileDesc *fd, void *client_data) -{ - struct tls_connection *conn = client_data; - wpa_printf(MSG_DEBUG, "NSS: Handshake completed"); - conn->established = 1; -} - - -struct tls_connection * tls_connection_init(void *tls_ctx) -{ - struct tls_connection *conn; - - conn = os_zalloc(sizeof(*conn)); - if (conn == NULL) - return NULL; - - conn->fd = PR_CreateIOLayerStub(nss_layer_id, &nss_io); - if (conn->fd == NULL) { - os_free(conn); - return NULL; - } - conn->fd->secret = (void *) conn; - - conn->fd = SSL_ImportFD(NULL, conn->fd); - if (conn->fd == NULL) { - os_free(conn); - return NULL; - } - - if (SSL_OptionSet(conn->fd, SSL_SECURITY, PR_TRUE) != SECSuccess || - SSL_OptionSet(conn->fd, SSL_HANDSHAKE_AS_CLIENT, PR_TRUE) != - SECSuccess || - SSL_OptionSet(conn->fd, SSL_HANDSHAKE_AS_SERVER, PR_FALSE) != - SECSuccess || - SSL_OptionSet(conn->fd, SSL_ENABLE_TLS, PR_TRUE) != SECSuccess || - SSL_BadCertHook(conn->fd, nss_bad_cert_cb, conn) != SECSuccess || - SSL_HandshakeCallback(conn->fd, nss_handshake_cb, conn) != - SECSuccess) { - wpa_printf(MSG_ERROR, "NSS: Failed to set options"); - PR_Close(conn->fd); - os_free(conn); - return NULL; - } - - SSL_ResetHandshake(conn->fd, PR_FALSE); - - return conn; -} - - -void tls_connection_deinit(void *tls_ctx, struct tls_connection *conn) -{ - PR_Close(conn->fd); - os_free(conn->push_buf); - os_free(conn->pull_buf); - os_free(conn); -} - - -int tls_connection_established(void *tls_ctx, struct tls_connection *conn) -{ - return conn->established; -} - - -int tls_connection_shutdown(void *tls_ctx, struct tls_connection *conn) -{ - return -1; -} - - -int tls_connection_set_params(void *tls_ctx, struct tls_connection *conn, - const struct tls_connection_params *params) -{ - wpa_printf(MSG_ERROR, "NSS: TODO - %s", __func__); - return 0; -} - - -int tls_global_set_params(void *tls_ctx, - const struct tls_connection_params *params) -{ - return -1; -} - - -int tls_global_set_verify(void *tls_ctx, int check_crl) -{ - return -1; -} - - -int tls_connection_set_verify(void *tls_ctx, struct tls_connection *conn, - int verify_peer) -{ - conn->verify_peer = verify_peer; - return 0; -} - - -int tls_connection_set_ia(void *tls_ctx, struct tls_connection *conn, - int tls_ia) -{ - return -1; -} - - -int tls_connection_get_keys(void *tls_ctx, struct tls_connection *conn, - struct tls_keys *keys) -{ - /* NSS does not export master secret or client/server random. */ - return -1; -} - - -int tls_connection_prf(void *tls_ctx, struct tls_connection *conn, - const char *label, int server_random_first, - u8 *out, size_t out_len) -{ - if (conn == NULL || server_random_first) { - wpa_printf(MSG_INFO, "NSS: Unsupported PRF request " - "(server_random_first=%d)", - server_random_first); - return -1; - } - - if (SSL_ExportKeyingMaterial(conn->fd, label, NULL, 0, out, out_len) != - SECSuccess) { - wpa_printf(MSG_INFO, "NSS: Failed to use TLS extractor " - "(label='%s' out_len=%d", label, (int) out_len); - return -1; - } - - return 0; -} - - -struct wpabuf * tls_connection_handshake(void *tls_ctx, - struct tls_connection *conn, - const struct wpabuf *in_data, - struct wpabuf **appl_data) -{ - struct wpabuf *out_data; - - wpa_printf(MSG_DEBUG, "NSS: handshake: in_len=%u", - in_data ? (unsigned int) wpabuf_len(in_data) : 0); - - if (appl_data) - *appl_data = NULL; - - if (in_data && wpabuf_len(in_data) > 0) { - if (conn->pull_buf) { - wpa_printf(MSG_DEBUG, "%s - %lu bytes remaining in " - "pull_buf", __func__, - (unsigned long) conn->pull_buf_len); - os_free(conn->pull_buf); - } - conn->pull_buf = os_malloc(wpabuf_len(in_data)); - if (conn->pull_buf == NULL) - return NULL; - os_memcpy(conn->pull_buf, wpabuf_head(in_data), - wpabuf_len(in_data)); - conn->pull_buf_offset = conn->pull_buf; - conn->pull_buf_len = wpabuf_len(in_data); - } - - SSL_ForceHandshake(conn->fd); - - if (conn->established && conn->push_buf == NULL) { - /* Need to return something to get final TLS ACK. */ - conn->push_buf = os_malloc(1); - } - - if (conn->push_buf == NULL) - return NULL; - out_data = wpabuf_alloc_ext_data(conn->push_buf, conn->push_buf_len); - if (out_data == NULL) - os_free(conn->push_buf); - conn->push_buf = NULL; - conn->push_buf_len = 0; - return out_data; -} - - -struct wpabuf * tls_connection_server_handshake(void *tls_ctx, - struct tls_connection *conn, - const struct wpabuf *in_data, - struct wpabuf **appl_data) -{ - return NULL; -} - - -struct wpabuf * tls_connection_encrypt(void *tls_ctx, - struct tls_connection *conn, - const struct wpabuf *in_data) -{ - PRInt32 res; - struct wpabuf *buf; - - wpa_printf(MSG_DEBUG, "NSS: encrypt %d bytes", - (int) wpabuf_len(in_data)); - res = PR_Send(conn->fd, wpabuf_head(in_data), wpabuf_len(in_data), 0, - 0); - if (res < 0) { - wpa_printf(MSG_ERROR, "NSS: Encryption failed"); - return NULL; - } - if (conn->push_buf == NULL) - return NULL; - buf = wpabuf_alloc_ext_data(conn->push_buf, conn->push_buf_len); - if (buf == NULL) - os_free(conn->push_buf); - conn->push_buf = NULL; - conn->push_buf_len = 0; - return buf; -} - - -struct wpabuf * tls_connection_decrypt(void *tls_ctx, - struct tls_connection *conn, - const struct wpabuf *in_data) -{ - PRInt32 res; - struct wpabuf *out; - - wpa_printf(MSG_DEBUG, "NSS: decrypt %d bytes", - (int) wpabuf_len(in_data)); - if (conn->pull_buf) { - wpa_printf(MSG_DEBUG, "%s - %lu bytes remaining in " - "pull_buf", __func__, - (unsigned long) conn->pull_buf_len); - os_free(conn->pull_buf); - } - conn->pull_buf = os_malloc(wpabuf_len(in_data)); - if (conn->pull_buf == NULL) - return NULL; - os_memcpy(conn->pull_buf, wpabuf_head(in_data), wpabuf_len(in_data)); - conn->pull_buf_offset = conn->pull_buf; - conn->pull_buf_len = wpabuf_len(in_data); - - /* - * Even though we try to disable TLS compression, it is possible that - * this cannot be done with all TLS libraries. Add extra buffer space - * to handle the possibility of the decrypted data being longer than - * input data. - */ - out = wpabuf_alloc((wpabuf_len(in_data) + 500) * 3); - if (out == NULL) - return NULL; - - res = PR_Recv(conn->fd, wpabuf_mhead(out), wpabuf_size(out), 0, 0); - wpa_printf(MSG_DEBUG, "NSS: PR_Recv: %d", res); - if (res < 0) { - wpabuf_free(out); - return NULL; - } - wpabuf_put(out, res); - - return out; -} - - -int tls_connection_resumed(void *tls_ctx, struct tls_connection *conn) -{ - return 0; -} - - -int tls_connection_set_cipher_list(void *tls_ctx, struct tls_connection *conn, - u8 *ciphers) -{ - return -1; -} - - -int tls_get_cipher(void *tls_ctx, struct tls_connection *conn, - char *buf, size_t buflen) -{ - return -1; -} - - -int tls_connection_enable_workaround(void *tls_ctx, - struct tls_connection *conn) -{ - return -1; -} - - -int tls_connection_client_hello_ext(void *tls_ctx, struct tls_connection *conn, - int ext_type, const u8 *data, - size_t data_len) -{ - return -1; -} - - -int tls_connection_get_failed(void *tls_ctx, struct tls_connection *conn) -{ - return 0; -} - - -int tls_connection_get_read_alerts(void *tls_ctx, struct tls_connection *conn) -{ - return 0; -} - - -int tls_connection_get_write_alerts(void *tls_ctx, - struct tls_connection *conn) -{ - return 0; -} - - -int tls_connection_get_keyblock_size(void *tls_ctx, - struct tls_connection *conn) -{ - return -1; -} - - -unsigned int tls_capabilities(void *tls_ctx) -{ - return 0; -} - - -struct wpabuf * tls_connection_ia_send_phase_finished( - void *tls_ctx, struct tls_connection *conn, int final) -{ - return NULL; -} - - -int tls_connection_ia_final_phase_finished(void *tls_ctx, - struct tls_connection *conn) -{ - return -1; -} - - -int tls_connection_ia_permute_inner_secret(void *tls_ctx, - struct tls_connection *conn, - const u8 *key, size_t key_len) -{ - return -1; -} - - -int tls_connection_set_session_ticket_cb(void *tls_ctx, - struct tls_connection *conn, - tls_session_ticket_cb cb, - void *ctx) -{ - return -1; -} diff --git a/hostapd-0.8/src/crypto/tls_openssl.c b/hostapd-0.8/src/crypto/tls_openssl.c deleted file mode 100644 index bf92a11..0000000 --- a/hostapd-0.8/src/crypto/tls_openssl.c +++ /dev/null @@ -1,2992 +0,0 @@ -/* - * SSL/TLS interface functions for OpenSSL - * Copyright (c) 2004-2010, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#include "includes.h" - -#ifndef CONFIG_SMARTCARD -#ifndef OPENSSL_NO_ENGINE -#define OPENSSL_NO_ENGINE -#endif -#endif - -#include -#include -#include -#include -#ifndef OPENSSL_NO_ENGINE -#include -#endif /* OPENSSL_NO_ENGINE */ - -#ifdef ANDROID -#include -#include "keystore_get.h" -#endif /* ANDROID */ - -#include "common.h" -#include "crypto.h" -#include "tls.h" - -#if OPENSSL_VERSION_NUMBER >= 0x0090800fL -#define OPENSSL_d2i_TYPE const unsigned char ** -#else -#define OPENSSL_d2i_TYPE unsigned char ** -#endif - -#ifdef SSL_F_SSL_SET_SESSION_TICKET_EXT -#ifdef SSL_OP_NO_TICKET -/* - * Session ticket override patch was merged into OpenSSL 0.9.9 tree on - * 2008-11-15. This version uses a bit different API compared to the old patch. - */ -#define CONFIG_OPENSSL_TICKET_OVERRIDE -#endif -#endif - -static int tls_openssl_ref_count = 0; - -struct tls_global { - void (*event_cb)(void *ctx, enum tls_event ev, - union tls_event_data *data); - void *cb_ctx; -}; - -static struct tls_global *tls_global = NULL; - - -struct tls_connection { - SSL *ssl; - BIO *ssl_in, *ssl_out; -#ifndef OPENSSL_NO_ENGINE - ENGINE *engine; /* functional reference to the engine */ - EVP_PKEY *private_key; /* the private key if using engine */ -#endif /* OPENSSL_NO_ENGINE */ - char *subject_match, *altsubject_match; - int read_alerts, write_alerts, failed; - - tls_session_ticket_cb session_ticket_cb; - void *session_ticket_cb_ctx; - - /* SessionTicket received from OpenSSL hello_extension_cb (server) */ - u8 *session_ticket; - size_t session_ticket_len; - - unsigned int ca_cert_verify:1; - unsigned int cert_probe:1; - unsigned int server_cert_only:1; - - u8 srv_cert_hash[32]; -}; - - -#ifdef CONFIG_NO_STDOUT_DEBUG - -static void _tls_show_errors(void) -{ - unsigned long err; - - while ((err = ERR_get_error())) { - /* Just ignore the errors, since stdout is disabled */ - } -} -#define tls_show_errors(l, f, t) _tls_show_errors() - -#else /* CONFIG_NO_STDOUT_DEBUG */ - -static void tls_show_errors(int level, const char *func, const char *txt) -{ - unsigned long err; - - wpa_printf(level, "OpenSSL: %s - %s %s", - func, txt, ERR_error_string(ERR_get_error(), NULL)); - - while ((err = ERR_get_error())) { - wpa_printf(MSG_INFO, "OpenSSL: pending error: %s", - ERR_error_string(err, NULL)); - } -} - -#endif /* CONFIG_NO_STDOUT_DEBUG */ - - -#ifdef CONFIG_NATIVE_WINDOWS - -/* Windows CryptoAPI and access to certificate stores */ -#include - -#ifdef __MINGW32_VERSION -/* - * MinGW does not yet include all the needed definitions for CryptoAPI, so - * define here whatever extra is needed. - */ -#define CERT_SYSTEM_STORE_CURRENT_USER (1 << 16) -#define CERT_STORE_READONLY_FLAG 0x00008000 -#define CERT_STORE_OPEN_EXISTING_FLAG 0x00004000 - -#endif /* __MINGW32_VERSION */ - - -struct cryptoapi_rsa_data { - const CERT_CONTEXT *cert; - HCRYPTPROV crypt_prov; - DWORD key_spec; - BOOL free_crypt_prov; -}; - - -static void cryptoapi_error(const char *msg) -{ - wpa_printf(MSG_INFO, "CryptoAPI: %s; err=%u", - msg, (unsigned int) GetLastError()); -} - - -static int cryptoapi_rsa_pub_enc(int flen, const unsigned char *from, - unsigned char *to, RSA *rsa, int padding) -{ - wpa_printf(MSG_DEBUG, "%s - not implemented", __func__); - return 0; -} - - -static int cryptoapi_rsa_pub_dec(int flen, const unsigned char *from, - unsigned char *to, RSA *rsa, int padding) -{ - wpa_printf(MSG_DEBUG, "%s - not implemented", __func__); - return 0; -} - - -static int cryptoapi_rsa_priv_enc(int flen, const unsigned char *from, - unsigned char *to, RSA *rsa, int padding) -{ - struct cryptoapi_rsa_data *priv = - (struct cryptoapi_rsa_data *) rsa->meth->app_data; - HCRYPTHASH hash; - DWORD hash_size, len, i; - unsigned char *buf = NULL; - int ret = 0; - - if (priv == NULL) { - RSAerr(RSA_F_RSA_EAY_PRIVATE_ENCRYPT, - ERR_R_PASSED_NULL_PARAMETER); - return 0; - } - - if (padding != RSA_PKCS1_PADDING) { - RSAerr(RSA_F_RSA_EAY_PRIVATE_ENCRYPT, - RSA_R_UNKNOWN_PADDING_TYPE); - return 0; - } - - if (flen != 16 /* MD5 */ + 20 /* SHA-1 */) { - wpa_printf(MSG_INFO, "%s - only MD5-SHA1 hash supported", - __func__); - RSAerr(RSA_F_RSA_EAY_PRIVATE_ENCRYPT, - RSA_R_INVALID_MESSAGE_LENGTH); - return 0; - } - - if (!CryptCreateHash(priv->crypt_prov, CALG_SSL3_SHAMD5, 0, 0, &hash)) - { - cryptoapi_error("CryptCreateHash failed"); - return 0; - } - - len = sizeof(hash_size); - if (!CryptGetHashParam(hash, HP_HASHSIZE, (BYTE *) &hash_size, &len, - 0)) { - cryptoapi_error("CryptGetHashParam failed"); - goto err; - } - - if ((int) hash_size != flen) { - wpa_printf(MSG_INFO, "CryptoAPI: Invalid hash size (%u != %d)", - (unsigned) hash_size, flen); - RSAerr(RSA_F_RSA_EAY_PRIVATE_ENCRYPT, - RSA_R_INVALID_MESSAGE_LENGTH); - goto err; - } - if (!CryptSetHashParam(hash, HP_HASHVAL, (BYTE * ) from, 0)) { - cryptoapi_error("CryptSetHashParam failed"); - goto err; - } - - len = RSA_size(rsa); - buf = os_malloc(len); - if (buf == NULL) { - RSAerr(RSA_F_RSA_EAY_PRIVATE_ENCRYPT, ERR_R_MALLOC_FAILURE); - goto err; - } - - if (!CryptSignHash(hash, priv->key_spec, NULL, 0, buf, &len)) { - cryptoapi_error("CryptSignHash failed"); - goto err; - } - - for (i = 0; i < len; i++) - to[i] = buf[len - i - 1]; - ret = len; - -err: - os_free(buf); - CryptDestroyHash(hash); - - return ret; -} - - -static int cryptoapi_rsa_priv_dec(int flen, const unsigned char *from, - unsigned char *to, RSA *rsa, int padding) -{ - wpa_printf(MSG_DEBUG, "%s - not implemented", __func__); - return 0; -} - - -static void cryptoapi_free_data(struct cryptoapi_rsa_data *priv) -{ - if (priv == NULL) - return; - if (priv->crypt_prov && priv->free_crypt_prov) - CryptReleaseContext(priv->crypt_prov, 0); - if (priv->cert) - CertFreeCertificateContext(priv->cert); - os_free(priv); -} - - -static int cryptoapi_finish(RSA *rsa) -{ - cryptoapi_free_data((struct cryptoapi_rsa_data *) rsa->meth->app_data); - os_free((void *) rsa->meth); - rsa->meth = NULL; - return 1; -} - - -static const CERT_CONTEXT * cryptoapi_find_cert(const char *name, DWORD store) -{ - HCERTSTORE cs; - const CERT_CONTEXT *ret = NULL; - - cs = CertOpenStore((LPCSTR) CERT_STORE_PROV_SYSTEM, 0, 0, - store | CERT_STORE_OPEN_EXISTING_FLAG | - CERT_STORE_READONLY_FLAG, L"MY"); - if (cs == NULL) { - cryptoapi_error("Failed to open 'My system store'"); - return NULL; - } - - if (strncmp(name, "cert://", 7) == 0) { - unsigned short wbuf[255]; - MultiByteToWideChar(CP_ACP, 0, name + 7, -1, wbuf, 255); - ret = CertFindCertificateInStore(cs, X509_ASN_ENCODING | - PKCS_7_ASN_ENCODING, - 0, CERT_FIND_SUBJECT_STR, - wbuf, NULL); - } else if (strncmp(name, "hash://", 7) == 0) { - CRYPT_HASH_BLOB blob; - int len; - const char *hash = name + 7; - unsigned char *buf; - - len = os_strlen(hash) / 2; - buf = os_malloc(len); - if (buf && hexstr2bin(hash, buf, len) == 0) { - blob.cbData = len; - blob.pbData = buf; - ret = CertFindCertificateInStore(cs, - X509_ASN_ENCODING | - PKCS_7_ASN_ENCODING, - 0, CERT_FIND_HASH, - &blob, NULL); - } - os_free(buf); - } - - CertCloseStore(cs, 0); - - return ret; -} - - -static int tls_cryptoapi_cert(SSL *ssl, const char *name) -{ - X509 *cert = NULL; - RSA *rsa = NULL, *pub_rsa; - struct cryptoapi_rsa_data *priv; - RSA_METHOD *rsa_meth; - - if (name == NULL || - (strncmp(name, "cert://", 7) != 0 && - strncmp(name, "hash://", 7) != 0)) - return -1; - - priv = os_zalloc(sizeof(*priv)); - rsa_meth = os_zalloc(sizeof(*rsa_meth)); - if (priv == NULL || rsa_meth == NULL) { - wpa_printf(MSG_WARNING, "CryptoAPI: Failed to allocate memory " - "for CryptoAPI RSA method"); - os_free(priv); - os_free(rsa_meth); - return -1; - } - - priv->cert = cryptoapi_find_cert(name, CERT_SYSTEM_STORE_CURRENT_USER); - if (priv->cert == NULL) { - priv->cert = cryptoapi_find_cert( - name, CERT_SYSTEM_STORE_LOCAL_MACHINE); - } - if (priv->cert == NULL) { - wpa_printf(MSG_INFO, "CryptoAPI: Could not find certificate " - "'%s'", name); - goto err; - } - - cert = d2i_X509(NULL, (OPENSSL_d2i_TYPE) &priv->cert->pbCertEncoded, - priv->cert->cbCertEncoded); - if (cert == NULL) { - wpa_printf(MSG_INFO, "CryptoAPI: Could not process X509 DER " - "encoding"); - goto err; - } - - if (!CryptAcquireCertificatePrivateKey(priv->cert, - CRYPT_ACQUIRE_COMPARE_KEY_FLAG, - NULL, &priv->crypt_prov, - &priv->key_spec, - &priv->free_crypt_prov)) { - cryptoapi_error("Failed to acquire a private key for the " - "certificate"); - goto err; - } - - rsa_meth->name = "Microsoft CryptoAPI RSA Method"; - rsa_meth->rsa_pub_enc = cryptoapi_rsa_pub_enc; - rsa_meth->rsa_pub_dec = cryptoapi_rsa_pub_dec; - rsa_meth->rsa_priv_enc = cryptoapi_rsa_priv_enc; - rsa_meth->rsa_priv_dec = cryptoapi_rsa_priv_dec; - rsa_meth->finish = cryptoapi_finish; - rsa_meth->flags = RSA_METHOD_FLAG_NO_CHECK; - rsa_meth->app_data = (char *) priv; - - rsa = RSA_new(); - if (rsa == NULL) { - SSLerr(SSL_F_SSL_CTX_USE_CERTIFICATE_FILE, - ERR_R_MALLOC_FAILURE); - goto err; - } - - if (!SSL_use_certificate(ssl, cert)) { - RSA_free(rsa); - rsa = NULL; - goto err; - } - pub_rsa = cert->cert_info->key->pkey->pkey.rsa; - X509_free(cert); - cert = NULL; - - rsa->n = BN_dup(pub_rsa->n); - rsa->e = BN_dup(pub_rsa->e); - if (!RSA_set_method(rsa, rsa_meth)) - goto err; - - if (!SSL_use_RSAPrivateKey(ssl, rsa)) - goto err; - RSA_free(rsa); - - return 0; - -err: - if (cert) - X509_free(cert); - if (rsa) - RSA_free(rsa); - else { - os_free(rsa_meth); - cryptoapi_free_data(priv); - } - return -1; -} - - -static int tls_cryptoapi_ca_cert(SSL_CTX *ssl_ctx, SSL *ssl, const char *name) -{ - HCERTSTORE cs; - PCCERT_CONTEXT ctx = NULL; - X509 *cert; - char buf[128]; - const char *store; -#ifdef UNICODE - WCHAR *wstore; -#endif /* UNICODE */ - - if (name == NULL || strncmp(name, "cert_store://", 13) != 0) - return -1; - - store = name + 13; -#ifdef UNICODE - wstore = os_malloc((os_strlen(store) + 1) * sizeof(WCHAR)); - if (wstore == NULL) - return -1; - wsprintf(wstore, L"%S", store); - cs = CertOpenSystemStore(0, wstore); - os_free(wstore); -#else /* UNICODE */ - cs = CertOpenSystemStore(0, store); -#endif /* UNICODE */ - if (cs == NULL) { - wpa_printf(MSG_DEBUG, "%s: failed to open system cert store " - "'%s': error=%d", __func__, store, - (int) GetLastError()); - return -1; - } - - while ((ctx = CertEnumCertificatesInStore(cs, ctx))) { - cert = d2i_X509(NULL, (OPENSSL_d2i_TYPE) &ctx->pbCertEncoded, - ctx->cbCertEncoded); - if (cert == NULL) { - wpa_printf(MSG_INFO, "CryptoAPI: Could not process " - "X509 DER encoding for CA cert"); - continue; - } - - X509_NAME_oneline(X509_get_subject_name(cert), buf, - sizeof(buf)); - wpa_printf(MSG_DEBUG, "OpenSSL: Loaded CA certificate for " - "system certificate store: subject='%s'", buf); - - if (!X509_STORE_add_cert(ssl_ctx->cert_store, cert)) { - tls_show_errors(MSG_WARNING, __func__, - "Failed to add ca_cert to OpenSSL " - "certificate store"); - } - - X509_free(cert); - } - - if (!CertCloseStore(cs, 0)) { - wpa_printf(MSG_DEBUG, "%s: failed to close system cert store " - "'%s': error=%d", __func__, name + 13, - (int) GetLastError()); - } - - return 0; -} - - -#else /* CONFIG_NATIVE_WINDOWS */ - -static int tls_cryptoapi_cert(SSL *ssl, const char *name) -{ - return -1; -} - -#endif /* CONFIG_NATIVE_WINDOWS */ - - -static void ssl_info_cb(const SSL *ssl, int where, int ret) -{ - const char *str; - int w; - - wpa_printf(MSG_DEBUG, "SSL: (where=0x%x ret=0x%x)", where, ret); - w = where & ~SSL_ST_MASK; - if (w & SSL_ST_CONNECT) - str = "SSL_connect"; - else if (w & SSL_ST_ACCEPT) - str = "SSL_accept"; - else - str = "undefined"; - - if (where & SSL_CB_LOOP) { - wpa_printf(MSG_DEBUG, "SSL: %s:%s", - str, SSL_state_string_long(ssl)); - } else if (where & SSL_CB_ALERT) { - wpa_printf(MSG_INFO, "SSL: SSL3 alert: %s:%s:%s", - where & SSL_CB_READ ? - "read (remote end reported an error)" : - "write (local SSL3 detected an error)", - SSL_alert_type_string_long(ret), - SSL_alert_desc_string_long(ret)); - if ((ret >> 8) == SSL3_AL_FATAL) { - struct tls_connection *conn = - SSL_get_app_data((SSL *) ssl); - if (where & SSL_CB_READ) - conn->read_alerts++; - else - conn->write_alerts++; - } - } else if (where & SSL_CB_EXIT && ret <= 0) { - wpa_printf(MSG_DEBUG, "SSL: %s:%s in %s", - str, ret == 0 ? "failed" : "error", - SSL_state_string_long(ssl)); - } -} - - -#ifndef OPENSSL_NO_ENGINE -/** - * tls_engine_load_dynamic_generic - load any openssl engine - * @pre: an array of commands and values that load an engine initialized - * in the engine specific function - * @post: an array of commands and values that initialize an already loaded - * engine (or %NULL if not required) - * @id: the engine id of the engine to load (only required if post is not %NULL - * - * This function is a generic function that loads any openssl engine. - * - * Returns: 0 on success, -1 on failure - */ -static int tls_engine_load_dynamic_generic(const char *pre[], - const char *post[], const char *id) -{ - ENGINE *engine; - const char *dynamic_id = "dynamic"; - - engine = ENGINE_by_id(id); - if (engine) { - ENGINE_free(engine); - wpa_printf(MSG_DEBUG, "ENGINE: engine '%s' is already " - "available", id); - return 0; - } - ERR_clear_error(); - - engine = ENGINE_by_id(dynamic_id); - if (engine == NULL) { - wpa_printf(MSG_INFO, "ENGINE: Can't find engine %s [%s]", - dynamic_id, - ERR_error_string(ERR_get_error(), NULL)); - return -1; - } - - /* Perform the pre commands. This will load the engine. */ - while (pre && pre[0]) { - wpa_printf(MSG_DEBUG, "ENGINE: '%s' '%s'", pre[0], pre[1]); - if (ENGINE_ctrl_cmd_string(engine, pre[0], pre[1], 0) == 0) { - wpa_printf(MSG_INFO, "ENGINE: ctrl cmd_string failed: " - "%s %s [%s]", pre[0], pre[1], - ERR_error_string(ERR_get_error(), NULL)); - ENGINE_free(engine); - return -1; - } - pre += 2; - } - - /* - * Free the reference to the "dynamic" engine. The loaded engine can - * now be looked up using ENGINE_by_id(). - */ - ENGINE_free(engine); - - engine = ENGINE_by_id(id); - if (engine == NULL) { - wpa_printf(MSG_INFO, "ENGINE: Can't find engine %s [%s]", - id, ERR_error_string(ERR_get_error(), NULL)); - return -1; - } - - while (post && post[0]) { - wpa_printf(MSG_DEBUG, "ENGINE: '%s' '%s'", post[0], post[1]); - if (ENGINE_ctrl_cmd_string(engine, post[0], post[1], 0) == 0) { - wpa_printf(MSG_DEBUG, "ENGINE: ctrl cmd_string failed:" - " %s %s [%s]", post[0], post[1], - ERR_error_string(ERR_get_error(), NULL)); - ENGINE_remove(engine); - ENGINE_free(engine); - return -1; - } - post += 2; - } - ENGINE_free(engine); - - return 0; -} - - -/** - * tls_engine_load_dynamic_pkcs11 - load the pkcs11 engine provided by opensc - * @pkcs11_so_path: pksc11_so_path from the configuration - * @pcks11_module_path: pkcs11_module_path from the configuration - */ -static int tls_engine_load_dynamic_pkcs11(const char *pkcs11_so_path, - const char *pkcs11_module_path) -{ - char *engine_id = "pkcs11"; - const char *pre_cmd[] = { - "SO_PATH", NULL /* pkcs11_so_path */, - "ID", NULL /* engine_id */, - "LIST_ADD", "1", - /* "NO_VCHECK", "1", */ - "LOAD", NULL, - NULL, NULL - }; - const char *post_cmd[] = { - "MODULE_PATH", NULL /* pkcs11_module_path */, - NULL, NULL - }; - - if (!pkcs11_so_path || !pkcs11_module_path) - return 0; - - pre_cmd[1] = pkcs11_so_path; - pre_cmd[3] = engine_id; - post_cmd[1] = pkcs11_module_path; - - wpa_printf(MSG_DEBUG, "ENGINE: Loading pkcs11 Engine from %s", - pkcs11_so_path); - - return tls_engine_load_dynamic_generic(pre_cmd, post_cmd, engine_id); -} - - -/** - * tls_engine_load_dynamic_opensc - load the opensc engine provided by opensc - * @opensc_so_path: opensc_so_path from the configuration - */ -static int tls_engine_load_dynamic_opensc(const char *opensc_so_path) -{ - char *engine_id = "opensc"; - const char *pre_cmd[] = { - "SO_PATH", NULL /* opensc_so_path */, - "ID", NULL /* engine_id */, - "LIST_ADD", "1", - "LOAD", NULL, - NULL, NULL - }; - - if (!opensc_so_path) - return 0; - - pre_cmd[1] = opensc_so_path; - pre_cmd[3] = engine_id; - - wpa_printf(MSG_DEBUG, "ENGINE: Loading OpenSC Engine from %s", - opensc_so_path); - - return tls_engine_load_dynamic_generic(pre_cmd, NULL, engine_id); -} -#endif /* OPENSSL_NO_ENGINE */ - - -void * tls_init(const struct tls_config *conf) -{ - SSL_CTX *ssl; - - if (tls_openssl_ref_count == 0) { - tls_global = os_zalloc(sizeof(*tls_global)); - if (tls_global == NULL) - return NULL; - if (conf) { - tls_global->event_cb = conf->event_cb; - tls_global->cb_ctx = conf->cb_ctx; - } - -#ifdef CONFIG_FIPS -#ifdef OPENSSL_FIPS - if (conf && conf->fips_mode) { - if (!FIPS_mode_set(1)) { - wpa_printf(MSG_ERROR, "Failed to enable FIPS " - "mode"); - ERR_load_crypto_strings(); - ERR_print_errors_fp(stderr); - return NULL; - } else - wpa_printf(MSG_INFO, "Running in FIPS mode"); - } -#else /* OPENSSL_FIPS */ - if (conf && conf->fips_mode) { - wpa_printf(MSG_ERROR, "FIPS mode requested, but not " - "supported"); - return NULL; - } -#endif /* OPENSSL_FIPS */ -#endif /* CONFIG_FIPS */ - SSL_load_error_strings(); - SSL_library_init(); -#if (OPENSSL_VERSION_NUMBER >= 0x0090800fL) && !defined(OPENSSL_NO_SHA256) - EVP_add_digest(EVP_sha256()); -#endif /* OPENSSL_NO_SHA256 */ - /* TODO: if /dev/urandom is available, PRNG is seeded - * automatically. If this is not the case, random data should - * be added here. */ - -#ifdef PKCS12_FUNCS -#ifndef OPENSSL_NO_RC2 - /* - * 40-bit RC2 is commonly used in PKCS#12 files, so enable it. - * This is enabled by PKCS12_PBE_add() in OpenSSL 0.9.8 - * versions, but it looks like OpenSSL 1.0.0 does not do that - * anymore. - */ - EVP_add_cipher(EVP_rc2_40_cbc()); -#endif /* OPENSSL_NO_RC2 */ - PKCS12_PBE_add(); -#endif /* PKCS12_FUNCS */ - } - tls_openssl_ref_count++; - - ssl = SSL_CTX_new(TLSv1_method()); - if (ssl == NULL) - return NULL; - - SSL_CTX_set_info_callback(ssl, ssl_info_cb); - -#ifndef OPENSSL_NO_ENGINE - if (conf && - (conf->opensc_engine_path || conf->pkcs11_engine_path || - conf->pkcs11_module_path)) { - wpa_printf(MSG_DEBUG, "ENGINE: Loading dynamic engine"); - ERR_load_ENGINE_strings(); - ENGINE_load_dynamic(); - - if (tls_engine_load_dynamic_opensc(conf->opensc_engine_path) || - tls_engine_load_dynamic_pkcs11(conf->pkcs11_engine_path, - conf->pkcs11_module_path)) { - tls_deinit(ssl); - return NULL; - } - } -#endif /* OPENSSL_NO_ENGINE */ - - return ssl; -} - - -void tls_deinit(void *ssl_ctx) -{ - SSL_CTX *ssl = ssl_ctx; - SSL_CTX_free(ssl); - - tls_openssl_ref_count--; - if (tls_openssl_ref_count == 0) { -#ifndef OPENSSL_NO_ENGINE - ENGINE_cleanup(); -#endif /* OPENSSL_NO_ENGINE */ - CRYPTO_cleanup_all_ex_data(); - ERR_remove_state(0); - ERR_free_strings(); - EVP_cleanup(); - os_free(tls_global); - tls_global = NULL; - } -} - - -static int tls_engine_init(struct tls_connection *conn, const char *engine_id, - const char *pin, const char *key_id, - const char *cert_id, const char *ca_cert_id) -{ -#ifndef OPENSSL_NO_ENGINE - int ret = -1; - if (engine_id == NULL) { - wpa_printf(MSG_ERROR, "ENGINE: Engine ID not set"); - return -1; - } - if (pin == NULL) { - wpa_printf(MSG_ERROR, "ENGINE: Smartcard PIN not set"); - return -1; - } - if (key_id == NULL) { - wpa_printf(MSG_ERROR, "ENGINE: Key Id not set"); - return -1; - } - - ERR_clear_error(); - conn->engine = ENGINE_by_id(engine_id); - if (!conn->engine) { - wpa_printf(MSG_ERROR, "ENGINE: engine %s not available [%s]", - engine_id, ERR_error_string(ERR_get_error(), NULL)); - goto err; - } - if (ENGINE_init(conn->engine) != 1) { - wpa_printf(MSG_ERROR, "ENGINE: engine init failed " - "(engine: %s) [%s]", engine_id, - ERR_error_string(ERR_get_error(), NULL)); - goto err; - } - wpa_printf(MSG_DEBUG, "ENGINE: engine initialized"); - - if (ENGINE_ctrl_cmd_string(conn->engine, "PIN", pin, 0) == 0) { - wpa_printf(MSG_ERROR, "ENGINE: cannot set pin [%s]", - ERR_error_string(ERR_get_error(), NULL)); - goto err; - } - /* load private key first in-case PIN is required for cert */ - conn->private_key = ENGINE_load_private_key(conn->engine, - key_id, NULL, NULL); - if (!conn->private_key) { - wpa_printf(MSG_ERROR, "ENGINE: cannot load private key with id" - " '%s' [%s]", key_id, - ERR_error_string(ERR_get_error(), NULL)); - ret = TLS_SET_PARAMS_ENGINE_PRV_INIT_FAILED; - goto err; - } - - /* handle a certificate and/or CA certificate */ - if (cert_id || ca_cert_id) { - const char *cmd_name = "LOAD_CERT_CTRL"; - - /* test if the engine supports a LOAD_CERT_CTRL */ - if (!ENGINE_ctrl(conn->engine, ENGINE_CTRL_GET_CMD_FROM_NAME, - 0, (void *)cmd_name, NULL)) { - wpa_printf(MSG_ERROR, "ENGINE: engine does not support" - " loading certificates"); - ret = TLS_SET_PARAMS_ENGINE_PRV_INIT_FAILED; - goto err; - } - } - - return 0; - -err: - if (conn->engine) { - ENGINE_free(conn->engine); - conn->engine = NULL; - } - - if (conn->private_key) { - EVP_PKEY_free(conn->private_key); - conn->private_key = NULL; - } - - return ret; -#else /* OPENSSL_NO_ENGINE */ - return 0; -#endif /* OPENSSL_NO_ENGINE */ -} - - -static void tls_engine_deinit(struct tls_connection *conn) -{ -#ifndef OPENSSL_NO_ENGINE - wpa_printf(MSG_DEBUG, "ENGINE: engine deinit"); - if (conn->private_key) { - EVP_PKEY_free(conn->private_key); - conn->private_key = NULL; - } - if (conn->engine) { - ENGINE_finish(conn->engine); - conn->engine = NULL; - } -#endif /* OPENSSL_NO_ENGINE */ -} - - -int tls_get_errors(void *ssl_ctx) -{ - int count = 0; - unsigned long err; - - while ((err = ERR_get_error())) { - wpa_printf(MSG_INFO, "TLS - SSL error: %s", - ERR_error_string(err, NULL)); - count++; - } - - return count; -} - -struct tls_connection * tls_connection_init(void *ssl_ctx) -{ - SSL_CTX *ssl = ssl_ctx; - struct tls_connection *conn; - long options; - - conn = os_zalloc(sizeof(*conn)); - if (conn == NULL) - return NULL; - conn->ssl = SSL_new(ssl); - if (conn->ssl == NULL) { - tls_show_errors(MSG_INFO, __func__, - "Failed to initialize new SSL connection"); - os_free(conn); - return NULL; - } - - SSL_set_app_data(conn->ssl, conn); - options = SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3 | - SSL_OP_SINGLE_DH_USE; -#ifdef SSL_OP_NO_COMPRESSION - options |= SSL_OP_NO_COMPRESSION; -#endif /* SSL_OP_NO_COMPRESSION */ - SSL_set_options(conn->ssl, options); - - conn->ssl_in = BIO_new(BIO_s_mem()); - if (!conn->ssl_in) { - tls_show_errors(MSG_INFO, __func__, - "Failed to create a new BIO for ssl_in"); - SSL_free(conn->ssl); - os_free(conn); - return NULL; - } - - conn->ssl_out = BIO_new(BIO_s_mem()); - if (!conn->ssl_out) { - tls_show_errors(MSG_INFO, __func__, - "Failed to create a new BIO for ssl_out"); - SSL_free(conn->ssl); - BIO_free(conn->ssl_in); - os_free(conn); - return NULL; - } - - SSL_set_bio(conn->ssl, conn->ssl_in, conn->ssl_out); - - return conn; -} - - -void tls_connection_deinit(void *ssl_ctx, struct tls_connection *conn) -{ - if (conn == NULL) - return; - SSL_free(conn->ssl); - tls_engine_deinit(conn); - os_free(conn->subject_match); - os_free(conn->altsubject_match); - os_free(conn->session_ticket); - os_free(conn); -} - - -int tls_connection_established(void *ssl_ctx, struct tls_connection *conn) -{ - return conn ? SSL_is_init_finished(conn->ssl) : 0; -} - - -int tls_connection_shutdown(void *ssl_ctx, struct tls_connection *conn) -{ - if (conn == NULL) - return -1; - - /* Shutdown previous TLS connection without notifying the peer - * because the connection was already terminated in practice - * and "close notify" shutdown alert would confuse AS. */ - SSL_set_quiet_shutdown(conn->ssl, 1); - SSL_shutdown(conn->ssl); - return 0; -} - - -static int tls_match_altsubject_component(X509 *cert, int type, - const char *value, size_t len) -{ - GENERAL_NAME *gen; - void *ext; - int i, found = 0; - - ext = X509_get_ext_d2i(cert, NID_subject_alt_name, NULL, NULL); - - for (i = 0; ext && i < sk_GENERAL_NAME_num(ext); i++) { - gen = sk_GENERAL_NAME_value(ext, i); - if (gen->type != type) - continue; - if (os_strlen((char *) gen->d.ia5->data) == len && - os_memcmp(value, gen->d.ia5->data, len) == 0) - found++; - } - - return found; -} - - -static int tls_match_altsubject(X509 *cert, const char *match) -{ - int type; - const char *pos, *end; - size_t len; - - pos = match; - do { - if (os_strncmp(pos, "EMAIL:", 6) == 0) { - type = GEN_EMAIL; - pos += 6; - } else if (os_strncmp(pos, "DNS:", 4) == 0) { - type = GEN_DNS; - pos += 4; - } else if (os_strncmp(pos, "URI:", 4) == 0) { - type = GEN_URI; - pos += 4; - } else { - wpa_printf(MSG_INFO, "TLS: Invalid altSubjectName " - "match '%s'", pos); - return 0; - } - end = os_strchr(pos, ';'); - while (end) { - if (os_strncmp(end + 1, "EMAIL:", 6) == 0 || - os_strncmp(end + 1, "DNS:", 4) == 0 || - os_strncmp(end + 1, "URI:", 4) == 0) - break; - end = os_strchr(end + 1, ';'); - } - if (end) - len = end - pos; - else - len = os_strlen(pos); - if (tls_match_altsubject_component(cert, type, pos, len) > 0) - return 1; - pos = end + 1; - } while (end); - - return 0; -} - - -static enum tls_fail_reason openssl_tls_fail_reason(int err) -{ - switch (err) { - case X509_V_ERR_CERT_REVOKED: - return TLS_FAIL_REVOKED; - case X509_V_ERR_CERT_NOT_YET_VALID: - case X509_V_ERR_CRL_NOT_YET_VALID: - return TLS_FAIL_NOT_YET_VALID; - case X509_V_ERR_CERT_HAS_EXPIRED: - case X509_V_ERR_CRL_HAS_EXPIRED: - return TLS_FAIL_EXPIRED; - case X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT: - case X509_V_ERR_UNABLE_TO_GET_CRL: - case X509_V_ERR_UNABLE_TO_GET_CRL_ISSUER: - case X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN: - case X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY: - case X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT: - case X509_V_ERR_UNABLE_TO_VERIFY_LEAF_SIGNATURE: - case X509_V_ERR_CERT_CHAIN_TOO_LONG: - case X509_V_ERR_PATH_LENGTH_EXCEEDED: - case X509_V_ERR_INVALID_CA: - return TLS_FAIL_UNTRUSTED; - case X509_V_ERR_UNABLE_TO_DECRYPT_CERT_SIGNATURE: - case X509_V_ERR_UNABLE_TO_DECRYPT_CRL_SIGNATURE: - case X509_V_ERR_UNABLE_TO_DECODE_ISSUER_PUBLIC_KEY: - case X509_V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD: - case X509_V_ERR_ERROR_IN_CERT_NOT_AFTER_FIELD: - case X509_V_ERR_ERROR_IN_CRL_LAST_UPDATE_FIELD: - case X509_V_ERR_ERROR_IN_CRL_NEXT_UPDATE_FIELD: - case X509_V_ERR_CERT_UNTRUSTED: - case X509_V_ERR_CERT_REJECTED: - return TLS_FAIL_BAD_CERTIFICATE; - default: - return TLS_FAIL_UNSPECIFIED; - } -} - - -static struct wpabuf * get_x509_cert(X509 *cert) -{ - struct wpabuf *buf; - u8 *tmp; - - int cert_len = i2d_X509(cert, NULL); - if (cert_len <= 0) - return NULL; - - buf = wpabuf_alloc(cert_len); - if (buf == NULL) - return NULL; - - tmp = wpabuf_put(buf, cert_len); - i2d_X509(cert, &tmp); - return buf; -} - - -static void openssl_tls_fail_event(struct tls_connection *conn, - X509 *err_cert, int err, int depth, - const char *subject, const char *err_str, - enum tls_fail_reason reason) -{ - union tls_event_data ev; - struct wpabuf *cert = NULL; - - if (tls_global->event_cb == NULL) - return; - - cert = get_x509_cert(err_cert); - os_memset(&ev, 0, sizeof(ev)); - ev.cert_fail.reason = reason != TLS_FAIL_UNSPECIFIED ? - reason : openssl_tls_fail_reason(err); - ev.cert_fail.depth = depth; - ev.cert_fail.subject = subject; - ev.cert_fail.reason_txt = err_str; - ev.cert_fail.cert = cert; - tls_global->event_cb(tls_global->cb_ctx, TLS_CERT_CHAIN_FAILURE, &ev); - wpabuf_free(cert); -} - - -static void openssl_tls_cert_event(struct tls_connection *conn, - X509 *err_cert, int depth, - const char *subject) -{ - struct wpabuf *cert = NULL; - union tls_event_data ev; -#ifdef CONFIG_SHA256 - u8 hash[32]; -#endif /* CONFIG_SHA256 */ - - if (tls_global->event_cb == NULL) - return; - - os_memset(&ev, 0, sizeof(ev)); - if (conn->cert_probe) { - cert = get_x509_cert(err_cert); - ev.peer_cert.cert = cert; - } -#ifdef CONFIG_SHA256 - if (cert) { - const u8 *addr[1]; - size_t len[1]; - addr[0] = wpabuf_head(cert); - len[0] = wpabuf_len(cert); - if (sha256_vector(1, addr, len, hash) == 0) { - ev.peer_cert.hash = hash; - ev.peer_cert.hash_len = sizeof(hash); - } - } -#endif /* CONFIG_SHA256 */ - ev.peer_cert.depth = depth; - ev.peer_cert.subject = subject; - tls_global->event_cb(tls_global->cb_ctx, TLS_PEER_CERTIFICATE, &ev); - wpabuf_free(cert); -} - - -static int tls_verify_cb(int preverify_ok, X509_STORE_CTX *x509_ctx) -{ - char buf[256]; - X509 *err_cert; - int err, depth; - SSL *ssl; - struct tls_connection *conn; - char *match, *altmatch; - const char *err_str; - - err_cert = X509_STORE_CTX_get_current_cert(x509_ctx); - err = X509_STORE_CTX_get_error(x509_ctx); - depth = X509_STORE_CTX_get_error_depth(x509_ctx); - ssl = X509_STORE_CTX_get_ex_data(x509_ctx, - SSL_get_ex_data_X509_STORE_CTX_idx()); - X509_NAME_oneline(X509_get_subject_name(err_cert), buf, sizeof(buf)); - - conn = SSL_get_app_data(ssl); - if (conn == NULL) - return 0; - match = conn->subject_match; - altmatch = conn->altsubject_match; - - if (!preverify_ok && !conn->ca_cert_verify) - preverify_ok = 1; - if (!preverify_ok && depth > 0 && conn->server_cert_only) - preverify_ok = 1; - - err_str = X509_verify_cert_error_string(err); - -#ifdef CONFIG_SHA256 - if (preverify_ok && depth == 0 && conn->server_cert_only) { - struct wpabuf *cert; - cert = get_x509_cert(err_cert); - if (!cert) { - wpa_printf(MSG_DEBUG, "OpenSSL: Could not fetch " - "server certificate data"); - preverify_ok = 0; - } else { - u8 hash[32]; - const u8 *addr[1]; - size_t len[1]; - addr[0] = wpabuf_head(cert); - len[0] = wpabuf_len(cert); - if (sha256_vector(1, addr, len, hash) < 0 || - os_memcmp(conn->srv_cert_hash, hash, 32) != 0) { - err_str = "Server certificate mismatch"; - err = X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN; - preverify_ok = 0; - } - wpabuf_free(cert); - } - } -#endif /* CONFIG_SHA256 */ - - if (!preverify_ok) { - wpa_printf(MSG_WARNING, "TLS: Certificate verification failed," - " error %d (%s) depth %d for '%s'", err, err_str, - depth, buf); - openssl_tls_fail_event(conn, err_cert, err, depth, buf, - err_str, TLS_FAIL_UNSPECIFIED); - return preverify_ok; - } - - wpa_printf(MSG_DEBUG, "TLS: tls_verify_cb - preverify_ok=%d " - "err=%d (%s) ca_cert_verify=%d depth=%d buf='%s'", - preverify_ok, err, err_str, - conn->ca_cert_verify, depth, buf); - if (depth == 0 && match && os_strstr(buf, match) == NULL) { - wpa_printf(MSG_WARNING, "TLS: Subject '%s' did not " - "match with '%s'", buf, match); - preverify_ok = 0; - openssl_tls_fail_event(conn, err_cert, err, depth, buf, - "Subject mismatch", - TLS_FAIL_SUBJECT_MISMATCH); - } else if (depth == 0 && altmatch && - !tls_match_altsubject(err_cert, altmatch)) { - wpa_printf(MSG_WARNING, "TLS: altSubjectName match " - "'%s' not found", altmatch); - preverify_ok = 0; - openssl_tls_fail_event(conn, err_cert, err, depth, buf, - "AltSubject mismatch", - TLS_FAIL_ALTSUBJECT_MISMATCH); - } else - openssl_tls_cert_event(conn, err_cert, depth, buf); - - if (conn->cert_probe && preverify_ok && depth == 0) { - wpa_printf(MSG_DEBUG, "OpenSSL: Reject server certificate " - "on probe-only run"); - preverify_ok = 0; - openssl_tls_fail_event(conn, err_cert, err, depth, buf, - "Server certificate chain probe", - TLS_FAIL_SERVER_CHAIN_PROBE); - } - - return preverify_ok; -} - - -#ifndef OPENSSL_NO_STDIO -static int tls_load_ca_der(void *_ssl_ctx, const char *ca_cert) -{ - SSL_CTX *ssl_ctx = _ssl_ctx; - X509_LOOKUP *lookup; - int ret = 0; - - lookup = X509_STORE_add_lookup(ssl_ctx->cert_store, - X509_LOOKUP_file()); - if (lookup == NULL) { - tls_show_errors(MSG_WARNING, __func__, - "Failed add lookup for X509 store"); - return -1; - } - - if (!X509_LOOKUP_load_file(lookup, ca_cert, X509_FILETYPE_ASN1)) { - unsigned long err = ERR_peek_error(); - tls_show_errors(MSG_WARNING, __func__, - "Failed load CA in DER format"); - if (ERR_GET_LIB(err) == ERR_LIB_X509 && - ERR_GET_REASON(err) == X509_R_CERT_ALREADY_IN_HASH_TABLE) { - wpa_printf(MSG_DEBUG, "OpenSSL: %s - ignoring " - "cert already in hash table error", - __func__); - } else - ret = -1; - } - - return ret; -} -#endif /* OPENSSL_NO_STDIO */ - - -#ifdef ANDROID -static BIO * BIO_from_keystore(const char *key) -{ - BIO *bio = NULL; - char value[KEYSTORE_MESSAGE_SIZE]; - int length = keystore_get(key, strlen(key), value); - if (length != -1 && (bio = BIO_new(BIO_s_mem())) != NULL) - BIO_write(bio, value, length); - return bio; -} -#endif /* ANDROID */ - - -static int tls_connection_ca_cert(void *_ssl_ctx, struct tls_connection *conn, - const char *ca_cert, const u8 *ca_cert_blob, - size_t ca_cert_blob_len, const char *ca_path) -{ - SSL_CTX *ssl_ctx = _ssl_ctx; - - /* - * Remove previously configured trusted CA certificates before adding - * new ones. - */ - X509_STORE_free(ssl_ctx->cert_store); - ssl_ctx->cert_store = X509_STORE_new(); - if (ssl_ctx->cert_store == NULL) { - wpa_printf(MSG_DEBUG, "OpenSSL: %s - failed to allocate new " - "certificate store", __func__); - return -1; - } - - SSL_set_verify(conn->ssl, SSL_VERIFY_PEER, tls_verify_cb); - conn->ca_cert_verify = 1; - - if (ca_cert && os_strncmp(ca_cert, "probe://", 8) == 0) { - wpa_printf(MSG_DEBUG, "OpenSSL: Probe for server certificate " - "chain"); - conn->cert_probe = 1; - conn->ca_cert_verify = 0; - return 0; - } - - if (ca_cert && os_strncmp(ca_cert, "hash://", 7) == 0) { -#ifdef CONFIG_SHA256 - const char *pos = ca_cert + 7; - if (os_strncmp(pos, "server/sha256/", 14) != 0) { - wpa_printf(MSG_DEBUG, "OpenSSL: Unsupported ca_cert " - "hash value '%s'", ca_cert); - return -1; - } - pos += 14; - if (os_strlen(pos) != 32 * 2) { - wpa_printf(MSG_DEBUG, "OpenSSL: Unexpected SHA256 " - "hash length in ca_cert '%s'", ca_cert); - return -1; - } - if (hexstr2bin(pos, conn->srv_cert_hash, 32) < 0) { - wpa_printf(MSG_DEBUG, "OpenSSL: Invalid SHA256 hash " - "value in ca_cert '%s'", ca_cert); - return -1; - } - conn->server_cert_only = 1; - wpa_printf(MSG_DEBUG, "OpenSSL: Checking only server " - "certificate match"); - return 0; -#else /* CONFIG_SHA256 */ - wpa_printf(MSG_INFO, "No SHA256 included in the build - " - "cannot validate server certificate hash"); - return -1; -#endif /* CONFIG_SHA256 */ - } - - if (ca_cert_blob) { - X509 *cert = d2i_X509(NULL, (OPENSSL_d2i_TYPE) &ca_cert_blob, - ca_cert_blob_len); - if (cert == NULL) { - tls_show_errors(MSG_WARNING, __func__, - "Failed to parse ca_cert_blob"); - return -1; - } - - if (!X509_STORE_add_cert(ssl_ctx->cert_store, cert)) { - unsigned long err = ERR_peek_error(); - tls_show_errors(MSG_WARNING, __func__, - "Failed to add ca_cert_blob to " - "certificate store"); - if (ERR_GET_LIB(err) == ERR_LIB_X509 && - ERR_GET_REASON(err) == - X509_R_CERT_ALREADY_IN_HASH_TABLE) { - wpa_printf(MSG_DEBUG, "OpenSSL: %s - ignoring " - "cert already in hash table error", - __func__); - } else { - X509_free(cert); - return -1; - } - } - X509_free(cert); - wpa_printf(MSG_DEBUG, "OpenSSL: %s - added ca_cert_blob " - "to certificate store", __func__); - return 0; - } - -#ifdef ANDROID - if (ca_cert && os_strncmp("keystore://", ca_cert, 11) == 0) { - BIO *bio = BIO_from_keystore(&ca_cert[11]); - STACK_OF(X509_INFO) *stack = NULL; - int i; - - if (bio) { - stack = PEM_X509_INFO_read_bio(bio, NULL, NULL, NULL); - BIO_free(bio); - } - if (!stack) - return -1; - - for (i = 0; i < sk_X509_INFO_num(stack); ++i) { - X509_INFO *info = sk_X509_INFO_value(stack, i); - if (info->x509) { - X509_STORE_add_cert(ssl_ctx->cert_store, - info->x509); - } - if (info->crl) { - X509_STORE_add_crl(ssl_ctx->cert_store, - info->crl); - } - } - sk_X509_INFO_pop_free(stack, X509_INFO_free); - SSL_set_verify(conn->ssl, SSL_VERIFY_PEER, tls_verify_cb); - return 0; - } -#endif /* ANDROID */ - -#ifdef CONFIG_NATIVE_WINDOWS - if (ca_cert && tls_cryptoapi_ca_cert(ssl_ctx, conn->ssl, ca_cert) == - 0) { - wpa_printf(MSG_DEBUG, "OpenSSL: Added CA certificates from " - "system certificate store"); - return 0; - } -#endif /* CONFIG_NATIVE_WINDOWS */ - - if (ca_cert || ca_path) { -#ifndef OPENSSL_NO_STDIO - if (SSL_CTX_load_verify_locations(ssl_ctx, ca_cert, ca_path) != - 1) { - tls_show_errors(MSG_WARNING, __func__, - "Failed to load root certificates"); - if (ca_cert && - tls_load_ca_der(ssl_ctx, ca_cert) == 0) { - wpa_printf(MSG_DEBUG, "OpenSSL: %s - loaded " - "DER format CA certificate", - __func__); - } else - return -1; - } else { - wpa_printf(MSG_DEBUG, "TLS: Trusted root " - "certificate(s) loaded"); - tls_get_errors(ssl_ctx); - } -#else /* OPENSSL_NO_STDIO */ - wpa_printf(MSG_DEBUG, "OpenSSL: %s - OPENSSL_NO_STDIO", - __func__); - return -1; -#endif /* OPENSSL_NO_STDIO */ - } else { - /* No ca_cert configured - do not try to verify server - * certificate */ - conn->ca_cert_verify = 0; - } - - return 0; -} - - -static int tls_global_ca_cert(SSL_CTX *ssl_ctx, const char *ca_cert) -{ - if (ca_cert) { - if (SSL_CTX_load_verify_locations(ssl_ctx, ca_cert, NULL) != 1) - { - tls_show_errors(MSG_WARNING, __func__, - "Failed to load root certificates"); - return -1; - } - - wpa_printf(MSG_DEBUG, "TLS: Trusted root " - "certificate(s) loaded"); - -#ifndef OPENSSL_NO_STDIO - /* Add the same CAs to the client certificate requests */ - SSL_CTX_set_client_CA_list(ssl_ctx, - SSL_load_client_CA_file(ca_cert)); -#endif /* OPENSSL_NO_STDIO */ - } - - return 0; -} - - -int tls_global_set_verify(void *ssl_ctx, int check_crl) -{ - int flags; - - if (check_crl) { - X509_STORE *cs = SSL_CTX_get_cert_store(ssl_ctx); - if (cs == NULL) { - tls_show_errors(MSG_INFO, __func__, "Failed to get " - "certificate store when enabling " - "check_crl"); - return -1; - } - flags = X509_V_FLAG_CRL_CHECK; - if (check_crl == 2) - flags |= X509_V_FLAG_CRL_CHECK_ALL; - X509_STORE_set_flags(cs, flags); - } - return 0; -} - - -static int tls_connection_set_subject_match(struct tls_connection *conn, - const char *subject_match, - const char *altsubject_match) -{ - os_free(conn->subject_match); - conn->subject_match = NULL; - if (subject_match) { - conn->subject_match = os_strdup(subject_match); - if (conn->subject_match == NULL) - return -1; - } - - os_free(conn->altsubject_match); - conn->altsubject_match = NULL; - if (altsubject_match) { - conn->altsubject_match = os_strdup(altsubject_match); - if (conn->altsubject_match == NULL) - return -1; - } - - return 0; -} - - -int tls_connection_set_verify(void *ssl_ctx, struct tls_connection *conn, - int verify_peer) -{ - static int counter = 0; - - if (conn == NULL) - return -1; - - if (verify_peer) { - conn->ca_cert_verify = 1; - SSL_set_verify(conn->ssl, SSL_VERIFY_PEER | - SSL_VERIFY_FAIL_IF_NO_PEER_CERT | - SSL_VERIFY_CLIENT_ONCE, tls_verify_cb); - } else { - conn->ca_cert_verify = 0; - SSL_set_verify(conn->ssl, SSL_VERIFY_NONE, NULL); - } - - SSL_set_accept_state(conn->ssl); - - /* - * Set session id context in order to avoid fatal errors when client - * tries to resume a session. However, set the context to a unique - * value in order to effectively disable session resumption for now - * since not all areas of the server code are ready for it (e.g., - * EAP-TTLS needs special handling for Phase 2 after abbreviated TLS - * handshake). - */ - counter++; - SSL_set_session_id_context(conn->ssl, - (const unsigned char *) &counter, - sizeof(counter)); - - return 0; -} - - -static int tls_connection_client_cert(struct tls_connection *conn, - const char *client_cert, - const u8 *client_cert_blob, - size_t client_cert_blob_len) -{ - if (client_cert == NULL && client_cert_blob == NULL) - return 0; - - if (client_cert_blob && - SSL_use_certificate_ASN1(conn->ssl, (u8 *) client_cert_blob, - client_cert_blob_len) == 1) { - wpa_printf(MSG_DEBUG, "OpenSSL: SSL_use_certificate_ASN1 --> " - "OK"); - return 0; - } else if (client_cert_blob) { - tls_show_errors(MSG_DEBUG, __func__, - "SSL_use_certificate_ASN1 failed"); - } - - if (client_cert == NULL) - return -1; - -#ifdef ANDROID - if (os_strncmp("keystore://", client_cert, 11) == 0) { - BIO *bio = BIO_from_keystore(&client_cert[11]); - X509 *x509 = NULL; - int ret = -1; - if (bio) { - x509 = PEM_read_bio_X509(bio, NULL, NULL, NULL); - BIO_free(bio); - } - if (x509) { - if (SSL_use_certificate(conn->ssl, x509) == 1) - ret = 0; - X509_free(x509); - } - return ret; - } -#endif /* ANDROID */ - -#ifndef OPENSSL_NO_STDIO - if (SSL_use_certificate_file(conn->ssl, client_cert, - SSL_FILETYPE_ASN1) == 1) { - wpa_printf(MSG_DEBUG, "OpenSSL: SSL_use_certificate_file (DER)" - " --> OK"); - return 0; - } - - if (SSL_use_certificate_file(conn->ssl, client_cert, - SSL_FILETYPE_PEM) == 1) { - ERR_clear_error(); - wpa_printf(MSG_DEBUG, "OpenSSL: SSL_use_certificate_file (PEM)" - " --> OK"); - return 0; - } - - tls_show_errors(MSG_DEBUG, __func__, - "SSL_use_certificate_file failed"); -#else /* OPENSSL_NO_STDIO */ - wpa_printf(MSG_DEBUG, "OpenSSL: %s - OPENSSL_NO_STDIO", __func__); -#endif /* OPENSSL_NO_STDIO */ - - return -1; -} - - -static int tls_global_client_cert(SSL_CTX *ssl_ctx, const char *client_cert) -{ -#ifndef OPENSSL_NO_STDIO - if (client_cert == NULL) - return 0; - - if (SSL_CTX_use_certificate_file(ssl_ctx, client_cert, - SSL_FILETYPE_ASN1) != 1 && - SSL_CTX_use_certificate_file(ssl_ctx, client_cert, - SSL_FILETYPE_PEM) != 1) { - tls_show_errors(MSG_INFO, __func__, - "Failed to load client certificate"); - return -1; - } - return 0; -#else /* OPENSSL_NO_STDIO */ - if (client_cert == NULL) - return 0; - wpa_printf(MSG_DEBUG, "OpenSSL: %s - OPENSSL_NO_STDIO", __func__); - return -1; -#endif /* OPENSSL_NO_STDIO */ -} - - -static int tls_passwd_cb(char *buf, int size, int rwflag, void *password) -{ - if (password == NULL) { - return 0; - } - os_strlcpy(buf, (char *) password, size); - return os_strlen(buf); -} - - -#ifdef PKCS12_FUNCS -static int tls_parse_pkcs12(SSL_CTX *ssl_ctx, SSL *ssl, PKCS12 *p12, - const char *passwd) -{ - EVP_PKEY *pkey; - X509 *cert; - STACK_OF(X509) *certs; - int res = 0; - char buf[256]; - - pkey = NULL; - cert = NULL; - certs = NULL; - if (!PKCS12_parse(p12, passwd, &pkey, &cert, &certs)) { - tls_show_errors(MSG_DEBUG, __func__, - "Failed to parse PKCS12 file"); - PKCS12_free(p12); - return -1; - } - wpa_printf(MSG_DEBUG, "TLS: Successfully parsed PKCS12 data"); - - if (cert) { - X509_NAME_oneline(X509_get_subject_name(cert), buf, - sizeof(buf)); - wpa_printf(MSG_DEBUG, "TLS: Got certificate from PKCS12: " - "subject='%s'", buf); - if (ssl) { - if (SSL_use_certificate(ssl, cert) != 1) - res = -1; - } else { - if (SSL_CTX_use_certificate(ssl_ctx, cert) != 1) - res = -1; - } - X509_free(cert); - } - - if (pkey) { - wpa_printf(MSG_DEBUG, "TLS: Got private key from PKCS12"); - if (ssl) { - if (SSL_use_PrivateKey(ssl, pkey) != 1) - res = -1; - } else { - if (SSL_CTX_use_PrivateKey(ssl_ctx, pkey) != 1) - res = -1; - } - EVP_PKEY_free(pkey); - } - - if (certs) { - while ((cert = sk_X509_pop(certs)) != NULL) { - X509_NAME_oneline(X509_get_subject_name(cert), buf, - sizeof(buf)); - wpa_printf(MSG_DEBUG, "TLS: additional certificate" - " from PKCS12: subject='%s'", buf); - /* - * There is no SSL equivalent for the chain cert - so - * always add it to the context... - */ - if (SSL_CTX_add_extra_chain_cert(ssl_ctx, cert) != 1) { - res = -1; - break; - } - } - sk_X509_free(certs); - } - - PKCS12_free(p12); - - if (res < 0) - tls_get_errors(ssl_ctx); - - return res; -} -#endif /* PKCS12_FUNCS */ - - -static int tls_read_pkcs12(SSL_CTX *ssl_ctx, SSL *ssl, const char *private_key, - const char *passwd) -{ -#ifdef PKCS12_FUNCS - FILE *f; - PKCS12 *p12; - - f = fopen(private_key, "rb"); - if (f == NULL) - return -1; - - p12 = d2i_PKCS12_fp(f, NULL); - fclose(f); - - if (p12 == NULL) { - tls_show_errors(MSG_INFO, __func__, - "Failed to use PKCS#12 file"); - return -1; - } - - return tls_parse_pkcs12(ssl_ctx, ssl, p12, passwd); - -#else /* PKCS12_FUNCS */ - wpa_printf(MSG_INFO, "TLS: PKCS12 support disabled - cannot read " - "p12/pfx files"); - return -1; -#endif /* PKCS12_FUNCS */ -} - - -static int tls_read_pkcs12_blob(SSL_CTX *ssl_ctx, SSL *ssl, - const u8 *blob, size_t len, const char *passwd) -{ -#ifdef PKCS12_FUNCS - PKCS12 *p12; - - p12 = d2i_PKCS12(NULL, (OPENSSL_d2i_TYPE) &blob, len); - if (p12 == NULL) { - tls_show_errors(MSG_INFO, __func__, - "Failed to use PKCS#12 blob"); - return -1; - } - - return tls_parse_pkcs12(ssl_ctx, ssl, p12, passwd); - -#else /* PKCS12_FUNCS */ - wpa_printf(MSG_INFO, "TLS: PKCS12 support disabled - cannot parse " - "p12/pfx blobs"); - return -1; -#endif /* PKCS12_FUNCS */ -} - - -#ifndef OPENSSL_NO_ENGINE -static int tls_engine_get_cert(struct tls_connection *conn, - const char *cert_id, - X509 **cert) -{ - /* this runs after the private key is loaded so no PIN is required */ - struct { - const char *cert_id; - X509 *cert; - } params; - params.cert_id = cert_id; - params.cert = NULL; - - if (!ENGINE_ctrl_cmd(conn->engine, "LOAD_CERT_CTRL", - 0, ¶ms, NULL, 1)) { - wpa_printf(MSG_ERROR, "ENGINE: cannot load client cert with id" - " '%s' [%s]", cert_id, - ERR_error_string(ERR_get_error(), NULL)); - return TLS_SET_PARAMS_ENGINE_PRV_INIT_FAILED; - } - if (!params.cert) { - wpa_printf(MSG_ERROR, "ENGINE: did not properly cert with id" - " '%s'", cert_id); - return TLS_SET_PARAMS_ENGINE_PRV_INIT_FAILED; - } - *cert = params.cert; - return 0; -} -#endif /* OPENSSL_NO_ENGINE */ - - -static int tls_connection_engine_client_cert(struct tls_connection *conn, - const char *cert_id) -{ -#ifndef OPENSSL_NO_ENGINE - X509 *cert; - - if (tls_engine_get_cert(conn, cert_id, &cert)) - return -1; - - if (!SSL_use_certificate(conn->ssl, cert)) { - tls_show_errors(MSG_ERROR, __func__, - "SSL_use_certificate failed"); - X509_free(cert); - return -1; - } - X509_free(cert); - wpa_printf(MSG_DEBUG, "ENGINE: SSL_use_certificate --> " - "OK"); - return 0; - -#else /* OPENSSL_NO_ENGINE */ - return -1; -#endif /* OPENSSL_NO_ENGINE */ -} - - -static int tls_connection_engine_ca_cert(void *_ssl_ctx, - struct tls_connection *conn, - const char *ca_cert_id) -{ -#ifndef OPENSSL_NO_ENGINE - X509 *cert; - SSL_CTX *ssl_ctx = _ssl_ctx; - - if (tls_engine_get_cert(conn, ca_cert_id, &cert)) - return -1; - - /* start off the same as tls_connection_ca_cert */ - X509_STORE_free(ssl_ctx->cert_store); - ssl_ctx->cert_store = X509_STORE_new(); - if (ssl_ctx->cert_store == NULL) { - wpa_printf(MSG_DEBUG, "OpenSSL: %s - failed to allocate new " - "certificate store", __func__); - X509_free(cert); - return -1; - } - if (!X509_STORE_add_cert(ssl_ctx->cert_store, cert)) { - unsigned long err = ERR_peek_error(); - tls_show_errors(MSG_WARNING, __func__, - "Failed to add CA certificate from engine " - "to certificate store"); - if (ERR_GET_LIB(err) == ERR_LIB_X509 && - ERR_GET_REASON(err) == X509_R_CERT_ALREADY_IN_HASH_TABLE) { - wpa_printf(MSG_DEBUG, "OpenSSL: %s - ignoring cert" - " already in hash table error", - __func__); - } else { - X509_free(cert); - return -1; - } - } - X509_free(cert); - wpa_printf(MSG_DEBUG, "OpenSSL: %s - added CA certificate from engine " - "to certificate store", __func__); - SSL_set_verify(conn->ssl, SSL_VERIFY_PEER, tls_verify_cb); - return 0; - -#else /* OPENSSL_NO_ENGINE */ - return -1; -#endif /* OPENSSL_NO_ENGINE */ -} - - -static int tls_connection_engine_private_key(struct tls_connection *conn) -{ -#ifndef OPENSSL_NO_ENGINE - if (SSL_use_PrivateKey(conn->ssl, conn->private_key) != 1) { - tls_show_errors(MSG_ERROR, __func__, - "ENGINE: cannot use private key for TLS"); - return -1; - } - if (!SSL_check_private_key(conn->ssl)) { - tls_show_errors(MSG_INFO, __func__, - "Private key failed verification"); - return -1; - } - return 0; -#else /* OPENSSL_NO_ENGINE */ - wpa_printf(MSG_ERROR, "SSL: Configuration uses engine, but " - "engine support was not compiled in"); - return -1; -#endif /* OPENSSL_NO_ENGINE */ -} - - -static int tls_connection_private_key(void *_ssl_ctx, - struct tls_connection *conn, - const char *private_key, - const char *private_key_passwd, - const u8 *private_key_blob, - size_t private_key_blob_len) -{ - SSL_CTX *ssl_ctx = _ssl_ctx; - char *passwd; - int ok; - - if (private_key == NULL && private_key_blob == NULL) - return 0; - - if (private_key_passwd) { - passwd = os_strdup(private_key_passwd); - if (passwd == NULL) - return -1; - } else - passwd = NULL; - - SSL_CTX_set_default_passwd_cb(ssl_ctx, tls_passwd_cb); - SSL_CTX_set_default_passwd_cb_userdata(ssl_ctx, passwd); - - ok = 0; - while (private_key_blob) { - if (SSL_use_PrivateKey_ASN1(EVP_PKEY_RSA, conn->ssl, - (u8 *) private_key_blob, - private_key_blob_len) == 1) { - wpa_printf(MSG_DEBUG, "OpenSSL: SSL_use_PrivateKey_" - "ASN1(EVP_PKEY_RSA) --> OK"); - ok = 1; - break; - } - - if (SSL_use_PrivateKey_ASN1(EVP_PKEY_DSA, conn->ssl, - (u8 *) private_key_blob, - private_key_blob_len) == 1) { - wpa_printf(MSG_DEBUG, "OpenSSL: SSL_use_PrivateKey_" - "ASN1(EVP_PKEY_DSA) --> OK"); - ok = 1; - break; - } - - if (SSL_use_RSAPrivateKey_ASN1(conn->ssl, - (u8 *) private_key_blob, - private_key_blob_len) == 1) { - wpa_printf(MSG_DEBUG, "OpenSSL: " - "SSL_use_RSAPrivateKey_ASN1 --> OK"); - ok = 1; - break; - } - - if (tls_read_pkcs12_blob(ssl_ctx, conn->ssl, private_key_blob, - private_key_blob_len, passwd) == 0) { - wpa_printf(MSG_DEBUG, "OpenSSL: PKCS#12 as blob --> " - "OK"); - ok = 1; - break; - } - - break; - } - -#ifdef ANDROID - if (!ok && private_key && - os_strncmp("keystore://", private_key, 11) == 0) { - BIO *bio = BIO_from_keystore(&private_key[11]); - EVP_PKEY *pkey = NULL; - if (bio) { - pkey = PEM_read_bio_PrivateKey(bio, NULL, NULL, NULL); - BIO_free(bio); - } - if (pkey) { - if (SSL_use_PrivateKey(conn->ssl, pkey) == 1) { - wpa_printf(MSG_DEBUG, "OpenSSL: Private key " - "from keystore"); - ok = 1; - } - EVP_PKEY_free(pkey); - } - } -#endif /* ANDROID */ - - while (!ok && private_key) { -#ifndef OPENSSL_NO_STDIO - if (SSL_use_PrivateKey_file(conn->ssl, private_key, - SSL_FILETYPE_ASN1) == 1) { - wpa_printf(MSG_DEBUG, "OpenSSL: " - "SSL_use_PrivateKey_File (DER) --> OK"); - ok = 1; - break; - } - - if (SSL_use_PrivateKey_file(conn->ssl, private_key, - SSL_FILETYPE_PEM) == 1) { - wpa_printf(MSG_DEBUG, "OpenSSL: " - "SSL_use_PrivateKey_File (PEM) --> OK"); - ok = 1; - break; - } -#else /* OPENSSL_NO_STDIO */ - wpa_printf(MSG_DEBUG, "OpenSSL: %s - OPENSSL_NO_STDIO", - __func__); -#endif /* OPENSSL_NO_STDIO */ - - if (tls_read_pkcs12(ssl_ctx, conn->ssl, private_key, passwd) - == 0) { - wpa_printf(MSG_DEBUG, "OpenSSL: Reading PKCS#12 file " - "--> OK"); - ok = 1; - break; - } - - if (tls_cryptoapi_cert(conn->ssl, private_key) == 0) { - wpa_printf(MSG_DEBUG, "OpenSSL: Using CryptoAPI to " - "access certificate store --> OK"); - ok = 1; - break; - } - - break; - } - - if (!ok) { - tls_show_errors(MSG_INFO, __func__, - "Failed to load private key"); - os_free(passwd); - return -1; - } - ERR_clear_error(); - SSL_CTX_set_default_passwd_cb(ssl_ctx, NULL); - os_free(passwd); - - if (!SSL_check_private_key(conn->ssl)) { - tls_show_errors(MSG_INFO, __func__, "Private key failed " - "verification"); - return -1; - } - - wpa_printf(MSG_DEBUG, "SSL: Private key loaded successfully"); - return 0; -} - - -static int tls_global_private_key(SSL_CTX *ssl_ctx, const char *private_key, - const char *private_key_passwd) -{ - char *passwd; - - if (private_key == NULL) - return 0; - - if (private_key_passwd) { - passwd = os_strdup(private_key_passwd); - if (passwd == NULL) - return -1; - } else - passwd = NULL; - - SSL_CTX_set_default_passwd_cb(ssl_ctx, tls_passwd_cb); - SSL_CTX_set_default_passwd_cb_userdata(ssl_ctx, passwd); - if ( -#ifndef OPENSSL_NO_STDIO - SSL_CTX_use_PrivateKey_file(ssl_ctx, private_key, - SSL_FILETYPE_ASN1) != 1 && - SSL_CTX_use_PrivateKey_file(ssl_ctx, private_key, - SSL_FILETYPE_PEM) != 1 && -#endif /* OPENSSL_NO_STDIO */ - tls_read_pkcs12(ssl_ctx, NULL, private_key, passwd)) { - tls_show_errors(MSG_INFO, __func__, - "Failed to load private key"); - os_free(passwd); - ERR_clear_error(); - return -1; - } - os_free(passwd); - ERR_clear_error(); - SSL_CTX_set_default_passwd_cb(ssl_ctx, NULL); - - if (!SSL_CTX_check_private_key(ssl_ctx)) { - tls_show_errors(MSG_INFO, __func__, - "Private key failed verification"); - return -1; - } - - return 0; -} - - -static int tls_connection_dh(struct tls_connection *conn, const char *dh_file) -{ -#ifdef OPENSSL_NO_DH - if (dh_file == NULL) - return 0; - wpa_printf(MSG_ERROR, "TLS: openssl does not include DH support, but " - "dh_file specified"); - return -1; -#else /* OPENSSL_NO_DH */ - DH *dh; - BIO *bio; - - /* TODO: add support for dh_blob */ - if (dh_file == NULL) - return 0; - if (conn == NULL) - return -1; - - bio = BIO_new_file(dh_file, "r"); - if (bio == NULL) { - wpa_printf(MSG_INFO, "TLS: Failed to open DH file '%s': %s", - dh_file, ERR_error_string(ERR_get_error(), NULL)); - return -1; - } - dh = PEM_read_bio_DHparams(bio, NULL, NULL, NULL); - BIO_free(bio); -#ifndef OPENSSL_NO_DSA - while (dh == NULL) { - DSA *dsa; - wpa_printf(MSG_DEBUG, "TLS: Failed to parse DH file '%s': %s -" - " trying to parse as DSA params", dh_file, - ERR_error_string(ERR_get_error(), NULL)); - bio = BIO_new_file(dh_file, "r"); - if (bio == NULL) - break; - dsa = PEM_read_bio_DSAparams(bio, NULL, NULL, NULL); - BIO_free(bio); - if (!dsa) { - wpa_printf(MSG_DEBUG, "TLS: Failed to parse DSA file " - "'%s': %s", dh_file, - ERR_error_string(ERR_get_error(), NULL)); - break; - } - - wpa_printf(MSG_DEBUG, "TLS: DH file in DSA param format"); - dh = DSA_dup_DH(dsa); - DSA_free(dsa); - if (dh == NULL) { - wpa_printf(MSG_INFO, "TLS: Failed to convert DSA " - "params into DH params"); - break; - } - break; - } -#endif /* !OPENSSL_NO_DSA */ - if (dh == NULL) { - wpa_printf(MSG_INFO, "TLS: Failed to read/parse DH/DSA file " - "'%s'", dh_file); - return -1; - } - - if (SSL_set_tmp_dh(conn->ssl, dh) != 1) { - wpa_printf(MSG_INFO, "TLS: Failed to set DH params from '%s': " - "%s", dh_file, - ERR_error_string(ERR_get_error(), NULL)); - DH_free(dh); - return -1; - } - DH_free(dh); - return 0; -#endif /* OPENSSL_NO_DH */ -} - - -static int tls_global_dh(SSL_CTX *ssl_ctx, const char *dh_file) -{ -#ifdef OPENSSL_NO_DH - if (dh_file == NULL) - return 0; - wpa_printf(MSG_ERROR, "TLS: openssl does not include DH support, but " - "dh_file specified"); - return -1; -#else /* OPENSSL_NO_DH */ - DH *dh; - BIO *bio; - - /* TODO: add support for dh_blob */ - if (dh_file == NULL) - return 0; - if (ssl_ctx == NULL) - return -1; - - bio = BIO_new_file(dh_file, "r"); - if (bio == NULL) { - wpa_printf(MSG_INFO, "TLS: Failed to open DH file '%s': %s", - dh_file, ERR_error_string(ERR_get_error(), NULL)); - return -1; - } - dh = PEM_read_bio_DHparams(bio, NULL, NULL, NULL); - BIO_free(bio); -#ifndef OPENSSL_NO_DSA - while (dh == NULL) { - DSA *dsa; - wpa_printf(MSG_DEBUG, "TLS: Failed to parse DH file '%s': %s -" - " trying to parse as DSA params", dh_file, - ERR_error_string(ERR_get_error(), NULL)); - bio = BIO_new_file(dh_file, "r"); - if (bio == NULL) - break; - dsa = PEM_read_bio_DSAparams(bio, NULL, NULL, NULL); - BIO_free(bio); - if (!dsa) { - wpa_printf(MSG_DEBUG, "TLS: Failed to parse DSA file " - "'%s': %s", dh_file, - ERR_error_string(ERR_get_error(), NULL)); - break; - } - - wpa_printf(MSG_DEBUG, "TLS: DH file in DSA param format"); - dh = DSA_dup_DH(dsa); - DSA_free(dsa); - if (dh == NULL) { - wpa_printf(MSG_INFO, "TLS: Failed to convert DSA " - "params into DH params"); - break; - } - break; - } -#endif /* !OPENSSL_NO_DSA */ - if (dh == NULL) { - wpa_printf(MSG_INFO, "TLS: Failed to read/parse DH/DSA file " - "'%s'", dh_file); - return -1; - } - - if (SSL_CTX_set_tmp_dh(ssl_ctx, dh) != 1) { - wpa_printf(MSG_INFO, "TLS: Failed to set DH params from '%s': " - "%s", dh_file, - ERR_error_string(ERR_get_error(), NULL)); - DH_free(dh); - return -1; - } - DH_free(dh); - return 0; -#endif /* OPENSSL_NO_DH */ -} - - -int tls_connection_get_keys(void *ssl_ctx, struct tls_connection *conn, - struct tls_keys *keys) -{ - SSL *ssl; - - if (conn == NULL || keys == NULL) - return -1; - ssl = conn->ssl; - if (ssl == NULL || ssl->s3 == NULL || ssl->session == NULL) - return -1; - - os_memset(keys, 0, sizeof(*keys)); - keys->master_key = ssl->session->master_key; - keys->master_key_len = ssl->session->master_key_length; - keys->client_random = ssl->s3->client_random; - keys->client_random_len = SSL3_RANDOM_SIZE; - keys->server_random = ssl->s3->server_random; - keys->server_random_len = SSL3_RANDOM_SIZE; - - return 0; -} - - -int tls_connection_prf(void *tls_ctx, struct tls_connection *conn, - const char *label, int server_random_first, - u8 *out, size_t out_len) -{ - return -1; -} - - -static struct wpabuf * -openssl_handshake(struct tls_connection *conn, const struct wpabuf *in_data, - int server) -{ - int res; - struct wpabuf *out_data; - - /* - * Give TLS handshake data from the server (if available) to OpenSSL - * for processing. - */ - if (in_data && - BIO_write(conn->ssl_in, wpabuf_head(in_data), wpabuf_len(in_data)) - < 0) { - tls_show_errors(MSG_INFO, __func__, - "Handshake failed - BIO_write"); - return NULL; - } - - /* Initiate TLS handshake or continue the existing handshake */ - if (server) - res = SSL_accept(conn->ssl); - else - res = SSL_connect(conn->ssl); - if (res != 1) { - int err = SSL_get_error(conn->ssl, res); - if (err == SSL_ERROR_WANT_READ) - wpa_printf(MSG_DEBUG, "SSL: SSL_connect - want " - "more data"); - else if (err == SSL_ERROR_WANT_WRITE) - wpa_printf(MSG_DEBUG, "SSL: SSL_connect - want to " - "write"); - else { - tls_show_errors(MSG_INFO, __func__, "SSL_connect"); - conn->failed++; - } - } - - /* Get the TLS handshake data to be sent to the server */ - res = BIO_ctrl_pending(conn->ssl_out); - wpa_printf(MSG_DEBUG, "SSL: %d bytes pending from ssl_out", res); - out_data = wpabuf_alloc(res); - if (out_data == NULL) { - wpa_printf(MSG_DEBUG, "SSL: Failed to allocate memory for " - "handshake output (%d bytes)", res); - if (BIO_reset(conn->ssl_out) < 0) { - tls_show_errors(MSG_INFO, __func__, - "BIO_reset failed"); - } - return NULL; - } - res = res == 0 ? 0 : BIO_read(conn->ssl_out, wpabuf_mhead(out_data), - res); - if (res < 0) { - tls_show_errors(MSG_INFO, __func__, - "Handshake failed - BIO_read"); - if (BIO_reset(conn->ssl_out) < 0) { - tls_show_errors(MSG_INFO, __func__, - "BIO_reset failed"); - } - wpabuf_free(out_data); - return NULL; - } - wpabuf_put(out_data, res); - - return out_data; -} - - -static struct wpabuf * -openssl_get_appl_data(struct tls_connection *conn, size_t max_len) -{ - struct wpabuf *appl_data; - int res; - - appl_data = wpabuf_alloc(max_len + 100); - if (appl_data == NULL) - return NULL; - - res = SSL_read(conn->ssl, wpabuf_mhead(appl_data), - wpabuf_size(appl_data)); - if (res < 0) { - int err = SSL_get_error(conn->ssl, res); - if (err == SSL_ERROR_WANT_READ || - err == SSL_ERROR_WANT_WRITE) { - wpa_printf(MSG_DEBUG, "SSL: No Application Data " - "included"); - } else { - tls_show_errors(MSG_INFO, __func__, - "Failed to read possible " - "Application Data"); - } - wpabuf_free(appl_data); - return NULL; - } - - wpabuf_put(appl_data, res); - wpa_hexdump_buf_key(MSG_MSGDUMP, "SSL: Application Data in Finished " - "message", appl_data); - - return appl_data; -} - - -static struct wpabuf * -openssl_connection_handshake(struct tls_connection *conn, - const struct wpabuf *in_data, - struct wpabuf **appl_data, int server) -{ - struct wpabuf *out_data; - - if (appl_data) - *appl_data = NULL; - - out_data = openssl_handshake(conn, in_data, server); - if (out_data == NULL) - return NULL; - - if (SSL_is_init_finished(conn->ssl) && appl_data && in_data) - *appl_data = openssl_get_appl_data(conn, wpabuf_len(in_data)); - - return out_data; -} - - -struct wpabuf * -tls_connection_handshake(void *ssl_ctx, struct tls_connection *conn, - const struct wpabuf *in_data, - struct wpabuf **appl_data) -{ - return openssl_connection_handshake(conn, in_data, appl_data, 0); -} - - -struct wpabuf * tls_connection_server_handshake(void *tls_ctx, - struct tls_connection *conn, - const struct wpabuf *in_data, - struct wpabuf **appl_data) -{ - return openssl_connection_handshake(conn, in_data, appl_data, 1); -} - - -struct wpabuf * tls_connection_encrypt(void *tls_ctx, - struct tls_connection *conn, - const struct wpabuf *in_data) -{ - int res; - struct wpabuf *buf; - - if (conn == NULL) - return NULL; - - /* Give plaintext data for OpenSSL to encrypt into the TLS tunnel. */ - if ((res = BIO_reset(conn->ssl_in)) < 0 || - (res = BIO_reset(conn->ssl_out)) < 0) { - tls_show_errors(MSG_INFO, __func__, "BIO_reset failed"); - return NULL; - } - res = SSL_write(conn->ssl, wpabuf_head(in_data), wpabuf_len(in_data)); - if (res < 0) { - tls_show_errors(MSG_INFO, __func__, - "Encryption failed - SSL_write"); - return NULL; - } - - /* Read encrypted data to be sent to the server */ - buf = wpabuf_alloc(wpabuf_len(in_data) + 300); - if (buf == NULL) - return NULL; - res = BIO_read(conn->ssl_out, wpabuf_mhead(buf), wpabuf_size(buf)); - if (res < 0) { - tls_show_errors(MSG_INFO, __func__, - "Encryption failed - BIO_read"); - wpabuf_free(buf); - return NULL; - } - wpabuf_put(buf, res); - - return buf; -} - - -struct wpabuf * tls_connection_decrypt(void *tls_ctx, - struct tls_connection *conn, - const struct wpabuf *in_data) -{ - int res; - struct wpabuf *buf; - - /* Give encrypted data from TLS tunnel for OpenSSL to decrypt. */ - res = BIO_write(conn->ssl_in, wpabuf_head(in_data), - wpabuf_len(in_data)); - if (res < 0) { - tls_show_errors(MSG_INFO, __func__, - "Decryption failed - BIO_write"); - return NULL; - } - if (BIO_reset(conn->ssl_out) < 0) { - tls_show_errors(MSG_INFO, __func__, "BIO_reset failed"); - return NULL; - } - - /* Read decrypted data for further processing */ - /* - * Even though we try to disable TLS compression, it is possible that - * this cannot be done with all TLS libraries. Add extra buffer space - * to handle the possibility of the decrypted data being longer than - * input data. - */ - buf = wpabuf_alloc((wpabuf_len(in_data) + 500) * 3); - if (buf == NULL) - return NULL; - res = SSL_read(conn->ssl, wpabuf_mhead(buf), wpabuf_size(buf)); - if (res < 0) { - tls_show_errors(MSG_INFO, __func__, - "Decryption failed - SSL_read"); - wpabuf_free(buf); - return NULL; - } - wpabuf_put(buf, res); - - return buf; -} - - -int tls_connection_resumed(void *ssl_ctx, struct tls_connection *conn) -{ - return conn ? conn->ssl->hit : 0; -} - - -int tls_connection_set_cipher_list(void *tls_ctx, struct tls_connection *conn, - u8 *ciphers) -{ - char buf[100], *pos, *end; - u8 *c; - int ret; - - if (conn == NULL || conn->ssl == NULL || ciphers == NULL) - return -1; - - buf[0] = '\0'; - pos = buf; - end = pos + sizeof(buf); - - c = ciphers; - while (*c != TLS_CIPHER_NONE) { - const char *suite; - - switch (*c) { - case TLS_CIPHER_RC4_SHA: - suite = "RC4-SHA"; - break; - case TLS_CIPHER_AES128_SHA: - suite = "AES128-SHA"; - break; - case TLS_CIPHER_RSA_DHE_AES128_SHA: - suite = "DHE-RSA-AES128-SHA"; - break; - case TLS_CIPHER_ANON_DH_AES128_SHA: - suite = "ADH-AES128-SHA"; - break; - default: - wpa_printf(MSG_DEBUG, "TLS: Unsupported " - "cipher selection: %d", *c); - return -1; - } - ret = os_snprintf(pos, end - pos, ":%s", suite); - if (ret < 0 || ret >= end - pos) - break; - pos += ret; - - c++; - } - - wpa_printf(MSG_DEBUG, "OpenSSL: cipher suites: %s", buf + 1); - - if (SSL_set_cipher_list(conn->ssl, buf + 1) != 1) { - tls_show_errors(MSG_INFO, __func__, - "Cipher suite configuration failed"); - return -1; - } - - return 0; -} - - -int tls_get_cipher(void *ssl_ctx, struct tls_connection *conn, - char *buf, size_t buflen) -{ - const char *name; - if (conn == NULL || conn->ssl == NULL) - return -1; - - name = SSL_get_cipher(conn->ssl); - if (name == NULL) - return -1; - - os_strlcpy(buf, name, buflen); - return 0; -} - - -int tls_connection_enable_workaround(void *ssl_ctx, - struct tls_connection *conn) -{ - SSL_set_options(conn->ssl, SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS); - - return 0; -} - - -#if defined(EAP_FAST) || defined(EAP_FAST_DYNAMIC) || defined(EAP_SERVER_FAST) -/* ClientHello TLS extensions require a patch to openssl, so this function is - * commented out unless explicitly needed for EAP-FAST in order to be able to - * build this file with unmodified openssl. */ -int tls_connection_client_hello_ext(void *ssl_ctx, struct tls_connection *conn, - int ext_type, const u8 *data, - size_t data_len) -{ - if (conn == NULL || conn->ssl == NULL || ext_type != 35) - return -1; - -#ifdef CONFIG_OPENSSL_TICKET_OVERRIDE - if (SSL_set_session_ticket_ext(conn->ssl, (void *) data, - data_len) != 1) - return -1; -#else /* CONFIG_OPENSSL_TICKET_OVERRIDE */ - if (SSL_set_hello_extension(conn->ssl, ext_type, (void *) data, - data_len) != 1) - return -1; -#endif /* CONFIG_OPENSSL_TICKET_OVERRIDE */ - - return 0; -} -#endif /* EAP_FAST || EAP_FAST_DYNAMIC || EAP_SERVER_FAST */ - - -int tls_connection_get_failed(void *ssl_ctx, struct tls_connection *conn) -{ - if (conn == NULL) - return -1; - return conn->failed; -} - - -int tls_connection_get_read_alerts(void *ssl_ctx, struct tls_connection *conn) -{ - if (conn == NULL) - return -1; - return conn->read_alerts; -} - - -int tls_connection_get_write_alerts(void *ssl_ctx, struct tls_connection *conn) -{ - if (conn == NULL) - return -1; - return conn->write_alerts; -} - - -int tls_connection_set_params(void *tls_ctx, struct tls_connection *conn, - const struct tls_connection_params *params) -{ - int ret; - unsigned long err; - - if (conn == NULL) - return -1; - - while ((err = ERR_get_error())) { - wpa_printf(MSG_INFO, "%s: Clearing pending SSL error: %s", - __func__, ERR_error_string(err, NULL)); - } - - if (params->engine) { - wpa_printf(MSG_DEBUG, "SSL: Initializing TLS engine"); - ret = tls_engine_init(conn, params->engine_id, params->pin, - params->key_id, params->cert_id, - params->ca_cert_id); - if (ret) - return ret; - } - if (tls_connection_set_subject_match(conn, - params->subject_match, - params->altsubject_match)) - return -1; - - if (params->engine && params->ca_cert_id) { - if (tls_connection_engine_ca_cert(tls_ctx, conn, - params->ca_cert_id)) - return TLS_SET_PARAMS_ENGINE_PRV_VERIFY_FAILED; - } else if (tls_connection_ca_cert(tls_ctx, conn, params->ca_cert, - params->ca_cert_blob, - params->ca_cert_blob_len, - params->ca_path)) - return -1; - - if (params->engine && params->cert_id) { - if (tls_connection_engine_client_cert(conn, params->cert_id)) - return TLS_SET_PARAMS_ENGINE_PRV_VERIFY_FAILED; - } else if (tls_connection_client_cert(conn, params->client_cert, - params->client_cert_blob, - params->client_cert_blob_len)) - return -1; - - if (params->engine && params->key_id) { - wpa_printf(MSG_DEBUG, "TLS: Using private key from engine"); - if (tls_connection_engine_private_key(conn)) - return TLS_SET_PARAMS_ENGINE_PRV_VERIFY_FAILED; - } else if (tls_connection_private_key(tls_ctx, conn, - params->private_key, - params->private_key_passwd, - params->private_key_blob, - params->private_key_blob_len)) { - wpa_printf(MSG_INFO, "TLS: Failed to load private key '%s'", - params->private_key); - return -1; - } - - if (tls_connection_dh(conn, params->dh_file)) { - wpa_printf(MSG_INFO, "TLS: Failed to load DH file '%s'", - params->dh_file); - return -1; - } - - tls_get_errors(tls_ctx); - - return 0; -} - - -int tls_global_set_params(void *tls_ctx, - const struct tls_connection_params *params) -{ - SSL_CTX *ssl_ctx = tls_ctx; - unsigned long err; - - while ((err = ERR_get_error())) { - wpa_printf(MSG_INFO, "%s: Clearing pending SSL error: %s", - __func__, ERR_error_string(err, NULL)); - } - - if (tls_global_ca_cert(ssl_ctx, params->ca_cert)) - return -1; - - if (tls_global_client_cert(ssl_ctx, params->client_cert)) - return -1; - - if (tls_global_private_key(ssl_ctx, params->private_key, - params->private_key_passwd)) - return -1; - - if (tls_global_dh(ssl_ctx, params->dh_file)) { - wpa_printf(MSG_INFO, "TLS: Failed to load DH file '%s'", - params->dh_file); - return -1; - } - - return 0; -} - - -int tls_connection_get_keyblock_size(void *tls_ctx, - struct tls_connection *conn) -{ - const EVP_CIPHER *c; - const EVP_MD *h; - - if (conn == NULL || conn->ssl == NULL || - conn->ssl->enc_read_ctx == NULL || - conn->ssl->enc_read_ctx->cipher == NULL || - conn->ssl->read_hash == NULL) - return -1; - - c = conn->ssl->enc_read_ctx->cipher; -#if OPENSSL_VERSION_NUMBER >= 0x00909000L - h = EVP_MD_CTX_md(conn->ssl->read_hash); -#else - h = conn->ssl->read_hash; -#endif - - return 2 * (EVP_CIPHER_key_length(c) + - EVP_MD_size(h) + - EVP_CIPHER_iv_length(c)); -} - - -unsigned int tls_capabilities(void *tls_ctx) -{ - return 0; -} - - -int tls_connection_set_ia(void *tls_ctx, struct tls_connection *conn, - int tls_ia) -{ - return -1; -} - - -struct wpabuf * tls_connection_ia_send_phase_finished( - void *tls_ctx, struct tls_connection *conn, int final) -{ - return NULL; -} - - -int tls_connection_ia_final_phase_finished(void *tls_ctx, - struct tls_connection *conn) -{ - return -1; -} - - -int tls_connection_ia_permute_inner_secret(void *tls_ctx, - struct tls_connection *conn, - const u8 *key, size_t key_len) -{ - return -1; -} - - -#if defined(EAP_FAST) || defined(EAP_FAST_DYNAMIC) || defined(EAP_SERVER_FAST) -/* Pre-shared secred requires a patch to openssl, so this function is - * commented out unless explicitly needed for EAP-FAST in order to be able to - * build this file with unmodified openssl. */ - -static int tls_sess_sec_cb(SSL *s, void *secret, int *secret_len, - STACK_OF(SSL_CIPHER) *peer_ciphers, - SSL_CIPHER **cipher, void *arg) -{ - struct tls_connection *conn = arg; - int ret; - - if (conn == NULL || conn->session_ticket_cb == NULL) - return 0; - - ret = conn->session_ticket_cb(conn->session_ticket_cb_ctx, - conn->session_ticket, - conn->session_ticket_len, - s->s3->client_random, - s->s3->server_random, secret); - os_free(conn->session_ticket); - conn->session_ticket = NULL; - - if (ret <= 0) - return 0; - - *secret_len = SSL_MAX_MASTER_KEY_LENGTH; - return 1; -} - - -#ifdef CONFIG_OPENSSL_TICKET_OVERRIDE -static int tls_session_ticket_ext_cb(SSL *s, const unsigned char *data, - int len, void *arg) -{ - struct tls_connection *conn = arg; - - if (conn == NULL || conn->session_ticket_cb == NULL) - return 0; - - wpa_printf(MSG_DEBUG, "OpenSSL: %s: length=%d", __func__, len); - - os_free(conn->session_ticket); - conn->session_ticket = NULL; - - wpa_hexdump(MSG_DEBUG, "OpenSSL: ClientHello SessionTicket " - "extension", data, len); - - conn->session_ticket = os_malloc(len); - if (conn->session_ticket == NULL) - return 0; - - os_memcpy(conn->session_ticket, data, len); - conn->session_ticket_len = len; - - return 1; -} -#else /* CONFIG_OPENSSL_TICKET_OVERRIDE */ -#ifdef SSL_OP_NO_TICKET -static void tls_hello_ext_cb(SSL *s, int client_server, int type, - unsigned char *data, int len, void *arg) -{ - struct tls_connection *conn = arg; - - if (conn == NULL || conn->session_ticket_cb == NULL) - return; - - wpa_printf(MSG_DEBUG, "OpenSSL: %s: type=%d length=%d", __func__, - type, len); - - if (type == TLSEXT_TYPE_session_ticket && !client_server) { - os_free(conn->session_ticket); - conn->session_ticket = NULL; - - wpa_hexdump(MSG_DEBUG, "OpenSSL: ClientHello SessionTicket " - "extension", data, len); - conn->session_ticket = os_malloc(len); - if (conn->session_ticket == NULL) - return; - - os_memcpy(conn->session_ticket, data, len); - conn->session_ticket_len = len; - } -} -#else /* SSL_OP_NO_TICKET */ -static int tls_hello_ext_cb(SSL *s, TLS_EXTENSION *ext, void *arg) -{ - struct tls_connection *conn = arg; - - if (conn == NULL || conn->session_ticket_cb == NULL) - return 0; - - wpa_printf(MSG_DEBUG, "OpenSSL: %s: type=%d length=%d", __func__, - ext->type, ext->length); - - os_free(conn->session_ticket); - conn->session_ticket = NULL; - - if (ext->type == 35) { - wpa_hexdump(MSG_DEBUG, "OpenSSL: ClientHello SessionTicket " - "extension", ext->data, ext->length); - conn->session_ticket = os_malloc(ext->length); - if (conn->session_ticket == NULL) - return SSL_AD_INTERNAL_ERROR; - - os_memcpy(conn->session_ticket, ext->data, ext->length); - conn->session_ticket_len = ext->length; - } - - return 0; -} -#endif /* SSL_OP_NO_TICKET */ -#endif /* CONFIG_OPENSSL_TICKET_OVERRIDE */ -#endif /* EAP_FAST || EAP_FAST_DYNAMIC || EAP_SERVER_FAST */ - - -int tls_connection_set_session_ticket_cb(void *tls_ctx, - struct tls_connection *conn, - tls_session_ticket_cb cb, - void *ctx) -{ -#if defined(EAP_FAST) || defined(EAP_FAST_DYNAMIC) || defined(EAP_SERVER_FAST) - conn->session_ticket_cb = cb; - conn->session_ticket_cb_ctx = ctx; - - if (cb) { - if (SSL_set_session_secret_cb(conn->ssl, tls_sess_sec_cb, - conn) != 1) - return -1; -#ifdef CONFIG_OPENSSL_TICKET_OVERRIDE - SSL_set_session_ticket_ext_cb(conn->ssl, - tls_session_ticket_ext_cb, conn); -#else /* CONFIG_OPENSSL_TICKET_OVERRIDE */ -#ifdef SSL_OP_NO_TICKET - SSL_set_tlsext_debug_callback(conn->ssl, tls_hello_ext_cb); - SSL_set_tlsext_debug_arg(conn->ssl, conn); -#else /* SSL_OP_NO_TICKET */ - if (SSL_set_hello_extension_cb(conn->ssl, tls_hello_ext_cb, - conn) != 1) - return -1; -#endif /* SSL_OP_NO_TICKET */ -#endif /* CONFIG_OPENSSL_TICKET_OVERRIDE */ - } else { - if (SSL_set_session_secret_cb(conn->ssl, NULL, NULL) != 1) - return -1; -#ifdef CONFIG_OPENSSL_TICKET_OVERRIDE - SSL_set_session_ticket_ext_cb(conn->ssl, NULL, NULL); -#else /* CONFIG_OPENSSL_TICKET_OVERRIDE */ -#ifdef SSL_OP_NO_TICKET - SSL_set_tlsext_debug_callback(conn->ssl, NULL); - SSL_set_tlsext_debug_arg(conn->ssl, conn); -#else /* SSL_OP_NO_TICKET */ - if (SSL_set_hello_extension_cb(conn->ssl, NULL, NULL) != 1) - return -1; -#endif /* SSL_OP_NO_TICKET */ -#endif /* CONFIG_OPENSSL_TICKET_OVERRIDE */ - } - - return 0; -#else /* EAP_FAST || EAP_FAST_DYNAMIC || EAP_SERVER_FAST */ - return -1; -#endif /* EAP_FAST || EAP_FAST_DYNAMIC || EAP_SERVER_FAST */ -} diff --git a/hostapd-0.8/src/crypto/tls_schannel.c b/hostapd-0.8/src/crypto/tls_schannel.c deleted file mode 100644 index 4a94e99..0000000 --- a/hostapd-0.8/src/crypto/tls_schannel.c +++ /dev/null @@ -1,767 +0,0 @@ -/* - * SSL/TLS interface functions for Microsoft Schannel - * Copyright (c) 2005-2009, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -/* - * FIX: Go through all SSPI functions and verify what needs to be freed - * FIX: session resumption - * TODO: add support for server cert chain validation - * TODO: add support for CA cert validation - * TODO: add support for EAP-TLS (client cert/key conf) - */ - -#include "includes.h" -#include -#include -#include -#define SECURITY_WIN32 -#include -#include - -#include "common.h" -#include "tls.h" - - -struct tls_global { - HMODULE hsecurity; - PSecurityFunctionTable sspi; - HCERTSTORE my_cert_store; -}; - -struct tls_connection { - int established, start; - int failed, read_alerts, write_alerts; - - SCHANNEL_CRED schannel_cred; - CredHandle creds; - CtxtHandle context; - - u8 eap_tls_prf[128]; - int eap_tls_prf_set; -}; - - -static int schannel_load_lib(struct tls_global *global) -{ - INIT_SECURITY_INTERFACE pInitSecurityInterface; - - global->hsecurity = LoadLibrary(TEXT("Secur32.dll")); - if (global->hsecurity == NULL) { - wpa_printf(MSG_ERROR, "%s: Could not load Secur32.dll - 0x%x", - __func__, (unsigned int) GetLastError()); - return -1; - } - - pInitSecurityInterface = (INIT_SECURITY_INTERFACE) GetProcAddress( - global->hsecurity, "InitSecurityInterfaceA"); - if (pInitSecurityInterface == NULL) { - wpa_printf(MSG_ERROR, "%s: Could not find " - "InitSecurityInterfaceA from Secur32.dll", - __func__); - FreeLibrary(global->hsecurity); - global->hsecurity = NULL; - return -1; - } - - global->sspi = pInitSecurityInterface(); - if (global->sspi == NULL) { - wpa_printf(MSG_ERROR, "%s: Could not read security " - "interface - 0x%x", - __func__, (unsigned int) GetLastError()); - FreeLibrary(global->hsecurity); - global->hsecurity = NULL; - return -1; - } - - return 0; -} - - -void * tls_init(const struct tls_config *conf) -{ - struct tls_global *global; - - global = os_zalloc(sizeof(*global)); - if (global == NULL) - return NULL; - if (schannel_load_lib(global)) { - os_free(global); - return NULL; - } - return global; -} - - -void tls_deinit(void *ssl_ctx) -{ - struct tls_global *global = ssl_ctx; - - if (global->my_cert_store) - CertCloseStore(global->my_cert_store, 0); - FreeLibrary(global->hsecurity); - os_free(global); -} - - -int tls_get_errors(void *ssl_ctx) -{ - return 0; -} - - -struct tls_connection * tls_connection_init(void *ssl_ctx) -{ - struct tls_connection *conn; - - conn = os_zalloc(sizeof(*conn)); - if (conn == NULL) - return NULL; - conn->start = 1; - - return conn; -} - - -void tls_connection_deinit(void *ssl_ctx, struct tls_connection *conn) -{ - if (conn == NULL) - return; - - os_free(conn); -} - - -int tls_connection_established(void *ssl_ctx, struct tls_connection *conn) -{ - return conn ? conn->established : 0; -} - - -int tls_connection_shutdown(void *ssl_ctx, struct tls_connection *conn) -{ - struct tls_global *global = ssl_ctx; - if (conn == NULL) - return -1; - - conn->eap_tls_prf_set = 0; - conn->established = conn->failed = 0; - conn->read_alerts = conn->write_alerts = 0; - global->sspi->DeleteSecurityContext(&conn->context); - /* FIX: what else needs to be reseted? */ - - return 0; -} - - -int tls_global_set_params(void *tls_ctx, - const struct tls_connection_params *params) -{ - return -1; -} - - -int tls_global_set_verify(void *ssl_ctx, int check_crl) -{ - return -1; -} - - -int tls_connection_set_verify(void *ssl_ctx, struct tls_connection *conn, - int verify_peer) -{ - return -1; -} - - -int tls_connection_get_keys(void *ssl_ctx, struct tls_connection *conn, - struct tls_keys *keys) -{ - /* Schannel does not export master secret or client/server random. */ - return -1; -} - - -int tls_connection_prf(void *tls_ctx, struct tls_connection *conn, - const char *label, int server_random_first, - u8 *out, size_t out_len) -{ - /* - * Cannot get master_key from Schannel, but EapKeyBlock can be used to - * generate session keys for EAP-TLS and EAP-PEAPv0. EAP-PEAPv2 and - * EAP-TTLS cannot use this, though, since they are using different - * labels. The only option could be to implement TLSv1 completely here - * and just use Schannel or CryptoAPI for low-level crypto - * functionality.. - */ - - if (conn == NULL || !conn->eap_tls_prf_set || server_random_first || - os_strcmp(label, "client EAP encryption") != 0 || - out_len > sizeof(conn->eap_tls_prf)) - return -1; - - os_memcpy(out, conn->eap_tls_prf, out_len); - - return 0; -} - - -static struct wpabuf * tls_conn_hs_clienthello(struct tls_global *global, - struct tls_connection *conn) -{ - DWORD sspi_flags, sspi_flags_out; - SecBufferDesc outbuf; - SecBuffer outbufs[1]; - SECURITY_STATUS status; - TimeStamp ts_expiry; - - sspi_flags = ISC_REQ_REPLAY_DETECT | - ISC_REQ_CONFIDENTIALITY | - ISC_RET_EXTENDED_ERROR | - ISC_REQ_ALLOCATE_MEMORY | - ISC_REQ_MANUAL_CRED_VALIDATION; - - wpa_printf(MSG_DEBUG, "%s: Generating ClientHello", __func__); - - outbufs[0].pvBuffer = NULL; - outbufs[0].BufferType = SECBUFFER_TOKEN; - outbufs[0].cbBuffer = 0; - - outbuf.cBuffers = 1; - outbuf.pBuffers = outbufs; - outbuf.ulVersion = SECBUFFER_VERSION; - -#ifdef UNICODE - status = global->sspi->InitializeSecurityContextW( - &conn->creds, NULL, NULL /* server name */, sspi_flags, 0, - SECURITY_NATIVE_DREP, NULL, 0, &conn->context, - &outbuf, &sspi_flags_out, &ts_expiry); -#else /* UNICODE */ - status = global->sspi->InitializeSecurityContextA( - &conn->creds, NULL, NULL /* server name */, sspi_flags, 0, - SECURITY_NATIVE_DREP, NULL, 0, &conn->context, - &outbuf, &sspi_flags_out, &ts_expiry); -#endif /* UNICODE */ - if (status != SEC_I_CONTINUE_NEEDED) { - wpa_printf(MSG_ERROR, "%s: InitializeSecurityContextA " - "failed - 0x%x", - __func__, (unsigned int) status); - return NULL; - } - - if (outbufs[0].cbBuffer != 0 && outbufs[0].pvBuffer) { - struct wpabuf *buf; - wpa_hexdump(MSG_MSGDUMP, "SChannel - ClientHello", - outbufs[0].pvBuffer, outbufs[0].cbBuffer); - conn->start = 0; - buf = wpabuf_alloc_copy(outbufs[0].pvBuffer, - outbufs[0].cbBuffer); - if (buf == NULL) - return NULL; - global->sspi->FreeContextBuffer(outbufs[0].pvBuffer); - return buf; - } - - wpa_printf(MSG_ERROR, "SChannel: Failed to generate ClientHello"); - - return NULL; -} - - -#ifndef SECPKG_ATTR_EAP_KEY_BLOCK -#define SECPKG_ATTR_EAP_KEY_BLOCK 0x5b - -typedef struct _SecPkgContext_EapKeyBlock { - BYTE rgbKeys[128]; - BYTE rgbIVs[64]; -} SecPkgContext_EapKeyBlock, *PSecPkgContext_EapKeyBlock; -#endif /* !SECPKG_ATTR_EAP_KEY_BLOCK */ - -static int tls_get_eap(struct tls_global *global, struct tls_connection *conn) -{ - SECURITY_STATUS status; - SecPkgContext_EapKeyBlock kb; - - /* Note: Windows NT and Windows Me/98/95 do not support getting - * EapKeyBlock */ - - status = global->sspi->QueryContextAttributes( - &conn->context, SECPKG_ATTR_EAP_KEY_BLOCK, &kb); - if (status != SEC_E_OK) { - wpa_printf(MSG_DEBUG, "%s: QueryContextAttributes(" - "SECPKG_ATTR_EAP_KEY_BLOCK) failed (%d)", - __func__, (int) status); - return -1; - } - - wpa_hexdump_key(MSG_MSGDUMP, "Schannel - EapKeyBlock - rgbKeys", - kb.rgbKeys, sizeof(kb.rgbKeys)); - wpa_hexdump_key(MSG_MSGDUMP, "Schannel - EapKeyBlock - rgbIVs", - kb.rgbIVs, sizeof(kb.rgbIVs)); - - os_memcpy(conn->eap_tls_prf, kb.rgbKeys, sizeof(kb.rgbKeys)); - conn->eap_tls_prf_set = 1; - return 0; -} - - -struct wpabuf * tls_connection_handshake(void *tls_ctx, - struct tls_connection *conn, - const struct wpabuf *in_data, - struct wpabuf **appl_data) -{ - struct tls_global *global = tls_ctx; - DWORD sspi_flags, sspi_flags_out; - SecBufferDesc inbuf, outbuf; - SecBuffer inbufs[2], outbufs[1]; - SECURITY_STATUS status; - TimeStamp ts_expiry; - struct wpabuf *out_buf = NULL; - - if (appl_data) - *appl_data = NULL; - - if (conn->start) - return tls_conn_hs_clienthello(global, conn); - - wpa_printf(MSG_DEBUG, "SChannel: %d bytes handshake data to process", - (int) wpabuf_len(in_data)); - - sspi_flags = ISC_REQ_REPLAY_DETECT | - ISC_REQ_CONFIDENTIALITY | - ISC_RET_EXTENDED_ERROR | - ISC_REQ_ALLOCATE_MEMORY | - ISC_REQ_MANUAL_CRED_VALIDATION; - - /* Input buffer for Schannel */ - inbufs[0].pvBuffer = (u8 *) wpabuf_head(in_data); - inbufs[0].cbBuffer = wpabuf_len(in_data); - inbufs[0].BufferType = SECBUFFER_TOKEN; - - /* Place for leftover data from Schannel */ - inbufs[1].pvBuffer = NULL; - inbufs[1].cbBuffer = 0; - inbufs[1].BufferType = SECBUFFER_EMPTY; - - inbuf.cBuffers = 2; - inbuf.pBuffers = inbufs; - inbuf.ulVersion = SECBUFFER_VERSION; - - /* Output buffer for Schannel */ - outbufs[0].pvBuffer = NULL; - outbufs[0].cbBuffer = 0; - outbufs[0].BufferType = SECBUFFER_TOKEN; - - outbuf.cBuffers = 1; - outbuf.pBuffers = outbufs; - outbuf.ulVersion = SECBUFFER_VERSION; - -#ifdef UNICODE - status = global->sspi->InitializeSecurityContextW( - &conn->creds, &conn->context, NULL, sspi_flags, 0, - SECURITY_NATIVE_DREP, &inbuf, 0, NULL, - &outbuf, &sspi_flags_out, &ts_expiry); -#else /* UNICODE */ - status = global->sspi->InitializeSecurityContextA( - &conn->creds, &conn->context, NULL, sspi_flags, 0, - SECURITY_NATIVE_DREP, &inbuf, 0, NULL, - &outbuf, &sspi_flags_out, &ts_expiry); -#endif /* UNICODE */ - - wpa_printf(MSG_MSGDUMP, "Schannel: InitializeSecurityContext -> " - "status=%d inlen[0]=%d intype[0]=%d inlen[1]=%d " - "intype[1]=%d outlen[0]=%d", - (int) status, (int) inbufs[0].cbBuffer, - (int) inbufs[0].BufferType, (int) inbufs[1].cbBuffer, - (int) inbufs[1].BufferType, - (int) outbufs[0].cbBuffer); - if (status == SEC_E_OK || status == SEC_I_CONTINUE_NEEDED || - (FAILED(status) && (sspi_flags_out & ISC_RET_EXTENDED_ERROR))) { - if (outbufs[0].cbBuffer != 0 && outbufs[0].pvBuffer) { - wpa_hexdump(MSG_MSGDUMP, "SChannel - output", - outbufs[0].pvBuffer, outbufs[0].cbBuffer); - out_buf = wpabuf_alloc_copy(outbufs[0].pvBuffer, - outbufs[0].cbBuffer); - global->sspi->FreeContextBuffer(outbufs[0].pvBuffer); - outbufs[0].pvBuffer = NULL; - if (out_buf == NULL) - return NULL; - } - } - - switch (status) { - case SEC_E_INCOMPLETE_MESSAGE: - wpa_printf(MSG_DEBUG, "Schannel: SEC_E_INCOMPLETE_MESSAGE"); - break; - case SEC_I_CONTINUE_NEEDED: - wpa_printf(MSG_DEBUG, "Schannel: SEC_I_CONTINUE_NEEDED"); - break; - case SEC_E_OK: - /* TODO: verify server certificate chain */ - wpa_printf(MSG_DEBUG, "Schannel: SEC_E_OK - Handshake " - "completed successfully"); - conn->established = 1; - tls_get_eap(global, conn); - - /* Need to return something to get final TLS ACK. */ - if (out_buf == NULL) - out_buf = wpabuf_alloc(0); - - if (inbufs[1].BufferType == SECBUFFER_EXTRA) { - wpa_hexdump(MSG_MSGDUMP, "SChannel - Encrypted " - "application data", - inbufs[1].pvBuffer, inbufs[1].cbBuffer); - if (appl_data) { - *appl_data = wpabuf_alloc_copy( - outbufs[1].pvBuffer, - outbufs[1].cbBuffer); - } - global->sspi->FreeContextBuffer(inbufs[1].pvBuffer); - inbufs[1].pvBuffer = NULL; - } - break; - case SEC_I_INCOMPLETE_CREDENTIALS: - wpa_printf(MSG_DEBUG, - "Schannel: SEC_I_INCOMPLETE_CREDENTIALS"); - break; - case SEC_E_WRONG_PRINCIPAL: - wpa_printf(MSG_DEBUG, "Schannel: SEC_E_WRONG_PRINCIPAL"); - break; - case SEC_E_INTERNAL_ERROR: - wpa_printf(MSG_DEBUG, "Schannel: SEC_E_INTERNAL_ERROR"); - break; - } - - if (FAILED(status)) { - wpa_printf(MSG_DEBUG, "Schannel: Handshake failed " - "(out_buf=%p)", out_buf); - conn->failed++; - global->sspi->DeleteSecurityContext(&conn->context); - return out_buf; - } - - if (inbufs[1].BufferType == SECBUFFER_EXTRA) { - /* TODO: Can this happen? What to do with this data? */ - wpa_hexdump(MSG_MSGDUMP, "SChannel - Leftover data", - inbufs[1].pvBuffer, inbufs[1].cbBuffer); - global->sspi->FreeContextBuffer(inbufs[1].pvBuffer); - inbufs[1].pvBuffer = NULL; - } - - return out_buf; -} - - -struct wpabuf * tls_connection_server_handshake(void *tls_ctx, - struct tls_connection *conn, - const struct wpabuf *in_data, - struct wpabuf **appl_data) -{ - return NULL; -} - - -struct wpabuf * tls_connection_encrypt(void *tls_ctx, - struct tls_connection *conn, - const struct wpabuf *in_data) -{ - struct tls_global *global = tls_ctx; - SECURITY_STATUS status; - SecBufferDesc buf; - SecBuffer bufs[4]; - SecPkgContext_StreamSizes sizes; - int i; - struct wpabuf *out; - - status = global->sspi->QueryContextAttributes(&conn->context, - SECPKG_ATTR_STREAM_SIZES, - &sizes); - if (status != SEC_E_OK) { - wpa_printf(MSG_DEBUG, "%s: QueryContextAttributes failed", - __func__); - return NULL; - } - wpa_printf(MSG_DEBUG, "%s: Stream sizes: header=%u trailer=%u", - __func__, - (unsigned int) sizes.cbHeader, - (unsigned int) sizes.cbTrailer); - - out = wpabuf_alloc(sizes.cbHeader + wpabuf_len(in_data) + - sizes.cbTrailer); - - os_memset(&bufs, 0, sizeof(bufs)); - bufs[0].pvBuffer = wpabuf_put(out, sizes.cbHeader); - bufs[0].cbBuffer = sizes.cbHeader; - bufs[0].BufferType = SECBUFFER_STREAM_HEADER; - - bufs[1].pvBuffer = wpabuf_put(out, 0); - wpabuf_put_buf(out, in_data); - bufs[1].cbBuffer = wpabuf_len(in_data); - bufs[1].BufferType = SECBUFFER_DATA; - - bufs[2].pvBuffer = wpabuf_put(out, sizes.cbTrailer); - bufs[2].cbBuffer = sizes.cbTrailer; - bufs[2].BufferType = SECBUFFER_STREAM_TRAILER; - - buf.ulVersion = SECBUFFER_VERSION; - buf.cBuffers = 3; - buf.pBuffers = bufs; - - status = global->sspi->EncryptMessage(&conn->context, 0, &buf, 0); - - wpa_printf(MSG_MSGDUMP, "Schannel: EncryptMessage -> " - "status=%d len[0]=%d type[0]=%d len[1]=%d type[1]=%d " - "len[2]=%d type[2]=%d", - (int) status, - (int) bufs[0].cbBuffer, (int) bufs[0].BufferType, - (int) bufs[1].cbBuffer, (int) bufs[1].BufferType, - (int) bufs[2].cbBuffer, (int) bufs[2].BufferType); - wpa_printf(MSG_MSGDUMP, "Schannel: EncryptMessage pointers: " - "out_data=%p bufs %p %p %p", - wpabuf_head(out), bufs[0].pvBuffer, bufs[1].pvBuffer, - bufs[2].pvBuffer); - - for (i = 0; i < 3; i++) { - if (bufs[i].pvBuffer && bufs[i].BufferType != SECBUFFER_EMPTY) - { - wpa_hexdump(MSG_MSGDUMP, "SChannel: bufs", - bufs[i].pvBuffer, bufs[i].cbBuffer); - } - } - - if (status == SEC_E_OK) { - wpa_printf(MSG_DEBUG, "%s: SEC_E_OK", __func__); - wpa_hexdump_buf_key(MSG_MSGDUMP, "Schannel: Encrypted data " - "from EncryptMessage", out); - return out; - } - - wpa_printf(MSG_DEBUG, "%s: Failed - status=%d", - __func__, (int) status); - wpabuf_free(out); - return NULL; -} - - -struct wpabuf * tls_connection_decrypt(void *tls_ctx, - struct tls_connection *conn, - const struct wpabuf *in_data) -{ - struct tls_global *global = tls_ctx; - SECURITY_STATUS status; - SecBufferDesc buf; - SecBuffer bufs[4]; - int i; - struct wpabuf *out, *tmp; - - wpa_hexdump_buf(MSG_MSGDUMP, - "Schannel: Encrypted data to DecryptMessage", in_data); - os_memset(&bufs, 0, sizeof(bufs)); - tmp = wpabuf_dup(in_data); - if (tmp == NULL) - return NULL; - bufs[0].pvBuffer = wpabuf_mhead(tmp); - bufs[0].cbBuffer = wpabuf_len(in_data); - bufs[0].BufferType = SECBUFFER_DATA; - - bufs[1].BufferType = SECBUFFER_EMPTY; - bufs[2].BufferType = SECBUFFER_EMPTY; - bufs[3].BufferType = SECBUFFER_EMPTY; - - buf.ulVersion = SECBUFFER_VERSION; - buf.cBuffers = 4; - buf.pBuffers = bufs; - - status = global->sspi->DecryptMessage(&conn->context, &buf, 0, - NULL); - wpa_printf(MSG_MSGDUMP, "Schannel: DecryptMessage -> " - "status=%d len[0]=%d type[0]=%d len[1]=%d type[1]=%d " - "len[2]=%d type[2]=%d len[3]=%d type[3]=%d", - (int) status, - (int) bufs[0].cbBuffer, (int) bufs[0].BufferType, - (int) bufs[1].cbBuffer, (int) bufs[1].BufferType, - (int) bufs[2].cbBuffer, (int) bufs[2].BufferType, - (int) bufs[3].cbBuffer, (int) bufs[3].BufferType); - wpa_printf(MSG_MSGDUMP, "Schannel: DecryptMessage pointers: " - "out_data=%p bufs %p %p %p %p", - wpabuf_head(tmp), bufs[0].pvBuffer, bufs[1].pvBuffer, - bufs[2].pvBuffer, bufs[3].pvBuffer); - - switch (status) { - case SEC_E_INCOMPLETE_MESSAGE: - wpa_printf(MSG_DEBUG, "%s: SEC_E_INCOMPLETE_MESSAGE", - __func__); - break; - case SEC_E_OK: - wpa_printf(MSG_DEBUG, "%s: SEC_E_OK", __func__); - for (i = 0; i < 4; i++) { - if (bufs[i].BufferType == SECBUFFER_DATA) - break; - } - if (i == 4) { - wpa_printf(MSG_DEBUG, "%s: No output data from " - "DecryptMessage", __func__); - wpabuf_free(tmp); - return NULL; - } - wpa_hexdump_key(MSG_MSGDUMP, "Schannel: Decrypted data from " - "DecryptMessage", - bufs[i].pvBuffer, bufs[i].cbBuffer); - out = wpabuf_alloc_copy(bufs[i].pvBuffer, bufs[i].cbBuffer); - wpabuf_free(tmp); - return out; - } - - wpa_printf(MSG_DEBUG, "%s: Failed - status=%d", - __func__, (int) status); - wpabuf_free(tmp); - return NULL; -} - - -int tls_connection_resumed(void *ssl_ctx, struct tls_connection *conn) -{ - return 0; -} - - -int tls_connection_set_cipher_list(void *tls_ctx, struct tls_connection *conn, - u8 *ciphers) -{ - return -1; -} - - -int tls_get_cipher(void *ssl_ctx, struct tls_connection *conn, - char *buf, size_t buflen) -{ - return -1; -} - - -int tls_connection_enable_workaround(void *ssl_ctx, - struct tls_connection *conn) -{ - return 0; -} - - -int tls_connection_client_hello_ext(void *ssl_ctx, struct tls_connection *conn, - int ext_type, const u8 *data, - size_t data_len) -{ - return -1; -} - - -int tls_connection_get_failed(void *ssl_ctx, struct tls_connection *conn) -{ - if (conn == NULL) - return -1; - return conn->failed; -} - - -int tls_connection_get_read_alerts(void *ssl_ctx, struct tls_connection *conn) -{ - if (conn == NULL) - return -1; - return conn->read_alerts; -} - - -int tls_connection_get_write_alerts(void *ssl_ctx, struct tls_connection *conn) -{ - if (conn == NULL) - return -1; - return conn->write_alerts; -} - - -int tls_connection_set_params(void *tls_ctx, struct tls_connection *conn, - const struct tls_connection_params *params) -{ - struct tls_global *global = tls_ctx; - ALG_ID algs[1]; - SECURITY_STATUS status; - TimeStamp ts_expiry; - - if (conn == NULL) - return -1; - - if (global->my_cert_store == NULL && - (global->my_cert_store = CertOpenSystemStore(0, TEXT("MY"))) == - NULL) { - wpa_printf(MSG_ERROR, "%s: CertOpenSystemStore failed - 0x%x", - __func__, (unsigned int) GetLastError()); - return -1; - } - - os_memset(&conn->schannel_cred, 0, sizeof(conn->schannel_cred)); - conn->schannel_cred.dwVersion = SCHANNEL_CRED_VERSION; - conn->schannel_cred.grbitEnabledProtocols = SP_PROT_TLS1; - algs[0] = CALG_RSA_KEYX; - conn->schannel_cred.cSupportedAlgs = 1; - conn->schannel_cred.palgSupportedAlgs = algs; - conn->schannel_cred.dwFlags |= SCH_CRED_NO_DEFAULT_CREDS; -#ifdef UNICODE - status = global->sspi->AcquireCredentialsHandleW( - NULL, UNISP_NAME_W, SECPKG_CRED_OUTBOUND, NULL, - &conn->schannel_cred, NULL, NULL, &conn->creds, &ts_expiry); -#else /* UNICODE */ - status = global->sspi->AcquireCredentialsHandleA( - NULL, UNISP_NAME_A, SECPKG_CRED_OUTBOUND, NULL, - &conn->schannel_cred, NULL, NULL, &conn->creds, &ts_expiry); -#endif /* UNICODE */ - if (status != SEC_E_OK) { - wpa_printf(MSG_DEBUG, "%s: AcquireCredentialsHandleA failed - " - "0x%x", __func__, (unsigned int) status); - return -1; - } - - return 0; -} - - -unsigned int tls_capabilities(void *tls_ctx) -{ - return 0; -} - - -int tls_connection_set_ia(void *tls_ctx, struct tls_connection *conn, - int tls_ia) -{ - return -1; -} - - -struct wpabuf * tls_connection_ia_send_phase_finished( - void *tls_ctx, struct tls_connection *conn, int final); -{ - return NULL; -} - - -int tls_connection_ia_final_phase_finished(void *tls_ctx, - struct tls_connection *conn) -{ - return -1; -} - - -int tls_connection_ia_permute_inner_secret(void *tls_ctx, - struct tls_connection *conn, - const u8 *key, size_t key_len) -{ - return -1; -} diff --git a/hostapd-0.8/src/drivers/.gitignore b/hostapd-0.8/src/drivers/.gitignore deleted file mode 100644 index 1d9e0e6..0000000 --- a/hostapd-0.8/src/drivers/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -build.wpa_supplicant -build.hostapd diff --git a/hostapd-0.8/src/drivers/Apple80211.h b/hostapd-0.8/src/drivers/Apple80211.h deleted file mode 100644 index 2a612e7..0000000 --- a/hostapd-0.8/src/drivers/Apple80211.h +++ /dev/null @@ -1,156 +0,0 @@ -#ifndef APPLE80211_H -#define APPLE80211_H - -/* - * Apple80211 framework definitions - * This is an undocumented interface and the definitions here are based on - * information from MacStumbler (http://www.macstumbler.com/Apple80211.h) and - * whatever related information can be found with google and experiments ;-). - */ - -typedef struct __WirelessRef *WirelessRef; -typedef SInt32 WirelessError; -#define errWirelessNoError 0 - -typedef struct WirelessInfo { - UInt16 link_qual; - UInt16 comms_qual; - UInt16 signal; - UInt16 noise; - UInt16 port_stat; - UInt16 client_mode; - UInt16 res1; - UInt16 power; - UInt16 res2; - UInt8 bssID[6]; - UInt8 ssid[34]; -} WirelessInfo; - -typedef struct WirelessInfo2 { - /* TODO - these are probably not in correct order or complete */ - WirelessInfo info1; - UInt8 macAddress[6]; -} WirelessInfo2; - -typedef struct WirelessNetworkInfo { - UInt16 channel; - UInt16 noise; - UInt16 signal; - UInt8 bssid[6]; - UInt16 beacon_int; - UInt16 capability; - UInt16 ssid_len; - UInt8 ssid[32]; -} WirelessNetworkInfo; - -typedef int wirelessKeyType; /* TODO */ - -int WirelessIsAvailable(void); -WirelessError WirelessAttach(WirelessRef *ref, UInt32 res); -WirelessError WirelessDetach(WirelessRef ref); -WirelessError WirelessPrivate(WirelessRef ref, void *in_ptr, int in_bytes, - void *out_ptr, int out_bytes); -WirelessError WirelessSetEnabled(WirelessRef ref, UInt8 enabled); -WirelessError WirelessGetEnabled(WirelessRef ref, UInt8 *enabled); -WirelessError WirelessSetPower(WirelessRef ref, UInt8 power); -WirelessError WirelessGetPower(WirelessRef ref, UInt8 *power); -WirelessError WirelessGetInfo(WirelessRef ref, WirelessInfo *info); -WirelessError WirelessGetInfo2(WirelessRef ref, WirelessInfo2 *info); -WirelessError WirelessScan(WirelessRef ref, CFArrayRef *results, - UInt32 strip_dups); -WirelessError WirelessScanSplit(WirelessRef ref, CFArrayRef *ap_results, - CFArrayRef *ibss_results, UInt32 strip_dups); -WirelessError WirelessDirectedScan(WirelessRef ref, CFArrayRef *results, - UInt32 strip_dups, CFStringRef ssid); -WirelessError WirelessDirectedScan2(WirelessRef ref, CFDataRef ssid, - UInt32 strip_dups, CFArrayRef *results); -WirelessError WirelessJoin(WirelessRef ref, CFStringRef ssid); -WirelessError WirelessJoinWEP(WirelessRef ref, CFStringRef ssid, - CFStringRef passwd); -WirelessError WirelessJoin8021x(WirelessRef ref, CFStringRef ssid); -/* - * Set WEP key - * ref: wireless reference from WirelessAttach() - * type: ? - * key_idx: 0..3 - * key_len: 13 for WEP-104 or 0 for clearing the key - * key: Pointer to the key or %NULL if key_len = 0 - */ -WirelessError WirelessSetKey(WirelessRef ref, wirelessKeyType type, - int key_idx, int key_len, - const unsigned char *key); -/* - * Set WPA key (e.g., PMK for 4-way handshake) - * ref: wireless reference from WirelessAttach() - * type: 0..4; 1 = PMK - * key_len: 16, 32, or 0 - * key: Pointer to the key or %NULL if key_len = 0 - */ -WirelessError WirelessSetWPAKey(WirelessRef ref, wirelessKeyType type, - int key_len, const unsigned char *key); -WirelessError WirelessAssociate(WirelessRef ref, int type, CFDataRef ssid, - CFStringRef key); -WirelessError WirelessAssociate2(WirelessRef ref, CFDictionaryRef scan_res, - CFStringRef key); -WirelessError WirelessDisassociate(WirelessRef ref); - -/* - * Get a copy of scan results for the given SSID - * The returned dictionary includes following entries: - * beaconInterval: CFNumber(kCFNumberSInt32Type) - * SSID: CFData buffer of the SSID - * isWPA: CFNumber(kCFNumberSInt32Type); 0 = not used, 1 = WPA, -128 = WPA2 - * name: Name of the network (SSID string) - * BSSID: CFData buffer of the BSSID - * channel: CFNumber(kCFNumberSInt32Type) - * signal: CFNumber(kCFNumberSInt32Type) - * appleIE: CFData - * WPSNOPINRequired: CFBoolean - * noise: CFNumber(kCFNumberSInt32Type) - * capability: CFNumber(kCFNumberSInt32Type) - * uniCipher: CFArray of CFNumber(kCFNumberSInt32Type) - * appleIE_Version: CFNumber(kCFNumberSInt32Type) - * appleIE_Robust: CFBoolean - * WPSConfigured: CFBoolean - * scanWasDirected: CFBoolean - * appleIE_Product: CFNumber(kCFNumberSInt32Type) - * authModes: CFArray of CFNumber(kCFNumberSInt32Type) - * multiCipher: CFNumber(kCFNumberSInt32Type) - */ -CFDictionaryRef WirelessSafeDirectedScanCopy(WirelessRef ref, CFDataRef ssid); - -/* - * Get information about the current association - * The returned dictionary includes following entries: - * keyData: CFData buffer of the key (e.g., 32-octet PSK) - * multiCipher: CFNumber(kCFNumberSInt32Type); 0 = none, 5 = CCMP? - * channel: CFNumber(kCFNumberSInt32Type) - * isIBSS: CFBoolean - * authMode: CFNumber(kCFNumberSInt32Type); 2 = WPA-Personal; 3 = open, - * 129 = WPA2-Enterprise - * isWPA: CFNumber(kCFNumberSInt32Type); 0 = not used, 1 = WPA, -128 == WPA2 - * SSID: CFData buffer of the SSID - * cipherMode: CFNumber(kCFNumberSInt32Type); 0 = none, 4 = CCMP? - */ -CFDictionaryRef WirelessGetAssociationInfo(WirelessRef ref); - -WirelessError WirelessConfigure(WirelessRef ref); - -/* - * Get ASP information - * The returned dictionary includes following entries: - * Version: version number (e.g., 3.0) - * Channel: channel (e.g., 1) - * Vendor: vendor (e.g., 2) - */ -CFDictionaryRef WirelessGetInfoASP(void); - -/* - * Get a copy of the interface dictionary - * The returned dictionary has a key,value pairs for wireless interfaces. - * The key is the interface name and the value is the driver identifier, e.g., - * en1: com.apple.driver.AirPort.Atheros - */ -CFDictionaryRef WirelessCopyInterfaceDict(void); - -#endif /* APPLE80211_H */ diff --git a/hostapd-0.8/src/drivers/Makefile b/hostapd-0.8/src/drivers/Makefile deleted file mode 100644 index 07600e5..0000000 --- a/hostapd-0.8/src/drivers/Makefile +++ /dev/null @@ -1,9 +0,0 @@ -all: - @echo Nothing to be made. - -clean: - rm -f *~ *.o *.d - rm -f build.wpa_supplicant build.hostapd - -install: - @echo Nothing to be made. diff --git a/hostapd-0.8/src/drivers/MobileApple80211.c b/hostapd-0.8/src/drivers/MobileApple80211.c deleted file mode 100644 index ce004fe..0000000 --- a/hostapd-0.8/src/drivers/MobileApple80211.c +++ /dev/null @@ -1,189 +0,0 @@ -#include "includes.h" -#include - -#include "common.h" - -#include -#include "MobileApple80211.h" - -/* - * Code for dynamically loading Apple80211 functions from Aeropuerto to avoid - * having to link with full Preferences.framework. - */ - -static void *aeropuerto = NULL; - - -int _Apple80211Initialized(void) -{ - return aeropuerto ? 1 : 0; -} - - -static int (*__Apple80211Open)(Apple80211Ref *ctx) = NULL; - -int Apple80211Open(Apple80211Ref *ctx) -{ - return __Apple80211Open(ctx); -} - - -static int (*__Apple80211Close)(Apple80211Ref ctx) = NULL; - -int Apple80211Close(Apple80211Ref ctx) -{ - return __Apple80211Close(ctx); -} - - -static int (*__Apple80211GetIfListCopy)(Apple80211Ref handle, CFArrayRef *list) - = NULL; - -int Apple80211GetIfListCopy(Apple80211Ref handle, CFArrayRef *list) -{ - return __Apple80211GetIfListCopy(handle, list); -} - - -static int (*__Apple80211BindToInterface)(Apple80211Ref handle, - CFStringRef interface) = NULL; - -int Apple80211BindToInterface(Apple80211Ref handle, - CFStringRef interface) -{ - return __Apple80211BindToInterface(handle, interface); -} - - -static int (*__Apple80211GetInterfaceNameCopy)(Apple80211Ref handle, - CFStringRef *name) = NULL; - -int Apple80211GetInterfaceNameCopy(Apple80211Ref handle, - CFStringRef *name) -{ - return __Apple80211GetInterfaceNameCopy(handle, name); -} - - -static int (*__Apple80211GetInfoCopy)(Apple80211Ref handle, - CFDictionaryRef *info) = NULL; - -int Apple80211GetInfoCopy(Apple80211Ref handle, - CFDictionaryRef *info) -{ - return __Apple80211GetInfoCopy(handle, info); -} - - -static int (*__Apple80211GetPower)(Apple80211Ref handle, char *pwr) = NULL; - -int Apple80211GetPower(Apple80211Ref handle, char *pwr) -{ - return __Apple80211GetPower(handle, pwr); -} - - -static int (*__Apple80211SetPower)(Apple80211Ref handle, char pwr) = NULL; - -int Apple80211SetPower(Apple80211Ref handle, char pwr) -{ - return __Apple80211SetPower(handle, pwr); -} - - -static int (*__Apple80211Scan)(Apple80211Ref handle, CFArrayRef *list, - CFDictionaryRef parameters) = NULL; - -int Apple80211Scan(Apple80211Ref handle, CFArrayRef *list, - CFDictionaryRef parameters) -{ - return __Apple80211Scan(handle, list, parameters); -} - - -static int (*__Apple80211Associate)(Apple80211Ref handle, CFDictionaryRef bss, - CFStringRef password) = NULL; - -int Apple80211Associate(Apple80211Ref handle, CFDictionaryRef bss, - CFStringRef password) -{ - return __Apple80211Associate(handle, bss, password); -} - - -static int (*__Apple80211AssociateAndCopyInfo)(Apple80211Ref handle, - CFDictionaryRef bss, - CFStringRef password, - CFDictionaryRef *info) = - NULL; - -int Apple80211AssociateAndCopyInfo(Apple80211Ref handle, CFDictionaryRef bss, - CFStringRef password, CFDictionaryRef *info) -{ - return __Apple80211AssociateAndCopyInfo(handle, bss, password, info); -} - - -static int (*__Apple80211CopyValue)(Apple80211Ref handle, int field, - CFDictionaryRef arg2, void *value) = NULL; - -int Apple80211CopyValue(Apple80211Ref handle, int field, CFDictionaryRef arg2, - void *value) -{ - return __Apple80211CopyValue(handle, field, arg2, value); -} - - -#define DLSYM(s) \ -do { \ - __ ## s = dlsym(aeropuerto, #s); \ - if (__ ## s == NULL) { \ - wpa_printf(MSG_ERROR, "MobileApple80211: Could not resolve " \ - "symbol '" #s "' (%s)", dlerror()); \ - err = 1; \ - } \ -} while (0) - - -__attribute__ ((constructor)) -void _Apple80211_constructor(void) -{ - const char *fname = "/System/Library/SystemConfiguration/" - "Aeropuerto.bundle/Aeropuerto"; - int err = 0; - - aeropuerto = dlopen(fname, RTLD_LAZY); - if (!aeropuerto) { - wpa_printf(MSG_ERROR, "MobileApple80211: Failed to open %s " - "for symbols", fname); - return; - } - - DLSYM(Apple80211Open); - DLSYM(Apple80211Close); - DLSYM(Apple80211GetIfListCopy); - DLSYM(Apple80211BindToInterface); - DLSYM(Apple80211GetInterfaceNameCopy); - DLSYM(Apple80211GetInfoCopy); - DLSYM(Apple80211GetPower); - DLSYM(Apple80211SetPower); - DLSYM(Apple80211Scan); - DLSYM(Apple80211Associate); - DLSYM(Apple80211AssociateAndCopyInfo); - DLSYM(Apple80211CopyValue); - - if (err) { - dlclose(aeropuerto); - aeropuerto = NULL; - } -} - - -__attribute__ ((destructor)) -void _Apple80211_destructor(void) -{ - if (aeropuerto) { - dlclose(aeropuerto); - aeropuerto = NULL; - } -} diff --git a/hostapd-0.8/src/drivers/MobileApple80211.h b/hostapd-0.8/src/drivers/MobileApple80211.h deleted file mode 100644 index 64d439d..0000000 --- a/hostapd-0.8/src/drivers/MobileApple80211.h +++ /dev/null @@ -1,43 +0,0 @@ -#ifndef MOBILEAPPLE80211_H -#define MOBILEAPPLE80211_H - -/* - * MobileApple80211 interface for iPhone/iPod touch - * These functions are available from Aeropuerto. - */ - -struct Apple80211; -typedef struct Apple80211 *Apple80211Ref; - -int Apple80211Open(Apple80211Ref *ctx); -int Apple80211Close(Apple80211Ref ctx); -int Apple80211GetIfListCopy(Apple80211Ref handle, CFArrayRef *list); -int Apple80211BindToInterface(Apple80211Ref handle, - CFStringRef interface); -int Apple80211GetInterfaceNameCopy(Apple80211Ref handle, - CFStringRef *name); -int Apple80211GetInfoCopy(Apple80211Ref handle, - CFDictionaryRef *info); -int Apple80211GetPower(Apple80211Ref handle, char *pwr); -int Apple80211SetPower(Apple80211Ref handle, char pwr); - -/* parameters can be NULL; returns scan results in CFArrayRef *list; - * caller will need to free with CFRelease() */ -int Apple80211Scan(Apple80211Ref handle, CFArrayRef *list, - CFDictionaryRef parameters); - -int Apple80211Associate(Apple80211Ref handle, CFDictionaryRef bss, - CFStringRef password); -int Apple80211AssociateAndCopyInfo(Apple80211Ref handle, CFDictionaryRef bss, - CFStringRef password, - CFDictionaryRef *info); - -enum { - APPLE80211_VALUE_SSID = 1, - APPLE80211_VALUE_BSSID = 9 -}; - -int Apple80211CopyValue(Apple80211Ref handle, int field, CFDictionaryRef arg2, - void *value); - -#endif /* MOBILEAPPLE80211_H */ diff --git a/hostapd-0.8/src/drivers/driver.h b/hostapd-0.8/src/drivers/driver.h deleted file mode 100644 index 8efd697..0000000 --- a/hostapd-0.8/src/drivers/driver.h +++ /dev/null @@ -1,3230 +0,0 @@ -/* - * Driver interface definition - * Copyright (c) 2003-2010, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - * - * This file defines a driver interface used by both %wpa_supplicant and - * hostapd. The first part of the file defines data structures used in various - * driver operations. This is followed by the struct wpa_driver_ops that each - * driver wrapper will beed to define with callback functions for requesting - * driver operations. After this, there are definitions for driver event - * reporting with wpa_supplicant_event() and some convenience helper functions - * that can be used to report events. - */ - -#ifndef DRIVER_H -#define DRIVER_H - -#define WPA_SUPPLICANT_DRIVER_VERSION 4 - -#include "common/defs.h" - -#define HOSTAPD_CHAN_DISABLED 0x00000001 -#define HOSTAPD_CHAN_PASSIVE_SCAN 0x00000002 -#define HOSTAPD_CHAN_NO_IBSS 0x00000004 -#define HOSTAPD_CHAN_RADAR 0x00000008 -#define HOSTAPD_CHAN_HT40PLUS 0x00000010 -#define HOSTAPD_CHAN_HT40MINUS 0x00000020 -#define HOSTAPD_CHAN_HT40 0x00000040 - -/** - * struct hostapd_channel_data - Channel information - */ -struct hostapd_channel_data { - /** - * chan - Channel number (IEEE 802.11) - */ - short chan; - - /** - * freq - Frequency in MHz - */ - short freq; - - /** - * flag - Channel flags (HOSTAPD_CHAN_*) - */ - int flag; - - /** - * max_tx_power - maximum transmit power in dBm - */ - u8 max_tx_power; -}; - -/** - * struct hostapd_hw_modes - Supported hardware mode information - */ -struct hostapd_hw_modes { - /** - * mode - Hardware mode - */ - enum hostapd_hw_mode mode; - - /** - * num_channels - Number of entries in the channels array - */ - int num_channels; - - /** - * channels - Array of supported channels - */ - struct hostapd_channel_data *channels; - - /** - * num_rates - Number of entries in the rates array - */ - int num_rates; - - /** - * rates - Array of supported rates in 100 kbps units - */ - int *rates; - - /** - * ht_capab - HT (IEEE 802.11n) capabilities - */ - u16 ht_capab; - - /** - * mcs_set - MCS (IEEE 802.11n) rate parameters - */ - u8 mcs_set[16]; - - /** - * a_mpdu_params - A-MPDU (IEEE 802.11n) parameters - */ - u8 a_mpdu_params; -}; - - -#define IEEE80211_MODE_INFRA 0 -#define IEEE80211_MODE_IBSS 1 -#define IEEE80211_MODE_AP 2 - -#define IEEE80211_CAP_ESS 0x0001 -#define IEEE80211_CAP_IBSS 0x0002 -#define IEEE80211_CAP_PRIVACY 0x0010 - -#define WPA_SCAN_QUAL_INVALID BIT(0) -#define WPA_SCAN_NOISE_INVALID BIT(1) -#define WPA_SCAN_LEVEL_INVALID BIT(2) -#define WPA_SCAN_LEVEL_DBM BIT(3) -#define WPA_SCAN_AUTHENTICATED BIT(4) -#define WPA_SCAN_ASSOCIATED BIT(5) - -/** - * struct wpa_scan_res - Scan result for an BSS/IBSS - * @flags: information flags about the BSS/IBSS (WPA_SCAN_*) - * @bssid: BSSID - * @freq: frequency of the channel in MHz (e.g., 2412 = channel 1) - * @beacon_int: beacon interval in TUs (host byte order) - * @caps: capability information field in host byte order - * @qual: signal quality - * @noise: noise level - * @level: signal level - * @tsf: Timestamp - * @age: Age of the information in milliseconds (i.e., how many milliseconds - * ago the last Beacon or Probe Response frame was received) - * @ie_len: length of the following IE field in octets - * @beacon_ie_len: length of the following Beacon IE field in octets - * - * This structure is used as a generic format for scan results from the - * driver. Each driver interface implementation is responsible for converting - * the driver or OS specific scan results into this format. - * - * If the driver does not support reporting all IEs, the IE data structure is - * constructed of the IEs that are available. This field will also need to - * include SSID in IE format. All drivers are encouraged to be extended to - * report all IEs to make it easier to support future additions. - */ -struct wpa_scan_res { - unsigned int flags; - u8 bssid[ETH_ALEN]; - int freq; - u16 beacon_int; - u16 caps; - int qual; - int noise; - int level; - u64 tsf; - unsigned int age; - size_t ie_len; - size_t beacon_ie_len; - /* - * Followed by ie_len octets of IEs from Probe Response frame (or if - * the driver does not indicate source of IEs, these may also be from - * Beacon frame). After the first set of IEs, another set of IEs may - * follow (with beacon_ie_len octets of data) if the driver provides - * both IE sets. - */ -}; - -/** - * struct wpa_scan_results - Scan results - * @res: Array of pointers to allocated variable length scan result entries - * @num: Number of entries in the scan result array - */ -struct wpa_scan_results { - struct wpa_scan_res **res; - size_t num; -}; - -/** - * struct wpa_interface_info - Network interface information - * @next: Pointer to the next interface or NULL if this is the last one - * @ifname: Interface name that can be used with init() or init2() - * @desc: Human readable adapter description (e.g., vendor/model) or NULL if - * not available - * @drv_name: struct wpa_driver_ops::name (note: unlike other strings, this one - * is not an allocated copy, i.e., get_interfaces() caller will not free - * this) - */ -struct wpa_interface_info { - struct wpa_interface_info *next; - char *ifname; - char *desc; - const char *drv_name; -}; - -#define WPAS_MAX_SCAN_SSIDS 4 - -/** - * struct wpa_driver_scan_params - Scan parameters - * Data for struct wpa_driver_ops::scan2(). - */ -struct wpa_driver_scan_params { - /** - * ssids - SSIDs to scan for - */ - struct wpa_driver_scan_ssid { - /** - * ssid - specific SSID to scan for (ProbeReq) - * %NULL or zero-length SSID is used to indicate active scan - * with wildcard SSID. - */ - const u8 *ssid; - /** - * ssid_len: Length of the SSID in octets - */ - size_t ssid_len; - } ssids[WPAS_MAX_SCAN_SSIDS]; - - /** - * num_ssids - Number of entries in ssids array - * Zero indicates a request for a passive scan. - */ - size_t num_ssids; - - /** - * extra_ies - Extra IE(s) to add into Probe Request or %NULL - */ - const u8 *extra_ies; - - /** - * extra_ies_len - Length of extra_ies in octets - */ - size_t extra_ies_len; - - /** - * freqs - Array of frequencies to scan or %NULL for all frequencies - * - * The frequency is set in MHz. The array is zero-terminated. - */ - int *freqs; - - /** - * filter_ssids - Filter for reporting SSIDs - * - * This optional parameter can be used to request the driver wrapper to - * filter scan results to include only the specified SSIDs. %NULL - * indicates that no filtering is to be done. This can be used to - * reduce memory needs for scan results in environments that have large - * number of APs with different SSIDs. - * - * The driver wrapper is allowed to take this allocated buffer into its - * own use by setting the pointer to %NULL. In that case, the driver - * wrapper is responsible for freeing the buffer with os_free() once it - * is not needed anymore. - */ - struct wpa_driver_scan_filter { - u8 ssid[32]; - size_t ssid_len; - } *filter_ssids; - - /** - * num_filter_ssids - Number of entries in filter_ssids array - */ - size_t num_filter_ssids; -}; - -/** - * struct wpa_driver_auth_params - Authentication parameters - * Data for struct wpa_driver_ops::authenticate(). - */ -struct wpa_driver_auth_params { - int freq; - const u8 *bssid; - const u8 *ssid; - size_t ssid_len; - int auth_alg; - const u8 *ie; - size_t ie_len; - const u8 *wep_key[4]; - size_t wep_key_len[4]; - int wep_tx_keyidx; - int local_state_change; -}; - -enum wps_mode { - WPS_MODE_NONE /* no WPS provisioning being used */, - WPS_MODE_OPEN /* WPS provisioning with AP that is in open mode */, - WPS_MODE_PRIVACY /* WPS provisioning with AP that is using protection - */ -}; - -/** - * struct wpa_driver_associate_params - Association parameters - * Data for struct wpa_driver_ops::associate(). - */ -struct wpa_driver_associate_params { - /** - * bssid - BSSID of the selected AP - * This can be %NULL, if ap_scan=2 mode is used and the driver is - * responsible for selecting with which BSS to associate. */ - const u8 *bssid; - - /** - * ssid - The selected SSID - */ - const u8 *ssid; - - /** - * ssid_len - Length of the SSID (1..32) - */ - size_t ssid_len; - - /** - * freq - Frequency of the channel the selected AP is using - * Frequency that the selected AP is using (in MHz as - * reported in the scan results) - */ - int freq; - - /** - * wpa_ie - WPA information element for (Re)Association Request - * WPA information element to be included in (Re)Association - * Request (including information element id and length). Use - * of this WPA IE is optional. If the driver generates the WPA - * IE, it can use pairwise_suite, group_suite, and - * key_mgmt_suite to select proper algorithms. In this case, - * the driver has to notify wpa_supplicant about the used WPA - * IE by generating an event that the interface code will - * convert into EVENT_ASSOCINFO data (see below). - * - * When using WPA2/IEEE 802.11i, wpa_ie is used for RSN IE - * instead. The driver can determine which version is used by - * looking at the first byte of the IE (0xdd for WPA, 0x30 for - * WPA2/RSN). - * - * When using WPS, wpa_ie is used for WPS IE instead of WPA/RSN IE. - */ - const u8 *wpa_ie; - - /** - * wpa_ie_len - length of the wpa_ie - */ - size_t wpa_ie_len; - - /** - * pairwise_suite - Selected pairwise cipher suite - * - * This is usually ignored if @wpa_ie is used. - */ - enum wpa_cipher pairwise_suite; - - /** - * group_suite - Selected group cipher suite - * - * This is usually ignored if @wpa_ie is used. - */ - enum wpa_cipher group_suite; - - /** - * key_mgmt_suite - Selected key management suite - * - * This is usually ignored if @wpa_ie is used. - */ - enum wpa_key_mgmt key_mgmt_suite; - - /** - * auth_alg - Allowed authentication algorithms - * Bit field of WPA_AUTH_ALG_* - */ - int auth_alg; - - /** - * mode - Operation mode (infra/ibss) IEEE80211_MODE_* - */ - int mode; - - /** - * wep_key - WEP keys for static WEP configuration - */ - const u8 *wep_key[4]; - - /** - * wep_key_len - WEP key length for static WEP configuration - */ - size_t wep_key_len[4]; - - /** - * wep_tx_keyidx - WEP TX key index for static WEP configuration - */ - int wep_tx_keyidx; - - /** - * mgmt_frame_protection - IEEE 802.11w management frame protection - */ - enum mfp_options mgmt_frame_protection; - - /** - * ft_ies - IEEE 802.11r / FT information elements - * If the supplicant is using IEEE 802.11r (FT) and has the needed keys - * for fast transition, this parameter is set to include the IEs that - * are to be sent in the next FT Authentication Request message. - * update_ft_ies() handler is called to update the IEs for further - * FT messages in the sequence. - * - * The driver should use these IEs only if the target AP is advertising - * the same mobility domain as the one included in the MDIE here. - * - * In ap_scan=2 mode, the driver can use these IEs when moving to a new - * AP after the initial association. These IEs can only be used if the - * target AP is advertising support for FT and is using the same MDIE - * and SSID as the current AP. - * - * The driver is responsible for reporting the FT IEs received from the - * AP's response using wpa_supplicant_event() with EVENT_FT_RESPONSE - * type. update_ft_ies() handler will then be called with the FT IEs to - * include in the next frame in the authentication sequence. - */ - const u8 *ft_ies; - - /** - * ft_ies_len - Length of ft_ies in bytes - */ - size_t ft_ies_len; - - /** - * ft_md - FT Mobility domain (6 octets) (also included inside ft_ies) - * - * This value is provided to allow the driver interface easier access - * to the current mobility domain. This value is set to %NULL if no - * mobility domain is currently active. - */ - const u8 *ft_md; - - /** - * passphrase - RSN passphrase for PSK - * - * This value is made available only for WPA/WPA2-Personal (PSK) and - * only for drivers that set WPA_DRIVER_FLAGS_4WAY_HANDSHAKE. This is - * the 8..63 character ASCII passphrase, if available. Please note that - * this can be %NULL if passphrase was not used to generate the PSK. In - * that case, the psk field must be used to fetch the PSK. - */ - const char *passphrase; - - /** - * psk - RSN PSK (alternative for passphrase for PSK) - * - * This value is made available only for WPA/WPA2-Personal (PSK) and - * only for drivers that set WPA_DRIVER_FLAGS_4WAY_HANDSHAKE. This is - * the 32-octet (256-bit) PSK, if available. The driver wrapper should - * be prepared to handle %NULL value as an error. - */ - const u8 *psk; - - /** - * drop_unencrypted - Enable/disable unencrypted frame filtering - * - * Configure the driver to drop all non-EAPOL frames (both receive and - * transmit paths). Unencrypted EAPOL frames (ethertype 0x888e) must - * still be allowed for key negotiation. - */ - int drop_unencrypted; - - /** - * prev_bssid - Previously used BSSID in this ESS - * - * When not %NULL, this is a request to use reassociation instead of - * association. - */ - const u8 *prev_bssid; - - /** - * wps - WPS mode - * - * If the driver needs to do special configuration for WPS association, - * this variable provides more information on what type of association - * is being requested. Most drivers should not need ot use this. - */ - enum wps_mode wps; - - /** - * p2p - Whether this connection is a P2P group - */ - int p2p; - - /** - * uapsd - UAPSD parameters for the network - * -1 = do not change defaults - * AP mode: 1 = enabled, 0 = disabled - * STA mode: bits 0..3 UAPSD enabled for VO,VI,BK,BE - */ - int uapsd; -}; - -/** - * struct wpa_driver_capa - Driver capability information - */ -struct wpa_driver_capa { -#define WPA_DRIVER_CAPA_KEY_MGMT_WPA 0x00000001 -#define WPA_DRIVER_CAPA_KEY_MGMT_WPA2 0x00000002 -#define WPA_DRIVER_CAPA_KEY_MGMT_WPA_PSK 0x00000004 -#define WPA_DRIVER_CAPA_KEY_MGMT_WPA2_PSK 0x00000008 -#define WPA_DRIVER_CAPA_KEY_MGMT_WPA_NONE 0x00000010 -#define WPA_DRIVER_CAPA_KEY_MGMT_FT 0x00000020 -#define WPA_DRIVER_CAPA_KEY_MGMT_FT_PSK 0x00000040 - unsigned int key_mgmt; - -#define WPA_DRIVER_CAPA_ENC_WEP40 0x00000001 -#define WPA_DRIVER_CAPA_ENC_WEP104 0x00000002 -#define WPA_DRIVER_CAPA_ENC_TKIP 0x00000004 -#define WPA_DRIVER_CAPA_ENC_CCMP 0x00000008 - unsigned int enc; - -#define WPA_DRIVER_AUTH_OPEN 0x00000001 -#define WPA_DRIVER_AUTH_SHARED 0x00000002 -#define WPA_DRIVER_AUTH_LEAP 0x00000004 - unsigned int auth; - -/* Driver generated WPA/RSN IE */ -#define WPA_DRIVER_FLAGS_DRIVER_IE 0x00000001 -/* Driver needs static WEP key setup after association command */ -#define WPA_DRIVER_FLAGS_SET_KEYS_AFTER_ASSOC 0x00000002 -#define WPA_DRIVER_FLAGS_USER_SPACE_MLME 0x00000004 -/* Driver takes care of RSN 4-way handshake internally; PMK is configured with - * struct wpa_driver_ops::set_key using alg = WPA_ALG_PMK */ -#define WPA_DRIVER_FLAGS_4WAY_HANDSHAKE 0x00000008 -#define WPA_DRIVER_FLAGS_WIRED 0x00000010 -/* Driver provides separate commands for authentication and association (SME in - * wpa_supplicant). */ -#define WPA_DRIVER_FLAGS_SME 0x00000020 -/* Driver supports AP mode */ -#define WPA_DRIVER_FLAGS_AP 0x00000040 -/* Driver needs static WEP key setup after association has been completed */ -#define WPA_DRIVER_FLAGS_SET_KEYS_AFTER_ASSOC_DONE 0x00000080 -/* Driver takes care of P2P management operations */ -#define WPA_DRIVER_FLAGS_P2P_MGMT 0x00000100 -/* Driver supports concurrent P2P operations */ -#define WPA_DRIVER_FLAGS_P2P_CONCURRENT 0x00000200 -/* - * Driver uses the initial interface as a dedicated management interface, i.e., - * it cannot be used for P2P group operations or non-P2P purposes. - */ -#define WPA_DRIVER_FLAGS_P2P_DEDICATED_INTERFACE 0x00000400 -/* This interface is P2P capable (P2P Device, GO, or P2P Client */ -#define WPA_DRIVER_FLAGS_P2P_CAPABLE 0x00000800 -/* Driver supports concurrent operations on multiple channels */ -#define WPA_DRIVER_FLAGS_MULTI_CHANNEL_CONCURRENT 0x00001000 -/* - * Driver uses the initial interface for P2P management interface and non-P2P - * purposes (e.g., connect to infra AP), but this interface cannot be used for - * P2P group operations. - */ -#define WPA_DRIVER_FLAGS_P2P_MGMT_AND_NON_P2P 0x00002000 -/* - * Driver is known to use sane error codes, i.e., when it indicates that - * something (e.g., association) fails, there was indeed a failure and the - * operation does not end up getting completed successfully later. - */ -#define WPA_DRIVER_FLAGS_SANE_ERROR_CODES 0x00004000 -/* Driver supports off-channel TX */ -#define WPA_DRIVER_FLAGS_OFFCHANNEL_TX 0x00008000 -/* Driver indicates TX status events for EAPOL Data frames */ -#define WPA_DRIVER_FLAGS_EAPOL_TX_STATUS 0x00010000 - unsigned int flags; - - int max_scan_ssids; - - /** - * max_remain_on_chan - Maximum remain-on-channel duration in msec - */ - unsigned int max_remain_on_chan; - - /** - * max_stations - Maximum number of associated stations the driver - * supports in AP mode - */ - unsigned int max_stations; -}; - - -struct hostapd_data; - -struct hostap_sta_driver_data { - unsigned long rx_packets, tx_packets, rx_bytes, tx_bytes; - unsigned long current_tx_rate; - unsigned long inactive_msec; - unsigned long flags; - unsigned long num_ps_buf_frames; - unsigned long tx_retry_failed; - unsigned long tx_retry_count; - int last_rssi; - int last_ack_rssi; -}; - -struct hostapd_sta_add_params { - const u8 *addr; - u16 aid; - u16 capability; - const u8 *supp_rates; - size_t supp_rates_len; - u16 listen_interval; - const struct ieee80211_ht_capabilities *ht_capabilities; -}; - -struct hostapd_freq_params { - int mode; - int freq; - int channel; - int ht_enabled; - int sec_channel_offset; /* 0 = HT40 disabled, -1 = HT40 enabled, - * secondary channel below primary, 1 = HT40 - * enabled, secondary channel above primary */ -}; - -enum wpa_driver_if_type { - /** - * WPA_IF_STATION - Station mode interface - */ - WPA_IF_STATION, - - /** - * WPA_IF_AP_VLAN - AP mode VLAN interface - * - * This interface shares its address and Beacon frame with the main - * BSS. - */ - WPA_IF_AP_VLAN, - - /** - * WPA_IF_AP_BSS - AP mode BSS interface - * - * This interface has its own address and Beacon frame. - */ - WPA_IF_AP_BSS, - - /** - * WPA_IF_P2P_GO - P2P Group Owner - */ - WPA_IF_P2P_GO, - - /** - * WPA_IF_P2P_CLIENT - P2P Client - */ - WPA_IF_P2P_CLIENT, - - /** - * WPA_IF_P2P_GROUP - P2P Group interface (will become either - * WPA_IF_P2P_GO or WPA_IF_P2P_CLIENT, but the role is not yet known) - */ - WPA_IF_P2P_GROUP -}; - -struct wpa_init_params { - const u8 *bssid; - const char *ifname; - const u8 *ssid; - size_t ssid_len; - const char *test_socket; - int use_pae_group_addr; - char **bridge; - size_t num_bridge; - - u8 *own_addr; /* buffer for writing own MAC address */ -}; - - -struct wpa_bss_params { - /** Interface name (for multi-SSID/VLAN support) */ - const char *ifname; - /** Whether IEEE 802.1X or WPA/WPA2 is enabled */ - int enabled; - - int wpa; - int ieee802_1x; - int wpa_group; - int wpa_pairwise; - int wpa_key_mgmt; - int rsn_preauth; - enum mfp_options ieee80211w; -}; - -#define WPA_STA_AUTHORIZED BIT(0) -#define WPA_STA_WMM BIT(1) -#define WPA_STA_SHORT_PREAMBLE BIT(2) -#define WPA_STA_MFP BIT(3) - -/** - * struct p2p_params - P2P parameters for driver-based P2P management - */ -struct p2p_params { - const char *dev_name; - u8 pri_dev_type[8]; -#define DRV_MAX_SEC_DEV_TYPES 5 - u8 sec_dev_type[DRV_MAX_SEC_DEV_TYPES][8]; - size_t num_sec_dev_types; -}; - -enum tdls_oper { - TDLS_DISCOVERY_REQ, - TDLS_SETUP, - TDLS_TEARDOWN, - TDLS_ENABLE_LINK, - TDLS_DISABLE_LINK, - TDLS_ENABLE, - TDLS_DISABLE -}; - -/** - * struct wpa_signal_info - Information about channel signal quality - */ -struct wpa_signal_info { - u32 frequency; - int above_threshold; - int current_signal; - int current_noise; - int current_txrate; -}; - -/** - * struct wpa_driver_ops - Driver interface API definition - * - * This structure defines the API that each driver interface needs to implement - * for core wpa_supplicant code. All driver specific functionality is captured - * in this wrapper. - */ -struct wpa_driver_ops { - /** Name of the driver interface */ - const char *name; - /** One line description of the driver interface */ - const char *desc; - - /** - * get_bssid - Get the current BSSID - * @priv: private driver interface data - * @bssid: buffer for BSSID (ETH_ALEN = 6 bytes) - * - * Returns: 0 on success, -1 on failure - * - * Query kernel driver for the current BSSID and copy it to bssid. - * Setting bssid to 00:00:00:00:00:00 is recommended if the STA is not - * associated. - */ - int (*get_bssid)(void *priv, u8 *bssid); - - /** - * get_ssid - Get the current SSID - * @priv: private driver interface data - * @ssid: buffer for SSID (at least 32 bytes) - * - * Returns: Length of the SSID on success, -1 on failure - * - * Query kernel driver for the current SSID and copy it to ssid. - * Returning zero is recommended if the STA is not associated. - * - * Note: SSID is an array of octets, i.e., it is not nul terminated and - * can, at least in theory, contain control characters (including nul) - * and as such, should be processed as binary data, not a printable - * string. - */ - int (*get_ssid)(void *priv, u8 *ssid); - - /** - * set_key - Configure encryption key - * @ifname: Interface name (for multi-SSID/VLAN support) - * @priv: private driver interface data - * @alg: encryption algorithm (%WPA_ALG_NONE, %WPA_ALG_WEP, - * %WPA_ALG_TKIP, %WPA_ALG_CCMP, %WPA_ALG_IGTK, %WPA_ALG_PMK); - * %WPA_ALG_NONE clears the key. - * @addr: Address of the peer STA (BSSID of the current AP when setting - * pairwise key in station mode), ff:ff:ff:ff:ff:ff for - * broadcast keys, %NULL for default keys that are used both for - * broadcast and unicast; when clearing keys, %NULL is used to - * indicate that both the broadcast-only and default key of the - * specified key index is to be cleared - * @key_idx: key index (0..3), usually 0 for unicast keys; 0..4095 for - * IGTK - * @set_tx: configure this key as the default Tx key (only used when - * driver does not support separate unicast/individual key - * @seq: sequence number/packet number, seq_len octets, the next - * packet number to be used for in replay protection; configured - * for Rx keys (in most cases, this is only used with broadcast - * keys and set to zero for unicast keys); %NULL if not set - * @seq_len: length of the seq, depends on the algorithm: - * TKIP: 6 octets, CCMP: 6 octets, IGTK: 6 octets - * @key: key buffer; TKIP: 16-byte temporal key, 8-byte Tx Mic key, - * 8-byte Rx Mic Key - * @key_len: length of the key buffer in octets (WEP: 5 or 13, - * TKIP: 32, CCMP: 16, IGTK: 16) - * - * Returns: 0 on success, -1 on failure - * - * Configure the given key for the kernel driver. If the driver - * supports separate individual keys (4 default keys + 1 individual), - * addr can be used to determine whether the key is default or - * individual. If only 4 keys are supported, the default key with key - * index 0 is used as the individual key. STA must be configured to use - * it as the default Tx key (set_tx is set) and accept Rx for all the - * key indexes. In most cases, WPA uses only key indexes 1 and 2 for - * broadcast keys, so key index 0 is available for this kind of - * configuration. - * - * Please note that TKIP keys include separate TX and RX MIC keys and - * some drivers may expect them in different order than wpa_supplicant - * is using. If the TX/RX keys are swapped, all TKIP encrypted packets - * will trigger Michael MIC errors. This can be fixed by changing the - * order of MIC keys by swapping te bytes 16..23 and 24..31 of the key - * in driver_*.c set_key() implementation, see driver_ndis.c for an - * example on how this can be done. - */ - int (*set_key)(const char *ifname, void *priv, enum wpa_alg alg, - const u8 *addr, int key_idx, int set_tx, - const u8 *seq, size_t seq_len, - const u8 *key, size_t key_len); - - /** - * init - Initialize driver interface - * @ctx: context to be used when calling wpa_supplicant functions, - * e.g., wpa_supplicant_event() - * @ifname: interface name, e.g., wlan0 - * - * Returns: Pointer to private data, %NULL on failure - * - * Initialize driver interface, including event processing for kernel - * driver events (e.g., associated, scan results, Michael MIC failure). - * This function can allocate a private configuration data area for - * @ctx, file descriptor, interface name, etc. information that may be - * needed in future driver operations. If this is not used, non-NULL - * value will need to be returned because %NULL is used to indicate - * failure. The returned value will be used as 'void *priv' data for - * all other driver_ops functions. - * - * The main event loop (eloop.c) of wpa_supplicant can be used to - * register callback for read sockets (eloop_register_read_sock()). - * - * See below for more information about events and - * wpa_supplicant_event() function. - */ - void * (*init)(void *ctx, const char *ifname); - - /** - * deinit - Deinitialize driver interface - * @priv: private driver interface data from init() - * - * Shut down driver interface and processing of driver events. Free - * private data buffer if one was allocated in init() handler. - */ - void (*deinit)(void *priv); - - /** - * set_param - Set driver configuration parameters - * @priv: private driver interface data from init() - * @param: driver specific configuration parameters - * - * Returns: 0 on success, -1 on failure - * - * Optional handler for notifying driver interface about configuration - * parameters (driver_param). - */ - int (*set_param)(void *priv, const char *param); - - /** - * set_countermeasures - Enable/disable TKIP countermeasures - * @priv: private driver interface data - * @enabled: 1 = countermeasures enabled, 0 = disabled - * - * Returns: 0 on success, -1 on failure - * - * Configure TKIP countermeasures. When these are enabled, the driver - * should drop all received and queued frames that are using TKIP. - */ - int (*set_countermeasures)(void *priv, int enabled); - - /** - * deauthenticate - Request driver to deauthenticate - * @priv: private driver interface data - * @addr: peer address (BSSID of the AP) - * @reason_code: 16-bit reason code to be sent in the deauthentication - * frame - * - * Returns: 0 on success, -1 on failure - */ - int (*deauthenticate)(void *priv, const u8 *addr, int reason_code); - - /** - * disassociate - Request driver to disassociate - * @priv: private driver interface data - * @addr: peer address (BSSID of the AP) - * @reason_code: 16-bit reason code to be sent in the disassociation - * frame - * - * Returns: 0 on success, -1 on failure - */ - int (*disassociate)(void *priv, const u8 *addr, int reason_code); - - /** - * associate - Request driver to associate - * @priv: private driver interface data - * @params: association parameters - * - * Returns: 0 on success, -1 on failure - */ - int (*associate)(void *priv, - struct wpa_driver_associate_params *params); - - /** - * add_pmkid - Add PMKSA cache entry to the driver - * @priv: private driver interface data - * @bssid: BSSID for the PMKSA cache entry - * @pmkid: PMKID for the PMKSA cache entry - * - * Returns: 0 on success, -1 on failure - * - * This function is called when a new PMK is received, as a result of - * either normal authentication or RSN pre-authentication. - * - * If the driver generates RSN IE, i.e., it does not use wpa_ie in - * associate(), add_pmkid() can be used to add new PMKSA cache entries - * in the driver. If the driver uses wpa_ie from wpa_supplicant, this - * driver_ops function does not need to be implemented. Likewise, if - * the driver does not support WPA, this function is not needed. - */ - int (*add_pmkid)(void *priv, const u8 *bssid, const u8 *pmkid); - - /** - * remove_pmkid - Remove PMKSA cache entry to the driver - * @priv: private driver interface data - * @bssid: BSSID for the PMKSA cache entry - * @pmkid: PMKID for the PMKSA cache entry - * - * Returns: 0 on success, -1 on failure - * - * This function is called when the supplicant drops a PMKSA cache - * entry for any reason. - * - * If the driver generates RSN IE, i.e., it does not use wpa_ie in - * associate(), remove_pmkid() can be used to synchronize PMKSA caches - * between the driver and wpa_supplicant. If the driver uses wpa_ie - * from wpa_supplicant, this driver_ops function does not need to be - * implemented. Likewise, if the driver does not support WPA, this - * function is not needed. - */ - int (*remove_pmkid)(void *priv, const u8 *bssid, const u8 *pmkid); - - /** - * flush_pmkid - Flush PMKSA cache - * @priv: private driver interface data - * - * Returns: 0 on success, -1 on failure - * - * This function is called when the supplicant drops all PMKSA cache - * entries for any reason. - * - * If the driver generates RSN IE, i.e., it does not use wpa_ie in - * associate(), remove_pmkid() can be used to synchronize PMKSA caches - * between the driver and wpa_supplicant. If the driver uses wpa_ie - * from wpa_supplicant, this driver_ops function does not need to be - * implemented. Likewise, if the driver does not support WPA, this - * function is not needed. - */ - int (*flush_pmkid)(void *priv); - - /** - * get_capa - Get driver capabilities - * @priv: private driver interface data - * - * Returns: 0 on success, -1 on failure - * - * Get driver/firmware/hardware capabilities. - */ - int (*get_capa)(void *priv, struct wpa_driver_capa *capa); - - /** - * poll - Poll driver for association information - * @priv: private driver interface data - * - * This is an option callback that can be used when the driver does not - * provide event mechanism for association events. This is called when - * receiving WPA EAPOL-Key messages that require association - * information. The driver interface is supposed to generate associnfo - * event before returning from this callback function. In addition, the - * driver interface should generate an association event after having - * sent out associnfo. - */ - void (*poll)(void *priv); - - /** - * get_ifname - Get interface name - * @priv: private driver interface data - * - * Returns: Pointer to the interface name. This can differ from the - * interface name used in init() call. Init() is called first. - * - * This optional function can be used to allow the driver interface to - * replace the interface name with something else, e.g., based on an - * interface mapping from a more descriptive name. - */ - const char * (*get_ifname)(void *priv); - - /** - * get_mac_addr - Get own MAC address - * @priv: private driver interface data - * - * Returns: Pointer to own MAC address or %NULL on failure - * - * This optional function can be used to get the own MAC address of the - * device from the driver interface code. This is only needed if the - * l2_packet implementation for the OS does not provide easy access to - * a MAC address. */ - const u8 * (*get_mac_addr)(void *priv); - - /** - * send_eapol - Optional function for sending EAPOL packets - * @priv: private driver interface data - * @dest: Destination MAC address - * @proto: Ethertype - * @data: EAPOL packet starting with IEEE 802.1X header - * @data_len: Size of the EAPOL packet - * - * Returns: 0 on success, -1 on failure - * - * This optional function can be used to override l2_packet operations - * with driver specific functionality. If this function pointer is set, - * l2_packet module is not used at all and the driver interface code is - * responsible for receiving and sending all EAPOL packets. The - * received EAPOL packets are sent to core code with EVENT_EAPOL_RX - * event. The driver interface is required to implement get_mac_addr() - * handler if send_eapol() is used. - */ - int (*send_eapol)(void *priv, const u8 *dest, u16 proto, - const u8 *data, size_t data_len); - - /** - * set_operstate - Sets device operating state to DORMANT or UP - * @priv: private driver interface data - * @state: 0 = dormant, 1 = up - * Returns: 0 on success, -1 on failure - * - * This is an optional function that can be used on operating systems - * that support a concept of controlling network device state from user - * space applications. This function, if set, gets called with - * state = 1 when authentication has been completed and with state = 0 - * when connection is lost. - */ - int (*set_operstate)(void *priv, int state); - - /** - * mlme_setprotection - MLME-SETPROTECTION.request primitive - * @priv: Private driver interface data - * @addr: Address of the station for which to set protection (may be - * %NULL for group keys) - * @protect_type: MLME_SETPROTECTION_PROTECT_TYPE_* - * @key_type: MLME_SETPROTECTION_KEY_TYPE_* - * Returns: 0 on success, -1 on failure - * - * This is an optional function that can be used to set the driver to - * require protection for Tx and/or Rx frames. This uses the layer - * interface defined in IEEE 802.11i-2004 clause 10.3.22.1 - * (MLME-SETPROTECTION.request). Many drivers do not use explicit - * set protection operation; instead, they set protection implicitly - * based on configured keys. - */ - int (*mlme_setprotection)(void *priv, const u8 *addr, int protect_type, - int key_type); - - /** - * get_hw_feature_data - Get hardware support data (channels and rates) - * @priv: Private driver interface data - * @num_modes: Variable for returning the number of returned modes - * flags: Variable for returning hardware feature flags - * Returns: Pointer to allocated hardware data on success or %NULL on - * failure. Caller is responsible for freeing this. - * - * This function is only needed for drivers that export MLME - * (management frame processing) to %wpa_supplicant or hostapd. - */ - struct hostapd_hw_modes * (*get_hw_feature_data)(void *priv, - u16 *num_modes, - u16 *flags); - - /** - * set_channel - Set channel - * @priv: Private driver interface data - * @phymode: HOSTAPD_MODE_IEEE80211B, .. - * @chan: IEEE 802.11 channel number - * @freq: Frequency of the channel in MHz - * Returns: 0 on success, -1 on failure - * - * This function is only needed for drivers that export MLME - * (management frame processing) to wpa_supplicant. - */ - int (*set_channel)(void *priv, enum hostapd_hw_mode phymode, int chan, - int freq); - - /** - * set_ssid - Set SSID - * @priv: Private driver interface data - * @ssid: SSID - * @ssid_len: SSID length - * Returns: 0 on success, -1 on failure - * - * This function is only needed for drivers that export MLME - * (management frame processing) to wpa_supplicant. - */ - int (*set_ssid)(void *priv, const u8 *ssid, size_t ssid_len); - - /** - * set_bssid - Set BSSID - * @priv: Private driver interface data - * @bssid: BSSID - * Returns: 0 on success, -1 on failure - * - * This function is only needed for drivers that export MLME - * (management frame processing) to wpa_supplicant. - */ - int (*set_bssid)(void *priv, const u8 *bssid); - - /** - * send_mlme - Send management frame from MLME - * @priv: Private driver interface data - * @data: IEEE 802.11 management frame with IEEE 802.11 header - * @data_len: Size of the management frame - * Returns: 0 on success, -1 on failure - * - * This function is only needed for drivers that export MLME - * (management frame processing) to wpa_supplicant. - */ - int (*send_mlme)(void *priv, const u8 *data, size_t data_len); - - /** - * mlme_add_sta - Add a STA entry into the driver/netstack - * @priv: Private driver interface data - * @addr: MAC address of the STA (e.g., BSSID of the AP) - * @supp_rates: Supported rate set (from (Re)AssocResp); in IEEE 802.11 - * format (one octet per rate, 1 = 0.5 Mbps) - * @supp_rates_len: Number of entries in supp_rates - * Returns: 0 on success, -1 on failure - * - * This function is only needed for drivers that export MLME - * (management frame processing) to wpa_supplicant. When the MLME code - * completes association with an AP, this function is called to - * configure the driver/netstack with a STA entry for data frame - * processing (TX rate control, encryption/decryption). - */ - int (*mlme_add_sta)(void *priv, const u8 *addr, const u8 *supp_rates, - size_t supp_rates_len); - - /** - * mlme_remove_sta - Remove a STA entry from the driver/netstack - * @priv: Private driver interface data - * @addr: MAC address of the STA (e.g., BSSID of the AP) - * Returns: 0 on success, -1 on failure - * - * This function is only needed for drivers that export MLME - * (management frame processing) to wpa_supplicant. - */ - int (*mlme_remove_sta)(void *priv, const u8 *addr); - - /** - * update_ft_ies - Update FT (IEEE 802.11r) IEs - * @priv: Private driver interface data - * @md: Mobility domain (2 octets) (also included inside ies) - * @ies: FT IEs (MDIE, FTIE, ...) or %NULL to remove IEs - * @ies_len: Length of FT IEs in bytes - * Returns: 0 on success, -1 on failure - * - * The supplicant uses this callback to let the driver know that keying - * material for FT is available and that the driver can use the - * provided IEs in the next message in FT authentication sequence. - * - * This function is only needed for driver that support IEEE 802.11r - * (Fast BSS Transition). - */ - int (*update_ft_ies)(void *priv, const u8 *md, const u8 *ies, - size_t ies_len); - - /** - * send_ft_action - Send FT Action frame (IEEE 802.11r) - * @priv: Private driver interface data - * @action: Action field value - * @target_ap: Target AP address - * @ies: FT IEs (MDIE, FTIE, ...) (FT Request action frame body) - * @ies_len: Length of FT IEs in bytes - * Returns: 0 on success, -1 on failure - * - * The supplicant uses this callback to request the driver to transmit - * an FT Action frame (action category 6) for over-the-DS fast BSS - * transition. - */ - int (*send_ft_action)(void *priv, u8 action, const u8 *target_ap, - const u8 *ies, size_t ies_len); - - /** - * get_scan_results2 - Fetch the latest scan results - * @priv: private driver interface data - * - * Returns: Allocated buffer of scan results (caller is responsible for - * freeing the data structure) on success, NULL on failure - */ - struct wpa_scan_results * (*get_scan_results2)(void *priv); - - /** - * set_country - Set country - * @priv: Private driver interface data - * @alpha2: country to which to switch to - * Returns: 0 on success, -1 on failure - * - * This function is for drivers which support some form - * of setting a regulatory domain. - */ - int (*set_country)(void *priv, const char *alpha2); - - /** - * global_init - Global driver initialization - * Returns: Pointer to private data (global), %NULL on failure - * - * This optional function is called to initialize the driver wrapper - * for global data, i.e., data that applies to all interfaces. If this - * function is implemented, global_deinit() will also need to be - * implemented to free the private data. The driver will also likely - * use init2() function instead of init() to get the pointer to global - * data available to per-interface initializer. - */ - void * (*global_init)(void); - - /** - * global_deinit - Global driver deinitialization - * @priv: private driver global data from global_init() - * - * Terminate any global driver related functionality and free the - * global data structure. - */ - void (*global_deinit)(void *priv); - - /** - * init2 - Initialize driver interface (with global data) - * @ctx: context to be used when calling wpa_supplicant functions, - * e.g., wpa_supplicant_event() - * @ifname: interface name, e.g., wlan0 - * @global_priv: private driver global data from global_init() - * Returns: Pointer to private data, %NULL on failure - * - * This function can be used instead of init() if the driver wrapper - * uses global data. - */ - void * (*init2)(void *ctx, const char *ifname, void *global_priv); - - /** - * get_interfaces - Get information about available interfaces - * @global_priv: private driver global data from global_init() - * Returns: Allocated buffer of interface information (caller is - * responsible for freeing the data structure) on success, NULL on - * failure - */ - struct wpa_interface_info * (*get_interfaces)(void *global_priv); - - /** - * scan2 - Request the driver to initiate scan - * @priv: private driver interface data - * @params: Scan parameters - * - * Returns: 0 on success, -1 on failure - * - * Once the scan results are ready, the driver should report scan - * results event for wpa_supplicant which will eventually request the - * results with wpa_driver_get_scan_results2(). - */ - int (*scan2)(void *priv, struct wpa_driver_scan_params *params); - - /** - * authenticate - Request driver to authenticate - * @priv: private driver interface data - * @params: authentication parameters - * Returns: 0 on success, -1 on failure - * - * This is an optional function that can be used with drivers that - * support separate authentication and association steps, i.e., when - * wpa_supplicant can act as the SME. If not implemented, associate() - * function is expected to take care of IEEE 802.11 authentication, - * too. - */ - int (*authenticate)(void *priv, - struct wpa_driver_auth_params *params); - - /** - * set_beacon - Set Beacon frame template - * @priv: Private driver interface data - * @head: Beacon head from IEEE 802.11 header to IEs before TIM IE - * @head_len: Length of the head buffer in octets - * @tail: Beacon tail following TIM IE - * @tail_len: Length of the tail buffer in octets - * @dtim_period: DTIM period - * @beacon_int: Beacon interval - * Returns: 0 on success, -1 on failure - * - * This function is used to configure Beacon template for the driver in - * AP mode. The driver is responsible for building the full Beacon - * frame by concatenating the head part with TIM IE generated by the - * driver/firmware and finishing with the tail part. - */ - int (*set_beacon)(void *priv, const u8 *head, size_t head_len, - const u8 *tail, size_t tail_len, int dtim_period, - int beacon_int); - - /** - * hapd_init - Initialize driver interface (hostapd only) - * @hapd: Pointer to hostapd context - * @params: Configuration for the driver wrapper - * Returns: Pointer to private data, %NULL on failure - * - * This function is used instead of init() or init2() when the driver - * wrapper is used withh hostapd. - */ - void * (*hapd_init)(struct hostapd_data *hapd, - struct wpa_init_params *params); - - /** - * hapd_deinit - Deinitialize driver interface (hostapd only) - * @priv: Private driver interface data from hapd_init() - */ - void (*hapd_deinit)(void *priv); - - /** - * set_ieee8021x - Enable/disable IEEE 802.1X support (AP only) - * @priv: Private driver interface data - * @params: BSS parameters - * Returns: 0 on success, -1 on failure - * - * This is an optional function to configure the kernel driver to - * enable/disable IEEE 802.1X support and set WPA/WPA2 parameters. This - * can be left undefined (set to %NULL) if IEEE 802.1X support is - * always enabled and the driver uses set_beacon() to set WPA/RSN IE - * for Beacon frames. - */ - int (*set_ieee8021x)(void *priv, struct wpa_bss_params *params); - - /** - * set_privacy - Enable/disable privacy (AP only) - * @priv: Private driver interface data - * @enabled: 1 = privacy enabled, 0 = disabled - * Returns: 0 on success, -1 on failure - * - * This is an optional function to configure privacy field in the - * kernel driver for Beacon frames. This can be left undefined (set to - * %NULL) if the driver uses the Beacon template from set_beacon(). - */ - int (*set_privacy)(void *priv, int enabled); - - /** - * get_seqnum - Fetch the current TSC/packet number (AP only) - * @ifname: The interface name (main or virtual) - * @priv: Private driver interface data - * @addr: MAC address of the station or %NULL for group keys - * @idx: Key index - * @seq: Buffer for returning the latest used TSC/packet number - * Returns: 0 on success, -1 on failure - * - * This function is used to fetch the last used TSC/packet number for - * a TKIP, CCMP, or BIP/IGTK key. It is mainly used with group keys, so - * there is no strict requirement on implementing support for unicast - * keys (i.e., addr != %NULL). - */ - int (*get_seqnum)(const char *ifname, void *priv, const u8 *addr, - int idx, u8 *seq); - - /** - * flush - Flush all association stations (AP only) - * @priv: Private driver interface data - * Returns: 0 on success, -1 on failure - * - * This function requests the driver to disassociate all associated - * stations. This function does not need to be implemented if the - * driver does not process association frames internally. - */ - int (*flush)(void *priv); - - /** - * set_generic_elem - Add IEs into Beacon/Probe Response frames (AP) - * @priv: Private driver interface data - * @elem: Information elements - * @elem_len: Length of the elem buffer in octets - * Returns: 0 on success, -1 on failure - * - * This is an optional function to add information elements in the - * kernel driver for Beacon and Probe Response frames. This can be left - * undefined (set to %NULL) if the driver uses the Beacon template from - * set_beacon(). - */ - int (*set_generic_elem)(void *priv, const u8 *elem, size_t elem_len); - - /** - * read_sta_data - Fetch station data (AP only) - * @priv: Private driver interface data - * @data: Buffer for returning station information - * @addr: MAC address of the station - * Returns: 0 on success, -1 on failure - */ - int (*read_sta_data)(void *priv, struct hostap_sta_driver_data *data, - const u8 *addr); - - /** - * hapd_send_eapol - Send an EAPOL packet (AP only) - * @priv: private driver interface data - * @addr: Destination MAC address - * @data: EAPOL packet starting with IEEE 802.1X header - * @data_len: Length of the EAPOL packet in octets - * @encrypt: Whether the frame should be encrypted - * @own_addr: Source MAC address - * @flags: WPA_STA_* flags for the destination station - * - * Returns: 0 on success, -1 on failure - */ - int (*hapd_send_eapol)(void *priv, const u8 *addr, const u8 *data, - size_t data_len, int encrypt, - const u8 *own_addr, u32 flags); - - /** - * sta_deauth - Deauthenticate a station (AP only) - * @priv: Private driver interface data - * @own_addr: Source address and BSSID for the Deauthentication frame - * @addr: MAC address of the station to deauthenticate - * @reason: Reason code for the Deauthentiation frame - * Returns: 0 on success, -1 on failure - * - * This function requests a specific station to be deauthenticated and - * a Deauthentication frame to be sent to it. - */ - int (*sta_deauth)(void *priv, const u8 *own_addr, const u8 *addr, - int reason); - - /** - * sta_disassoc - Disassociate a station (AP only) - * @priv: Private driver interface data - * @own_addr: Source address and BSSID for the Disassociation frame - * @addr: MAC address of the station to disassociate - * @reason: Reason code for the Disassociation frame - * Returns: 0 on success, -1 on failure - * - * This function requests a specific station to be disassociated and - * a Disassociation frame to be sent to it. - */ - int (*sta_disassoc)(void *priv, const u8 *own_addr, const u8 *addr, - int reason); - - /** - * sta_remove - Remove a station entry (AP only) - * @priv: Private driver interface data - * @addr: MAC address of the station to be removed - * Returns: 0 on success, -1 on failure - */ - int (*sta_remove)(void *priv, const u8 *addr); - - /** - * hapd_get_ssid - Get the current SSID (AP only) - * @priv: Private driver interface data - * @buf: Buffer for returning the SSID - * @len: Maximum length of the buffer - * Returns: Length of the SSID on success, -1 on failure - * - * This function need not be implemented if the driver uses Beacon - * template from set_beacon() and does not reply to Probe Request - * frames. - */ - int (*hapd_get_ssid)(void *priv, u8 *buf, int len); - - /** - * hapd_set_ssid - Set SSID (AP only) - * @priv: Private driver interface data - * @buf: SSID - * @len: Length of the SSID in octets - * Returns: 0 on success, -1 on failure - */ - int (*hapd_set_ssid)(void *priv, const u8 *buf, int len); - - /** - * hapd_set_countermeasures - Enable/disable TKIP countermeasures (AP) - * @priv: Private driver interface data - * @enabled: 1 = countermeasures enabled, 0 = disabled - * Returns: 0 on success, -1 on failure - * - * This need not be implemented if the driver does not take care of - * association processing. - */ - int (*hapd_set_countermeasures)(void *priv, int enabled); - - /** - * sta_add - Add a station entry - * @priv: Private driver interface data - * @params: Station parameters - * Returns: 0 on success, -1 on failure - * - * This function is used to add a station entry to the driver once the - * station has completed association. This is only used if the driver - * does not take care of association processing. - */ - int (*sta_add)(void *priv, struct hostapd_sta_add_params *params); - - /** - * get_inact_sec - Get station inactivity duration (AP only) - * @priv: Private driver interface data - * @addr: Station address - * Returns: Number of seconds station has been inactive, -1 on failure - */ - int (*get_inact_sec)(void *priv, const u8 *addr); - - /** - * sta_clear_stats - Clear station statistics (AP only) - * @priv: Private driver interface data - * @addr: Station address - * Returns: 0 on success, -1 on failure - */ - int (*sta_clear_stats)(void *priv, const u8 *addr); - - /** - * set_freq - Set channel/frequency (AP only) - * @priv: Private driver interface data - * @freq: Channel parameters - * Returns: 0 on success, -1 on failure - */ - int (*set_freq)(void *priv, struct hostapd_freq_params *freq); - - /** - * set_rts - Set RTS threshold - * @priv: Private driver interface data - * @rts: RTS threshold in octets - * Returns: 0 on success, -1 on failure - */ - int (*set_rts)(void *priv, int rts); - - /** - * set_frag - Set fragmentation threshold - * @priv: Private driver interface data - * @frag: Fragmentation threshold in octets - * Returns: 0 on success, -1 on failure - */ - int (*set_frag)(void *priv, int frag); - - /** - * sta_set_flags - Set station flags (AP only) - * @priv: Private driver interface data - * @addr: Station address - * @total_flags: Bitmap of all WPA_STA_* flags currently set - * @flags_or: Bitmap of WPA_STA_* flags to add - * @flags_and: Bitmap of WPA_STA_* flags to us as a mask - * Returns: 0 on success, -1 on failure - */ - int (*sta_set_flags)(void *priv, const u8 *addr, - int total_flags, int flags_or, int flags_and); - - /** - * set_rate_sets - Set supported and basic rate sets (AP only) - * @priv: Private driver interface data - * @supp_rates: -1 terminated array of supported rates in 100 kbps - * @basic_rates: -1 terminated array of basic rates in 100 kbps - * @mode: hardware mode (HOSTAPD_MODE_*) - * Returns: 0 on success, -1 on failure - */ - int (*set_rate_sets)(void *priv, int *supp_rates, int *basic_rates, - int mode); - - /** - * set_cts_protect - Set CTS protection mode (AP only) - * @priv: Private driver interface data - * @value: Whether CTS protection is enabled - * Returns: 0 on success, -1 on failure - */ - int (*set_cts_protect)(void *priv, int value); - - /** - * set_preamble - Set preamble mode (AP only) - * @priv: Private driver interface data - * @value: Whether short preamble is enabled - * Returns: 0 on success, -1 on failure - */ - int (*set_preamble)(void *priv, int value); - - /** - * set_short_slot_time - Set short slot time (AP only) - * @priv: Private driver interface data - * @value: Whether short slot time is enabled - * Returns: 0 on success, -1 on failure - */ - int (*set_short_slot_time)(void *priv, int value); - - /** - * set_tx_queue_params - Set TX queue parameters - * @priv: Private driver interface data - * @queue: Queue number (0 = VO, 1 = VI, 2 = BE, 3 = BK) - * @aifs: AIFS - * @cw_min: cwMin - * @cw_max: cwMax - * @burst_time: Maximum length for bursting in 0.1 msec units - */ - int (*set_tx_queue_params)(void *priv, int queue, int aifs, int cw_min, - int cw_max, int burst_time); - - /** - * valid_bss_mask - Validate BSSID mask - * @priv: Private driver interface data - * @addr: Address - * @mask: Mask - * Returns: 0 if mask is valid, -1 if mask is not valid, 1 if mask can - * be used, but the main interface address must be the first address in - * the block if mask is applied - */ - int (*valid_bss_mask)(void *priv, const u8 *addr, const u8 *mask); - - /** - * if_add - Add a virtual interface - * @priv: Private driver interface data - * @type: Interface type - * @ifname: Interface name for the new virtual interface - * @addr: Local address to use for the interface or %NULL to use the - * parent interface address - * @bss_ctx: BSS context for %WPA_IF_AP_BSS interfaces - * @drv_priv: Pointer for overwriting the driver context or %NULL if - * not allowed (applies only to %WPA_IF_AP_BSS type) - * @force_ifname: Buffer for returning an interface name that the - * driver ended up using if it differs from the requested ifname - * @if_addr: Buffer for returning the allocated interface address - * (this may differ from the requested addr if the driver cannot - * change interface address) - * @bridge: Bridge interface to use or %NULL if no bridge configured - * Returns: 0 on success, -1 on failure - */ - int (*if_add)(void *priv, enum wpa_driver_if_type type, - const char *ifname, const u8 *addr, void *bss_ctx, - void **drv_priv, char *force_ifname, u8 *if_addr, - const char *bridge); - - /** - * if_remove - Remove a virtual interface - * @priv: Private driver interface data - * @type: Interface type - * @ifname: Interface name of the virtual interface to be removed - * Returns: 0 on success, -1 on failure - */ - int (*if_remove)(void *priv, enum wpa_driver_if_type type, - const char *ifname); - - /** - * set_sta_vlan - Bind a station into a specific interface (AP only) - * @priv: Private driver interface data - * @ifname: Interface (main or virtual BSS or VLAN) - * @addr: MAC address of the associated station - * @vlan_id: VLAN ID - * Returns: 0 on success, -1 on failure - * - * This function is used to bind a station to a specific virtual - * interface. It is only used if when virtual interfaces are supported, - * e.g., to assign stations to different VLAN interfaces based on - * information from a RADIUS server. This allows separate broadcast - * domains to be used with a single BSS. - */ - int (*set_sta_vlan)(void *priv, const u8 *addr, const char *ifname, - int vlan_id); - - /** - * commit - Optional commit changes handler (AP only) - * @priv: driver private data - * Returns: 0 on success, -1 on failure - * - * This optional handler function can be registered if the driver - * interface implementation needs to commit changes (e.g., by setting - * network interface up) at the end of initial configuration. If set, - * this handler will be called after initial setup has been completed. - */ - int (*commit)(void *priv); - - /** - * send_ether - Send an ethernet packet (AP only) - * @priv: private driver interface data - * @dst: Destination MAC address - * @src: Source MAC address - * @proto: Ethertype - * @data: EAPOL packet starting with IEEE 802.1X header - * @data_len: Length of the EAPOL packet in octets - * Returns: 0 on success, -1 on failure - */ - int (*send_ether)(void *priv, const u8 *dst, const u8 *src, u16 proto, - const u8 *data, size_t data_len); - - /** - * set_radius_acl_auth - Notification of RADIUS ACL change - * @priv: Private driver interface data - * @mac: MAC address of the station - * @accepted: Whether the station was accepted - * @session_timeout: Session timeout for the station - * Returns: 0 on success, -1 on failure - */ - int (*set_radius_acl_auth)(void *priv, const u8 *mac, int accepted, - u32 session_timeout); - - /** - * set_radius_acl_expire - Notification of RADIUS ACL expiration - * @priv: Private driver interface data - * @mac: MAC address of the station - * Returns: 0 on success, -1 on failure - */ - int (*set_radius_acl_expire)(void *priv, const u8 *mac); - - /** - * set_ht_params - Set HT parameters (AP only) - * @priv: Private driver interface data - * @ht_capab: HT Capabilities IE - * @ht_capab_len: Length of ht_capab in octets - * @ht_oper: HT Operation IE - * @ht_oper_len: Length of ht_oper in octets - * Returns: 0 on success, -1 on failure - */ - int (*set_ht_params)(void *priv, - const u8 *ht_capab, size_t ht_capab_len, - const u8 *ht_oper, size_t ht_oper_len); - - /** - * set_ap_wps_ie - Add WPS IE(s) into Beacon/Probe Response frames (AP) - * @priv: Private driver interface data - * @beacon: WPS IE(s) for Beacon frames or %NULL to remove extra IE(s) - * @proberesp: WPS IE(s) for Probe Response frames or %NULL to remove - * extra IE(s) - * @assocresp: WPS IE(s) for (Re)Association Response frames or %NULL - * to remove extra IE(s) - * Returns: 0 on success, -1 on failure - * - * This is an optional function to add WPS IE in the kernel driver for - * Beacon and Probe Response frames. This can be left undefined (set - * to %NULL) if the driver uses the Beacon template from set_beacon() - * and does not process Probe Request frames. If the driver takes care - * of (Re)Association frame processing, the assocresp buffer includes - * WPS IE(s) that need to be added to (Re)Association Response frames - * whenever a (Re)Association Request frame indicated use of WPS. - * - * This will also be used to add P2P IE(s) into Beacon/Probe Response - * frames when operating as a GO. The driver is responsible for adding - * timing related attributes (e.g., NoA) in addition to the IEs - * included here by appending them after these buffers. This call is - * also used to provide Probe Response IEs for P2P Listen state - * operations for drivers that generate the Probe Response frames - * internally. - */ - int (*set_ap_wps_ie)(void *priv, const struct wpabuf *beacon, - const struct wpabuf *proberesp, - const struct wpabuf *assocresp); - - /** - * set_supp_port - Set IEEE 802.1X Supplicant Port status - * @priv: Private driver interface data - * @authorized: Whether the port is authorized - * Returns: 0 on success, -1 on failure - */ - int (*set_supp_port)(void *priv, int authorized); - - /** - * set_wds_sta - Bind a station into a 4-address WDS (AP only) - * @priv: Private driver interface data - * @addr: MAC address of the associated station - * @aid: Association ID - * @val: 1 = bind to 4-address WDS; 0 = unbind - * @bridge_ifname: Bridge interface to use for the WDS station or %NULL - * to indicate that bridge is not to be used - * Returns: 0 on success, -1 on failure - */ - int (*set_wds_sta)(void *priv, const u8 *addr, int aid, int val, - const char *bridge_ifname); - - /** - * send_action - Transmit an Action frame - * @priv: Private driver interface data - * @freq: Frequency (in MHz) of the channel - * @wait: Time to wait off-channel for a response (in ms), or zero - * @dst: Destination MAC address (Address 1) - * @src: Source MAC address (Address 2) - * @bssid: BSSID (Address 3) - * @data: Frame body - * @data_len: data length in octets - * Returns: 0 on success, -1 on failure - * - * This command can be used to request the driver to transmit an action - * frame to the specified destination. - * - * If the %WPA_DRIVER_FLAGS_OFFCHANNEL_TX flag is set, the frame will - * be transmitted on the given channel and the device will wait for a - * response on that channel for the given wait time. - * - * If the flag is not set, the wait time will be ignored. In this case, - * if a remain-on-channel duration is in progress, the frame must be - * transmitted on that channel; alternatively the frame may be sent on - * the current operational channel (if in associated state in station - * mode or while operating as an AP.) - */ - int (*send_action)(void *priv, unsigned int freq, unsigned int wait, - const u8 *dst, const u8 *src, const u8 *bssid, - const u8 *data, size_t data_len); - - /** - * send_action_cancel_wait - Cancel action frame TX wait - * @priv: Private driver interface data - * - * This command cancels the wait time associated with sending an action - * frame. It is only available when %WPA_DRIVER_FLAGS_OFFCHANNEL_TX is - * set in the driver flags. - */ - void (*send_action_cancel_wait)(void *priv); - - /** - * remain_on_channel - Remain awake on a channel - * @priv: Private driver interface data - * @freq: Frequency (in MHz) of the channel - * @duration: Duration in milliseconds - * Returns: 0 on success, -1 on failure - * - * This command is used to request the driver to remain awake on the - * specified channel for the specified duration and report received - * Action frames with EVENT_RX_ACTION events. Optionally, received - * Probe Request frames may also be requested to be reported by calling - * probe_req_report(). These will be reported with EVENT_RX_PROBE_REQ. - * - * The driver may not be at the requested channel when this function - * returns, i.e., the return code is only indicating whether the - * request was accepted. The caller will need to wait until the - * EVENT_REMAIN_ON_CHANNEL event indicates that the driver has - * completed the channel change. This may take some time due to other - * need for the radio and the caller should be prepared to timing out - * its wait since there are no guarantees on when this request can be - * executed. - */ - int (*remain_on_channel)(void *priv, unsigned int freq, - unsigned int duration); - - /** - * cancel_remain_on_channel - Cancel remain-on-channel operation - * @priv: Private driver interface data - * - * This command can be used to cancel a remain-on-channel operation - * before its originally requested duration has passed. This could be - * used, e.g., when remain_on_channel() is used to request extra time - * to receive a response to an Action frame and the response is - * received when there is still unneeded time remaining on the - * remain-on-channel operation. - */ - int (*cancel_remain_on_channel)(void *priv); - - /** - * probe_req_report - Request Probe Request frames to be indicated - * @priv: Private driver interface data - * @report: Whether to report received Probe Request frames - * Returns: 0 on success, -1 on failure (or if not supported) - * - * This command can be used to request the driver to indicate when - * Probe Request frames are received with EVENT_RX_PROBE_REQ events. - * Since this operation may require extra resources, e.g., due to less - * optimal hardware/firmware RX filtering, many drivers may disable - * Probe Request reporting at least in station mode. This command is - * used to notify the driver when the Probe Request frames need to be - * reported, e.g., during remain-on-channel operations. - */ - int (*probe_req_report)(void *priv, int report); - - /** - * disable_11b_rates - Set whether IEEE 802.11b rates are used for TX - * @priv: Private driver interface data - * @disabled: Whether IEEE 802.11b rates are disabled - * Returns: 0 on success, -1 on failure (or if not supported) - * - * This command is used to disable IEEE 802.11b rates (1, 2, 5.5, and - * 11 Mbps) as TX rates for data and management frames. This can be - * used to optimize channel use when there is no need to support IEEE - * 802.11b-only devices. - */ - int (*disable_11b_rates)(void *priv, int disabled); - - /** - * deinit_ap - Deinitialize AP mode - * @priv: Private driver interface data - * Returns: 0 on success, -1 on failure (or if not supported) - * - * This optional function can be used to disable AP mode related - * configuration and change the driver mode to station mode to allow - * normal station operations like scanning to be completed. - */ - int (*deinit_ap)(void *priv); - - /** - * suspend - Notification on system suspend/hibernate event - * @priv: Private driver interface data - */ - void (*suspend)(void *priv); - - /** - * resume - Notification on system resume/thaw event - * @priv: Private driver interface data - */ - void (*resume)(void *priv); - - /** - * signal_monitor - Set signal monitoring parameters - * @priv: Private driver interface data - * @threshold: Threshold value for signal change events; 0 = disabled - * @hysteresis: Minimum change in signal strength before indicating a - * new event - * Returns: 0 on success, -1 on failure (or if not supported) - * - * This function can be used to configure monitoring of signal strength - * with the current AP. Whenever signal strength drops below the - * %threshold value or increases above it, EVENT_SIGNAL_CHANGE event - * should be generated assuming the signal strength has changed at - * least %hysteresis from the previously indicated signal change event. - */ - int (*signal_monitor)(void *priv, int threshold, int hysteresis); - - /** - * send_frame - Send IEEE 802.11 frame (testing use only) - * @priv: Private driver interface data - * @data: IEEE 802.11 frame with IEEE 802.11 header - * @data_len: Size of the frame - * @encrypt: Whether to encrypt the frame (if keys are set) - * Returns: 0 on success, -1 on failure - * - * This function is only used for debugging purposes and is not - * required to be implemented for normal operations. - */ - int (*send_frame)(void *priv, const u8 *data, size_t data_len, - int encrypt); - - /** - * shared_freq - Get operating frequency of shared interface(s) - * @priv: Private driver interface data - * Returns: Operating frequency in MHz, 0 if no shared operation in - * use, or -1 on failure - * - * This command can be used to request the current operating frequency - * of any virtual interface that shares the same radio to provide - * information for channel selection for other virtual interfaces. - */ - int (*shared_freq)(void *priv); - - /** - * get_noa - Get current Notice of Absence attribute payload - * @priv: Private driver interface data - * @buf: Buffer for returning NoA - * @buf_len: Buffer length in octets - * Returns: Number of octets used in buf, 0 to indicate no NoA is being - * advertized, or -1 on failure - * - * This function is used to fetch the current Notice of Absence - * attribute value from GO. - */ - int (*get_noa)(void *priv, u8 *buf, size_t buf_len); - - /** - * set_noa - Set Notice of Absence parameters for GO (testing) - * @priv: Private driver interface data - * @count: Count - * @start: Start time in ms from next TBTT - * @duration: Duration in ms - * Returns: 0 on success or -1 on failure - * - * This function is used to set Notice of Absence parameters for GO. It - * is used only for testing. To disable NoA, all parameters are set to - * 0. - */ - int (*set_noa)(void *priv, u8 count, int start, int duration); - - /** - * set_p2p_powersave - Set P2P power save options - * @priv: Private driver interface data - * @legacy_ps: 0 = disable, 1 = enable, 2 = maximum PS, -1 = no change - * @opp_ps: 0 = disable, 1 = enable, -1 = no change - * @ctwindow: 0.. = change (msec), -1 = no change - * Returns: 0 on success or -1 on failure - */ - int (*set_p2p_powersave)(void *priv, int legacy_ps, int opp_ps, - int ctwindow); - - /** - * ampdu - Enable/disable aggregation - * @priv: Private driver interface data - * @ampdu: 1/0 = enable/disable A-MPDU aggregation - * Returns: 0 on success or -1 on failure - */ - int (*ampdu)(void *priv, int ampdu); - - /** - * set_intra_bss - Enables/Disables intra BSS bridging - */ - int (*set_intra_bss)(void *priv, int enabled); - - /** - * get_radio_name - Get physical radio name for the device - * @priv: Private driver interface data - * Returns: Radio name or %NULL if not known - * - * The returned data must not be modified by the caller. It is assumed - * that any interface that has the same radio name as another is - * sharing the same physical radio. This information can be used to - * share scan results etc. information between the virtual interfaces - * to speed up various operations. - */ - const char * (*get_radio_name)(void *priv); - - /** - * p2p_find - Start P2P Device Discovery - * @priv: Private driver interface data - * @timeout: Timeout for find operation in seconds or 0 for no timeout - * @type: Device Discovery type (enum p2p_discovery_type) - * Returns: 0 on success, -1 on failure - * - * This function is only used if the driver implements P2P management, - * i.e., if it sets WPA_DRIVER_FLAGS_P2P_MGMT in - * struct wpa_driver_capa. - */ - int (*p2p_find)(void *priv, unsigned int timeout, int type); - - /** - * p2p_stop_find - Stop P2P Device Discovery - * @priv: Private driver interface data - * Returns: 0 on success, -1 on failure - * - * This function is only used if the driver implements P2P management, - * i.e., if it sets WPA_DRIVER_FLAGS_P2P_MGMT in - * struct wpa_driver_capa. - */ - int (*p2p_stop_find)(void *priv); - - /** - * p2p_listen - Start P2P Listen state for specified duration - * @priv: Private driver interface data - * @timeout: Listen state duration in milliseconds - * Returns: 0 on success, -1 on failure - * - * This function can be used to request the P2P module to keep the - * device discoverable on the listen channel for an extended set of - * time. At least in its current form, this is mainly used for testing - * purposes and may not be of much use for normal P2P operations. - * - * This function is only used if the driver implements P2P management, - * i.e., if it sets WPA_DRIVER_FLAGS_P2P_MGMT in - * struct wpa_driver_capa. - */ - int (*p2p_listen)(void *priv, unsigned int timeout); - - /** - * p2p_connect - Start P2P group formation (GO negotiation) - * @priv: Private driver interface data - * @peer_addr: MAC address of the peer P2P client - * @wps_method: enum p2p_wps_method value indicating config method - * @go_intent: Local GO intent value (1..15) - * @own_interface_addr: Intended interface address to use with the - * group - * @force_freq: The only allowed channel frequency in MHz or 0 - * @persistent_group: Whether to create persistent group - * Returns: 0 on success, -1 on failure - * - * This function is only used if the driver implements P2P management, - * i.e., if it sets WPA_DRIVER_FLAGS_P2P_MGMT in - * struct wpa_driver_capa. - */ - int (*p2p_connect)(void *priv, const u8 *peer_addr, int wps_method, - int go_intent, const u8 *own_interface_addr, - unsigned int force_freq, int persistent_group); - - /** - * wps_success_cb - Report successfully completed WPS provisioning - * @priv: Private driver interface data - * @peer_addr: Peer address - * Returns: 0 on success, -1 on failure - * - * This function is used to report successfully completed WPS - * provisioning during group formation in both GO/Registrar and - * client/Enrollee roles. - * - * This function is only used if the driver implements P2P management, - * i.e., if it sets WPA_DRIVER_FLAGS_P2P_MGMT in - * struct wpa_driver_capa. - */ - int (*wps_success_cb)(void *priv, const u8 *peer_addr); - - /** - * p2p_group_formation_failed - Report failed WPS provisioning - * @priv: Private driver interface data - * Returns: 0 on success, -1 on failure - * - * This function is used to report failed group formation. This can - * happen either due to failed WPS provisioning or due to 15 second - * timeout during the provisioning phase. - * - * This function is only used if the driver implements P2P management, - * i.e., if it sets WPA_DRIVER_FLAGS_P2P_MGMT in - * struct wpa_driver_capa. - */ - int (*p2p_group_formation_failed)(void *priv); - - /** - * p2p_set_params - Set P2P parameters - * @priv: Private driver interface data - * @params: P2P parameters - * Returns: 0 on success, -1 on failure - * - * This function is only used if the driver implements P2P management, - * i.e., if it sets WPA_DRIVER_FLAGS_P2P_MGMT in - * struct wpa_driver_capa. - */ - int (*p2p_set_params)(void *priv, const struct p2p_params *params); - - /** - * p2p_prov_disc_req - Send Provision Discovery Request - * @priv: Private driver interface data - * @peer_addr: MAC address of the peer P2P client - * @config_methods: WPS Config Methods value (only one bit set) - * Returns: 0 on success, -1 on failure - * - * This function can be used to request a discovered P2P peer to - * display a PIN (config_methods = WPS_CONFIG_DISPLAY) or be prepared - * to enter a PIN from us (config_methods = WPS_CONFIG_KEYPAD). The - * Provision Discovery Request frame is transmitted once immediately - * and if no response is received, the frame will be sent again - * whenever the target device is discovered during device dsicovery - * (start with a p2p_find() call). Response from the peer is indicated - * with the EVENT_P2P_PROV_DISC_RESPONSE event. - * - * This function is only used if the driver implements P2P management, - * i.e., if it sets WPA_DRIVER_FLAGS_P2P_MGMT in - * struct wpa_driver_capa. - */ - int (*p2p_prov_disc_req)(void *priv, const u8 *peer_addr, - u16 config_methods); - - /** - * p2p_sd_request - Schedule a service discovery query - * @priv: Private driver interface data - * @dst: Destination peer or %NULL to apply for all peers - * @tlvs: P2P Service Query TLV(s) - * Returns: Reference to the query or 0 on failure - * - * Response to the query is indicated with the - * EVENT_P2P_SD_RESPONSE driver event. - * - * This function is only used if the driver implements P2P management, - * i.e., if it sets WPA_DRIVER_FLAGS_P2P_MGMT in - * struct wpa_driver_capa. - */ - u64 (*p2p_sd_request)(void *priv, const u8 *dst, - const struct wpabuf *tlvs); - - /** - * p2p_sd_cancel_request - Cancel a pending service discovery query - * @priv: Private driver interface data - * @req: Query reference from p2p_sd_request() - * Returns: 0 on success, -1 on failure - * - * This function is only used if the driver implements P2P management, - * i.e., if it sets WPA_DRIVER_FLAGS_P2P_MGMT in - * struct wpa_driver_capa. - */ - int (*p2p_sd_cancel_request)(void *priv, u64 req); - - /** - * p2p_sd_response - Send response to a service discovery query - * @priv: Private driver interface data - * @freq: Frequency from EVENT_P2P_SD_REQUEST event - * @dst: Destination address from EVENT_P2P_SD_REQUEST event - * @dialog_token: Dialog token from EVENT_P2P_SD_REQUEST event - * @resp_tlvs: P2P Service Response TLV(s) - * Returns: 0 on success, -1 on failure - * - * This function is called as a response to the request indicated with - * the EVENT_P2P_SD_REQUEST driver event. - * - * This function is only used if the driver implements P2P management, - * i.e., if it sets WPA_DRIVER_FLAGS_P2P_MGMT in - * struct wpa_driver_capa. - */ - int (*p2p_sd_response)(void *priv, int freq, const u8 *dst, - u8 dialog_token, - const struct wpabuf *resp_tlvs); - - /** - * p2p_service_update - Indicate a change in local services - * @priv: Private driver interface data - * Returns: 0 on success, -1 on failure - * - * This function needs to be called whenever there is a change in - * availability of the local services. This will increment the - * Service Update Indicator value which will be used in SD Request and - * Response frames. - * - * This function is only used if the driver implements P2P management, - * i.e., if it sets WPA_DRIVER_FLAGS_P2P_MGMT in - * struct wpa_driver_capa. - */ - int (*p2p_service_update)(void *priv); - - /** - * p2p_reject - Reject peer device (explicitly block connections) - * @priv: Private driver interface data - * @addr: MAC address of the peer - * Returns: 0 on success, -1 on failure - */ - int (*p2p_reject)(void *priv, const u8 *addr); - - /** - * p2p_invite - Invite a P2P Device into a group - * @priv: Private driver interface data - * @peer: Device Address of the peer P2P Device - * @role: Local role in the group - * @bssid: Group BSSID or %NULL if not known - * @ssid: Group SSID - * @ssid_len: Length of ssid in octets - * @go_dev_addr: Forced GO Device Address or %NULL if none - * @persistent_group: Whether this is to reinvoke a persistent group - * Returns: 0 on success, -1 on failure - */ - int (*p2p_invite)(void *priv, const u8 *peer, int role, - const u8 *bssid, const u8 *ssid, size_t ssid_len, - const u8 *go_dev_addr, int persistent_group); - - /** - * send_tdls_mgmt - for sending TDLS management packets - * @priv: private driver interface data - * @dst: Destination (peer) MAC address - * @action_code: TDLS action code for the mssage - * @dialog_token: Dialog Token to use in the message (if needed) - * @status_code: Status Code or Reason Code to use (if needed) - * @buf: TDLS IEs to add to the message - * @len: Length of buf in octets - * Returns: 0 on success, -1 on failure - * - * This optional function can be used to send packet to driver which is - * responsible for receiving and sending all TDLS packets. - */ - int (*send_tdls_mgmt)(void *priv, const u8 *dst, u8 action_code, - u8 dialog_token, u16 status_code, - const u8 *buf, size_t len); - - int (*tdls_oper)(void *priv, enum tdls_oper oper, const u8 *peer); - - /** - * signal_poll - Get current connection information - * @priv: Private driver interface data - * @signal_info: Connection info structure - */ - int (*signal_poll)(void *priv, struct wpa_signal_info *signal_info); -}; - - -/** - * enum wpa_event_type - Event type for wpa_supplicant_event() calls - */ -enum wpa_event_type { - /** - * EVENT_ASSOC - Association completed - * - * This event needs to be delivered when the driver completes IEEE - * 802.11 association or reassociation successfully. - * wpa_driver_ops::get_bssid() is expected to provide the current BSSID - * after this event has been generated. In addition, optional - * EVENT_ASSOCINFO may be generated just before EVENT_ASSOC to provide - * more information about the association. If the driver interface gets - * both of these events at the same time, it can also include the - * assoc_info data in EVENT_ASSOC call. - */ - EVENT_ASSOC, - - /** - * EVENT_DISASSOC - Association lost - * - * This event should be called when association is lost either due to - * receiving deauthenticate or disassociate frame from the AP or when - * sending either of these frames to the current AP. If the driver - * supports separate deauthentication event, EVENT_DISASSOC should only - * be used for disassociation and EVENT_DEAUTH for deauthentication. - * In AP mode, union wpa_event_data::disassoc_info is required. - */ - EVENT_DISASSOC, - - /** - * EVENT_MICHAEL_MIC_FAILURE - Michael MIC (TKIP) detected - * - * This event must be delivered when a Michael MIC error is detected by - * the local driver. Additional data for event processing is - * provided with union wpa_event_data::michael_mic_failure. This - * information is used to request new encyption key and to initiate - * TKIP countermeasures if needed. - */ - EVENT_MICHAEL_MIC_FAILURE, - - /** - * EVENT_SCAN_RESULTS - Scan results available - * - * This event must be called whenever scan results are available to be - * fetched with struct wpa_driver_ops::get_scan_results(). This event - * is expected to be used some time after struct wpa_driver_ops::scan() - * is called. If the driver provides an unsolicited event when the scan - * has been completed, this event can be used to trigger - * EVENT_SCAN_RESULTS call. If such event is not available from the - * driver, the driver wrapper code is expected to use a registered - * timeout to generate EVENT_SCAN_RESULTS call after the time that the - * scan is expected to be completed. Optional information about - * completed scan can be provided with union wpa_event_data::scan_info. - */ - EVENT_SCAN_RESULTS, - - /** - * EVENT_ASSOCINFO - Report optional extra information for association - * - * This event can be used to report extra association information for - * EVENT_ASSOC processing. This extra information includes IEs from - * association frames and Beacon/Probe Response frames in union - * wpa_event_data::assoc_info. EVENT_ASSOCINFO must be send just before - * EVENT_ASSOC. Alternatively, the driver interface can include - * assoc_info data in the EVENT_ASSOC call if it has all the - * information available at the same point. - */ - EVENT_ASSOCINFO, - - /** - * EVENT_INTERFACE_STATUS - Report interface status changes - * - * This optional event can be used to report changes in interface - * status (interface added/removed) using union - * wpa_event_data::interface_status. This can be used to trigger - * wpa_supplicant to stop and re-start processing for the interface, - * e.g., when a cardbus card is ejected/inserted. - */ - EVENT_INTERFACE_STATUS, - - /** - * EVENT_PMKID_CANDIDATE - Report a candidate AP for pre-authentication - * - * This event can be used to inform wpa_supplicant about candidates for - * RSN (WPA2) pre-authentication. If wpa_supplicant is not responsible - * for scan request (ap_scan=2 mode), this event is required for - * pre-authentication. If wpa_supplicant is performing scan request - * (ap_scan=1), this event is optional since scan results can be used - * to add pre-authentication candidates. union - * wpa_event_data::pmkid_candidate is used to report the BSSID of the - * candidate and priority of the candidate, e.g., based on the signal - * strength, in order to try to pre-authenticate first with candidates - * that are most likely targets for re-association. - * - * EVENT_PMKID_CANDIDATE can be called whenever the driver has updates - * on the candidate list. In addition, it can be called for the current - * AP and APs that have existing PMKSA cache entries. wpa_supplicant - * will automatically skip pre-authentication in cases where a valid - * PMKSA exists. When more than one candidate exists, this event should - * be generated once for each candidate. - * - * Driver will be notified about successful pre-authentication with - * struct wpa_driver_ops::add_pmkid() calls. - */ - EVENT_PMKID_CANDIDATE, - - /** - * EVENT_STKSTART - Request STK handshake (MLME-STKSTART.request) - * - * This event can be used to inform wpa_supplicant about desire to set - * up secure direct link connection between two stations as defined in - * IEEE 802.11e with a new PeerKey mechanism that replaced the original - * STAKey negotiation. The caller will need to set peer address for the - * event. - */ - EVENT_STKSTART, - - /** - * EVENT_TDLS - Request TDLS operation - * - * This event can be used to request a TDLS operation to be performed. - */ - EVENT_TDLS, - - /** - * EVENT_FT_RESPONSE - Report FT (IEEE 802.11r) response IEs - * - * The driver is expected to report the received FT IEs from - * FT authentication sequence from the AP. The FT IEs are included in - * the extra information in union wpa_event_data::ft_ies. - */ - EVENT_FT_RESPONSE, - - /** - * EVENT_IBSS_RSN_START - Request RSN authentication in IBSS - * - * The driver can use this event to inform wpa_supplicant about a STA - * in an IBSS with which protected frames could be exchanged. This - * event starts RSN authentication with the other STA to authenticate - * the STA and set up encryption keys with it. - */ - EVENT_IBSS_RSN_START, - - /** - * EVENT_AUTH - Authentication result - * - * This event should be called when authentication attempt has been - * completed. This is only used if the driver supports separate - * authentication step (struct wpa_driver_ops::authenticate). - * Information about authentication result is included in - * union wpa_event_data::auth. - */ - EVENT_AUTH, - - /** - * EVENT_DEAUTH - Authentication lost - * - * This event should be called when authentication is lost either due - * to receiving deauthenticate frame from the AP or when sending that - * frame to the current AP. - * In AP mode, union wpa_event_data::deauth_info is required. - */ - EVENT_DEAUTH, - - /** - * EVENT_ASSOC_REJECT - Association rejected - * - * This event should be called when (re)association attempt has been - * rejected by the AP. Information about the association response is - * included in union wpa_event_data::assoc_reject. - */ - EVENT_ASSOC_REJECT, - - /** - * EVENT_AUTH_TIMED_OUT - Authentication timed out - */ - EVENT_AUTH_TIMED_OUT, - - /** - * EVENT_ASSOC_TIMED_OUT - Association timed out - */ - EVENT_ASSOC_TIMED_OUT, - - /** - * EVENT_FT_RRB_RX - FT (IEEE 802.11r) RRB frame received - */ - EVENT_FT_RRB_RX, - - /** - * EVENT_WPS_BUTTON_PUSHED - Report hardware push button press for WPS - */ - EVENT_WPS_BUTTON_PUSHED, - - /** - * EVENT_TX_STATUS - Report TX status - */ - EVENT_TX_STATUS, - - /** - * EVENT_RX_FROM_UNKNOWN - Report RX from unknown STA - */ - EVENT_RX_FROM_UNKNOWN, - - /** - * EVENT_RX_MGMT - Report RX of a management frame - */ - EVENT_RX_MGMT, - - /** - * EVENT_RX_ACTION - Action frame received - * - * This event is used to indicate when an Action frame has been - * received. Information about the received frame is included in - * union wpa_event_data::rx_action. - */ - EVENT_RX_ACTION, - - /** - * EVENT_REMAIN_ON_CHANNEL - Remain-on-channel duration started - * - * This event is used to indicate when the driver has started the - * requested remain-on-channel duration. Information about the - * operation is included in union wpa_event_data::remain_on_channel. - */ - EVENT_REMAIN_ON_CHANNEL, - - /** - * EVENT_CANCEL_REMAIN_ON_CHANNEL - Remain-on-channel timed out - * - * This event is used to indicate when the driver has completed - * remain-on-channel duration, i.e., may noot be available on the - * requested channel anymore. Information about the - * operation is included in union wpa_event_data::remain_on_channel. - */ - EVENT_CANCEL_REMAIN_ON_CHANNEL, - - /** - * EVENT_MLME_RX - Report reception of frame for MLME (test use only) - * - * This event is used only by driver_test.c and userspace MLME. - */ - EVENT_MLME_RX, - - /** - * EVENT_RX_PROBE_REQ - Indicate received Probe Request frame - * - * This event is used to indicate when a Probe Request frame has been - * received. Information about the received frame is included in - * union wpa_event_data::rx_probe_req. The driver is required to report - * these events only after successfully completed probe_req_report() - * commands to request the events (i.e., report parameter is non-zero) - * in station mode. In AP mode, Probe Request frames should always be - * reported. - */ - EVENT_RX_PROBE_REQ, - - /** - * EVENT_NEW_STA - New wired device noticed - * - * This event is used to indicate that a new device has been detected - * in a network that does not use association-like functionality (i.e., - * mainly wired Ethernet). This can be used to start EAPOL - * authenticator when receiving a frame from a device. The address of - * the device is included in union wpa_event_data::new_sta. - */ - EVENT_NEW_STA, - - /** - * EVENT_EAPOL_RX - Report received EAPOL frame - * - * When in AP mode with hostapd, this event is required to be used to - * deliver the receive EAPOL frames from the driver. With - * %wpa_supplicant, this event is used only if the send_eapol() handler - * is used to override the use of l2_packet for EAPOL frame TX. - */ - EVENT_EAPOL_RX, - - /** - * EVENT_SIGNAL_CHANGE - Indicate change in signal strength - * - * This event is used to indicate changes in the signal strength - * observed in frames received from the current AP if signal strength - * monitoring has been enabled with signal_monitor(). - */ - EVENT_SIGNAL_CHANGE, - - /** - * EVENT_INTERFACE_ENABLED - Notify that interface was enabled - * - * This event is used to indicate that the interface was enabled after - * having been previously disabled, e.g., due to rfkill. - */ - EVENT_INTERFACE_ENABLED, - - /** - * EVENT_INTERFACE_DISABLED - Notify that interface was disabled - * - * This event is used to indicate that the interface was disabled, - * e.g., due to rfkill. - */ - EVENT_INTERFACE_DISABLED, - - /** - * EVENT_CHANNEL_LIST_CHANGED - Channel list changed - * - * This event is used to indicate that the channel list has changed, - * e.g., because of a regulatory domain change triggered by scan - * results including an AP advertising a country code. - */ - EVENT_CHANNEL_LIST_CHANGED, - - /** - * EVENT_INTERFACE_UNAVAILABLE - Notify that interface is unavailable - * - * This event is used to indicate that the driver cannot maintain this - * interface in its operation mode anymore. The most likely use for - * this is to indicate that AP mode operation is not available due to - * operating channel would need to be changed to a DFS channel when - * the driver does not support radar detection and another virtual - * interfaces caused the operating channel to change. Other similar - * resource conflicts could also trigger this for station mode - * interfaces. - */ - EVENT_INTERFACE_UNAVAILABLE, - - /** - * EVENT_BEST_CHANNEL - * - * Driver generates this event whenever it detects a better channel - * (e.g., based on RSSI or channel use). This information can be used - * to improve channel selection for a new AP/P2P group. - */ - EVENT_BEST_CHANNEL, - - /** - * EVENT_UNPROT_DEAUTH - Unprotected Deauthentication frame received - * - * This event should be called when a Deauthentication frame is dropped - * due to it not being protected (MFP/IEEE 802.11w). - * union wpa_event_data::unprot_deauth is required to provide more - * details of the frame. - */ - EVENT_UNPROT_DEAUTH, - - /** - * EVENT_UNPROT_DISASSOC - Unprotected Disassociation frame received - * - * This event should be called when a Disassociation frame is dropped - * due to it not being protected (MFP/IEEE 802.11w). - * union wpa_event_data::unprot_disassoc is required to provide more - * details of the frame. - */ - EVENT_UNPROT_DISASSOC, - - /** - * EVENT_STATION_LOW_ACK - * - * Driver generates this event whenever it detected that a particular - * station was lost. Detection can be through massive transmission - * failures for example. - */ - EVENT_STATION_LOW_ACK, - - /** - * EVENT_P2P_DEV_FOUND - Report a discovered P2P device - * - * This event is used only if the driver implements P2P management - * internally. Event data is stored in - * union wpa_event_data::p2p_dev_found. - */ - EVENT_P2P_DEV_FOUND, - - /** - * EVENT_P2P_GO_NEG_REQ_RX - Report reception of GO Negotiation Request - * - * This event is used only if the driver implements P2P management - * internally. Event data is stored in - * union wpa_event_data::p2p_go_neg_req_rx. - */ - EVENT_P2P_GO_NEG_REQ_RX, - - /** - * EVENT_P2P_GO_NEG_COMPLETED - Report completion of GO Negotiation - * - * This event is used only if the driver implements P2P management - * internally. Event data is stored in - * union wpa_event_data::p2p_go_neg_completed. - */ - EVENT_P2P_GO_NEG_COMPLETED, - - EVENT_P2P_PROV_DISC_REQUEST, - EVENT_P2P_PROV_DISC_RESPONSE, - EVENT_P2P_SD_REQUEST, - EVENT_P2P_SD_RESPONSE, - - /** - * EVENT_IBSS_PEER_LOST - IBSS peer not reachable anymore - */ - EVENT_IBSS_PEER_LOST -}; - - -/** - * union wpa_event_data - Additional data for wpa_supplicant_event() calls - */ -union wpa_event_data { - /** - * struct assoc_info - Data for EVENT_ASSOC and EVENT_ASSOCINFO events - * - * This structure is optional for EVENT_ASSOC calls and required for - * EVENT_ASSOCINFO calls. By using EVENT_ASSOC with this data, the - * driver interface does not need to generate separate EVENT_ASSOCINFO - * calls. - */ - struct assoc_info { - /** - * reassoc - Flag to indicate association or reassociation - */ - int reassoc; - - /** - * req_ies - (Re)Association Request IEs - * - * If the driver generates WPA/RSN IE, this event data must be - * returned for WPA handshake to have needed information. If - * wpa_supplicant-generated WPA/RSN IE is used, this - * information event is optional. - * - * This should start with the first IE (fixed fields before IEs - * are not included). - */ - const u8 *req_ies; - - /** - * req_ies_len - Length of req_ies in bytes - */ - size_t req_ies_len; - - /** - * resp_ies - (Re)Association Response IEs - * - * Optional association data from the driver. This data is not - * required WPA, but may be useful for some protocols and as - * such, should be reported if this is available to the driver - * interface. - * - * This should start with the first IE (fixed fields before IEs - * are not included). - */ - const u8 *resp_ies; - - /** - * resp_ies_len - Length of resp_ies in bytes - */ - size_t resp_ies_len; - - /** - * beacon_ies - Beacon or Probe Response IEs - * - * Optional Beacon/ProbeResp data: IEs included in Beacon or - * Probe Response frames from the current AP (i.e., the one - * that the client just associated with). This information is - * used to update WPA/RSN IE for the AP. If this field is not - * set, the results from previous scan will be used. If no - * data for the new AP is found, scan results will be requested - * again (without scan request). At this point, the driver is - * expected to provide WPA/RSN IE for the AP (if WPA/WPA2 is - * used). - * - * This should start with the first IE (fixed fields before IEs - * are not included). - */ - const u8 *beacon_ies; - - /** - * beacon_ies_len - Length of beacon_ies */ - size_t beacon_ies_len; - - /** - * freq - Frequency of the operational channel in MHz - */ - unsigned int freq; - - /** - * addr - Station address (for AP mode) - */ - const u8 *addr; - } assoc_info; - - /** - * struct disassoc_info - Data for EVENT_DISASSOC events - */ - struct disassoc_info { - /** - * addr - Station address (for AP mode) - */ - const u8 *addr; - - /** - * reason_code - Reason Code (host byte order) used in - * Deauthentication frame - */ - u16 reason_code; - - /** - * ie - Optional IE(s) in Disassociation frame - */ - const u8 *ie; - - /** - * ie_len - Length of ie buffer in octets - */ - size_t ie_len; - } disassoc_info; - - /** - * struct deauth_info - Data for EVENT_DEAUTH events - */ - struct deauth_info { - /** - * addr - Station address (for AP mode) - */ - const u8 *addr; - - /** - * reason_code - Reason Code (host byte order) used in - * Deauthentication frame - */ - u16 reason_code; - - /** - * ie - Optional IE(s) in Deauthentication frame - */ - const u8 *ie; - - /** - * ie_len - Length of ie buffer in octets - */ - size_t ie_len; - } deauth_info; - - /** - * struct michael_mic_failure - Data for EVENT_MICHAEL_MIC_FAILURE - */ - struct michael_mic_failure { - int unicast; - const u8 *src; - } michael_mic_failure; - - /** - * struct interface_status - Data for EVENT_INTERFACE_STATUS - */ - struct interface_status { - char ifname[100]; - enum { - EVENT_INTERFACE_ADDED, EVENT_INTERFACE_REMOVED - } ievent; - } interface_status; - - /** - * struct pmkid_candidate - Data for EVENT_PMKID_CANDIDATE - */ - struct pmkid_candidate { - /** BSSID of the PMKID candidate */ - u8 bssid[ETH_ALEN]; - /** Smaller the index, higher the priority */ - int index; - /** Whether RSN IE includes pre-authenticate flag */ - int preauth; - } pmkid_candidate; - - /** - * struct stkstart - Data for EVENT_STKSTART - */ - struct stkstart { - u8 peer[ETH_ALEN]; - } stkstart; - - /** - * struct tdls - Data for EVENT_TDLS - */ - struct tdls { - u8 peer[ETH_ALEN]; - enum { - TDLS_REQUEST_SETUP, - TDLS_REQUEST_TEARDOWN - } oper; - u16 reason_code; /* for teardown */ - } tdls; - - /** - * struct ft_ies - FT information elements (EVENT_FT_RESPONSE) - * - * During FT (IEEE 802.11r) authentication sequence, the driver is - * expected to use this event to report received FT IEs (MDIE, FTIE, - * RSN IE, TIE, possible resource request) to the supplicant. The FT - * IEs for the next message will be delivered through the - * struct wpa_driver_ops::update_ft_ies() callback. - */ - struct ft_ies { - const u8 *ies; - size_t ies_len; - int ft_action; - u8 target_ap[ETH_ALEN]; - /** Optional IE(s), e.g., WMM TSPEC(s), for RIC-Request */ - const u8 *ric_ies; - /** Length of ric_ies buffer in octets */ - size_t ric_ies_len; - } ft_ies; - - /** - * struct ibss_rsn_start - Data for EVENT_IBSS_RSN_START - */ - struct ibss_rsn_start { - u8 peer[ETH_ALEN]; - } ibss_rsn_start; - - /** - * struct auth_info - Data for EVENT_AUTH events - */ - struct auth_info { - u8 peer[ETH_ALEN]; - u16 auth_type; - u16 status_code; - const u8 *ies; - size_t ies_len; - } auth; - - /** - * struct assoc_reject - Data for EVENT_ASSOC_REJECT events - */ - struct assoc_reject { - /** - * bssid - BSSID of the AP that rejected association - */ - const u8 *bssid; - - /** - * resp_ies - (Re)Association Response IEs - * - * Optional association data from the driver. This data is not - * required WPA, but may be useful for some protocols and as - * such, should be reported if this is available to the driver - * interface. - * - * This should start with the first IE (fixed fields before IEs - * are not included). - */ - const u8 *resp_ies; - - /** - * resp_ies_len - Length of resp_ies in bytes - */ - size_t resp_ies_len; - - /** - * status_code - Status Code from (Re)association Response - */ - u16 status_code; - } assoc_reject; - - struct timeout_event { - u8 addr[ETH_ALEN]; - } timeout_event; - - /** - * struct ft_rrb_rx - Data for EVENT_FT_RRB_RX events - */ - struct ft_rrb_rx { - const u8 *src; - const u8 *data; - size_t data_len; - } ft_rrb_rx; - - /** - * struct tx_status - Data for EVENT_TX_STATUS events - */ - struct tx_status { - u16 type; - u16 stype; - const u8 *dst; - const u8 *data; - size_t data_len; - int ack; - } tx_status; - - /** - * struct rx_from_unknown - Data for EVENT_RX_FROM_UNKNOWN events - */ - struct rx_from_unknown { - const u8 *frame; - size_t len; - } rx_from_unknown; - - /** - * struct rx_mgmt - Data for EVENT_RX_MGMT events - */ - struct rx_mgmt { - const u8 *frame; - size_t frame_len; - u32 datarate; - u32 ssi_signal; - } rx_mgmt; - - /** - * struct rx_action - Data for EVENT_RX_ACTION events - */ - struct rx_action { - /** - * da - Destination address of the received Action frame - */ - const u8 *da; - - /** - * sa - Source address of the received Action frame - */ - const u8 *sa; - - /** - * bssid - Address 3 of the received Action frame - */ - const u8 *bssid; - - /** - * category - Action frame category - */ - u8 category; - - /** - * data - Action frame body after category field - */ - const u8 *data; - - /** - * len - Length of data in octets - */ - size_t len; - - /** - * freq - Frequency (in MHz) on which the frame was received - */ - int freq; - } rx_action; - - /** - * struct remain_on_channel - Data for EVENT_REMAIN_ON_CHANNEL events - * - * This is also used with EVENT_CANCEL_REMAIN_ON_CHANNEL events. - */ - struct remain_on_channel { - /** - * freq - Channel frequency in MHz - */ - unsigned int freq; - - /** - * duration - Duration to remain on the channel in milliseconds - */ - unsigned int duration; - } remain_on_channel; - - /** - * struct scan_info - Optional data for EVENT_SCAN_RESULTS events - * @aborted: Whether the scan was aborted - * @freqs: Scanned frequencies in MHz (%NULL = all channels scanned) - * @num_freqs: Number of entries in freqs array - * @ssids: Scanned SSIDs (%NULL or zero-length SSID indicates wildcard - * SSID) - * @num_ssids: Number of entries in ssids array - */ - struct scan_info { - int aborted; - const int *freqs; - size_t num_freqs; - struct wpa_driver_scan_ssid ssids[WPAS_MAX_SCAN_SSIDS]; - size_t num_ssids; - } scan_info; - - /** - * struct mlme_rx - Data for EVENT_MLME_RX events - */ - struct mlme_rx { - const u8 *buf; - size_t len; - int freq; - int channel; - int ssi; - } mlme_rx; - - /** - * struct rx_probe_req - Data for EVENT_RX_PROBE_REQ events - */ - struct rx_probe_req { - /** - * sa - Source address of the received Probe Request frame - */ - const u8 *sa; - - /** - * ie - IEs from the Probe Request body - */ - const u8 *ie; - - /** - * ie_len - Length of ie buffer in octets - */ - size_t ie_len; - } rx_probe_req; - - /** - * struct new_sta - Data for EVENT_NEW_STA events - */ - struct new_sta { - const u8 *addr; - } new_sta; - - /** - * struct eapol_rx - Data for EVENT_EAPOL_RX events - */ - struct eapol_rx { - const u8 *src; - const u8 *data; - size_t data_len; - } eapol_rx; - - /** - * signal_change - Data for EVENT_SIGNAL_CHANGE events - */ - struct wpa_signal_info signal_change; - - /** - * struct best_channel - Data for EVENT_BEST_CHANNEL events - * @freq_24: Best 2.4 GHz band channel frequency in MHz - * @freq_5: Best 5 GHz band channel frequency in MHz - * @freq_overall: Best channel frequency in MHz - * - * 0 can be used to indicate no preference in either band. - */ - struct best_channel { - int freq_24; - int freq_5; - int freq_overall; - } best_chan; - - struct unprot_deauth { - const u8 *sa; - const u8 *da; - u16 reason_code; - } unprot_deauth; - - struct unprot_disassoc { - const u8 *sa; - const u8 *da; - u16 reason_code; - } unprot_disassoc; - - /** - * struct low_ack - Data for EVENT_STATION_LOW_ACK events - * @addr: station address - */ - struct low_ack { - u8 addr[ETH_ALEN]; - } low_ack; - - /** - * struct p2p_dev_found - Data for EVENT_P2P_DEV_FOUND - */ - struct p2p_dev_found { - const u8 *addr; - const u8 *dev_addr; - const u8 *pri_dev_type; - const char *dev_name; - u16 config_methods; - u8 dev_capab; - u8 group_capab; - } p2p_dev_found; - - /** - * struct p2p_go_neg_req_rx - Data for EVENT_P2P_GO_NEG_REQ_RX - */ - struct p2p_go_neg_req_rx { - const u8 *src; - u16 dev_passwd_id; - } p2p_go_neg_req_rx; - - /** - * struct p2p_go_neg_completed - Data for EVENT_P2P_GO_NEG_COMPLETED - */ - struct p2p_go_neg_completed { - struct p2p_go_neg_results *res; - } p2p_go_neg_completed; - - struct p2p_prov_disc_req { - const u8 *peer; - u16 config_methods; - const u8 *dev_addr; - const u8 *pri_dev_type; - const char *dev_name; - u16 supp_config_methods; - u8 dev_capab; - u8 group_capab; - } p2p_prov_disc_req; - - struct p2p_prov_disc_resp { - const u8 *peer; - u16 config_methods; - } p2p_prov_disc_resp; - - struct p2p_sd_req { - int freq; - const u8 *sa; - u8 dialog_token; - u16 update_indic; - const u8 *tlvs; - size_t tlvs_len; - } p2p_sd_req; - - struct p2p_sd_resp { - const u8 *sa; - u16 update_indic; - const u8 *tlvs; - size_t tlvs_len; - } p2p_sd_resp; - - /** - * struct ibss_peer_lost - Data for EVENT_IBSS_PEER_LOST - */ - struct ibss_peer_lost { - u8 peer[ETH_ALEN]; - } ibss_peer_lost; -}; - -/** - * wpa_supplicant_event - Report a driver event for wpa_supplicant - * @ctx: Context pointer (wpa_s); this is the ctx variable registered - * with struct wpa_driver_ops::init() - * @event: event type (defined above) - * @data: possible extra data for the event - * - * Driver wrapper code should call this function whenever an event is received - * from the driver. - */ -void wpa_supplicant_event(void *ctx, enum wpa_event_type event, - union wpa_event_data *data); - - -/* - * The following inline functions are provided for convenience to simplify - * event indication for some of the common events. - */ - -static inline void drv_event_assoc(void *ctx, const u8 *addr, const u8 *ie, - size_t ielen, int reassoc) -{ - union wpa_event_data event; - os_memset(&event, 0, sizeof(event)); - event.assoc_info.reassoc = reassoc; - event.assoc_info.req_ies = ie; - event.assoc_info.req_ies_len = ielen; - event.assoc_info.addr = addr; - wpa_supplicant_event(ctx, EVENT_ASSOC, &event); -} - -static inline void drv_event_disassoc(void *ctx, const u8 *addr) -{ - union wpa_event_data event; - os_memset(&event, 0, sizeof(event)); - event.disassoc_info.addr = addr; - wpa_supplicant_event(ctx, EVENT_DISASSOC, &event); -} - -static inline void drv_event_eapol_rx(void *ctx, const u8 *src, const u8 *data, - size_t data_len) -{ - union wpa_event_data event; - os_memset(&event, 0, sizeof(event)); - event.eapol_rx.src = src; - event.eapol_rx.data = data; - event.eapol_rx.data_len = data_len; - wpa_supplicant_event(ctx, EVENT_EAPOL_RX, &event); -} - -#endif /* DRIVER_H */ diff --git a/hostapd-0.8/src/drivers/driver_atheros.c b/hostapd-0.8/src/drivers/driver_atheros.c deleted file mode 100644 index 6ac1cea..0000000 --- a/hostapd-0.8/src/drivers/driver_atheros.c +++ /dev/null @@ -1,1381 +0,0 @@ -/* - * hostapd / Driver interaction with Atheros driver - * Copyright (c) 2004, Sam Leffler - * Copyright (c) 2004, Video54 Technologies - * Copyright (c) 2005-2007, Jouni Malinen - * Copyright (c) 2009, Atheros Communications - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#include "includes.h" -#include -#include - -#include "common.h" -#ifndef _BYTE_ORDER -#ifdef WORDS_BIGENDIAN -#define _BYTE_ORDER _BIG_ENDIAN -#else -#define _BYTE_ORDER _LITTLE_ENDIAN -#endif -#endif /* _BYTE_ORDER */ - -/* - * Note, the ATH_WPS_IE setting must match with the driver build.. If the - * driver does not include this, the IEEE80211_IOCTL_GETWPAIE ioctl will fail. - */ -#define ATH_WPS_IE - -#include "os/linux/include/ieee80211_external.h" - - -#ifdef CONFIG_WPS -#include - -#ifndef ETH_P_80211_RAW -#define ETH_P_80211_RAW 0x0019 -#endif -#endif /* CONFIG_WPS */ - -#include "wireless_copy.h" - -#include "driver.h" -#include "eloop.h" -#include "priv_netlink.h" -#include "l2_packet/l2_packet.h" -#include "common/ieee802_11_defs.h" -#include "netlink.h" -#include "linux_ioctl.h" - - -struct atheros_driver_data { - struct hostapd_data *hapd; /* back pointer */ - - char iface[IFNAMSIZ + 1]; - int ifindex; - struct l2_packet_data *sock_xmit; /* raw packet xmit socket */ - struct l2_packet_data *sock_recv; /* raw packet recv socket */ - int ioctl_sock; /* socket for ioctl() use */ - struct netlink_data *netlink; - int we_version; - u8 acct_mac[ETH_ALEN]; - struct hostap_sta_driver_data acct_data; - - struct l2_packet_data *sock_raw; /* raw 802.11 management frames */ - struct wpabuf *wpa_ie; - struct wpabuf *wps_beacon_ie; - struct wpabuf *wps_probe_resp_ie; -}; - -static int atheros_sta_deauth(void *priv, const u8 *own_addr, const u8 *addr, - int reason_code); -static int atheros_set_privacy(void *priv, int enabled); - -static const char * athr_get_ioctl_name(int op) -{ - switch (op) { - case IEEE80211_IOCTL_SETPARAM: - return "SETPARAM"; - case IEEE80211_IOCTL_GETPARAM: - return "GETPARAM"; - case IEEE80211_IOCTL_SETKEY: - return "SETKEY"; - case IEEE80211_IOCTL_SETWMMPARAMS: - return "SETWMMPARAMS"; - case IEEE80211_IOCTL_DELKEY: - return "DELKEY"; - case IEEE80211_IOCTL_GETWMMPARAMS: - return "GETWMMPARAMS"; - case IEEE80211_IOCTL_SETMLME: - return "SETMLME"; - case IEEE80211_IOCTL_GETCHANINFO: - return "GETCHANINFO"; - case IEEE80211_IOCTL_SETOPTIE: - return "SETOPTIE"; - case IEEE80211_IOCTL_GETOPTIE: - return "GETOPTIE"; - case IEEE80211_IOCTL_ADDMAC: - return "ADDMAC"; - case IEEE80211_IOCTL_DELMAC: - return "DELMAC"; - case IEEE80211_IOCTL_GETCHANLIST: - return "GETCHANLIST"; - case IEEE80211_IOCTL_SETCHANLIST: - return "SETCHANLIST"; - case IEEE80211_IOCTL_KICKMAC: - return "KICKMAC"; - case IEEE80211_IOCTL_CHANSWITCH: - return "CHANSWITCH"; - case IEEE80211_IOCTL_GETMODE: - return "GETMODE"; - case IEEE80211_IOCTL_SETMODE: - return "SETMODE"; - case IEEE80211_IOCTL_GET_APPIEBUF: - return "GET_APPIEBUF"; - case IEEE80211_IOCTL_SET_APPIEBUF: - return "SET_APPIEBUF"; - case IEEE80211_IOCTL_SET_ACPARAMS: - return "SET_ACPARAMS"; - case IEEE80211_IOCTL_FILTERFRAME: - return "FILTERFRAME"; - case IEEE80211_IOCTL_SET_RTPARAMS: - return "SET_RTPARAMS"; - case IEEE80211_IOCTL_SET_MEDENYENTRY: - return "SET_MEDENYENTRY"; - case IEEE80211_IOCTL_GET_MACADDR: - return "GET_MACADDR"; - case IEEE80211_IOCTL_SET_HBRPARAMS: - return "SET_HBRPARAMS"; - case IEEE80211_IOCTL_SET_RXTIMEOUT: - return "SET_RXTIMEOUT"; - case IEEE80211_IOCTL_STA_STATS: - return "STA_STATS"; - case IEEE80211_IOCTL_GETWPAIE: - return "GETWPAIE"; - default: - return "??"; - } -} - - -static const char * athr_get_param_name(int op) -{ - switch (op) { - case IEEE80211_IOC_MCASTCIPHER: - return "MCASTCIPHER"; - case IEEE80211_PARAM_MCASTKEYLEN: - return "MCASTKEYLEN"; - case IEEE80211_PARAM_UCASTCIPHERS: - return "UCASTCIPHERS"; - case IEEE80211_PARAM_KEYMGTALGS: - return "KEYMGTALGS"; - case IEEE80211_PARAM_RSNCAPS: - return "RSNCAPS"; - case IEEE80211_PARAM_WPA: - return "WPA"; - case IEEE80211_PARAM_AUTHMODE: - return "AUTHMODE"; - case IEEE80211_PARAM_PRIVACY: - return "PRIVACY"; - case IEEE80211_PARAM_COUNTERMEASURES: - return "COUNTERMEASURES"; - default: - return "??"; - } -} - - -static int -set80211priv(struct atheros_driver_data *drv, int op, void *data, int len) -{ - struct iwreq iwr; - int do_inline = len < IFNAMSIZ; - - /* Certain ioctls must use the non-inlined method */ - if (op == IEEE80211_IOCTL_SET_APPIEBUF || - op == IEEE80211_IOCTL_FILTERFRAME) - do_inline = 0; - - memset(&iwr, 0, sizeof(iwr)); - os_strlcpy(iwr.ifr_name, drv->iface, IFNAMSIZ); - if (do_inline) { - /* - * Argument data fits inline; put it there. - */ - memcpy(iwr.u.name, data, len); - } else { - /* - * Argument data too big for inline transfer; setup a - * parameter block instead; the kernel will transfer - * the data for the driver. - */ - iwr.u.data.pointer = data; - iwr.u.data.length = len; - } - - if (ioctl(drv->ioctl_sock, op, &iwr) < 0) { - wpa_printf(MSG_DEBUG, "atheros: %s: %s: ioctl op=0x%x " - "(%s) len=%d failed: %d (%s)", - __func__, drv->iface, op, - athr_get_ioctl_name(op), - len, errno, strerror(errno)); - return -1; - } - return 0; -} - -static int -set80211param(struct atheros_driver_data *drv, int op, int arg) -{ - struct iwreq iwr; - - memset(&iwr, 0, sizeof(iwr)); - os_strlcpy(iwr.ifr_name, drv->iface, IFNAMSIZ); - iwr.u.mode = op; - memcpy(iwr.u.name+sizeof(__u32), &arg, sizeof(arg)); - - if (ioctl(drv->ioctl_sock, IEEE80211_IOCTL_SETPARAM, &iwr) < 0) { - perror("ioctl[IEEE80211_IOCTL_SETPARAM]"); - wpa_printf(MSG_DEBUG, "%s: %s: Failed to set parameter (op %d " - "(%s) arg %d)", __func__, drv->iface, op, - athr_get_param_name(op), arg); - return -1; - } - return 0; -} - -#ifndef CONFIG_NO_STDOUT_DEBUG -static const char * -ether_sprintf(const u8 *addr) -{ - static char buf[sizeof(MACSTR)]; - - if (addr != NULL) - snprintf(buf, sizeof(buf), MACSTR, MAC2STR(addr)); - else - snprintf(buf, sizeof(buf), MACSTR, 0,0,0,0,0,0); - return buf; -} -#endif /* CONFIG_NO_STDOUT_DEBUG */ - -/* - * Configure WPA parameters. - */ -static int -atheros_configure_wpa(struct atheros_driver_data *drv, - struct wpa_bss_params *params) -{ - int v; - - switch (params->wpa_group) { - case WPA_CIPHER_CCMP: - v = IEEE80211_CIPHER_AES_CCM; - break; - case WPA_CIPHER_TKIP: - v = IEEE80211_CIPHER_TKIP; - break; - case WPA_CIPHER_WEP104: - v = IEEE80211_CIPHER_WEP; - break; - case WPA_CIPHER_WEP40: - v = IEEE80211_CIPHER_WEP; - break; - case WPA_CIPHER_NONE: - v = IEEE80211_CIPHER_NONE; - break; - default: - wpa_printf(MSG_ERROR, "Unknown group key cipher %u", - params->wpa_group); - return -1; - } - wpa_printf(MSG_DEBUG, "%s: group key cipher=%d", __func__, v); - if (set80211param(drv, IEEE80211_PARAM_MCASTCIPHER, v)) { - printf("Unable to set group key cipher to %u\n", v); - return -1; - } - if (v == IEEE80211_CIPHER_WEP) { - /* key length is done only for specific ciphers */ - v = (params->wpa_group == WPA_CIPHER_WEP104 ? 13 : 5); - if (set80211param(drv, IEEE80211_PARAM_MCASTKEYLEN, v)) { - printf("Unable to set group key length to %u\n", v); - return -1; - } - } - - v = 0; - if (params->wpa_pairwise & WPA_CIPHER_CCMP) - v |= 1<wpa_pairwise & WPA_CIPHER_TKIP) - v |= 1<wpa_pairwise & WPA_CIPHER_NONE) - v |= 1<wpa_key_mgmt); - if (set80211param(drv, IEEE80211_PARAM_KEYMGTALGS, - params->wpa_key_mgmt)) { - printf("Unable to set key management algorithms to 0x%x\n", - params->wpa_key_mgmt); - return -1; - } - - v = 0; - if (params->rsn_preauth) - v |= BIT(0); -#ifdef CONFIG_IEEE80211W - if (params->ieee80211w != NO_MGMT_FRAME_PROTECTION) { - v |= BIT(7); - if (params->ieee80211w == MGMT_FRAME_PROTECTION_REQUIRED) - v |= BIT(6); - } -#endif /* CONFIG_IEEE80211W */ - - wpa_printf(MSG_DEBUG, "%s: rsn capabilities=0x%x", - __func__, params->rsn_preauth); - if (set80211param(drv, IEEE80211_PARAM_RSNCAPS, v)) { - printf("Unable to set RSN capabilities to 0x%x\n", v); - return -1; - } - - wpa_printf(MSG_DEBUG, "%s: enable WPA=0x%x", __func__, params->wpa); - if (set80211param(drv, IEEE80211_PARAM_WPA, params->wpa)) { - printf("Unable to set WPA to %u\n", params->wpa); - return -1; - } - return 0; -} - -static int -atheros_set_ieee8021x(void *priv, struct wpa_bss_params *params) -{ - struct atheros_driver_data *drv = priv; - - wpa_printf(MSG_DEBUG, "%s: enabled=%d", __func__, params->enabled); - - if (!params->enabled) { - /* XXX restore state */ - if (set80211param(priv, IEEE80211_PARAM_AUTHMODE, - IEEE80211_AUTH_AUTO) < 0) - return -1; - /* IEEE80211_AUTH_AUTO ends up enabling Privacy; clear that */ - return atheros_set_privacy(drv, 0); - } - if (!params->wpa && !params->ieee802_1x) { - hostapd_logger(drv->hapd, NULL, HOSTAPD_MODULE_DRIVER, - HOSTAPD_LEVEL_WARNING, "No 802.1X or WPA enabled!"); - return -1; - } - if (params->wpa && atheros_configure_wpa(drv, params) != 0) { - hostapd_logger(drv->hapd, NULL, HOSTAPD_MODULE_DRIVER, - HOSTAPD_LEVEL_WARNING, "Error configuring WPA state!"); - return -1; - } - if (set80211param(priv, IEEE80211_PARAM_AUTHMODE, - (params->wpa ? IEEE80211_AUTH_WPA : IEEE80211_AUTH_8021X))) { - hostapd_logger(drv->hapd, NULL, HOSTAPD_MODULE_DRIVER, - HOSTAPD_LEVEL_WARNING, "Error enabling WPA/802.1X!"); - return -1; - } - - return 0; -} - -static int -atheros_set_privacy(void *priv, int enabled) -{ - struct atheros_driver_data *drv = priv; - - wpa_printf(MSG_DEBUG, "%s: enabled=%d", __func__, enabled); - - return set80211param(drv, IEEE80211_PARAM_PRIVACY, enabled); -} - -static int -atheros_set_sta_authorized(void *priv, const u8 *addr, int authorized) -{ - struct atheros_driver_data *drv = priv; - struct ieee80211req_mlme mlme; - int ret; - - wpa_printf(MSG_DEBUG, "%s: addr=%s authorized=%d", - __func__, ether_sprintf(addr), authorized); - - if (authorized) - mlme.im_op = IEEE80211_MLME_AUTHORIZE; - else - mlme.im_op = IEEE80211_MLME_UNAUTHORIZE; - mlme.im_reason = 0; - memcpy(mlme.im_macaddr, addr, IEEE80211_ADDR_LEN); - ret = set80211priv(drv, IEEE80211_IOCTL_SETMLME, &mlme, sizeof(mlme)); - if (ret < 0) { - wpa_printf(MSG_DEBUG, "%s: Failed to %sauthorize STA " MACSTR, - __func__, authorized ? "" : "un", MAC2STR(addr)); - } - - return ret; -} - -static int -atheros_sta_set_flags(void *priv, const u8 *addr, - int total_flags, int flags_or, int flags_and) -{ - /* For now, only support setting Authorized flag */ - if (flags_or & WPA_STA_AUTHORIZED) - return atheros_set_sta_authorized(priv, addr, 1); - if (!(flags_and & WPA_STA_AUTHORIZED)) - return atheros_set_sta_authorized(priv, addr, 0); - return 0; -} - -static int -atheros_del_key(void *priv, const u8 *addr, int key_idx) -{ - struct atheros_driver_data *drv = priv; - struct ieee80211req_del_key wk; - int ret; - - wpa_printf(MSG_DEBUG, "%s: addr=%s key_idx=%d", - __func__, ether_sprintf(addr), key_idx); - - memset(&wk, 0, sizeof(wk)); - if (addr != NULL) { - memcpy(wk.idk_macaddr, addr, IEEE80211_ADDR_LEN); - wk.idk_keyix = (u8) IEEE80211_KEYIX_NONE; - } else { - wk.idk_keyix = key_idx; - } - - ret = set80211priv(drv, IEEE80211_IOCTL_DELKEY, &wk, sizeof(wk)); - if (ret < 0) { - wpa_printf(MSG_DEBUG, "%s: Failed to delete key (addr %s" - " key_idx %d)", __func__, ether_sprintf(addr), - key_idx); - } - - return ret; -} - -static int -atheros_set_key(const char *ifname, void *priv, enum wpa_alg alg, - const u8 *addr, int key_idx, int set_tx, const u8 *seq, - size_t seq_len, const u8 *key, size_t key_len) -{ - struct atheros_driver_data *drv = priv; - struct ieee80211req_key wk; - u_int8_t cipher; - int ret; - - if (alg == WPA_ALG_NONE) - return atheros_del_key(drv, addr, key_idx); - - wpa_printf(MSG_DEBUG, "%s: alg=%d addr=%s key_idx=%d", - __func__, alg, ether_sprintf(addr), key_idx); - - switch (alg) { - case WPA_ALG_WEP: - cipher = IEEE80211_CIPHER_WEP; - break; - case WPA_ALG_TKIP: - cipher = IEEE80211_CIPHER_TKIP; - break; - case WPA_ALG_CCMP: - cipher = IEEE80211_CIPHER_AES_CCM; - break; -#ifdef CONFIG_IEEE80211W - case WPA_ALG_IGTK: - cipher = IEEE80211_CIPHER_AES_CMAC; - break; -#endif /* CONFIG_IEEE80211W */ - default: - printf("%s: unknown/unsupported algorithm %d\n", - __func__, alg); - return -1; - } - - if (key_len > sizeof(wk.ik_keydata)) { - printf("%s: key length %lu too big\n", __func__, - (unsigned long) key_len); - return -3; - } - - memset(&wk, 0, sizeof(wk)); - wk.ik_type = cipher; - wk.ik_flags = IEEE80211_KEY_RECV | IEEE80211_KEY_XMIT; - if (addr == NULL || is_broadcast_ether_addr(addr)) { - memset(wk.ik_macaddr, 0xff, IEEE80211_ADDR_LEN); - wk.ik_keyix = key_idx; - if (set_tx) - wk.ik_flags |= IEEE80211_KEY_DEFAULT; - } else { - memcpy(wk.ik_macaddr, addr, IEEE80211_ADDR_LEN); - wk.ik_keyix = IEEE80211_KEYIX_NONE; - } - wk.ik_keylen = key_len; - memcpy(wk.ik_keydata, key, key_len); - - ret = set80211priv(drv, IEEE80211_IOCTL_SETKEY, &wk, sizeof(wk)); - if (ret < 0) { - wpa_printf(MSG_DEBUG, "%s: Failed to set key (addr %s" - " key_idx %d alg %d key_len %lu set_tx %d)", - __func__, ether_sprintf(wk.ik_macaddr), key_idx, - alg, (unsigned long) key_len, set_tx); - } - - return ret; -} - - -static int -atheros_get_seqnum(const char *ifname, void *priv, const u8 *addr, int idx, - u8 *seq) -{ - struct atheros_driver_data *drv = priv; - struct ieee80211req_key wk; - - wpa_printf(MSG_DEBUG, "%s: addr=%s idx=%d", - __func__, ether_sprintf(addr), idx); - - memset(&wk, 0, sizeof(wk)); - if (addr == NULL) - memset(wk.ik_macaddr, 0xff, IEEE80211_ADDR_LEN); - else - memcpy(wk.ik_macaddr, addr, IEEE80211_ADDR_LEN); - wk.ik_keyix = idx; - - if (set80211priv(drv, IEEE80211_IOCTL_GETKEY, &wk, sizeof(wk))) { - wpa_printf(MSG_DEBUG, "%s: Failed to get encryption data " - "(addr " MACSTR " key_idx %d)", - __func__, MAC2STR(wk.ik_macaddr), idx); - return -1; - } - -#ifdef WORDS_BIGENDIAN - { - /* - * wk.ik_keytsc is in host byte order (big endian), need to - * swap it to match with the byte order used in WPA. - */ - int i; -#ifndef WPA_KEY_RSC_LEN -#define WPA_KEY_RSC_LEN 8 -#endif - u8 tmp[WPA_KEY_RSC_LEN]; - memcpy(tmp, &wk.ik_keytsc, sizeof(wk.ik_keytsc)); - for (i = 0; i < WPA_KEY_RSC_LEN; i++) { - seq[i] = tmp[WPA_KEY_RSC_LEN - i - 1]; - } - } -#else /* WORDS_BIGENDIAN */ - memcpy(seq, &wk.ik_keytsc, sizeof(wk.ik_keytsc)); -#endif /* WORDS_BIGENDIAN */ - return 0; -} - - -static int -atheros_flush(void *priv) -{ - u8 allsta[IEEE80211_ADDR_LEN]; - memset(allsta, 0xff, IEEE80211_ADDR_LEN); - return atheros_sta_deauth(priv, NULL, allsta, - IEEE80211_REASON_AUTH_LEAVE); -} - - -static int -atheros_read_sta_driver_data(void *priv, struct hostap_sta_driver_data *data, - const u8 *addr) -{ - struct atheros_driver_data *drv = priv; - struct ieee80211req_sta_stats stats; - - memset(data, 0, sizeof(*data)); - - /* - * Fetch statistics for station from the system. - */ - memset(&stats, 0, sizeof(stats)); - memcpy(stats.is_u.macaddr, addr, IEEE80211_ADDR_LEN); - if (set80211priv(drv, IEEE80211_IOCTL_STA_STATS, - &stats, sizeof(stats))) { - wpa_printf(MSG_DEBUG, "%s: Failed to fetch STA stats (addr " - MACSTR ")", __func__, MAC2STR(addr)); - if (memcmp(addr, drv->acct_mac, ETH_ALEN) == 0) { - memcpy(data, &drv->acct_data, sizeof(*data)); - return 0; - } - - printf("Failed to get station stats information element.\n"); - return -1; - } - - data->rx_packets = stats.is_stats.ns_rx_data; - data->rx_bytes = stats.is_stats.ns_rx_bytes; - data->tx_packets = stats.is_stats.ns_tx_data; - data->tx_bytes = stats.is_stats.ns_tx_bytes; - return 0; -} - - -static int -atheros_sta_clear_stats(void *priv, const u8 *addr) -{ - struct atheros_driver_data *drv = priv; - struct ieee80211req_mlme mlme; - int ret; - - wpa_printf(MSG_DEBUG, "%s: addr=%s", __func__, ether_sprintf(addr)); - - mlme.im_op = IEEE80211_MLME_CLEAR_STATS; - memcpy(mlme.im_macaddr, addr, IEEE80211_ADDR_LEN); - ret = set80211priv(drv, IEEE80211_IOCTL_SETMLME, &mlme, - sizeof(mlme)); - if (ret < 0) { - wpa_printf(MSG_DEBUG, "%s: Failed to clear STA stats (addr " - MACSTR ")", __func__, MAC2STR(addr)); - } - - return ret; -} - - -static int -atheros_set_opt_ie(void *priv, const u8 *ie, size_t ie_len) -{ - struct atheros_driver_data *drv = priv; - u8 buf[512]; - struct ieee80211req_getset_appiebuf *app_ie; - - wpa_printf(MSG_DEBUG, "%s buflen = %lu", __func__, - (unsigned long) ie_len); - - wpabuf_free(drv->wpa_ie); - drv->wpa_ie = wpabuf_alloc_copy(ie, ie_len); - - app_ie = (struct ieee80211req_getset_appiebuf *) buf; - os_memcpy(&(app_ie->app_buf[0]), ie, ie_len); - app_ie->app_buflen = ie_len; - - app_ie->app_frmtype = IEEE80211_APPIE_FRAME_BEACON; - - /* append WPS IE for Beacon */ - if (drv->wps_beacon_ie != NULL) { - os_memcpy(&(app_ie->app_buf[ie_len]), - wpabuf_head(drv->wps_beacon_ie), - wpabuf_len(drv->wps_beacon_ie)); - app_ie->app_buflen = ie_len + wpabuf_len(drv->wps_beacon_ie); - } - set80211priv(drv, IEEE80211_IOCTL_SET_APPIEBUF, app_ie, - sizeof(struct ieee80211req_getset_appiebuf) + - app_ie->app_buflen); - - /* append WPS IE for Probe Response */ - app_ie->app_frmtype = IEEE80211_APPIE_FRAME_PROBE_RESP; - if (drv->wps_probe_resp_ie != NULL) { - os_memcpy(&(app_ie->app_buf[ie_len]), - wpabuf_head(drv->wps_probe_resp_ie), - wpabuf_len(drv->wps_probe_resp_ie)); - app_ie->app_buflen = ie_len + - wpabuf_len(drv->wps_probe_resp_ie); - } else - app_ie->app_buflen = ie_len; - set80211priv(drv, IEEE80211_IOCTL_SET_APPIEBUF, app_ie, - sizeof(struct ieee80211req_getset_appiebuf) + - app_ie->app_buflen); - return 0; -} - -static int -atheros_sta_deauth(void *priv, const u8 *own_addr, const u8 *addr, - int reason_code) -{ - struct atheros_driver_data *drv = priv; - struct ieee80211req_mlme mlme; - int ret; - - wpa_printf(MSG_DEBUG, "%s: addr=%s reason_code=%d", - __func__, ether_sprintf(addr), reason_code); - - mlme.im_op = IEEE80211_MLME_DEAUTH; - mlme.im_reason = reason_code; - memcpy(mlme.im_macaddr, addr, IEEE80211_ADDR_LEN); - ret = set80211priv(drv, IEEE80211_IOCTL_SETMLME, &mlme, sizeof(mlme)); - if (ret < 0) { - wpa_printf(MSG_DEBUG, "%s: Failed to deauth STA (addr " MACSTR - " reason %d)", - __func__, MAC2STR(addr), reason_code); - } - - return ret; -} - -static int -atheros_sta_disassoc(void *priv, const u8 *own_addr, const u8 *addr, - int reason_code) -{ - struct atheros_driver_data *drv = priv; - struct ieee80211req_mlme mlme; - int ret; - - wpa_printf(MSG_DEBUG, "%s: addr=%s reason_code=%d", - __func__, ether_sprintf(addr), reason_code); - - mlme.im_op = IEEE80211_MLME_DISASSOC; - mlme.im_reason = reason_code; - memcpy(mlme.im_macaddr, addr, IEEE80211_ADDR_LEN); - ret = set80211priv(drv, IEEE80211_IOCTL_SETMLME, &mlme, sizeof(mlme)); - if (ret < 0) { - wpa_printf(MSG_DEBUG, "%s: Failed to disassoc STA (addr " - MACSTR " reason %d)", - __func__, MAC2STR(addr), reason_code); - } - - return ret; -} - -#ifdef CONFIG_WPS -static void atheros_raw_receive(void *ctx, const u8 *src_addr, const u8 *buf, - size_t len) -{ - struct atheros_driver_data *drv = ctx; - const struct ieee80211_mgmt *mgmt; - u16 fc; - union wpa_event_data event; - - /* Send Probe Request information to WPS processing */ - - if (len < IEEE80211_HDRLEN + sizeof(mgmt->u.probe_req)) - return; - mgmt = (const struct ieee80211_mgmt *) buf; - - fc = le_to_host16(mgmt->frame_control); - if (WLAN_FC_GET_TYPE(fc) != WLAN_FC_TYPE_MGMT || - WLAN_FC_GET_STYPE(fc) != WLAN_FC_STYPE_PROBE_REQ) - return; - - os_memset(&event, 0, sizeof(event)); - event.rx_probe_req.sa = mgmt->sa; - event.rx_probe_req.ie = mgmt->u.probe_req.variable; - event.rx_probe_req.ie_len = - len - (IEEE80211_HDRLEN + sizeof(mgmt->u.probe_req)); - wpa_supplicant_event(drv->hapd, EVENT_RX_PROBE_REQ, &event); -} -#endif /* CONFIG_WPS */ - -static int atheros_receive_probe_req(struct atheros_driver_data *drv) -{ - int ret = 0; -#ifdef CONFIG_WPS - struct ieee80211req_set_filter filt; - - wpa_printf(MSG_DEBUG, "%s Enter", __func__); - filt.app_filterype = IEEE80211_FILTER_TYPE_PROBE_REQ; - - ret = set80211priv(drv, IEEE80211_IOCTL_FILTERFRAME, &filt, - sizeof(struct ieee80211req_set_filter)); - if (ret) - return ret; - - drv->sock_raw = l2_packet_init(drv->iface, NULL, ETH_P_80211_RAW, - atheros_raw_receive, drv, 1); - if (drv->sock_raw == NULL) - return -1; -#endif /* CONFIG_WPS */ - return ret; -} - -#ifdef CONFIG_WPS -static int -atheros_set_wps_ie(void *priv, const u8 *ie, size_t len, u32 frametype) -{ - struct atheros_driver_data *drv = priv; - u8 buf[512]; - struct ieee80211req_getset_appiebuf *beac_ie; - - wpa_printf(MSG_DEBUG, "%s buflen = %lu", __func__, - (unsigned long) len); - - beac_ie = (struct ieee80211req_getset_appiebuf *) buf; - beac_ie->app_frmtype = frametype; - beac_ie->app_buflen = len; - os_memcpy(&(beac_ie->app_buf[0]), ie, len); - - /* append the WPA/RSN IE if it is set already */ - if (((frametype == IEEE80211_APPIE_FRAME_BEACON) || - (frametype == IEEE80211_APPIE_FRAME_PROBE_RESP)) && - (drv->wpa_ie != NULL)) { - os_memcpy(&(beac_ie->app_buf[len]), wpabuf_head(drv->wpa_ie), - wpabuf_len(drv->wpa_ie)); - beac_ie->app_buflen += wpabuf_len(drv->wpa_ie); - } - - return set80211priv(drv, IEEE80211_IOCTL_SET_APPIEBUF, beac_ie, - sizeof(struct ieee80211req_getset_appiebuf) + - beac_ie->app_buflen); -} - -static int -atheros_set_ap_wps_ie(void *priv, const struct wpabuf *beacon, - const struct wpabuf *proberesp, - const struct wpabuf *assocresp) -{ - struct atheros_driver_data *drv = priv; - - wpabuf_free(drv->wps_beacon_ie); - drv->wps_beacon_ie = beacon ? wpabuf_dup(beacon) : NULL; - wpabuf_free(drv->wps_probe_resp_ie); - drv->wps_probe_resp_ie = proberesp ? wpabuf_dup(proberesp) : NULL; - - atheros_set_wps_ie(priv, assocresp ? wpabuf_head(assocresp) : NULL, - assocresp ? wpabuf_len(assocresp) : 0, - IEEE80211_APPIE_FRAME_ASSOC_RESP); - if (atheros_set_wps_ie(priv, beacon ? wpabuf_head(beacon) : NULL, - beacon ? wpabuf_len(beacon) : 0, - IEEE80211_APPIE_FRAME_BEACON)) - return -1; - return atheros_set_wps_ie(priv, - proberesp ? wpabuf_head(proberesp) : NULL, - proberesp ? wpabuf_len(proberesp): 0, - IEEE80211_APPIE_FRAME_PROBE_RESP); -} -#else /* CONFIG_WPS */ -#define atheros_set_ap_wps_ie NULL -#endif /* CONFIG_WPS */ - -static void -atheros_new_sta(struct atheros_driver_data *drv, u8 addr[IEEE80211_ADDR_LEN]) -{ - struct hostapd_data *hapd = drv->hapd; - struct ieee80211req_wpaie ie; - int ielen = 0; - u8 *iebuf = NULL; - - /* - * Fetch negotiated WPA/RSN parameters from the system. - */ - memset(&ie, 0, sizeof(ie)); - memcpy(ie.wpa_macaddr, addr, IEEE80211_ADDR_LEN); - if (set80211priv(drv, IEEE80211_IOCTL_GETWPAIE, &ie, sizeof(ie))) { - /* - * See ATH_WPS_IE comment in the beginning of the file for a - * possible cause for the failure.. - */ - wpa_printf(MSG_DEBUG, "%s: Failed to get WPA/RSN IE: %s", - __func__, strerror(errno)); - goto no_ie; - } - wpa_hexdump(MSG_MSGDUMP, "atheros req WPA IE", - ie.wpa_ie, IEEE80211_MAX_OPT_IE); - wpa_hexdump(MSG_MSGDUMP, "atheros req RSN IE", - ie.rsn_ie, IEEE80211_MAX_OPT_IE); -#ifdef ATH_WPS_IE - wpa_hexdump(MSG_MSGDUMP, "atheros req WPS IE", - ie.wps_ie, IEEE80211_MAX_OPT_IE); -#endif /* ATH_WPS_IE */ - iebuf = ie.wpa_ie; - /* atheros seems to return some random data if WPA/RSN IE is not set. - * Assume the IE was not included if the IE type is unknown. */ - if (iebuf[0] != WLAN_EID_VENDOR_SPECIFIC) - iebuf[1] = 0; - if (iebuf[1] == 0 && ie.rsn_ie[1] > 0) { - /* atheros-ng svn #1453 added rsn_ie. Use it, if wpa_ie was not - * set. This is needed for WPA2. */ - iebuf = ie.rsn_ie; - if (iebuf[0] != WLAN_EID_RSN) - iebuf[1] = 0; - } - - ielen = iebuf[1]; - -#ifdef ATH_WPS_IE - /* if WPS IE is present, preference is given to WPS */ - if (ie.wps_ie && - (ie.wps_ie[1] > 0 && (ie.wps_ie[0] == WLAN_EID_VENDOR_SPECIFIC))) { - iebuf = ie.wps_ie; - ielen = ie.wps_ie[1]; - } -#endif /* ATH_WPS_IE */ - - if (ielen == 0) - iebuf = NULL; - else - ielen += 2; - -no_ie: - drv_event_assoc(hapd, addr, iebuf, ielen, 0); - - if (memcmp(addr, drv->acct_mac, ETH_ALEN) == 0) { - /* Cached accounting data is not valid anymore. */ - memset(drv->acct_mac, 0, ETH_ALEN); - memset(&drv->acct_data, 0, sizeof(drv->acct_data)); - } -} - -static void -atheros_wireless_event_wireless_custom(struct atheros_driver_data *drv, - char *custom, char *end) -{ - wpa_printf(MSG_DEBUG, "Custom wireless event: '%s'", custom); - - if (strncmp(custom, "MLME-MICHAELMICFAILURE.indication", 33) == 0) { - char *pos; - u8 addr[ETH_ALEN]; - pos = strstr(custom, "addr="); - if (pos == NULL) { - wpa_printf(MSG_DEBUG, - "MLME-MICHAELMICFAILURE.indication " - "without sender address ignored"); - return; - } - pos += 5; - if (hwaddr_aton(pos, addr) == 0) { - union wpa_event_data data; - os_memset(&data, 0, sizeof(data)); - data.michael_mic_failure.unicast = 1; - data.michael_mic_failure.src = addr; - wpa_supplicant_event(drv->hapd, - EVENT_MICHAEL_MIC_FAILURE, &data); - } else { - wpa_printf(MSG_DEBUG, - "MLME-MICHAELMICFAILURE.indication " - "with invalid MAC address"); - } - } else if (strncmp(custom, "STA-TRAFFIC-STAT", 16) == 0) { - char *key, *value; - u32 val; - key = custom; - while ((key = strchr(key, '\n')) != NULL) { - key++; - value = strchr(key, '='); - if (value == NULL) - continue; - *value++ = '\0'; - val = strtoul(value, NULL, 10); - if (strcmp(key, "mac") == 0) - hwaddr_aton(value, drv->acct_mac); - else if (strcmp(key, "rx_packets") == 0) - drv->acct_data.rx_packets = val; - else if (strcmp(key, "tx_packets") == 0) - drv->acct_data.tx_packets = val; - else if (strcmp(key, "rx_bytes") == 0) - drv->acct_data.rx_bytes = val; - else if (strcmp(key, "tx_bytes") == 0) - drv->acct_data.tx_bytes = val; - key = value; - } -#ifdef CONFIG_WPS - } else if (strncmp(custom, "PUSH-BUTTON.indication", 22) == 0) { - /* Some atheros kernels send push button as a wireless event */ - /* PROBLEM! this event is received for ALL BSSs ... - * so all are enabled for WPS... ugh. - */ - wpa_supplicant_event(drv->hapd, EVENT_WPS_BUTTON_PUSHED, NULL); - } else if (strncmp(custom, "Manage.prob_req ", 16) == 0) { - /* - * Atheros driver uses a hack to pass Probe Request frames as a - * binary data in the custom wireless event. The old way (using - * packet sniffing) didn't work when bridging. - * Format: "Manage.prob_req " | zero padding | frame - */ -#define WPS_FRAM_TAG_SIZE 30 /* hardcoded in driver */ - int len = atoi(custom + 16); - if (len < 0 || custom + WPS_FRAM_TAG_SIZE + len > end) { - wpa_printf(MSG_DEBUG, "Invalid Manage.prob_req event " - "length %d", len); - return; - } - atheros_raw_receive(drv, NULL, - (u8 *) custom + WPS_FRAM_TAG_SIZE, len); -#endif /* CONFIG_WPS */ - } -} - -static void -atheros_wireless_event_wireless(struct atheros_driver_data *drv, - char *data, int len) -{ - struct iw_event iwe_buf, *iwe = &iwe_buf; - char *pos, *end, *custom, *buf; - - pos = data; - end = data + len; - - while (pos + IW_EV_LCP_LEN <= end) { - /* Event data may be unaligned, so make a local, aligned copy - * before processing. */ - memcpy(&iwe_buf, pos, IW_EV_LCP_LEN); - wpa_printf(MSG_MSGDUMP, "Wireless event: cmd=0x%x len=%d", - iwe->cmd, iwe->len); - if (iwe->len <= IW_EV_LCP_LEN) - return; - - custom = pos + IW_EV_POINT_LEN; - if (drv->we_version > 18 && - (iwe->cmd == IWEVMICHAELMICFAILURE || - iwe->cmd == IWEVASSOCREQIE || - iwe->cmd == IWEVCUSTOM)) { - /* WE-19 removed the pointer from struct iw_point */ - char *dpos = (char *) &iwe_buf.u.data.length; - int dlen = dpos - (char *) &iwe_buf; - memcpy(dpos, pos + IW_EV_LCP_LEN, - sizeof(struct iw_event) - dlen); - } else { - memcpy(&iwe_buf, pos, sizeof(struct iw_event)); - custom += IW_EV_POINT_OFF; - } - - switch (iwe->cmd) { - case IWEVEXPIRED: - drv_event_disassoc(drv->hapd, - (u8 *) iwe->u.addr.sa_data); - break; - case IWEVREGISTERED: - atheros_new_sta(drv, (u8 *) iwe->u.addr.sa_data); - break; - case IWEVASSOCREQIE: - /* Driver hack.. Use IWEVASSOCREQIE to bypass - * IWEVCUSTOM size limitations. Need to handle this - * just like IWEVCUSTOM. - */ - case IWEVCUSTOM: - if (custom + iwe->u.data.length > end) - return; - buf = malloc(iwe->u.data.length + 1); - if (buf == NULL) - return; /* XXX */ - memcpy(buf, custom, iwe->u.data.length); - buf[iwe->u.data.length] = '\0'; - atheros_wireless_event_wireless_custom( - drv, buf, buf + iwe->u.data.length); - free(buf); - break; - } - - pos += iwe->len; - } -} - - -static void -atheros_wireless_event_rtm_newlink(void *ctx, - struct ifinfomsg *ifi, u8 *buf, size_t len) -{ - struct atheros_driver_data *drv = ctx; - int attrlen, rta_len; - struct rtattr *attr; - - if (ifi->ifi_index != drv->ifindex) - return; - - attrlen = len; - attr = (struct rtattr *) buf; - - rta_len = RTA_ALIGN(sizeof(struct rtattr)); - while (RTA_OK(attr, attrlen)) { - if (attr->rta_type == IFLA_WIRELESS) { - atheros_wireless_event_wireless( - drv, ((char *) attr) + rta_len, - attr->rta_len - rta_len); - } - attr = RTA_NEXT(attr, attrlen); - } -} - - -static int -atheros_get_we_version(struct atheros_driver_data *drv) -{ - struct iw_range *range; - struct iwreq iwr; - int minlen; - size_t buflen; - - drv->we_version = 0; - - /* - * Use larger buffer than struct iw_range in order to allow the - * structure to grow in the future. - */ - buflen = sizeof(struct iw_range) + 500; - range = os_zalloc(buflen); - if (range == NULL) - return -1; - - memset(&iwr, 0, sizeof(iwr)); - os_strlcpy(iwr.ifr_name, drv->iface, IFNAMSIZ); - iwr.u.data.pointer = (caddr_t) range; - iwr.u.data.length = buflen; - - minlen = ((char *) &range->enc_capa) - (char *) range + - sizeof(range->enc_capa); - - if (ioctl(drv->ioctl_sock, SIOCGIWRANGE, &iwr) < 0) { - perror("ioctl[SIOCGIWRANGE]"); - free(range); - return -1; - } else if (iwr.u.data.length >= minlen && - range->we_version_compiled >= 18) { - wpa_printf(MSG_DEBUG, "SIOCGIWRANGE: WE(compiled)=%d " - "WE(source)=%d enc_capa=0x%x", - range->we_version_compiled, - range->we_version_source, - range->enc_capa); - drv->we_version = range->we_version_compiled; - } - - free(range); - return 0; -} - - -static int -atheros_wireless_event_init(struct atheros_driver_data *drv) -{ - struct netlink_config *cfg; - - atheros_get_we_version(drv); - - cfg = os_zalloc(sizeof(*cfg)); - if (cfg == NULL) - return -1; - cfg->ctx = drv; - cfg->newlink_cb = atheros_wireless_event_rtm_newlink; - drv->netlink = netlink_init(cfg); - if (drv->netlink == NULL) { - os_free(cfg); - return -1; - } - - return 0; -} - - -static int -atheros_send_eapol(void *priv, const u8 *addr, const u8 *data, size_t data_len, - int encrypt, const u8 *own_addr, u32 flags) -{ - struct atheros_driver_data *drv = priv; - unsigned char buf[3000]; - unsigned char *bp = buf; - struct l2_ethhdr *eth; - size_t len; - int status; - - /* - * Prepend the Ethernet header. If the caller left us - * space at the front we could just insert it but since - * we don't know we copy to a local buffer. Given the frequency - * and size of frames this probably doesn't matter. - */ - len = data_len + sizeof(struct l2_ethhdr); - if (len > sizeof(buf)) { - bp = malloc(len); - if (bp == NULL) { - printf("EAPOL frame discarded, cannot malloc temp " - "buffer of size %lu!\n", (unsigned long) len); - return -1; - } - } - eth = (struct l2_ethhdr *) bp; - memcpy(eth->h_dest, addr, ETH_ALEN); - memcpy(eth->h_source, own_addr, ETH_ALEN); - eth->h_proto = host_to_be16(ETH_P_EAPOL); - memcpy(eth+1, data, data_len); - - wpa_hexdump(MSG_MSGDUMP, "TX EAPOL", bp, len); - - status = l2_packet_send(drv->sock_xmit, addr, ETH_P_EAPOL, bp, len); - - if (bp != buf) - free(bp); - return status; -} - -static void -handle_read(void *ctx, const u8 *src_addr, const u8 *buf, size_t len) -{ - struct atheros_driver_data *drv = ctx; - drv_event_eapol_rx(drv->hapd, src_addr, buf + sizeof(struct l2_ethhdr), - len - sizeof(struct l2_ethhdr)); -} - -static void * -atheros_init(struct hostapd_data *hapd, struct wpa_init_params *params) -{ - struct atheros_driver_data *drv; - struct ifreq ifr; - struct iwreq iwr; - char brname[IFNAMSIZ]; - - drv = os_zalloc(sizeof(struct atheros_driver_data)); - if (drv == NULL) { - printf("Could not allocate memory for atheros driver data\n"); - return NULL; - } - - drv->hapd = hapd; - drv->ioctl_sock = socket(PF_INET, SOCK_DGRAM, 0); - if (drv->ioctl_sock < 0) { - perror("socket[PF_INET,SOCK_DGRAM]"); - goto bad; - } - memcpy(drv->iface, params->ifname, sizeof(drv->iface)); - - memset(&ifr, 0, sizeof(ifr)); - os_strlcpy(ifr.ifr_name, drv->iface, sizeof(ifr.ifr_name)); - if (ioctl(drv->ioctl_sock, SIOCGIFINDEX, &ifr) != 0) { - perror("ioctl(SIOCGIFINDEX)"); - goto bad; - } - drv->ifindex = ifr.ifr_ifindex; - - drv->sock_xmit = l2_packet_init(drv->iface, NULL, ETH_P_EAPOL, - handle_read, drv, 1); - if (drv->sock_xmit == NULL) - goto bad; - if (l2_packet_get_own_addr(drv->sock_xmit, params->own_addr)) - goto bad; - if (params->bridge[0]) { - wpa_printf(MSG_DEBUG, "Configure bridge %s for EAPOL traffic.", - params->bridge[0]); - drv->sock_recv = l2_packet_init(params->bridge[0], NULL, - ETH_P_EAPOL, handle_read, drv, - 1); - if (drv->sock_recv == NULL) - goto bad; - } else if (linux_br_get(brname, drv->iface) == 0) { - wpa_printf(MSG_DEBUG, "Interface in bridge %s; configure for " - "EAPOL receive", brname); - drv->sock_recv = l2_packet_init(brname, NULL, ETH_P_EAPOL, - handle_read, drv, 1); - if (drv->sock_recv == NULL) - goto bad; - } else - drv->sock_recv = drv->sock_xmit; - - memset(&iwr, 0, sizeof(iwr)); - os_strlcpy(iwr.ifr_name, drv->iface, IFNAMSIZ); - - iwr.u.mode = IW_MODE_MASTER; - - if (ioctl(drv->ioctl_sock, SIOCSIWMODE, &iwr) < 0) { - perror("ioctl[SIOCSIWMODE]"); - printf("Could not set interface to master mode!\n"); - goto bad; - } - - /* mark down during setup */ - linux_set_iface_flags(drv->ioctl_sock, drv->iface, 0); - atheros_set_privacy(drv, 0); /* default to no privacy */ - - atheros_receive_probe_req(drv); - - if (atheros_wireless_event_init(drv)) - goto bad; - - return drv; -bad: - if (drv->sock_recv != NULL && drv->sock_recv != drv->sock_xmit) - l2_packet_deinit(drv->sock_recv); - if (drv->sock_xmit != NULL) - l2_packet_deinit(drv->sock_xmit); - if (drv->ioctl_sock >= 0) - close(drv->ioctl_sock); - if (drv != NULL) - free(drv); - return NULL; -} - - -static void -atheros_deinit(void *priv) -{ - struct atheros_driver_data *drv = priv; - - netlink_deinit(drv->netlink); - (void) linux_set_iface_flags(drv->ioctl_sock, drv->iface, 0); - if (drv->ioctl_sock >= 0) - close(drv->ioctl_sock); - if (drv->sock_recv != NULL && drv->sock_recv != drv->sock_xmit) - l2_packet_deinit(drv->sock_recv); - if (drv->sock_xmit != NULL) - l2_packet_deinit(drv->sock_xmit); - if (drv->sock_raw) - l2_packet_deinit(drv->sock_raw); - wpabuf_free(drv->wpa_ie); - wpabuf_free(drv->wps_beacon_ie); - wpabuf_free(drv->wps_probe_resp_ie); - free(drv); -} - -static int -atheros_set_ssid(void *priv, const u8 *buf, int len) -{ - struct atheros_driver_data *drv = priv; - struct iwreq iwr; - - memset(&iwr, 0, sizeof(iwr)); - os_strlcpy(iwr.ifr_name, drv->iface, IFNAMSIZ); - iwr.u.essid.flags = 1; /* SSID active */ - iwr.u.essid.pointer = (caddr_t) buf; - iwr.u.essid.length = len + 1; - - if (ioctl(drv->ioctl_sock, SIOCSIWESSID, &iwr) < 0) { - perror("ioctl[SIOCSIWESSID]"); - printf("len=%d\n", len); - return -1; - } - return 0; -} - -static int -atheros_get_ssid(void *priv, u8 *buf, int len) -{ - struct atheros_driver_data *drv = priv; - struct iwreq iwr; - int ret = 0; - - memset(&iwr, 0, sizeof(iwr)); - os_strlcpy(iwr.ifr_name, drv->iface, IFNAMSIZ); - iwr.u.essid.pointer = (caddr_t) buf; - iwr.u.essid.length = len; - - if (ioctl(drv->ioctl_sock, SIOCGIWESSID, &iwr) < 0) { - perror("ioctl[SIOCGIWESSID]"); - ret = -1; - } else - ret = iwr.u.essid.length; - - return ret; -} - -static int -atheros_set_countermeasures(void *priv, int enabled) -{ - struct atheros_driver_data *drv = priv; - wpa_printf(MSG_DEBUG, "%s: enabled=%d", __FUNCTION__, enabled); - return set80211param(drv, IEEE80211_PARAM_COUNTERMEASURES, enabled); -} - -static int -atheros_commit(void *priv) -{ - struct atheros_driver_data *drv = priv; - return linux_set_iface_flags(drv->ioctl_sock, drv->iface, 1); -} - -const struct wpa_driver_ops wpa_driver_atheros_ops = { - .name = "atheros", - .hapd_init = atheros_init, - .hapd_deinit = atheros_deinit, - .set_ieee8021x = atheros_set_ieee8021x, - .set_privacy = atheros_set_privacy, - .set_key = atheros_set_key, - .get_seqnum = atheros_get_seqnum, - .flush = atheros_flush, - .set_generic_elem = atheros_set_opt_ie, - .sta_set_flags = atheros_sta_set_flags, - .read_sta_data = atheros_read_sta_driver_data, - .hapd_send_eapol = atheros_send_eapol, - .sta_disassoc = atheros_sta_disassoc, - .sta_deauth = atheros_sta_deauth, - .hapd_set_ssid = atheros_set_ssid, - .hapd_get_ssid = atheros_get_ssid, - .set_countermeasures = atheros_set_countermeasures, - .sta_clear_stats = atheros_sta_clear_stats, - .commit = atheros_commit, - .set_ap_wps_ie = atheros_set_ap_wps_ie, -}; diff --git a/hostapd-0.8/src/drivers/driver_broadcom.c b/hostapd-0.8/src/drivers/driver_broadcom.c deleted file mode 100644 index cb88543..0000000 --- a/hostapd-0.8/src/drivers/driver_broadcom.c +++ /dev/null @@ -1,599 +0,0 @@ -/* - * WPA Supplicant - driver interaction with old Broadcom wl.o driver - * Copyright (c) 2004, Nikki Chumkov - * Copyright (c) 2004, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - * - * Please note that the newer Broadcom driver ("hybrid Linux driver") supports - * Linux wireless extensions and does not need (or even work) with this old - * driver wrapper. Use driver_wext.c with that driver. - */ - -#include "includes.h" - -#include - -#include "common.h" - -#if 0 -#include -#include /* the L2 protocols */ -#else -#include -#include /* The L2 protocols */ -#endif -#include -#include - -/* wlioctl.h is a Broadcom header file and it is available, e.g., from Linksys - * WRT54G GPL tarball. */ -#include - -#include "driver.h" -#include "eloop.h" - -struct wpa_driver_broadcom_data { - void *ctx; - int ioctl_sock; - int event_sock; - char ifname[IFNAMSIZ + 1]; -}; - - -#ifndef WLC_DEAUTHENTICATE -#define WLC_DEAUTHENTICATE 143 -#endif -#ifndef WLC_DEAUTHENTICATE_WITH_REASON -#define WLC_DEAUTHENTICATE_WITH_REASON 201 -#endif -#ifndef WLC_SET_TKIP_COUNTERMEASURES -#define WLC_SET_TKIP_COUNTERMEASURES 202 -#endif - -#if !defined(PSK_ENABLED) /* NEW driver interface */ -#define WL_VERSION 360130 -/* wireless authentication bit vector */ -#define WPA_ENABLED 1 -#define PSK_ENABLED 2 - -#define WAUTH_WPA_ENABLED(wauth) ((wauth) & WPA_ENABLED) -#define WAUTH_PSK_ENABLED(wauth) ((wauth) & PSK_ENABLED) -#define WAUTH_ENABLED(wauth) ((wauth) & (WPA_ENABLED | PSK_ENABLED)) - -#define WSEC_PRIMARY_KEY WL_PRIMARY_KEY - -typedef wl_wsec_key_t wsec_key_t; -#endif - -typedef struct { - uint32 val; - struct ether_addr ea; - uint16 res; -} wlc_deauth_t; - - -static void wpa_driver_broadcom_scan_timeout(void *eloop_ctx, - void *timeout_ctx); - -static int broadcom_ioctl(struct wpa_driver_broadcom_data *drv, int cmd, - void *buf, int len) -{ - struct ifreq ifr; - wl_ioctl_t ioc; - int ret = 0; - - wpa_printf(MSG_MSGDUMP, "BROADCOM: wlioctl(%s,%d,len=%d,val=%p)", - drv->ifname, cmd, len, buf); - /* wpa_hexdump(MSG_MSGDUMP, "BROADCOM: wlioctl buf", buf, len); */ - - ioc.cmd = cmd; - ioc.buf = buf; - ioc.len = len; - os_strlcpy(ifr.ifr_name, drv->ifname, IFNAMSIZ); - ifr.ifr_data = (caddr_t) &ioc; - if ((ret = ioctl(drv->ioctl_sock, SIOCDEVPRIVATE, &ifr)) < 0) { - if (cmd != WLC_GET_MAGIC) - perror(ifr.ifr_name); - wpa_printf(MSG_MSGDUMP, "BROADCOM: wlioctl cmd=%d res=%d", - cmd, ret); - } - - return ret; -} - -static int wpa_driver_broadcom_get_bssid(void *priv, u8 *bssid) -{ - struct wpa_driver_broadcom_data *drv = priv; - if (broadcom_ioctl(drv, WLC_GET_BSSID, bssid, ETH_ALEN) == 0) - return 0; - - os_memset(bssid, 0, ETH_ALEN); - return -1; -} - -static int wpa_driver_broadcom_get_ssid(void *priv, u8 *ssid) -{ - struct wpa_driver_broadcom_data *drv = priv; - wlc_ssid_t s; - - if (broadcom_ioctl(drv, WLC_GET_SSID, &s, sizeof(s)) == -1) - return -1; - - os_memcpy(ssid, s.SSID, s.SSID_len); - return s.SSID_len; -} - -static int wpa_driver_broadcom_set_wpa(void *priv, int enable) -{ - struct wpa_driver_broadcom_data *drv = priv; - unsigned int wauth, wsec; - struct ether_addr ea; - - os_memset(&ea, enable ? 0xff : 0, sizeof(ea)); - if (broadcom_ioctl(drv, WLC_GET_WPA_AUTH, &wauth, sizeof(wauth)) == - -1 || - broadcom_ioctl(drv, WLC_GET_WSEC, &wsec, sizeof(wsec)) == -1) - return -1; - - if (enable) { - wauth = PSK_ENABLED; - wsec = TKIP_ENABLED; - } else { - wauth = 255; - wsec &= ~(TKIP_ENABLED | AES_ENABLED); - } - - if (broadcom_ioctl(drv, WLC_SET_WPA_AUTH, &wauth, sizeof(wauth)) == - -1 || - broadcom_ioctl(drv, WLC_SET_WSEC, &wsec, sizeof(wsec)) == -1) - return -1; - - /* FIX: magic number / error handling? */ - broadcom_ioctl(drv, 122, &ea, sizeof(ea)); - - return 0; -} - -static int wpa_driver_broadcom_set_key(const char *ifname, void *priv, - enum wpa_alg alg, - const u8 *addr, int key_idx, int set_tx, - const u8 *seq, size_t seq_len, - const u8 *key, size_t key_len) -{ - struct wpa_driver_broadcom_data *drv = priv; - int ret; - wsec_key_t wkt; - - os_memset(&wkt, 0, sizeof wkt); - wpa_printf(MSG_MSGDUMP, "BROADCOM: SET %sKEY[%d] alg=%d", - set_tx ? "PRIMARY " : "", key_idx, alg); - if (key && key_len > 0) - wpa_hexdump_key(MSG_MSGDUMP, "BROADCOM: key", key, key_len); - - switch (alg) { - case WPA_ALG_NONE: - wkt.algo = CRYPTO_ALGO_OFF; - break; - case WPA_ALG_WEP: - wkt.algo = CRYPTO_ALGO_WEP128; /* CRYPTO_ALGO_WEP1? */ - break; - case WPA_ALG_TKIP: - wkt.algo = 0; /* CRYPTO_ALGO_TKIP? */ - break; - case WPA_ALG_CCMP: - wkt.algo = 0; /* CRYPTO_ALGO_AES_CCM; - * AES_OCB_MSDU, AES_OCB_MPDU? */ - break; - default: - wkt.algo = CRYPTO_ALGO_NALG; - break; - } - - if (seq && seq_len > 0) - wpa_hexdump(MSG_MSGDUMP, "BROADCOM: SEQ", seq, seq_len); - - if (addr) - wpa_hexdump(MSG_MSGDUMP, "BROADCOM: addr", addr, ETH_ALEN); - - wkt.index = key_idx; - wkt.len = key_len; - if (key && key_len > 0) { - os_memcpy(wkt.data, key, key_len); - if (key_len == 32) { - /* hack hack hack XXX */ - os_memcpy(&wkt.data[16], &key[24], 8); - os_memcpy(&wkt.data[24], &key[16], 8); - } - } - /* wkt.algo = CRYPTO_ALGO_...; */ - wkt.flags = set_tx ? 0 : WSEC_PRIMARY_KEY; - if (addr && set_tx) - os_memcpy(&wkt.ea, addr, sizeof(wkt.ea)); - ret = broadcom_ioctl(drv, WLC_SET_KEY, &wkt, sizeof(wkt)); - if (addr && set_tx) { - /* FIX: magic number / error handling? */ - broadcom_ioctl(drv, 121, &wkt.ea, sizeof(wkt.ea)); - } - return ret; -} - - -static void wpa_driver_broadcom_event_receive(int sock, void *ctx, - void *sock_ctx) -{ - char buf[8192]; - int left; - wl_wpa_header_t *wwh; - union wpa_event_data data; - u8 *resp_ies = NULL; - - if ((left = recv(sock, buf, sizeof buf, 0)) < 0) - return; - - wpa_hexdump(MSG_DEBUG, "RECEIVE EVENT", (u8 *) buf, left); - - if ((size_t) left < sizeof(wl_wpa_header_t)) - return; - - wwh = (wl_wpa_header_t *) buf; - - if (wwh->snap.type != WL_WPA_ETHER_TYPE) - return; - if (os_memcmp(&wwh->snap, wl_wpa_snap_template, 6) != 0) - return; - - os_memset(&data, 0, sizeof(data)); - - switch (wwh->type) { - case WLC_ASSOC_MSG: - left -= WL_WPA_HEADER_LEN; - wpa_printf(MSG_DEBUG, "BROADCOM: ASSOC MESSAGE (left: %d)", - left); - if (left > 0) { - resp_ies = os_malloc(left); - if (resp_ies == NULL) - return; - os_memcpy(resp_ies, buf + WL_WPA_HEADER_LEN, left); - data.assoc_info.resp_ies = resp_ies; - data.assoc_info.resp_ies_len = left; - } - - wpa_supplicant_event(ctx, EVENT_ASSOC, &data); - os_free(resp_ies); - break; - case WLC_DISASSOC_MSG: - wpa_printf(MSG_DEBUG, "BROADCOM: DISASSOC MESSAGE"); - wpa_supplicant_event(ctx, EVENT_DISASSOC, NULL); - break; - case WLC_PTK_MIC_MSG: - wpa_printf(MSG_DEBUG, "BROADCOM: PTK MIC MSG MESSAGE"); - data.michael_mic_failure.unicast = 1; - wpa_supplicant_event(ctx, EVENT_MICHAEL_MIC_FAILURE, &data); - break; - case WLC_GTK_MIC_MSG: - wpa_printf(MSG_DEBUG, "BROADCOM: GTK MIC MSG MESSAGE"); - data.michael_mic_failure.unicast = 0; - wpa_supplicant_event(ctx, EVENT_MICHAEL_MIC_FAILURE, &data); - break; - default: - wpa_printf(MSG_DEBUG, "BROADCOM: UNKNOWN MESSAGE (%d)", - wwh->type); - break; - } -} - -static void * wpa_driver_broadcom_init(void *ctx, const char *ifname) -{ - int s; - struct sockaddr_ll ll; - struct wpa_driver_broadcom_data *drv; - struct ifreq ifr; - - /* open socket to kernel */ - if ((s = socket(AF_INET, SOCK_DGRAM, 0)) < 0) { - perror("socket"); - return NULL; - } - /* do it */ - os_strlcpy(ifr.ifr_name, ifname, IFNAMSIZ); - if (ioctl(s, SIOCGIFINDEX, &ifr) < 0) { - perror(ifr.ifr_name); - return NULL; - } - - - drv = os_zalloc(sizeof(*drv)); - if (drv == NULL) - return NULL; - drv->ctx = ctx; - os_strlcpy(drv->ifname, ifname, sizeof(drv->ifname)); - drv->ioctl_sock = s; - - s = socket(PF_PACKET, SOCK_RAW, ntohs(ETH_P_802_2)); - if (s < 0) { - perror("socket(PF_PACKET, SOCK_RAW, ntohs(ETH_P_802_2))"); - close(drv->ioctl_sock); - os_free(drv); - return NULL; - } - - os_memset(&ll, 0, sizeof(ll)); - ll.sll_family = AF_PACKET; - ll.sll_protocol = ntohs(ETH_P_802_2); - ll.sll_ifindex = ifr.ifr_ifindex; - ll.sll_hatype = 0; - ll.sll_pkttype = PACKET_HOST; - ll.sll_halen = 0; - - if (bind(s, (struct sockaddr *) &ll, sizeof(ll)) < 0) { - perror("bind(netlink)"); - close(s); - close(drv->ioctl_sock); - os_free(drv); - return NULL; - } - - eloop_register_read_sock(s, wpa_driver_broadcom_event_receive, ctx, - NULL); - drv->event_sock = s; - wpa_driver_broadcom_set_wpa(drv, 1); - - return drv; -} - -static void wpa_driver_broadcom_deinit(void *priv) -{ - struct wpa_driver_broadcom_data *drv = priv; - wpa_driver_broadcom_set_wpa(drv, 0); - eloop_cancel_timeout(wpa_driver_broadcom_scan_timeout, drv, drv->ctx); - eloop_unregister_read_sock(drv->event_sock); - close(drv->event_sock); - close(drv->ioctl_sock); - os_free(drv); -} - -static int wpa_driver_broadcom_set_countermeasures(void *priv, - int enabled) -{ -#if 0 - struct wpa_driver_broadcom_data *drv = priv; - /* FIX: ? */ - return broadcom_ioctl(drv, WLC_SET_TKIP_COUNTERMEASURES, &enabled, - sizeof(enabled)); -#else - return 0; -#endif -} - -static int wpa_driver_broadcom_set_drop_unencrypted(void *priv, int enabled) -{ - struct wpa_driver_broadcom_data *drv = priv; - /* SET_EAP_RESTRICT, SET_WEP_RESTRICT */ - int _restrict = (enabled ? 1 : 0); - - if (broadcom_ioctl(drv, WLC_SET_WEP_RESTRICT, - &_restrict, sizeof(_restrict)) < 0 || - broadcom_ioctl(drv, WLC_SET_EAP_RESTRICT, - &_restrict, sizeof(_restrict)) < 0) - return -1; - - return 0; -} - -static void wpa_driver_broadcom_scan_timeout(void *eloop_ctx, - void *timeout_ctx) -{ - wpa_printf(MSG_DEBUG, "Scan timeout - try to get results"); - wpa_supplicant_event(timeout_ctx, EVENT_SCAN_RESULTS, NULL); -} - -static int wpa_driver_broadcom_scan(void *priv, - struct wpa_driver_scan_params *params) -{ - struct wpa_driver_broadcom_data *drv = priv; - wlc_ssid_t wst = { 0, "" }; - const u8 *ssid = params->ssids[0].ssid; - size_t ssid_len = params->ssids[0].ssid_len; - - if (ssid && ssid_len > 0 && ssid_len <= sizeof(wst.SSID)) { - wst.SSID_len = ssid_len; - os_memcpy(wst.SSID, ssid, ssid_len); - } - - if (broadcom_ioctl(drv, WLC_SCAN, &wst, sizeof(wst)) < 0) - return -1; - - eloop_cancel_timeout(wpa_driver_broadcom_scan_timeout, drv, drv->ctx); - eloop_register_timeout(3, 0, wpa_driver_broadcom_scan_timeout, drv, - drv->ctx); - return 0; -} - - -static const int frequency_list[] = { - 2412, 2417, 2422, 2427, 2432, 2437, 2442, - 2447, 2452, 2457, 2462, 2467, 2472, 2484 -}; - -struct bss_ie_hdr { - u8 elem_id; - u8 len; - u8 oui[3]; - /* u8 oui_type; */ - /* u16 version; */ -} __attribute__ ((packed)); - -static struct wpa_scan_results * -wpa_driver_broadcom_get_scan_results(void *priv) -{ - struct wpa_driver_broadcom_data *drv = priv; - char *buf; - wl_scan_results_t *wsr; - wl_bss_info_t *wbi; - size_t ap_num; - struct wpa_scan_results *res; - - buf = os_malloc(WLC_IOCTL_MAXLEN); - if (buf == NULL) - return NULL; - - wsr = (wl_scan_results_t *) buf; - - wsr->buflen = WLC_IOCTL_MAXLEN - sizeof(wsr); - wsr->version = 107; - wsr->count = 0; - - if (broadcom_ioctl(drv, WLC_SCAN_RESULTS, buf, WLC_IOCTL_MAXLEN) < 0) { - os_free(buf); - return NULL; - } - - res = os_zalloc(sizeof(*res)); - if (res == NULL) { - os_free(buf); - return NULL; - } - - res->res = os_zalloc(wsr->count * sizeof(struct wpa_scan_res *)); - if (res->res == NULL) { - os_free(res); - os_free(buf); - return NULL; - } - - for (ap_num = 0, wbi = wsr->bss_info; ap_num < wsr->count; ++ap_num) { - struct wpa_scan_res *r; - r = os_malloc(sizeof(*r) + wbi->ie_length); - if (r == NULL) - break; - res->res[res->num++] = r; - - os_memcpy(r->bssid, &wbi->BSSID, ETH_ALEN); - r->freq = frequency_list[wbi->channel - 1]; - /* get ie's */ - os_memcpy(r + 1, wbi + 1, wbi->ie_length); - r->ie_len = wbi->ie_length; - - wbi = (wl_bss_info_t *) ((u8 *) wbi + wbi->length); - } - - wpa_printf(MSG_MSGDUMP, "Received %d bytes of scan results (%lu " - "BSSes)", - wsr->buflen, (unsigned long) ap_num); - - os_free(buf); - return res; - } - -static int wpa_driver_broadcom_deauthenticate(void *priv, const u8 *addr, - int reason_code) -{ - struct wpa_driver_broadcom_data *drv = priv; - wlc_deauth_t wdt; - wdt.val = reason_code; - os_memcpy(&wdt.ea, addr, sizeof wdt.ea); - wdt.res = 0x7fff; - return broadcom_ioctl(drv, WLC_DEAUTHENTICATE_WITH_REASON, &wdt, - sizeof(wdt)); -} - -static int wpa_driver_broadcom_disassociate(void *priv, const u8 *addr, - int reason_code) -{ - struct wpa_driver_broadcom_data *drv = priv; - return broadcom_ioctl(drv, WLC_DISASSOC, NULL, 0); -} - -static int -wpa_driver_broadcom_associate(void *priv, - struct wpa_driver_associate_params *params) -{ - struct wpa_driver_broadcom_data *drv = priv; - wlc_ssid_t s; - int infra = 1; - int auth = 0; - int wsec = 4; - int dummy; - int wpa_auth; - int ret; - - ret = wpa_driver_broadcom_set_drop_unencrypted( - drv, params->drop_unencrypted); - - s.SSID_len = params->ssid_len; - os_memcpy(s.SSID, params->ssid, params->ssid_len); - - switch (params->pairwise_suite) { - case CIPHER_WEP40: - case CIPHER_WEP104: - wsec = 1; - break; - - case CIPHER_TKIP: - wsec = 2; - break; - - case CIPHER_CCMP: - wsec = 4; - break; - - default: - wsec = 0; - break; - } - - switch (params->key_mgmt_suite) { - case KEY_MGMT_802_1X: - wpa_auth = 1; - break; - - case KEY_MGMT_PSK: - wpa_auth = 2; - break; - - default: - wpa_auth = 255; - break; - } - - /* printf("broadcom_associate: %u %u %u\n", pairwise_suite, - * group_suite, key_mgmt_suite); - * broadcom_ioctl(ifname, WLC_GET_WSEC, &wsec, sizeof(wsec)); - * wl join uses wlc_sec_wep here, not wlc_set_wsec */ - - if (broadcom_ioctl(drv, WLC_SET_WSEC, &wsec, sizeof(wsec)) < 0 || - broadcom_ioctl(drv, WLC_SET_WPA_AUTH, &wpa_auth, - sizeof(wpa_auth)) < 0 || - broadcom_ioctl(drv, WLC_GET_WEP, &dummy, sizeof(dummy)) < 0 || - broadcom_ioctl(drv, WLC_SET_INFRA, &infra, sizeof(infra)) < 0 || - broadcom_ioctl(drv, WLC_SET_AUTH, &auth, sizeof(auth)) < 0 || - broadcom_ioctl(drv, WLC_SET_WEP, &wsec, sizeof(wsec)) < 0 || - broadcom_ioctl(drv, WLC_SET_SSID, &s, sizeof(s)) < 0) - return -1; - - return ret; -} - -const struct wpa_driver_ops wpa_driver_broadcom_ops = { - .name = "broadcom", - .desc = "Broadcom wl.o driver", - .get_bssid = wpa_driver_broadcom_get_bssid, - .get_ssid = wpa_driver_broadcom_get_ssid, - .set_key = wpa_driver_broadcom_set_key, - .init = wpa_driver_broadcom_init, - .deinit = wpa_driver_broadcom_deinit, - .set_countermeasures = wpa_driver_broadcom_set_countermeasures, - .scan2 = wpa_driver_broadcom_scan, - .get_scan_results2 = wpa_driver_broadcom_get_scan_results, - .deauthenticate = wpa_driver_broadcom_deauthenticate, - .disassociate = wpa_driver_broadcom_disassociate, - .associate = wpa_driver_broadcom_associate, -}; diff --git a/hostapd-0.8/src/drivers/driver_bsd.c b/hostapd-0.8/src/drivers/driver_bsd.c deleted file mode 100644 index 1b52865..0000000 --- a/hostapd-0.8/src/drivers/driver_bsd.c +++ /dev/null @@ -1,1573 +0,0 @@ -/* - * WPA Supplicant - driver interaction with BSD net80211 layer - * Copyright (c) 2004, Sam Leffler - * Copyright (c) 2004, 2Wire, Inc - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#include "includes.h" -#include -#include - -#include "common.h" -#include "driver.h" -#include "eloop.h" -#include "common/ieee802_11_defs.h" -#include "common/wpa_common.h" - -#include -#include - -#ifdef __NetBSD__ -#include -#else -#include -#endif -#include - -#ifdef __DragonFly__ -#include -#include -#else /* __DragonFly__ */ -#ifdef __GLIBC__ -#include -#endif /* __GLIBC__ */ -#include -#include -#include -#endif /* __DragonFly__ || __GLIBC__ */ -#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) -#include -#endif -#if __NetBSD__ -#include -#endif - -#include "l2_packet/l2_packet.h" - -struct bsd_driver_data { - struct hostapd_data *hapd; /* back pointer */ - - int sock; /* open socket for 802.11 ioctls */ - struct l2_packet_data *sock_xmit;/* raw packet xmit socket */ - int route; /* routing socket for events */ - char ifname[IFNAMSIZ+1]; /* interface name */ - unsigned int ifindex; /* interface index */ - void *ctx; - struct wpa_driver_capa capa; /* driver capability */ - int is_ap; /* Access point mode */ - int prev_roaming; /* roaming state to restore on deinit */ - int prev_privacy; /* privacy state to restore on deinit */ - int prev_wpa; /* wpa state to restore on deinit */ -}; - -/* Generic functions for hostapd and wpa_supplicant */ - -static int -bsd_set80211(void *priv, int op, int val, const void *arg, int arg_len) -{ - struct bsd_driver_data *drv = priv; - struct ieee80211req ireq; - - os_memset(&ireq, 0, sizeof(ireq)); - os_strlcpy(ireq.i_name, drv->ifname, sizeof(ireq.i_name)); - ireq.i_type = op; - ireq.i_val = val; - ireq.i_data = (void *) arg; - ireq.i_len = arg_len; - - if (ioctl(drv->sock, SIOCS80211, &ireq) < 0) { - wpa_printf(MSG_ERROR, "ioctl[SIOCS80211, op=%u, val=%u, " - "arg_len=%u]: %s", op, val, arg_len, - strerror(errno)); - return -1; - } - return 0; -} - -static int -bsd_get80211(void *priv, struct ieee80211req *ireq, int op, void *arg, - int arg_len) -{ - struct bsd_driver_data *drv = priv; - - os_memset(ireq, 0, sizeof(*ireq)); - os_strlcpy(ireq->i_name, drv->ifname, sizeof(ireq->i_name)); - ireq->i_type = op; - ireq->i_len = arg_len; - ireq->i_data = arg; - - if (ioctl(drv->sock, SIOCG80211, ireq) < 0) { - wpa_printf(MSG_ERROR, "ioctl[SIOCS80211, op=%u, " - "arg_len=%u]: %s", op, arg_len, strerror(errno)); - return -1; - } - return 0; -} - -static int -get80211var(struct bsd_driver_data *drv, int op, void *arg, int arg_len) -{ - struct ieee80211req ireq; - - if (bsd_get80211(drv, &ireq, op, arg, arg_len) < 0) - return -1; - return ireq.i_len; -} - -static int -set80211var(struct bsd_driver_data *drv, int op, const void *arg, int arg_len) -{ - return bsd_set80211(drv, op, 0, arg, arg_len); -} - -static int -set80211param(struct bsd_driver_data *drv, int op, int arg) -{ - return bsd_set80211(drv, op, arg, NULL, 0); -} - -static int -bsd_get_ssid(void *priv, u8 *ssid, int len) -{ - struct bsd_driver_data *drv = priv; -#ifdef SIOCG80211NWID - struct ieee80211_nwid nwid; - struct ifreq ifr; - - os_memset(&ifr, 0, sizeof(ifr)); - os_strlcpy(ifr.ifr_name, drv->ifname, sizeof(ifr.ifr_name)); - ifr.ifr_data = (void *)&nwid; - if (ioctl(drv->sock, SIOCG80211NWID, &ifr) < 0 || - nwid.i_len > IEEE80211_NWID_LEN) - return -1; - os_memcpy(ssid, nwid.i_nwid, nwid.i_len); - return nwid.i_len; -#else - return get80211var(drv, IEEE80211_IOC_SSID, ssid, IEEE80211_NWID_LEN); -#endif -} - -static int -bsd_set_ssid(void *priv, const u8 *ssid, int ssid_len) -{ - struct bsd_driver_data *drv = priv; -#ifdef SIOCS80211NWID - struct ieee80211_nwid nwid; - struct ifreq ifr; - - os_memcpy(nwid.i_nwid, ssid, ssid_len); - nwid.i_len = ssid_len; - os_memset(&ifr, 0, sizeof(ifr)); - os_strlcpy(ifr.ifr_name, drv->ifname, sizeof(ifr.ifr_name)); - ifr.ifr_data = (void *)&nwid; - return ioctl(drv->sock, SIOCS80211NWID, &ifr); -#else - return set80211var(drv, IEEE80211_IOC_SSID, ssid, ssid_len); -#endif -} - -static int -bsd_get_if_media(void *priv) -{ - struct bsd_driver_data *drv = priv; - struct ifmediareq ifmr; - - os_memset(&ifmr, 0, sizeof(ifmr)); - os_strlcpy(ifmr.ifm_name, drv->ifname, sizeof(ifmr.ifm_name)); - - if (ioctl(drv->sock, SIOCGIFMEDIA, &ifmr) < 0) { - wpa_printf(MSG_ERROR, "%s: SIOCGIFMEDIA %s", __func__, - strerror(errno)); - return -1; - } - - return ifmr.ifm_current; -} - -static int -bsd_set_if_media(void *priv, int media) -{ - struct bsd_driver_data *drv = priv; - struct ifreq ifr; - - os_memset(&ifr, 0, sizeof(ifr)); - os_strlcpy(ifr.ifr_name, drv->ifname, sizeof(ifr.ifr_name)); - ifr.ifr_media = media; - - if (ioctl(drv->sock, SIOCSIFMEDIA, &ifr) < 0) { - wpa_printf(MSG_ERROR, "%s: SIOCSIFMEDIA %s", __func__, - strerror(errno)); - return -1; - } - - return 0; -} - -static int -bsd_set_mediaopt(void *priv, uint32_t mask, uint32_t mode) -{ - int media = bsd_get_if_media(priv); - - if (media < 0) - return -1; - media &= ~mask; - media |= mode; - if (bsd_set_if_media(priv, media) < 0) - return -1; - return 0; -} - -static int -bsd_del_key(void *priv, const u8 *addr, int key_idx) -{ - struct ieee80211req_del_key wk; - - os_memset(&wk, 0, sizeof(wk)); - if (addr == NULL) { - wpa_printf(MSG_DEBUG, "%s: key_idx=%d", __func__, key_idx); - wk.idk_keyix = key_idx; - } else { - wpa_printf(MSG_DEBUG, "%s: addr=" MACSTR, __func__, - MAC2STR(addr)); - os_memcpy(wk.idk_macaddr, addr, IEEE80211_ADDR_LEN); - wk.idk_keyix = (u_int8_t) IEEE80211_KEYIX_NONE; /* XXX */ - } - - return set80211var(priv, IEEE80211_IOC_DELKEY, &wk, sizeof(wk)); -} - -static int -bsd_send_mlme_param(void *priv, const u8 op, const u16 reason, const u8 *addr) -{ - struct ieee80211req_mlme mlme; - - os_memset(&mlme, 0, sizeof(mlme)); - mlme.im_op = op; - mlme.im_reason = reason; - os_memcpy(mlme.im_macaddr, addr, IEEE80211_ADDR_LEN); - return set80211var(priv, IEEE80211_IOC_MLME, &mlme, sizeof(mlme)); -} - -static int -bsd_ctrl_iface(void *priv, int enable) -{ - struct bsd_driver_data *drv = priv; - struct ifreq ifr; - - os_memset(&ifr, 0, sizeof(ifr)); - os_strlcpy(ifr.ifr_name, drv->ifname, sizeof(ifr.ifr_name)); - - if (ioctl(drv->sock, SIOCGIFFLAGS, &ifr) < 0) { - perror("ioctl[SIOCGIFFLAGS]"); - return -1; - } - - if (enable) - ifr.ifr_flags |= IFF_UP; - else - ifr.ifr_flags &= ~IFF_UP; - - if (ioctl(drv->sock, SIOCSIFFLAGS, &ifr) < 0) { - perror("ioctl[SIOCSIFFLAGS]"); - return -1; - } - - return 0; -} - -static int -bsd_set_key(const char *ifname, void *priv, enum wpa_alg alg, - const unsigned char *addr, int key_idx, int set_tx, const u8 *seq, - size_t seq_len, const u8 *key, size_t key_len) -{ - struct ieee80211req_key wk; - - wpa_printf(MSG_DEBUG, "%s: alg=%d addr=%p key_idx=%d set_tx=%d " - "seq_len=%zu key_len=%zu", __func__, alg, addr, key_idx, - set_tx, seq_len, key_len); - - if (alg == WPA_ALG_NONE) { -#ifndef HOSTAPD - if (addr == NULL || is_broadcast_ether_addr(addr)) - return bsd_del_key(priv, NULL, key_idx); - else -#endif /* HOSTAPD */ - return bsd_del_key(priv, addr, key_idx); - } - - os_memset(&wk, 0, sizeof(wk)); - switch (alg) { - case WPA_ALG_WEP: - wk.ik_type = IEEE80211_CIPHER_WEP; - break; - case WPA_ALG_TKIP: - wk.ik_type = IEEE80211_CIPHER_TKIP; - break; - case WPA_ALG_CCMP: - wk.ik_type = IEEE80211_CIPHER_AES_CCM; - break; - default: - wpa_printf(MSG_ERROR, "%s: unknown alg=%d", __func__, alg); - return -1; - } - - wk.ik_flags = IEEE80211_KEY_RECV; - if (set_tx) - wk.ik_flags |= IEEE80211_KEY_XMIT; - - if (addr == NULL) { - os_memset(wk.ik_macaddr, 0xff, IEEE80211_ADDR_LEN); - wk.ik_keyix = key_idx; - } else { - os_memcpy(wk.ik_macaddr, addr, IEEE80211_ADDR_LEN); - /* - * Deduce whether group/global or unicast key by checking - * the address (yech). Note also that we can only mark global - * keys default; doing this for a unicast key is an error. - */ - if (is_broadcast_ether_addr(addr)) { - wk.ik_flags |= IEEE80211_KEY_GROUP; - wk.ik_keyix = key_idx; - } else { - wk.ik_keyix = key_idx == 0 ? IEEE80211_KEYIX_NONE : - key_idx; - } - } - if (wk.ik_keyix != IEEE80211_KEYIX_NONE && set_tx) - wk.ik_flags |= IEEE80211_KEY_DEFAULT; - wk.ik_keylen = key_len; - if (seq) - os_memcpy(&wk.ik_keyrsc, seq, seq_len); - os_memcpy(wk.ik_keydata, key, key_len); - - return set80211var(priv, IEEE80211_IOC_WPAKEY, &wk, sizeof(wk)); -} - -static int -bsd_configure_wpa(void *priv, struct wpa_bss_params *params) -{ -#ifndef IEEE80211_IOC_APPIE - static const char *ciphernames[] = - { "WEP", "TKIP", "AES-OCB", "AES-CCM", "CKIP", "NONE" }; - int v; - - switch (params->wpa_group) { - case WPA_CIPHER_CCMP: - v = IEEE80211_CIPHER_AES_CCM; - break; - case WPA_CIPHER_TKIP: - v = IEEE80211_CIPHER_TKIP; - break; - case WPA_CIPHER_WEP104: - v = IEEE80211_CIPHER_WEP; - break; - case WPA_CIPHER_WEP40: - v = IEEE80211_CIPHER_WEP; - break; - case WPA_CIPHER_NONE: - v = IEEE80211_CIPHER_NONE; - break; - default: - printf("Unknown group key cipher %u\n", - params->wpa_group); - return -1; - } - wpa_printf(MSG_DEBUG, "%s: group key cipher=%s (%u)", - __func__, ciphernames[v], v); - if (set80211param(priv, IEEE80211_IOC_MCASTCIPHER, v)) { - printf("Unable to set group key cipher to %u (%s)\n", - v, ciphernames[v]); - return -1; - } - if (v == IEEE80211_CIPHER_WEP) { - /* key length is done only for specific ciphers */ - v = (params->wpa_group == WPA_CIPHER_WEP104 ? 13 : 5); - if (set80211param(priv, IEEE80211_IOC_MCASTKEYLEN, v)) { - printf("Unable to set group key length to %u\n", v); - return -1; - } - } - - v = 0; - if (params->wpa_pairwise & WPA_CIPHER_CCMP) - v |= 1<wpa_pairwise & WPA_CIPHER_TKIP) - v |= 1<wpa_pairwise & WPA_CIPHER_NONE) - v |= 1<wpa_key_mgmt); - if (set80211param(priv, IEEE80211_IOC_KEYMGTALGS, - params->wpa_key_mgmt)) { - printf("Unable to set key management algorithms to 0x%x\n", - params->wpa_key_mgmt); - return -1; - } - - v = 0; - if (params->rsn_preauth) - v |= BIT(0); - wpa_printf(MSG_DEBUG, "%s: rsn capabilities=0x%x", - __func__, params->rsn_preauth); - if (set80211param(priv, IEEE80211_IOC_RSNCAPS, v)) { - printf("Unable to set RSN capabilities to 0x%x\n", v); - return -1; - } -#endif /* IEEE80211_IOC_APPIE */ - - wpa_printf(MSG_DEBUG, "%s: enable WPA= 0x%x", __func__, params->wpa); - if (set80211param(priv, IEEE80211_IOC_WPA, params->wpa)) { - printf("Unable to set WPA to %u\n", params->wpa); - return -1; - } - return 0; -} - -static int -bsd_set_ieee8021x(void *priv, struct wpa_bss_params *params) -{ - wpa_printf(MSG_DEBUG, "%s: enabled=%d", __func__, params->enabled); - - if (!params->enabled) { - /* XXX restore state */ - return set80211param(priv, IEEE80211_IOC_AUTHMODE, - IEEE80211_AUTH_AUTO); - } - if (!params->wpa && !params->ieee802_1x) { - wpa_printf(MSG_ERROR, "%s: No 802.1X or WPA enabled", - __func__); - return -1; - } - if (params->wpa && bsd_configure_wpa(priv, params) != 0) { - wpa_printf(MSG_ERROR, "%s: Failed to configure WPA state", - __func__); - return -1; - } - if (set80211param(priv, IEEE80211_IOC_AUTHMODE, - (params->wpa ? IEEE80211_AUTH_WPA : IEEE80211_AUTH_8021X))) { - wpa_printf(MSG_ERROR, "%s: Failed to enable WPA/802.1X", - __func__); - return -1; - } - return bsd_ctrl_iface(priv, 1); -} - -static int -bsd_set_sta_authorized(void *priv, const u8 *addr, - int total_flags, int flags_or, int flags_and) -{ - int authorized = -1; - - /* For now, only support setting Authorized flag */ - if (flags_or & WPA_STA_AUTHORIZED) - authorized = 1; - if (!(flags_and & WPA_STA_AUTHORIZED)) - authorized = 0; - - if (authorized < 0) - return 0; - - return bsd_send_mlme_param(priv, authorized ? - IEEE80211_MLME_AUTHORIZE : - IEEE80211_MLME_UNAUTHORIZE, 0, addr); -} - -static void -bsd_new_sta(void *priv, void *ctx, u8 addr[IEEE80211_ADDR_LEN]) -{ - struct ieee80211req_wpaie ie; - int ielen = 0; - u8 *iebuf = NULL; - - /* - * Fetch and validate any negotiated WPA/RSN parameters. - */ - memset(&ie, 0, sizeof(ie)); - memcpy(ie.wpa_macaddr, addr, IEEE80211_ADDR_LEN); - if (get80211var(priv, IEEE80211_IOC_WPAIE, &ie, sizeof(ie)) < 0) { - printf("Failed to get WPA/RSN information element.\n"); - goto no_ie; - } - iebuf = ie.wpa_ie; - ielen = ie.wpa_ie[1]; - if (ielen == 0) - iebuf = NULL; - else - ielen += 2; - -no_ie: - drv_event_assoc(ctx, addr, iebuf, ielen, 0); -} - -static int -bsd_send_eapol(void *priv, const u8 *addr, const u8 *data, size_t data_len, - int encrypt, const u8 *own_addr, u32 flags) -{ - struct bsd_driver_data *drv = priv; - - wpa_hexdump(MSG_MSGDUMP, "TX EAPOL", data, data_len); - - return l2_packet_send(drv->sock_xmit, addr, ETH_P_EAPOL, data, - data_len); -} - -static int -bsd_set_freq(void *priv, struct hostapd_freq_params *freq) -{ - struct bsd_driver_data *drv = priv; -#ifdef SIOCS80211CHANNEL - struct ieee80211chanreq creq; -#endif /* SIOCS80211CHANNEL */ - u32 mode; - int channel = freq->channel; - - if (channel < 14) { - mode = -#ifdef CONFIG_IEEE80211N - freq->ht_enabled ? IFM_IEEE80211_11NG : -#endif /* CONFIG_IEEE80211N */ - IFM_IEEE80211_11G; - } else if (channel == 14) { - mode = IFM_IEEE80211_11B; - } else { - mode = -#ifdef CONFIG_IEEE80211N - freq->ht_enabled ? IFM_IEEE80211_11NA : -#endif /* CONFIG_IEEE80211N */ - IFM_IEEE80211_11A; - } - if (bsd_set_mediaopt(drv, IFM_MMASK, mode) < 0) { - wpa_printf(MSG_ERROR, "%s: failed to set modulation mode", - __func__); - return -1; - } - -#ifdef SIOCS80211CHANNEL - os_memset(&creq, 0, sizeof(creq)); - os_strlcpy(creq.i_name, drv->ifname, sizeof(creq.i_name)); - creq.i_channel = (u_int16_t)channel; - return ioctl(drv->sock, SIOCS80211CHANNEL, &creq); -#else /* SIOCS80211CHANNEL */ - return set80211param(priv, IEEE80211_IOC_CHANNEL, channel); -#endif /* SIOCS80211CHANNEL */ -} - -static int -bsd_set_opt_ie(void *priv, const u8 *ie, size_t ie_len) -{ -#ifdef IEEE80211_IOC_APPIE - wpa_printf(MSG_DEBUG, "%s: set WPA+RSN ie (len %lu)", __func__, - (unsigned long)ie_len); - return bsd_set80211(priv, IEEE80211_IOC_APPIE, IEEE80211_APPIE_WPA, - ie, ie_len); -#endif /* IEEE80211_IOC_APPIE */ - return 0; -} - -static int -rtbuf_len(void) -{ - size_t len; - - int mib[6] = {CTL_NET, AF_ROUTE, 0, AF_INET, NET_RT_DUMP, 0}; - - if (sysctl(mib, 6, NULL, &len, NULL, 0) < 0) { - wpa_printf(MSG_WARNING, "%s failed: %s\n", __func__, - strerror(errno)); - len = 2048; - } - - return len; -} - -#ifdef HOSTAPD - -/* - * Avoid conflicts with hostapd definitions by undefining couple of defines - * from net80211 header files. - */ -#undef RSN_VERSION -#undef WPA_VERSION -#undef WPA_OUI_TYPE - -static int bsd_sta_deauth(void *priv, const u8 *own_addr, const u8 *addr, - int reason_code); - -static const char * -ether_sprintf(const u8 *addr) -{ - static char buf[sizeof(MACSTR)]; - - if (addr != NULL) - snprintf(buf, sizeof(buf), MACSTR, MAC2STR(addr)); - else - snprintf(buf, sizeof(buf), MACSTR, 0,0,0,0,0,0); - return buf; -} - -static int -bsd_set_privacy(void *priv, int enabled) -{ - wpa_printf(MSG_DEBUG, "%s: enabled=%d", __func__, enabled); - - return set80211param(priv, IEEE80211_IOC_PRIVACY, enabled); -} - -static int -bsd_get_seqnum(const char *ifname, void *priv, const u8 *addr, int idx, - u8 *seq) -{ - struct ieee80211req_key wk; - - wpa_printf(MSG_DEBUG, "%s: addr=%s idx=%d", - __func__, ether_sprintf(addr), idx); - - memset(&wk, 0, sizeof(wk)); - if (addr == NULL) - memset(wk.ik_macaddr, 0xff, IEEE80211_ADDR_LEN); - else - memcpy(wk.ik_macaddr, addr, IEEE80211_ADDR_LEN); - wk.ik_keyix = idx; - - if (get80211var(priv, IEEE80211_IOC_WPAKEY, &wk, sizeof(wk)) < 0) { - printf("Failed to get encryption.\n"); - return -1; - } - -#ifdef WORDS_BIGENDIAN - { - /* - * wk.ik_keytsc is in host byte order (big endian), need to - * swap it to match with the byte order used in WPA. - */ - int i; - u8 tmp[WPA_KEY_RSC_LEN]; - memcpy(tmp, &wk.ik_keytsc, sizeof(wk.ik_keytsc)); - for (i = 0; i < WPA_KEY_RSC_LEN; i++) { - seq[i] = tmp[WPA_KEY_RSC_LEN - i - 1]; - } - } -#else /* WORDS_BIGENDIAN */ - memcpy(seq, &wk.ik_keytsc, sizeof(wk.ik_keytsc)); -#endif /* WORDS_BIGENDIAN */ - return 0; -} - - -static int -bsd_flush(void *priv) -{ - u8 allsta[IEEE80211_ADDR_LEN]; - - memset(allsta, 0xff, IEEE80211_ADDR_LEN); - return bsd_sta_deauth(priv, NULL, allsta, IEEE80211_REASON_AUTH_LEAVE); -} - - -static int -bsd_read_sta_driver_data(void *priv, struct hostap_sta_driver_data *data, - const u8 *addr) -{ - struct ieee80211req_sta_stats stats; - - memcpy(stats.is_u.macaddr, addr, IEEE80211_ADDR_LEN); - if (get80211var(priv, IEEE80211_IOC_STA_STATS, &stats, sizeof(stats)) - > 0) { - /* XXX? do packets counts include non-data frames? */ - data->rx_packets = stats.is_stats.ns_rx_data; - data->rx_bytes = stats.is_stats.ns_rx_bytes; - data->tx_packets = stats.is_stats.ns_tx_data; - data->tx_bytes = stats.is_stats.ns_tx_bytes; - } - return 0; -} - -static int -bsd_sta_deauth(void *priv, const u8 *own_addr, const u8 *addr, int reason_code) -{ - return bsd_send_mlme_param(priv, IEEE80211_MLME_DEAUTH, reason_code, - addr); -} - -static int -bsd_sta_disassoc(void *priv, const u8 *own_addr, const u8 *addr, - int reason_code) -{ - return bsd_send_mlme_param(priv, IEEE80211_MLME_DISASSOC, reason_code, - addr); -} - -static void -bsd_wireless_event_receive(int sock, void *ctx, void *sock_ctx) -{ - struct bsd_driver_data *drv = ctx; - char *buf; - struct if_announcemsghdr *ifan; - struct rt_msghdr *rtm; - struct ieee80211_michael_event *mic; - struct ieee80211_join_event *join; - struct ieee80211_leave_event *leave; - int n, len; - union wpa_event_data data; - - len = rtbuf_len(); - - buf = os_malloc(len); - if (buf == NULL) { - wpa_printf(MSG_ERROR, "%s os_malloc() failed\n", __func__); - return; - } - - n = read(sock, buf, len); - if (n < 0) { - if (errno != EINTR && errno != EAGAIN) - wpa_printf(MSG_ERROR, "%s read() failed: %s\n", - __func__, strerror(errno)); - os_free(buf); - return; - } - - rtm = (struct rt_msghdr *) buf; - if (rtm->rtm_version != RTM_VERSION) { - wpa_printf(MSG_DEBUG, "Invalid routing message version=%d", - rtm->rtm_version); - os_free(buf); - return; - } - ifan = (struct if_announcemsghdr *) rtm; - switch (rtm->rtm_type) { - case RTM_IEEE80211: - switch (ifan->ifan_what) { - case RTM_IEEE80211_ASSOC: - case RTM_IEEE80211_REASSOC: - case RTM_IEEE80211_DISASSOC: - case RTM_IEEE80211_SCAN: - break; - case RTM_IEEE80211_LEAVE: - leave = (struct ieee80211_leave_event *) &ifan[1]; - drv_event_disassoc(drv->hapd, leave->iev_addr); - break; - case RTM_IEEE80211_JOIN: -#ifdef RTM_IEEE80211_REJOIN - case RTM_IEEE80211_REJOIN: -#endif - join = (struct ieee80211_join_event *) &ifan[1]; - bsd_new_sta(drv, drv->hapd, join->iev_addr); - break; - case RTM_IEEE80211_REPLAY: - /* ignore */ - break; - case RTM_IEEE80211_MICHAEL: - mic = (struct ieee80211_michael_event *) &ifan[1]; - wpa_printf(MSG_DEBUG, - "Michael MIC failure wireless event: " - "keyix=%u src_addr=" MACSTR, mic->iev_keyix, - MAC2STR(mic->iev_src)); - os_memset(&data, 0, sizeof(data)); - data.michael_mic_failure.unicast = 1; - data.michael_mic_failure.src = mic->iev_src; - wpa_supplicant_event(drv->hapd, - EVENT_MICHAEL_MIC_FAILURE, &data); - break; - } - break; - } - os_free(buf); -} - -static void -handle_read(void *ctx, const u8 *src_addr, const u8 *buf, size_t len) -{ - struct bsd_driver_data *drv = ctx; - drv_event_eapol_rx(drv->hapd, src_addr, buf, len); -} - -static void * -bsd_init(struct hostapd_data *hapd, struct wpa_init_params *params) -{ - struct bsd_driver_data *drv; - - drv = os_zalloc(sizeof(struct bsd_driver_data)); - if (drv == NULL) { - printf("Could not allocate memory for bsd driver data\n"); - goto bad; - } - - drv->hapd = hapd; - drv->sock = socket(PF_INET, SOCK_DGRAM, 0); - if (drv->sock < 0) { - perror("socket[PF_INET,SOCK_DGRAM]"); - goto bad; - } - os_strlcpy(drv->ifname, params->ifname, sizeof(drv->ifname)); - - drv->sock_xmit = l2_packet_init(drv->ifname, NULL, ETH_P_EAPOL, - handle_read, drv, 0); - if (drv->sock_xmit == NULL) - goto bad; - if (l2_packet_get_own_addr(drv->sock_xmit, params->own_addr)) - goto bad; - - /* mark down during setup */ - if (bsd_ctrl_iface(drv, 0) < 0) - goto bad; - - drv->route = socket(PF_ROUTE, SOCK_RAW, 0); - if (drv->route < 0) { - perror("socket(PF_ROUTE,SOCK_RAW)"); - goto bad; - } - eloop_register_read_sock(drv->route, bsd_wireless_event_receive, drv, - NULL); - - if (bsd_set_mediaopt(drv, IFM_OMASK, IFM_IEEE80211_HOSTAP) < 0) { - wpa_printf(MSG_ERROR, "%s: failed to set operation mode", - __func__); - goto bad; - } - - return drv; -bad: - if (drv->sock_xmit != NULL) - l2_packet_deinit(drv->sock_xmit); - if (drv->sock >= 0) - close(drv->sock); - if (drv != NULL) - os_free(drv); - return NULL; -} - - -static void -bsd_deinit(void *priv) -{ - struct bsd_driver_data *drv = priv; - - if (drv->route >= 0) { - eloop_unregister_read_sock(drv->route); - close(drv->route); - } - bsd_ctrl_iface(drv, 0); - if (drv->sock >= 0) - close(drv->sock); - if (drv->sock_xmit != NULL) - l2_packet_deinit(drv->sock_xmit); - os_free(drv); -} - -#else /* HOSTAPD */ - -static int -get80211param(struct bsd_driver_data *drv, int op) -{ - struct ieee80211req ireq; - - if (bsd_get80211(drv, &ireq, op, NULL, 0) < 0) - return -1; - return ireq.i_val; -} - -static int -wpa_driver_bsd_get_bssid(void *priv, u8 *bssid) -{ - struct bsd_driver_data *drv = priv; -#ifdef SIOCG80211BSSID - struct ieee80211_bssid bs; - - os_strlcpy(bs.i_name, drv->ifname, sizeof(bs.i_name)); - if (ioctl(drv->sock, SIOCG80211BSSID, &bs) < 0) - return -1; - os_memcpy(bssid, bs.i_bssid, sizeof(bs.i_bssid)); - return 0; -#else - return get80211var(drv, IEEE80211_IOC_BSSID, - bssid, IEEE80211_ADDR_LEN) < 0 ? -1 : 0; -#endif -} - -static int -wpa_driver_bsd_get_ssid(void *priv, u8 *ssid) -{ - struct bsd_driver_data *drv = priv; - return bsd_get_ssid(drv, ssid, 0); -} - -static int -wpa_driver_bsd_set_wpa_ie(struct bsd_driver_data *drv, const u8 *wpa_ie, - size_t wpa_ie_len) -{ -#ifdef IEEE80211_IOC_APPIE - return bsd_set_opt_ie(drv, wpa_ie, wpa_ie_len); -#else /* IEEE80211_IOC_APPIE */ - return set80211var(drv, IEEE80211_IOC_OPTIE, wpa_ie, wpa_ie_len); -#endif /* IEEE80211_IOC_APPIE */ -} - -static int -wpa_driver_bsd_set_wpa_internal(void *priv, int wpa, int privacy) -{ - int ret = 0; - - wpa_printf(MSG_DEBUG, "%s: wpa=%d privacy=%d", - __FUNCTION__, wpa, privacy); - - if (!wpa && wpa_driver_bsd_set_wpa_ie(priv, NULL, 0) < 0) - ret = -1; - if (set80211param(priv, IEEE80211_IOC_PRIVACY, privacy) < 0) - ret = -1; - if (set80211param(priv, IEEE80211_IOC_WPA, wpa) < 0) - ret = -1; - - return ret; -} - -static int -wpa_driver_bsd_set_wpa(void *priv, int enabled) -{ - wpa_printf(MSG_DEBUG, "%s: enabled=%d", __FUNCTION__, enabled); - - return wpa_driver_bsd_set_wpa_internal(priv, enabled ? 3 : 0, enabled); -} - -static int -wpa_driver_bsd_set_countermeasures(void *priv, int enabled) -{ - wpa_printf(MSG_DEBUG, "%s: enabled=%d", __func__, enabled); - return set80211param(priv, IEEE80211_IOC_COUNTERMEASURES, enabled); -} - - -static int -wpa_driver_bsd_set_drop_unencrypted(void *priv, int enabled) -{ - wpa_printf(MSG_DEBUG, "%s: enabled=%d", __func__, enabled); - return set80211param(priv, IEEE80211_IOC_DROPUNENCRYPTED, enabled); -} - -static int -wpa_driver_bsd_deauthenticate(void *priv, const u8 *addr, int reason_code) -{ - return bsd_send_mlme_param(priv, IEEE80211_MLME_DEAUTH, reason_code, - addr); -} - -static int -wpa_driver_bsd_disassociate(void *priv, const u8 *addr, int reason_code) -{ - return bsd_send_mlme_param(priv, IEEE80211_MLME_DISASSOC, reason_code, - addr); -} - -static int -wpa_driver_bsd_set_auth_alg(void *priv, int auth_alg) -{ - int authmode; - - if ((auth_alg & WPA_AUTH_ALG_OPEN) && - (auth_alg & WPA_AUTH_ALG_SHARED)) - authmode = IEEE80211_AUTH_AUTO; - else if (auth_alg & WPA_AUTH_ALG_SHARED) - authmode = IEEE80211_AUTH_SHARED; - else - authmode = IEEE80211_AUTH_OPEN; - - return set80211param(priv, IEEE80211_IOC_AUTHMODE, authmode); -} - -static void -handle_read(void *ctx, const u8 *src_addr, const u8 *buf, size_t len) -{ - struct bsd_driver_data *drv = ctx; - - drv_event_eapol_rx(drv->ctx, src_addr, buf, len); -} - -static int -wpa_driver_bsd_associate(void *priv, struct wpa_driver_associate_params *params) -{ - struct bsd_driver_data *drv = priv; - struct ieee80211req_mlme mlme; - u32 mode; - int privacy; - int ret = 0; - - wpa_printf(MSG_DEBUG, - "%s: ssid '%.*s' wpa ie len %u pairwise %u group %u key mgmt %u" - , __func__ - , (unsigned int) params->ssid_len, params->ssid - , (unsigned int) params->wpa_ie_len - , params->pairwise_suite - , params->group_suite - , params->key_mgmt_suite - ); - - switch (params->mode) { - case IEEE80211_MODE_INFRA: - mode = 0 /* STA */; - break; - case IEEE80211_MODE_IBSS: - mode = IFM_IEEE80211_IBSS; - break; - case IEEE80211_MODE_AP: - mode = IFM_IEEE80211_HOSTAP; - break; - default: - wpa_printf(MSG_ERROR, "%s: unknown operation mode", __func__); - return -1; - } - if (bsd_set_mediaopt(drv, IFM_OMASK, mode) < 0) { - wpa_printf(MSG_ERROR, "%s: failed to set operation mode", - __func__); - return -1; - } - - if (params->mode == IEEE80211_MODE_AP) { - drv->sock_xmit = l2_packet_init(drv->ifname, NULL, ETH_P_EAPOL, - handle_read, drv, 0); - if (drv->sock_xmit == NULL) - return -1; - drv->is_ap = 1; - return 0; - } - - if (wpa_driver_bsd_set_drop_unencrypted(drv, params->drop_unencrypted) - < 0) - ret = -1; - if (wpa_driver_bsd_set_auth_alg(drv, params->auth_alg) < 0) - ret = -1; - /* XXX error handling is wrong but unclear what to do... */ - if (wpa_driver_bsd_set_wpa_ie(drv, params->wpa_ie, params->wpa_ie_len) < 0) - return -1; - - privacy = !(params->pairwise_suite == CIPHER_NONE && - params->group_suite == CIPHER_NONE && - params->key_mgmt_suite == KEY_MGMT_NONE && - params->wpa_ie_len == 0); - wpa_printf(MSG_DEBUG, "%s: set PRIVACY %u", __func__, privacy); - - if (set80211param(drv, IEEE80211_IOC_PRIVACY, privacy) < 0) - return -1; - - if (params->wpa_ie_len && - set80211param(drv, IEEE80211_IOC_WPA, - params->wpa_ie[0] == WLAN_EID_RSN ? 2 : 1) < 0) - return -1; - - os_memset(&mlme, 0, sizeof(mlme)); - mlme.im_op = IEEE80211_MLME_ASSOC; - if (params->ssid != NULL) - os_memcpy(mlme.im_ssid, params->ssid, params->ssid_len); - mlme.im_ssid_len = params->ssid_len; - if (params->bssid != NULL) - os_memcpy(mlme.im_macaddr, params->bssid, IEEE80211_ADDR_LEN); - if (set80211var(drv, IEEE80211_IOC_MLME, &mlme, sizeof(mlme)) < 0) - return -1; - return ret; -} - -static int -wpa_driver_bsd_scan(void *priv, struct wpa_driver_scan_params *params) -{ - struct bsd_driver_data *drv = priv; -#ifdef IEEE80211_IOC_SCAN_MAX_SSID - struct ieee80211_scan_req sr; - int i; -#endif /* IEEE80211_IOC_SCAN_MAX_SSID */ - - if (bsd_set_mediaopt(drv, IFM_OMASK, 0 /* STA */) < 0) { - wpa_printf(MSG_ERROR, "%s: failed to set operation mode", - __func__); - return -1; - } - - if (set80211param(drv, IEEE80211_IOC_ROAMING, - IEEE80211_ROAMING_MANUAL) < 0) { - wpa_printf(MSG_ERROR, "%s: failed to set " - "wpa_supplicant-based roaming: %s", __func__, - strerror(errno)); - return -1; - } - - if (wpa_driver_bsd_set_wpa(drv, 1) < 0) { - wpa_printf(MSG_ERROR, "%s: failed to set wpa: %s", __func__, - strerror(errno)); - return -1; - } - - /* NB: interface must be marked UP to do a scan */ - if (bsd_ctrl_iface(drv, 1) < 0) - return -1; - -#ifdef IEEE80211_IOC_SCAN_MAX_SSID - os_memset(&sr, 0, sizeof(sr)); - sr.sr_flags = IEEE80211_IOC_SCAN_ACTIVE | IEEE80211_IOC_SCAN_ONCE | - IEEE80211_IOC_SCAN_NOJOIN; - sr.sr_duration = IEEE80211_IOC_SCAN_FOREVER; - if (params->num_ssids > 0) { - sr.sr_nssid = params->num_ssids; -#if 0 - /* Boundary check is done by upper layer */ - if (sr.sr_nssid > IEEE80211_IOC_SCAN_MAX_SSID) - sr.sr_nssid = IEEE80211_IOC_SCAN_MAX_SSID; -#endif - - /* NB: check scan cache first */ - sr.sr_flags |= IEEE80211_IOC_SCAN_CHECK; - } - for (i = 0; i < sr.sr_nssid; i++) { - sr.sr_ssid[i].len = params->ssids[i].ssid_len; - os_memcpy(sr.sr_ssid[i].ssid, params->ssids[i].ssid, - sr.sr_ssid[i].len); - } - - /* NB: net80211 delivers a scan complete event so no need to poll */ - return set80211var(drv, IEEE80211_IOC_SCAN_REQ, &sr, sizeof(sr)); -#else /* IEEE80211_IOC_SCAN_MAX_SSID */ - /* set desired ssid before scan */ - if (bsd_set_ssid(drv, params->ssids[0].ssid, - params->ssids[0].ssid_len) < 0) - return -1; - - /* NB: net80211 delivers a scan complete event so no need to poll */ - return set80211param(drv, IEEE80211_IOC_SCAN_REQ, 0); -#endif /* IEEE80211_IOC_SCAN_MAX_SSID */ -} - -static void -wpa_driver_bsd_event_receive(int sock, void *ctx, void *sock_ctx) -{ - struct bsd_driver_data *drv = sock_ctx; - char *buf; - struct if_announcemsghdr *ifan; - struct if_msghdr *ifm; - struct rt_msghdr *rtm; - union wpa_event_data event; - struct ieee80211_michael_event *mic; - struct ieee80211_leave_event *leave; - struct ieee80211_join_event *join; - int n, len; - - len = rtbuf_len(); - - buf = os_malloc(len); - if (buf == NULL) { - wpa_printf(MSG_ERROR, "%s os_malloc() failed\n", __func__); - return; - } - - n = read(sock, buf, len); - if (n < 0) { - if (errno != EINTR && errno != EAGAIN) - wpa_printf(MSG_ERROR, "%s read() failed: %s\n", - __func__, strerror(errno)); - os_free(buf); - return; - } - - rtm = (struct rt_msghdr *) buf; - if (rtm->rtm_version != RTM_VERSION) { - wpa_printf(MSG_DEBUG, "Invalid routing message version=%d", - rtm->rtm_version); - os_free(buf); - return; - } - os_memset(&event, 0, sizeof(event)); - switch (rtm->rtm_type) { - case RTM_IFANNOUNCE: - ifan = (struct if_announcemsghdr *) rtm; - if (ifan->ifan_index != drv->ifindex) - break; - os_strlcpy(event.interface_status.ifname, drv->ifname, - sizeof(event.interface_status.ifname)); - switch (ifan->ifan_what) { - case IFAN_DEPARTURE: - event.interface_status.ievent = EVENT_INTERFACE_REMOVED; - default: - os_free(buf); - return; - } - wpa_printf(MSG_DEBUG, "RTM_IFANNOUNCE: Interface '%s' %s", - event.interface_status.ifname, - ifan->ifan_what == IFAN_DEPARTURE ? - "removed" : "added"); - wpa_supplicant_event(ctx, EVENT_INTERFACE_STATUS, &event); - break; - case RTM_IEEE80211: - ifan = (struct if_announcemsghdr *) rtm; - if (ifan->ifan_index != drv->ifindex) - break; - switch (ifan->ifan_what) { - case RTM_IEEE80211_ASSOC: - case RTM_IEEE80211_REASSOC: - if (drv->is_ap) - break; - wpa_supplicant_event(ctx, EVENT_ASSOC, NULL); - break; - case RTM_IEEE80211_DISASSOC: - if (drv->is_ap) - break; - wpa_supplicant_event(ctx, EVENT_DISASSOC, NULL); - break; - case RTM_IEEE80211_SCAN: - if (drv->is_ap) - break; - wpa_supplicant_event(ctx, EVENT_SCAN_RESULTS, NULL); - break; - case RTM_IEEE80211_LEAVE: - leave = (struct ieee80211_leave_event *) &ifan[1]; - drv_event_disassoc(ctx, leave->iev_addr); - break; - case RTM_IEEE80211_JOIN: -#ifdef RTM_IEEE80211_REJOIN - case RTM_IEEE80211_REJOIN: -#endif - join = (struct ieee80211_join_event *) &ifan[1]; - bsd_new_sta(drv, ctx, join->iev_addr); - break; - case RTM_IEEE80211_REPLAY: - /* ignore */ - break; - case RTM_IEEE80211_MICHAEL: - mic = (struct ieee80211_michael_event *) &ifan[1]; - wpa_printf(MSG_DEBUG, - "Michael MIC failure wireless event: " - "keyix=%u src_addr=" MACSTR, mic->iev_keyix, - MAC2STR(mic->iev_src)); - - os_memset(&event, 0, sizeof(event)); - event.michael_mic_failure.unicast = - !IEEE80211_IS_MULTICAST(mic->iev_dst); - wpa_supplicant_event(ctx, EVENT_MICHAEL_MIC_FAILURE, - &event); - break; - } - break; - case RTM_IFINFO: - ifm = (struct if_msghdr *) rtm; - if (ifm->ifm_index != drv->ifindex) - break; - if ((rtm->rtm_flags & RTF_UP) == 0) { - os_strlcpy(event.interface_status.ifname, drv->ifname, - sizeof(event.interface_status.ifname)); - event.interface_status.ievent = EVENT_INTERFACE_REMOVED; - wpa_printf(MSG_DEBUG, "RTM_IFINFO: Interface '%s' DOWN", - event.interface_status.ifname); - wpa_supplicant_event(ctx, EVENT_INTERFACE_STATUS, &event); - } - break; - } - os_free(buf); -} - -static void -wpa_driver_bsd_add_scan_entry(struct wpa_scan_results *res, - struct ieee80211req_scan_result *sr) -{ - struct wpa_scan_res *result, **tmp; - size_t extra_len; - u8 *pos; - - extra_len = 2 + sr->isr_ssid_len; - extra_len += 2 + sr->isr_nrates; - extra_len += 3; /* ERP IE */ - extra_len += sr->isr_ie_len; - - result = os_zalloc(sizeof(*result) + extra_len); - if (result == NULL) - return; - os_memcpy(result->bssid, sr->isr_bssid, ETH_ALEN); - result->freq = sr->isr_freq; - result->beacon_int = sr->isr_intval; - result->caps = sr->isr_capinfo; - result->qual = sr->isr_rssi; - result->noise = sr->isr_noise; - - pos = (u8 *)(result + 1); - - *pos++ = WLAN_EID_SSID; - *pos++ = sr->isr_ssid_len; - os_memcpy(pos, sr + 1, sr->isr_ssid_len); - pos += sr->isr_ssid_len; - - /* - * Deal all rates as supported rate. - * Because net80211 doesn't report extended supported rate or not. - */ - *pos++ = WLAN_EID_SUPP_RATES; - *pos++ = sr->isr_nrates; - os_memcpy(pos, sr->isr_rates, sr->isr_nrates); - pos += sr->isr_nrates; - - *pos++ = WLAN_EID_ERP_INFO; - *pos++ = 1; - *pos++ = sr->isr_erp; - - os_memcpy(pos, (u8 *)(sr + 1) + sr->isr_ssid_len, sr->isr_ie_len); - pos += sr->isr_ie_len; - - result->ie_len = pos - (u8 *)(result + 1); - - tmp = os_realloc(res->res, - (res->num + 1) * sizeof(struct wpa_scan_res *)); - if (tmp == NULL) { - os_free(result); - return; - } - tmp[res->num++] = result; - res->res = tmp; -} - -struct wpa_scan_results * -wpa_driver_bsd_get_scan_results2(void *priv) -{ - struct ieee80211req_scan_result *sr; - struct wpa_scan_results *res; - int len, rest; - uint8_t buf[24*1024], *pos; - - len = get80211var(priv, IEEE80211_IOC_SCAN_RESULTS, buf, 24*1024); - if (len < 0) - return NULL; - - res = os_zalloc(sizeof(*res)); - if (res == NULL) - return NULL; - - pos = buf; - rest = len; - while (rest >= sizeof(struct ieee80211req_scan_result)) { - sr = (struct ieee80211req_scan_result *)pos; - wpa_driver_bsd_add_scan_entry(res, sr); - pos += sr->isr_len; - rest -= sr->isr_len; - } - - wpa_printf(MSG_DEBUG, "Received %d bytes of scan results (%lu BSSes)", - len, (unsigned long)res->num); - - return res; -} - -static int wpa_driver_bsd_capa(struct bsd_driver_data *drv) -{ -#ifdef IEEE80211_IOC_DEVCAPS -/* kernel definitions copied from net80211/ieee80211_var.h */ -#define IEEE80211_CIPHER_WEP 0 -#define IEEE80211_CIPHER_TKIP 1 -#define IEEE80211_CIPHER_AES_CCM 3 -#define IEEE80211_CRYPTO_WEP (1<capa.key_mgmt = WPA_DRIVER_CAPA_KEY_MGMT_WPA | - WPA_DRIVER_CAPA_KEY_MGMT_WPA_PSK; - if (devcaps.dc_drivercaps & IEEE80211_C_WPA2) - drv->capa.key_mgmt = WPA_DRIVER_CAPA_KEY_MGMT_WPA2 | - WPA_DRIVER_CAPA_KEY_MGMT_WPA2_PSK; - - if (devcaps.dc_cryptocaps & IEEE80211_CRYPTO_WEP) - drv->capa.enc |= WPA_DRIVER_CAPA_ENC_WEP40 | - WPA_DRIVER_CAPA_ENC_WEP104; - if (devcaps.dc_cryptocaps & IEEE80211_CRYPTO_TKIP) - drv->capa.enc |= WPA_DRIVER_CAPA_ENC_TKIP; - if (devcaps.dc_cryptocaps & IEEE80211_CRYPTO_AES_CCM) - drv->capa.enc |= WPA_DRIVER_CAPA_ENC_CCMP; - - if (devcaps.dc_drivercaps & IEEE80211_C_HOSTAP) - drv->capa.flags |= WPA_DRIVER_FLAGS_AP; -#undef IEEE80211_CIPHER_WEP -#undef IEEE80211_CIPHER_TKIP -#undef IEEE80211_CIPHER_AES_CCM -#undef IEEE80211_CRYPTO_WEP -#undef IEEE80211_CRYPTO_TKIP -#undef IEEE80211_CRYPTO_AES_CCM -#undef IEEE80211_C_HOSTAP -#undef IEEE80211_C_WPA1 -#undef IEEE80211_C_WPA2 -#else /* IEEE80211_IOC_DEVCAPS */ - /* For now, assume TKIP, CCMP, WPA, WPA2 are supported */ - drv->capa.key_mgmt = WPA_DRIVER_CAPA_KEY_MGMT_WPA | - WPA_DRIVER_CAPA_KEY_MGMT_WPA_PSK | - WPA_DRIVER_CAPA_KEY_MGMT_WPA2 | - WPA_DRIVER_CAPA_KEY_MGMT_WPA2_PSK; - drv->capa.enc = WPA_DRIVER_CAPA_ENC_WEP40 | - WPA_DRIVER_CAPA_ENC_WEP104 | - WPA_DRIVER_CAPA_ENC_TKIP | - WPA_DRIVER_CAPA_ENC_CCMP; - drv->capa.flags |= WPA_DRIVER_FLAGS_AP; -#endif /* IEEE80211_IOC_DEVCAPS */ -#ifdef IEEE80211_IOC_SCAN_MAX_SSID - drv->capa.max_scan_ssids = IEEE80211_IOC_SCAN_MAX_SSID; -#else /* IEEE80211_IOC_SCAN_MAX_SSID */ - drv->capa.max_scan_ssids = 1; -#endif /* IEEE80211_IOC_SCAN_MAX_SSID */ - drv->capa.auth = WPA_DRIVER_AUTH_OPEN | - WPA_DRIVER_AUTH_SHARED | - WPA_DRIVER_AUTH_LEAP; - return 0; -} - -static void * -wpa_driver_bsd_init(void *ctx, const char *ifname) -{ -#define GETPARAM(drv, param, v) \ - (((v) = get80211param(drv, param)) != -1) - struct bsd_driver_data *drv; - - drv = os_zalloc(sizeof(*drv)); - if (drv == NULL) - return NULL; - /* - * NB: We require the interface name be mappable to an index. - * This implies we do not support having wpa_supplicant - * wait for an interface to appear. This seems ok; that - * doesn't belong here; it's really the job of devd. - */ - drv->ifindex = if_nametoindex(ifname); - if (drv->ifindex == 0) { - wpa_printf(MSG_DEBUG, "%s: interface %s does not exist", - __func__, ifname); - goto fail1; - } - drv->sock = socket(PF_INET, SOCK_DGRAM, 0); - if (drv->sock < 0) - goto fail1; - drv->route = socket(PF_ROUTE, SOCK_RAW, 0); - if (drv->route < 0) - goto fail; - eloop_register_read_sock(drv->route, - wpa_driver_bsd_event_receive, ctx, drv); - - drv->ctx = ctx; - os_strlcpy(drv->ifname, ifname, sizeof(drv->ifname)); - - /* Down interface during setup. */ - if (bsd_ctrl_iface(drv, 0) < 0) - goto fail; - - if (!GETPARAM(drv, IEEE80211_IOC_ROAMING, drv->prev_roaming)) { - wpa_printf(MSG_DEBUG, "%s: failed to get roaming state: %s", - __func__, strerror(errno)); - goto fail; - } - if (!GETPARAM(drv, IEEE80211_IOC_PRIVACY, drv->prev_privacy)) { - wpa_printf(MSG_DEBUG, "%s: failed to get privacy state: %s", - __func__, strerror(errno)); - goto fail; - } - if (!GETPARAM(drv, IEEE80211_IOC_WPA, drv->prev_wpa)) { - wpa_printf(MSG_DEBUG, "%s: failed to get wpa state: %s", - __func__, strerror(errno)); - goto fail; - } - - if (wpa_driver_bsd_capa(drv)) - goto fail; - - return drv; -fail: - close(drv->sock); -fail1: - os_free(drv); - return NULL; -#undef GETPARAM -} - -static void -wpa_driver_bsd_deinit(void *priv) -{ - struct bsd_driver_data *drv = priv; - - wpa_driver_bsd_set_wpa(drv, 0); - eloop_unregister_read_sock(drv->route); - - /* NB: mark interface down */ - bsd_ctrl_iface(drv, 0); - - wpa_driver_bsd_set_wpa_internal(drv, drv->prev_wpa, drv->prev_privacy); - if (set80211param(drv, IEEE80211_IOC_ROAMING, drv->prev_roaming) < 0) - wpa_printf(MSG_DEBUG, "%s: failed to restore roaming state", - __func__); - - if (drv->sock_xmit != NULL) - l2_packet_deinit(drv->sock_xmit); - (void) close(drv->route); /* ioctl socket */ - (void) close(drv->sock); /* event socket */ - os_free(drv); -} - -static int -wpa_driver_bsd_get_capa(void *priv, struct wpa_driver_capa *capa) -{ - struct bsd_driver_data *drv = priv; - - os_memcpy(capa, &drv->capa, sizeof(*capa)); - return 0; -} -#endif /* HOSTAPD */ - - -const struct wpa_driver_ops wpa_driver_bsd_ops = { - .name = "bsd", - .desc = "BSD 802.11 support", -#ifdef HOSTAPD - .hapd_init = bsd_init, - .hapd_deinit = bsd_deinit, - .set_privacy = bsd_set_privacy, - .get_seqnum = bsd_get_seqnum, - .flush = bsd_flush, - .read_sta_data = bsd_read_sta_driver_data, - .sta_disassoc = bsd_sta_disassoc, - .sta_deauth = bsd_sta_deauth, -#else /* HOSTAPD */ - .init = wpa_driver_bsd_init, - .deinit = wpa_driver_bsd_deinit, - .get_bssid = wpa_driver_bsd_get_bssid, - .get_ssid = wpa_driver_bsd_get_ssid, - .set_countermeasures = wpa_driver_bsd_set_countermeasures, - .scan2 = wpa_driver_bsd_scan, - .get_scan_results2 = wpa_driver_bsd_get_scan_results2, - .deauthenticate = wpa_driver_bsd_deauthenticate, - .disassociate = wpa_driver_bsd_disassociate, - .associate = wpa_driver_bsd_associate, - .get_capa = wpa_driver_bsd_get_capa, -#endif /* HOSTAPD */ - .set_freq = bsd_set_freq, - .set_key = bsd_set_key, - .set_ieee8021x = bsd_set_ieee8021x, - .hapd_set_ssid = bsd_set_ssid, - .hapd_get_ssid = bsd_get_ssid, - .hapd_send_eapol = bsd_send_eapol, - .sta_set_flags = bsd_set_sta_authorized, - .set_generic_elem = bsd_set_opt_ie, -}; diff --git a/hostapd-0.8/src/drivers/driver_hostap.c b/hostapd-0.8/src/drivers/driver_hostap.c deleted file mode 100644 index e855c1b..0000000 --- a/hostapd-0.8/src/drivers/driver_hostap.c +++ /dev/null @@ -1,1648 +0,0 @@ -/* - * Driver interaction with Linux Host AP driver - * Copyright (c) 2003-2005, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#include "includes.h" -#include - -#include "wireless_copy.h" -#include "common.h" -#include "driver.h" -#include "driver_wext.h" -#include "eloop.h" -#include "driver_hostap.h" - - -#ifdef HOSTAPD - -#include -#include - -#include "priv_netlink.h" -#include "netlink.h" -#include "linux_ioctl.h" -#include "common/ieee802_11_defs.h" - - -/* MTU to be set for the wlan#ap device; this is mainly needed for IEEE 802.1X - * frames that might be longer than normal default MTU and they are not - * fragmented */ -#define HOSTAPD_MTU 2290 - -static const u8 rfc1042_header[6] = { 0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00 }; - -struct hostap_driver_data { - struct hostapd_data *hapd; - - char iface[IFNAMSIZ + 1]; - int sock; /* raw packet socket for driver access */ - int ioctl_sock; /* socket for ioctl() use */ - struct netlink_data *netlink; - - int we_version; - - u8 *generic_ie; - size_t generic_ie_len; - u8 *wps_ie; - size_t wps_ie_len; -}; - - -static int hostapd_ioctl(void *priv, struct prism2_hostapd_param *param, - int len); -static int hostap_set_iface_flags(void *priv, int dev_up); - -static void handle_data(struct hostap_driver_data *drv, u8 *buf, size_t len, - u16 stype) -{ - struct ieee80211_hdr *hdr; - u16 fc, ethertype; - u8 *pos, *sa; - size_t left; - union wpa_event_data event; - - if (len < sizeof(struct ieee80211_hdr)) - return; - - hdr = (struct ieee80211_hdr *) buf; - fc = le_to_host16(hdr->frame_control); - - if ((fc & (WLAN_FC_FROMDS | WLAN_FC_TODS)) != WLAN_FC_TODS) { - printf("Not ToDS data frame (fc=0x%04x)\n", fc); - return; - } - - sa = hdr->addr2; - os_memset(&event, 0, sizeof(event)); - event.rx_from_unknown.frame = buf; - event.rx_from_unknown.len = len; - wpa_supplicant_event(drv->hapd, EVENT_RX_FROM_UNKNOWN, &event); - - pos = (u8 *) (hdr + 1); - left = len - sizeof(*hdr); - - if (left < sizeof(rfc1042_header)) { - printf("Too short data frame\n"); - return; - } - - if (memcmp(pos, rfc1042_header, sizeof(rfc1042_header)) != 0) { - printf("Data frame with no RFC1042 header\n"); - return; - } - pos += sizeof(rfc1042_header); - left -= sizeof(rfc1042_header); - - if (left < 2) { - printf("No ethertype in data frame\n"); - return; - } - - ethertype = WPA_GET_BE16(pos); - pos += 2; - left -= 2; - switch (ethertype) { - case ETH_P_PAE: - drv_event_eapol_rx(drv->hapd, sa, pos, left); - break; - - default: - printf("Unknown ethertype 0x%04x in data frame\n", ethertype); - break; - } -} - - -static void handle_tx_callback(struct hostap_driver_data *drv, u8 *buf, - size_t len, int ok) -{ - struct ieee80211_hdr *hdr; - u16 fc; - union wpa_event_data event; - - hdr = (struct ieee80211_hdr *) buf; - fc = le_to_host16(hdr->frame_control); - - os_memset(&event, 0, sizeof(event)); - event.tx_status.type = WLAN_FC_GET_TYPE(fc); - event.tx_status.stype = WLAN_FC_GET_STYPE(fc); - event.tx_status.dst = hdr->addr1; - event.tx_status.data = buf; - event.tx_status.data_len = len; - event.tx_status.ack = ok; - wpa_supplicant_event(drv->hapd, EVENT_TX_STATUS, &event); -} - - -static void handle_frame(struct hostap_driver_data *drv, u8 *buf, size_t len) -{ - struct ieee80211_hdr *hdr; - u16 fc, extra_len, type, stype; - unsigned char *extra = NULL; - size_t data_len = len; - int ver; - union wpa_event_data event; - - /* PSPOLL is only 16 bytes, but driver does not (at least yet) pass - * these to user space */ - if (len < 24) { - wpa_printf(MSG_MSGDUMP, "handle_frame: too short (%lu)", - (unsigned long) len); - return; - } - - hdr = (struct ieee80211_hdr *) buf; - fc = le_to_host16(hdr->frame_control); - type = WLAN_FC_GET_TYPE(fc); - stype = WLAN_FC_GET_STYPE(fc); - - if (type != WLAN_FC_TYPE_MGMT || stype != WLAN_FC_STYPE_BEACON) { - wpa_hexdump(MSG_MSGDUMP, "Received management frame", - buf, len); - } - - ver = fc & WLAN_FC_PVER; - - /* protocol version 3 is reserved for indicating extra data after the - * payload, version 2 for indicating ACKed frame (TX callbacks), and - * version 1 for indicating failed frame (no ACK, TX callbacks) */ - if (ver == 3) { - u8 *pos = buf + len - 2; - extra_len = WPA_GET_LE16(pos); - printf("extra data in frame (elen=%d)\n", extra_len); - if ((size_t) extra_len + 2 > len) { - printf(" extra data overflow\n"); - return; - } - len -= extra_len + 2; - extra = buf + len; - } else if (ver == 1 || ver == 2) { - handle_tx_callback(drv, buf, data_len, ver == 2 ? 1 : 0); - return; - } else if (ver != 0) { - printf("unknown protocol version %d\n", ver); - return; - } - - switch (type) { - case WLAN_FC_TYPE_MGMT: - os_memset(&event, 0, sizeof(event)); - event.rx_mgmt.frame = buf; - event.rx_mgmt.frame_len = data_len; - wpa_supplicant_event(drv->hapd, EVENT_RX_MGMT, &event); - break; - case WLAN_FC_TYPE_CTRL: - wpa_printf(MSG_DEBUG, "CTRL"); - break; - case WLAN_FC_TYPE_DATA: - wpa_printf(MSG_DEBUG, "DATA"); - handle_data(drv, buf, data_len, stype); - break; - default: - wpa_printf(MSG_DEBUG, "unknown frame type %d", type); - break; - } -} - - -static void handle_read(int sock, void *eloop_ctx, void *sock_ctx) -{ - struct hostap_driver_data *drv = eloop_ctx; - int len; - unsigned char buf[3000]; - - len = recv(sock, buf, sizeof(buf), 0); - if (len < 0) { - perror("recv"); - return; - } - - handle_frame(drv, buf, len); -} - - -static int hostap_init_sockets(struct hostap_driver_data *drv, u8 *own_addr) -{ - struct ifreq ifr; - struct sockaddr_ll addr; - - drv->sock = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL)); - if (drv->sock < 0) { - perror("socket[PF_PACKET,SOCK_RAW]"); - return -1; - } - - if (eloop_register_read_sock(drv->sock, handle_read, drv, NULL)) { - printf("Could not register read socket\n"); - return -1; - } - - memset(&ifr, 0, sizeof(ifr)); - snprintf(ifr.ifr_name, sizeof(ifr.ifr_name), "%sap", drv->iface); - if (ioctl(drv->sock, SIOCGIFINDEX, &ifr) != 0) { - perror("ioctl(SIOCGIFINDEX)"); - return -1; - } - - if (hostap_set_iface_flags(drv, 1)) { - return -1; - } - - memset(&addr, 0, sizeof(addr)); - addr.sll_family = AF_PACKET; - addr.sll_ifindex = ifr.ifr_ifindex; - wpa_printf(MSG_DEBUG, "Opening raw packet socket for ifindex %d", - addr.sll_ifindex); - - if (bind(drv->sock, (struct sockaddr *) &addr, sizeof(addr)) < 0) { - perror("bind"); - return -1; - } - - return linux_get_ifhwaddr(drv->sock, drv->iface, own_addr); -} - - -static int hostap_send_mlme(void *priv, const u8 *msg, size_t len) -{ - struct hostap_driver_data *drv = priv; - struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) msg; - int res; - - /* Request TX callback */ - hdr->frame_control |= host_to_le16(BIT(1)); - res = send(drv->sock, msg, len, 0); - hdr->frame_control &= ~host_to_le16(BIT(1)); - - return res; -} - - -static int hostap_send_eapol(void *priv, const u8 *addr, const u8 *data, - size_t data_len, int encrypt, const u8 *own_addr, - u32 flags) -{ - struct hostap_driver_data *drv = priv; - struct ieee80211_hdr *hdr; - size_t len; - u8 *pos; - int res; - - len = sizeof(*hdr) + sizeof(rfc1042_header) + 2 + data_len; - hdr = os_zalloc(len); - if (hdr == NULL) { - printf("malloc() failed for hostapd_send_data(len=%lu)\n", - (unsigned long) len); - return -1; - } - - hdr->frame_control = - IEEE80211_FC(WLAN_FC_TYPE_DATA, WLAN_FC_STYPE_DATA); - hdr->frame_control |= host_to_le16(WLAN_FC_FROMDS); - if (encrypt) - hdr->frame_control |= host_to_le16(WLAN_FC_ISWEP); - memcpy(hdr->IEEE80211_DA_FROMDS, addr, ETH_ALEN); - memcpy(hdr->IEEE80211_BSSID_FROMDS, own_addr, ETH_ALEN); - memcpy(hdr->IEEE80211_SA_FROMDS, own_addr, ETH_ALEN); - - pos = (u8 *) (hdr + 1); - memcpy(pos, rfc1042_header, sizeof(rfc1042_header)); - pos += sizeof(rfc1042_header); - *((u16 *) pos) = htons(ETH_P_PAE); - pos += 2; - memcpy(pos, data, data_len); - - res = hostap_send_mlme(drv, (u8 *) hdr, len); - if (res < 0) { - wpa_printf(MSG_ERROR, "hostap_send_eapol - packet len: %lu - " - "failed: %d (%s)", - (unsigned long) len, errno, strerror(errno)); - } - free(hdr); - - return res; -} - - -static int hostap_sta_set_flags(void *priv, const u8 *addr, - int total_flags, int flags_or, int flags_and) -{ - struct hostap_driver_data *drv = priv; - struct prism2_hostapd_param param; - - if (flags_or & WPA_STA_AUTHORIZED) - flags_or = BIT(5); /* WLAN_STA_AUTHORIZED */ - if (!(flags_and & WPA_STA_AUTHORIZED)) - flags_and = ~BIT(5); - else - flags_and = ~0; - memset(¶m, 0, sizeof(param)); - param.cmd = PRISM2_HOSTAPD_SET_FLAGS_STA; - memcpy(param.sta_addr, addr, ETH_ALEN); - param.u.set_flags_sta.flags_or = flags_or; - param.u.set_flags_sta.flags_and = flags_and; - return hostapd_ioctl(drv, ¶m, sizeof(param)); -} - - -static int hostap_set_iface_flags(void *priv, int dev_up) -{ - struct hostap_driver_data *drv = priv; - struct ifreq ifr; - char ifname[IFNAMSIZ]; - - os_snprintf(ifname, IFNAMSIZ, "%sap", drv->iface); - if (linux_set_iface_flags(drv->ioctl_sock, ifname, dev_up) < 0) - return -1; - - if (dev_up) { - memset(&ifr, 0, sizeof(ifr)); - os_strlcpy(ifr.ifr_name, ifname, IFNAMSIZ); - ifr.ifr_mtu = HOSTAPD_MTU; - if (ioctl(drv->ioctl_sock, SIOCSIFMTU, &ifr) != 0) { - perror("ioctl[SIOCSIFMTU]"); - printf("Setting MTU failed - trying to survive with " - "current value\n"); - } - } - - return 0; -} - - -static int hostapd_ioctl(void *priv, struct prism2_hostapd_param *param, - int len) -{ - struct hostap_driver_data *drv = priv; - struct iwreq iwr; - - memset(&iwr, 0, sizeof(iwr)); - os_strlcpy(iwr.ifr_name, drv->iface, IFNAMSIZ); - iwr.u.data.pointer = (caddr_t) param; - iwr.u.data.length = len; - - if (ioctl(drv->ioctl_sock, PRISM2_IOCTL_HOSTAPD, &iwr) < 0) { - perror("ioctl[PRISM2_IOCTL_HOSTAPD]"); - return -1; - } - - return 0; -} - - -static int wpa_driver_hostap_set_key(const char *ifname, void *priv, - enum wpa_alg alg, const u8 *addr, - int key_idx, int set_tx, - const u8 *seq, size_t seq_len, - const u8 *key, size_t key_len) -{ - struct hostap_driver_data *drv = priv; - struct prism2_hostapd_param *param; - u8 *buf; - size_t blen; - int ret = 0; - - blen = sizeof(*param) + key_len; - buf = os_zalloc(blen); - if (buf == NULL) - return -1; - - param = (struct prism2_hostapd_param *) buf; - param->cmd = PRISM2_SET_ENCRYPTION; - if (addr == NULL) - memset(param->sta_addr, 0xff, ETH_ALEN); - else - memcpy(param->sta_addr, addr, ETH_ALEN); - switch (alg) { - case WPA_ALG_NONE: - os_strlcpy((char *) param->u.crypt.alg, "NONE", - HOSTAP_CRYPT_ALG_NAME_LEN); - break; - case WPA_ALG_WEP: - os_strlcpy((char *) param->u.crypt.alg, "WEP", - HOSTAP_CRYPT_ALG_NAME_LEN); - break; - case WPA_ALG_TKIP: - os_strlcpy((char *) param->u.crypt.alg, "TKIP", - HOSTAP_CRYPT_ALG_NAME_LEN); - break; - case WPA_ALG_CCMP: - os_strlcpy((char *) param->u.crypt.alg, "CCMP", - HOSTAP_CRYPT_ALG_NAME_LEN); - break; - default: - os_free(buf); - return -1; - } - param->u.crypt.flags = set_tx ? HOSTAP_CRYPT_FLAG_SET_TX_KEY : 0; - param->u.crypt.idx = key_idx; - param->u.crypt.key_len = key_len; - memcpy((u8 *) (param + 1), key, key_len); - - if (hostapd_ioctl(drv, param, blen)) { - printf("Failed to set encryption.\n"); - ret = -1; - } - free(buf); - - return ret; -} - - -static int hostap_get_seqnum(const char *ifname, void *priv, const u8 *addr, - int idx, u8 *seq) -{ - struct hostap_driver_data *drv = priv; - struct prism2_hostapd_param *param; - u8 *buf; - size_t blen; - int ret = 0; - - blen = sizeof(*param) + 32; - buf = os_zalloc(blen); - if (buf == NULL) - return -1; - - param = (struct prism2_hostapd_param *) buf; - param->cmd = PRISM2_GET_ENCRYPTION; - if (addr == NULL) - memset(param->sta_addr, 0xff, ETH_ALEN); - else - memcpy(param->sta_addr, addr, ETH_ALEN); - param->u.crypt.idx = idx; - - if (hostapd_ioctl(drv, param, blen)) { - printf("Failed to get encryption.\n"); - ret = -1; - } else { - memcpy(seq, param->u.crypt.seq, 8); - } - free(buf); - - return ret; -} - - -static int hostap_ioctl_prism2param(void *priv, int param, int value) -{ - struct hostap_driver_data *drv = priv; - struct iwreq iwr; - int *i; - - memset(&iwr, 0, sizeof(iwr)); - os_strlcpy(iwr.ifr_name, drv->iface, IFNAMSIZ); - i = (int *) iwr.u.name; - *i++ = param; - *i++ = value; - - if (ioctl(drv->ioctl_sock, PRISM2_IOCTL_PRISM2_PARAM, &iwr) < 0) { - perror("ioctl[PRISM2_IOCTL_PRISM2_PARAM]"); - return -1; - } - - return 0; -} - - -static int hostap_set_ieee8021x(void *priv, struct wpa_bss_params *params) -{ - struct hostap_driver_data *drv = priv; - int enabled = params->enabled; - - /* enable kernel driver support for IEEE 802.1X */ - if (hostap_ioctl_prism2param(drv, PRISM2_PARAM_IEEE_802_1X, enabled)) { - printf("Could not setup IEEE 802.1X support in kernel driver." - "\n"); - return -1; - } - - if (!enabled) - return 0; - - /* use host driver implementation of encryption to allow - * individual keys and passing plaintext EAPOL frames */ - if (hostap_ioctl_prism2param(drv, PRISM2_PARAM_HOST_DECRYPT, 1) || - hostap_ioctl_prism2param(drv, PRISM2_PARAM_HOST_ENCRYPT, 1)) { - printf("Could not setup host-based encryption in kernel " - "driver.\n"); - return -1; - } - - return 0; -} - - -static int hostap_set_privacy(void *priv, int enabled) -{ - struct hostap_drvier_data *drv = priv; - - return hostap_ioctl_prism2param(drv, PRISM2_PARAM_PRIVACY_INVOKED, - enabled); -} - - -static int hostap_set_ssid(void *priv, const u8 *buf, int len) -{ - struct hostap_driver_data *drv = priv; - struct iwreq iwr; - - memset(&iwr, 0, sizeof(iwr)); - os_strlcpy(iwr.ifr_name, drv->iface, IFNAMSIZ); - iwr.u.essid.flags = 1; /* SSID active */ - iwr.u.essid.pointer = (caddr_t) buf; - iwr.u.essid.length = len + 1; - - if (ioctl(drv->ioctl_sock, SIOCSIWESSID, &iwr) < 0) { - perror("ioctl[SIOCSIWESSID]"); - printf("len=%d\n", len); - return -1; - } - - return 0; -} - - -static int hostap_flush(void *priv) -{ - struct hostap_driver_data *drv = priv; - struct prism2_hostapd_param param; - - memset(¶m, 0, sizeof(param)); - param.cmd = PRISM2_HOSTAPD_FLUSH; - return hostapd_ioctl(drv, ¶m, sizeof(param)); -} - - -static int hostap_read_sta_data(void *priv, - struct hostap_sta_driver_data *data, - const u8 *addr) -{ - struct hostap_driver_data *drv = priv; - char buf[1024], line[128], *pos; - FILE *f; - unsigned long val; - - memset(data, 0, sizeof(*data)); - snprintf(buf, sizeof(buf), "/proc/net/hostap/%s/" MACSTR, - drv->iface, MAC2STR(addr)); - - f = fopen(buf, "r"); - if (!f) - return -1; - /* Need to read proc file with in one piece, so use large enough - * buffer. */ - setbuffer(f, buf, sizeof(buf)); - - while (fgets(line, sizeof(line), f)) { - pos = strchr(line, '='); - if (!pos) - continue; - *pos++ = '\0'; - val = strtoul(pos, NULL, 10); - if (strcmp(line, "rx_packets") == 0) - data->rx_packets = val; - else if (strcmp(line, "tx_packets") == 0) - data->tx_packets = val; - else if (strcmp(line, "rx_bytes") == 0) - data->rx_bytes = val; - else if (strcmp(line, "tx_bytes") == 0) - data->tx_bytes = val; - } - - fclose(f); - - return 0; -} - - -static int hostap_sta_add(void *priv, struct hostapd_sta_add_params *params) -{ - struct hostap_driver_data *drv = priv; - struct prism2_hostapd_param param; - int tx_supp_rates = 0; - size_t i; - -#define WLAN_RATE_1M BIT(0) -#define WLAN_RATE_2M BIT(1) -#define WLAN_RATE_5M5 BIT(2) -#define WLAN_RATE_11M BIT(3) - - for (i = 0; i < params->supp_rates_len; i++) { - if ((params->supp_rates[i] & 0x7f) == 2) - tx_supp_rates |= WLAN_RATE_1M; - if ((params->supp_rates[i] & 0x7f) == 4) - tx_supp_rates |= WLAN_RATE_2M; - if ((params->supp_rates[i] & 0x7f) == 11) - tx_supp_rates |= WLAN_RATE_5M5; - if ((params->supp_rates[i] & 0x7f) == 22) - tx_supp_rates |= WLAN_RATE_11M; - } - - memset(¶m, 0, sizeof(param)); - param.cmd = PRISM2_HOSTAPD_ADD_STA; - memcpy(param.sta_addr, params->addr, ETH_ALEN); - param.u.add_sta.aid = params->aid; - param.u.add_sta.capability = params->capability; - param.u.add_sta.tx_supp_rates = tx_supp_rates; - return hostapd_ioctl(drv, ¶m, sizeof(param)); -} - - -static int hostap_sta_remove(void *priv, const u8 *addr) -{ - struct hostap_driver_data *drv = priv; - struct prism2_hostapd_param param; - - hostap_sta_set_flags(drv, addr, 0, 0, ~WPA_STA_AUTHORIZED); - - memset(¶m, 0, sizeof(param)); - param.cmd = PRISM2_HOSTAPD_REMOVE_STA; - memcpy(param.sta_addr, addr, ETH_ALEN); - if (hostapd_ioctl(drv, ¶m, sizeof(param))) { - printf("Could not remove station from kernel driver.\n"); - return -1; - } - return 0; -} - - -static int hostap_get_inact_sec(void *priv, const u8 *addr) -{ - struct hostap_driver_data *drv = priv; - struct prism2_hostapd_param param; - - memset(¶m, 0, sizeof(param)); - param.cmd = PRISM2_HOSTAPD_GET_INFO_STA; - memcpy(param.sta_addr, addr, ETH_ALEN); - if (hostapd_ioctl(drv, ¶m, sizeof(param))) { - return -1; - } - - return param.u.get_info_sta.inactive_sec; -} - - -static int hostap_sta_clear_stats(void *priv, const u8 *addr) -{ - struct hostap_driver_data *drv = priv; - struct prism2_hostapd_param param; - - memset(¶m, 0, sizeof(param)); - param.cmd = PRISM2_HOSTAPD_STA_CLEAR_STATS; - memcpy(param.sta_addr, addr, ETH_ALEN); - if (hostapd_ioctl(drv, ¶m, sizeof(param))) { - return -1; - } - - return 0; -} - - -static int hostapd_ioctl_set_generic_elem(struct hostap_driver_data *drv) -{ - struct prism2_hostapd_param *param; - int res; - size_t blen, elem_len; - - elem_len = drv->generic_ie_len + drv->wps_ie_len; - blen = PRISM2_HOSTAPD_GENERIC_ELEMENT_HDR_LEN + elem_len; - if (blen < sizeof(*param)) - blen = sizeof(*param); - - param = os_zalloc(blen); - if (param == NULL) - return -1; - - param->cmd = PRISM2_HOSTAPD_SET_GENERIC_ELEMENT; - param->u.generic_elem.len = elem_len; - if (drv->generic_ie) { - os_memcpy(param->u.generic_elem.data, drv->generic_ie, - drv->generic_ie_len); - } - if (drv->wps_ie) { - os_memcpy(¶m->u.generic_elem.data[drv->generic_ie_len], - drv->wps_ie, drv->wps_ie_len); - } - wpa_hexdump(MSG_DEBUG, "hostap: Set generic IE", - param->u.generic_elem.data, elem_len); - res = hostapd_ioctl(drv, param, blen); - - os_free(param); - - return res; -} - - -static int hostap_set_generic_elem(void *priv, - const u8 *elem, size_t elem_len) -{ - struct hostap_driver_data *drv = priv; - - os_free(drv->generic_ie); - drv->generic_ie = NULL; - drv->generic_ie_len = 0; - if (elem) { - drv->generic_ie = os_malloc(elem_len); - if (drv->generic_ie == NULL) - return -1; - os_memcpy(drv->generic_ie, elem, elem_len); - drv->generic_ie_len = elem_len; - } - - return hostapd_ioctl_set_generic_elem(drv); -} - - -static int hostap_set_ap_wps_ie(void *priv, const struct wpabuf *beacon, - const struct wpabuf *proberesp, - const struct wpabuf *assocresp) -{ - struct hostap_driver_data *drv = priv; - - /* - * Host AP driver supports only one set of extra IEs, so we need to - * use the Probe Response IEs also for Beacon frames since they include - * more information. - */ - - os_free(drv->wps_ie); - drv->wps_ie = NULL; - drv->wps_ie_len = 0; - if (proberesp) { - drv->wps_ie = os_malloc(wpabuf_len(proberesp)); - if (drv->wps_ie == NULL) - return -1; - os_memcpy(drv->wps_ie, wpabuf_head(proberesp), - wpabuf_len(proberesp)); - drv->wps_ie_len = wpabuf_len(proberesp); - } - - return hostapd_ioctl_set_generic_elem(drv); -} - - -static void -hostapd_wireless_event_wireless_custom(struct hostap_driver_data *drv, - char *custom) -{ - wpa_printf(MSG_DEBUG, "Custom wireless event: '%s'", custom); - - if (strncmp(custom, "MLME-MICHAELMICFAILURE.indication", 33) == 0) { - char *pos; - u8 addr[ETH_ALEN]; - pos = strstr(custom, "addr="); - if (pos == NULL) { - wpa_printf(MSG_DEBUG, - "MLME-MICHAELMICFAILURE.indication " - "without sender address ignored"); - return; - } - pos += 5; - if (hwaddr_aton(pos, addr) == 0) { - union wpa_event_data data; - os_memset(&data, 0, sizeof(data)); - data.michael_mic_failure.unicast = 1; - data.michael_mic_failure.src = addr; - wpa_supplicant_event(drv->hapd, - EVENT_MICHAEL_MIC_FAILURE, &data); - } else { - wpa_printf(MSG_DEBUG, - "MLME-MICHAELMICFAILURE.indication " - "with invalid MAC address"); - } - } -} - - -static void hostapd_wireless_event_wireless(struct hostap_driver_data *drv, - char *data, int len) -{ - struct iw_event iwe_buf, *iwe = &iwe_buf; - char *pos, *end, *custom, *buf; - - pos = data; - end = data + len; - - while (pos + IW_EV_LCP_LEN <= end) { - /* Event data may be unaligned, so make a local, aligned copy - * before processing. */ - memcpy(&iwe_buf, pos, IW_EV_LCP_LEN); - wpa_printf(MSG_DEBUG, "Wireless event: cmd=0x%x len=%d", - iwe->cmd, iwe->len); - if (iwe->len <= IW_EV_LCP_LEN) - return; - - custom = pos + IW_EV_POINT_LEN; - if (drv->we_version > 18 && - (iwe->cmd == IWEVMICHAELMICFAILURE || - iwe->cmd == IWEVCUSTOM)) { - /* WE-19 removed the pointer from struct iw_point */ - char *dpos = (char *) &iwe_buf.u.data.length; - int dlen = dpos - (char *) &iwe_buf; - memcpy(dpos, pos + IW_EV_LCP_LEN, - sizeof(struct iw_event) - dlen); - } else { - memcpy(&iwe_buf, pos, sizeof(struct iw_event)); - custom += IW_EV_POINT_OFF; - } - - switch (iwe->cmd) { - case IWEVCUSTOM: - if (custom + iwe->u.data.length > end) - return; - buf = malloc(iwe->u.data.length + 1); - if (buf == NULL) - return; - memcpy(buf, custom, iwe->u.data.length); - buf[iwe->u.data.length] = '\0'; - hostapd_wireless_event_wireless_custom(drv, buf); - free(buf); - break; - } - - pos += iwe->len; - } -} - - -static void hostapd_wireless_event_rtm_newlink(void *ctx, - struct ifinfomsg *ifi, - u8 *buf, size_t len) -{ - struct hostap_driver_data *drv = ctx; - int attrlen, rta_len; - struct rtattr *attr; - - /* TODO: use ifi->ifi_index to filter out wireless events from other - * interfaces */ - - attrlen = len; - attr = (struct rtattr *) buf; - - rta_len = RTA_ALIGN(sizeof(struct rtattr)); - while (RTA_OK(attr, attrlen)) { - if (attr->rta_type == IFLA_WIRELESS) { - hostapd_wireless_event_wireless( - drv, ((char *) attr) + rta_len, - attr->rta_len - rta_len); - } - attr = RTA_NEXT(attr, attrlen); - } -} - - -static int hostap_get_we_version(struct hostap_driver_data *drv) -{ - struct iw_range *range; - struct iwreq iwr; - int minlen; - size_t buflen; - - drv->we_version = 0; - - /* - * Use larger buffer than struct iw_range in order to allow the - * structure to grow in the future. - */ - buflen = sizeof(struct iw_range) + 500; - range = os_zalloc(buflen); - if (range == NULL) - return -1; - - memset(&iwr, 0, sizeof(iwr)); - os_strlcpy(iwr.ifr_name, drv->iface, IFNAMSIZ); - iwr.u.data.pointer = (caddr_t) range; - iwr.u.data.length = buflen; - - minlen = ((char *) &range->enc_capa) - (char *) range + - sizeof(range->enc_capa); - - if (ioctl(drv->ioctl_sock, SIOCGIWRANGE, &iwr) < 0) { - perror("ioctl[SIOCGIWRANGE]"); - free(range); - return -1; - } else if (iwr.u.data.length >= minlen && - range->we_version_compiled >= 18) { - wpa_printf(MSG_DEBUG, "SIOCGIWRANGE: WE(compiled)=%d " - "WE(source)=%d enc_capa=0x%x", - range->we_version_compiled, - range->we_version_source, - range->enc_capa); - drv->we_version = range->we_version_compiled; - } - - free(range); - return 0; -} - - -static int hostap_wireless_event_init(struct hostap_driver_data *drv) -{ - struct netlink_config *cfg; - - hostap_get_we_version(drv); - - cfg = os_zalloc(sizeof(*cfg)); - if (cfg == NULL) - return -1; - cfg->ctx = drv; - cfg->newlink_cb = hostapd_wireless_event_rtm_newlink; - drv->netlink = netlink_init(cfg); - if (drv->netlink == NULL) { - os_free(cfg); - return -1; - } - - return 0; -} - - -static void * hostap_init(struct hostapd_data *hapd, - struct wpa_init_params *params) -{ - struct hostap_driver_data *drv; - - drv = os_zalloc(sizeof(struct hostap_driver_data)); - if (drv == NULL) { - printf("Could not allocate memory for hostapd driver data\n"); - return NULL; - } - - drv->hapd = hapd; - drv->ioctl_sock = drv->sock = -1; - memcpy(drv->iface, params->ifname, sizeof(drv->iface)); - - drv->ioctl_sock = socket(PF_INET, SOCK_DGRAM, 0); - if (drv->ioctl_sock < 0) { - perror("socket[PF_INET,SOCK_DGRAM]"); - free(drv); - return NULL; - } - - if (hostap_ioctl_prism2param(drv, PRISM2_PARAM_HOSTAPD, 1)) { - printf("Could not enable hostapd mode for interface %s\n", - drv->iface); - close(drv->ioctl_sock); - free(drv); - return NULL; - } - - if (hostap_init_sockets(drv, params->own_addr) || - hostap_wireless_event_init(drv)) { - close(drv->ioctl_sock); - free(drv); - return NULL; - } - - return drv; -} - - -static void hostap_driver_deinit(void *priv) -{ - struct hostap_driver_data *drv = priv; - - netlink_deinit(drv->netlink); - (void) hostap_set_iface_flags(drv, 0); - (void) hostap_ioctl_prism2param(drv, PRISM2_PARAM_HOSTAPD, 0); - (void) hostap_ioctl_prism2param(drv, PRISM2_PARAM_HOSTAPD_STA, 0); - - if (drv->ioctl_sock >= 0) - close(drv->ioctl_sock); - - if (drv->sock >= 0) - close(drv->sock); - - os_free(drv->generic_ie); - os_free(drv->wps_ie); - - free(drv); -} - - -static int hostap_sta_deauth(void *priv, const u8 *own_addr, const u8 *addr, - int reason) -{ - struct hostap_driver_data *drv = priv; - struct ieee80211_mgmt mgmt; - - if (is_broadcast_ether_addr(addr)) { - /* - * New Prism2.5/3 STA firmware versions seem to have issues - * with this broadcast deauth frame. This gets the firmware in - * odd state where nothing works correctly, so let's skip - * sending this for the hostap driver. - */ - return 0; - } - - memset(&mgmt, 0, sizeof(mgmt)); - mgmt.frame_control = IEEE80211_FC(WLAN_FC_TYPE_MGMT, - WLAN_FC_STYPE_DEAUTH); - memcpy(mgmt.da, addr, ETH_ALEN); - memcpy(mgmt.sa, own_addr, ETH_ALEN); - memcpy(mgmt.bssid, own_addr, ETH_ALEN); - mgmt.u.deauth.reason_code = host_to_le16(reason); - return hostap_send_mlme(drv, (u8 *) &mgmt, IEEE80211_HDRLEN + - sizeof(mgmt.u.deauth)); -} - - -static int hostap_sta_disassoc(void *priv, const u8 *own_addr, const u8 *addr, - int reason) -{ - struct hostap_driver_data *drv = priv; - struct ieee80211_mgmt mgmt; - - memset(&mgmt, 0, sizeof(mgmt)); - mgmt.frame_control = IEEE80211_FC(WLAN_FC_TYPE_MGMT, - WLAN_FC_STYPE_DISASSOC); - memcpy(mgmt.da, addr, ETH_ALEN); - memcpy(mgmt.sa, own_addr, ETH_ALEN); - memcpy(mgmt.bssid, own_addr, ETH_ALEN); - mgmt.u.disassoc.reason_code = host_to_le16(reason); - return hostap_send_mlme(drv, (u8 *) &mgmt, IEEE80211_HDRLEN + - sizeof(mgmt.u.disassoc)); -} - - -static struct hostapd_hw_modes * hostap_get_hw_feature_data(void *priv, - u16 *num_modes, - u16 *flags) -{ - struct hostapd_hw_modes *mode; - int i, clen, rlen; - const short chan2freq[14] = { - 2412, 2417, 2422, 2427, 2432, 2437, 2442, - 2447, 2452, 2457, 2462, 2467, 2472, 2484 - }; - - mode = os_zalloc(sizeof(struct hostapd_hw_modes)); - if (mode == NULL) - return NULL; - - *num_modes = 1; - *flags = 0; - - mode->mode = HOSTAPD_MODE_IEEE80211B; - mode->num_channels = 14; - mode->num_rates = 4; - - clen = mode->num_channels * sizeof(struct hostapd_channel_data); - rlen = mode->num_rates * sizeof(int); - - mode->channels = os_zalloc(clen); - mode->rates = os_zalloc(rlen); - if (mode->channels == NULL || mode->rates == NULL) { - os_free(mode->channels); - os_free(mode->rates); - os_free(mode); - return NULL; - } - - for (i = 0; i < 14; i++) { - mode->channels[i].chan = i + 1; - mode->channels[i].freq = chan2freq[i]; - /* TODO: Get allowed channel list from the driver */ - if (i >= 11) - mode->channels[i].flag = HOSTAPD_CHAN_DISABLED; - } - - mode->rates[0] = 10; - mode->rates[1] = 20; - mode->rates[2] = 55; - mode->rates[3] = 110; - - return mode; -} - -#else /* HOSTAPD */ - -struct wpa_driver_hostap_data { - void *wext; /* private data for driver_wext */ - void *ctx; - char ifname[IFNAMSIZ + 1]; - int sock; - int current_mode; /* infra/adhoc */ -}; - - -static int wpa_driver_hostap_set_auth_alg(void *priv, int auth_alg); - - -static int hostapd_ioctl(struct wpa_driver_hostap_data *drv, - struct prism2_hostapd_param *param, - int len, int show_err) -{ - struct iwreq iwr; - - os_memset(&iwr, 0, sizeof(iwr)); - os_strlcpy(iwr.ifr_name, drv->ifname, IFNAMSIZ); - iwr.u.data.pointer = (caddr_t) param; - iwr.u.data.length = len; - - if (ioctl(drv->sock, PRISM2_IOCTL_HOSTAPD, &iwr) < 0) { - int ret = errno; - if (show_err) - perror("ioctl[PRISM2_IOCTL_HOSTAPD]"); - return ret; - } - - return 0; -} - - -static int wpa_driver_hostap_set_wpa_ie(struct wpa_driver_hostap_data *drv, - const u8 *wpa_ie, size_t wpa_ie_len) -{ - struct prism2_hostapd_param *param; - int res; - size_t blen = PRISM2_HOSTAPD_GENERIC_ELEMENT_HDR_LEN + wpa_ie_len; - if (blen < sizeof(*param)) - blen = sizeof(*param); - - param = os_zalloc(blen); - if (param == NULL) - return -1; - - param->cmd = PRISM2_HOSTAPD_SET_GENERIC_ELEMENT; - param->u.generic_elem.len = wpa_ie_len; - os_memcpy(param->u.generic_elem.data, wpa_ie, wpa_ie_len); - res = hostapd_ioctl(drv, param, blen, 1); - - os_free(param); - - return res; -} - - -static int prism2param(struct wpa_driver_hostap_data *drv, int param, - int value) -{ - struct iwreq iwr; - int *i, ret = 0; - - os_memset(&iwr, 0, sizeof(iwr)); - os_strlcpy(iwr.ifr_name, drv->ifname, IFNAMSIZ); - i = (int *) iwr.u.name; - *i++ = param; - *i++ = value; - - if (ioctl(drv->sock, PRISM2_IOCTL_PRISM2_PARAM, &iwr) < 0) { - perror("ioctl[PRISM2_IOCTL_PRISM2_PARAM]"); - ret = -1; - } - return ret; -} - - -static int wpa_driver_hostap_set_wpa(void *priv, int enabled) -{ - struct wpa_driver_hostap_data *drv = priv; - int ret = 0; - - wpa_printf(MSG_DEBUG, "%s: enabled=%d", __FUNCTION__, enabled); - - if (!enabled && wpa_driver_hostap_set_wpa_ie(drv, NULL, 0) < 0) - ret = -1; - if (prism2param(drv, PRISM2_PARAM_HOST_ROAMING, enabled ? 2 : 0) < 0) - ret = -1; - if (prism2param(drv, PRISM2_PARAM_WPA, enabled) < 0) - ret = -1; - - return ret; -} - - -static void show_set_key_error(struct prism2_hostapd_param *param) -{ - switch (param->u.crypt.err) { - case HOSTAP_CRYPT_ERR_UNKNOWN_ALG: - wpa_printf(MSG_INFO, "Unknown algorithm '%s'.", - param->u.crypt.alg); - wpa_printf(MSG_INFO, "You may need to load kernel module to " - "register that algorithm."); - wpa_printf(MSG_INFO, "E.g., 'modprobe hostap_crypt_wep' for " - "WEP."); - break; - case HOSTAP_CRYPT_ERR_UNKNOWN_ADDR: - wpa_printf(MSG_INFO, "Unknown address " MACSTR ".", - MAC2STR(param->sta_addr)); - break; - case HOSTAP_CRYPT_ERR_CRYPT_INIT_FAILED: - wpa_printf(MSG_INFO, "Crypt algorithm initialization failed."); - break; - case HOSTAP_CRYPT_ERR_KEY_SET_FAILED: - wpa_printf(MSG_INFO, "Key setting failed."); - break; - case HOSTAP_CRYPT_ERR_TX_KEY_SET_FAILED: - wpa_printf(MSG_INFO, "TX key index setting failed."); - break; - case HOSTAP_CRYPT_ERR_CARD_CONF_FAILED: - wpa_printf(MSG_INFO, "Card configuration failed."); - break; - } -} - - -static int wpa_driver_hostap_set_key(const char *ifname, void *priv, - enum wpa_alg alg, const u8 *addr, - int key_idx, int set_tx, - const u8 *seq, size_t seq_len, - const u8 *key, size_t key_len) -{ - struct wpa_driver_hostap_data *drv = priv; - struct prism2_hostapd_param *param; - u8 *buf; - size_t blen; - int ret = 0; - char *alg_name; - - switch (alg) { - case WPA_ALG_NONE: - alg_name = "none"; - break; - case WPA_ALG_WEP: - alg_name = "WEP"; - break; - case WPA_ALG_TKIP: - alg_name = "TKIP"; - break; - case WPA_ALG_CCMP: - alg_name = "CCMP"; - break; - default: - return -1; - } - - wpa_printf(MSG_DEBUG, "%s: alg=%s key_idx=%d set_tx=%d seq_len=%lu " - "key_len=%lu", __FUNCTION__, alg_name, key_idx, set_tx, - (unsigned long) seq_len, (unsigned long) key_len); - - if (seq_len > 8) - return -2; - - blen = sizeof(*param) + key_len; - buf = os_zalloc(blen); - if (buf == NULL) - return -1; - - param = (struct prism2_hostapd_param *) buf; - param->cmd = PRISM2_SET_ENCRYPTION; - /* TODO: In theory, STA in client mode can use five keys; four default - * keys for receiving (with keyidx 0..3) and one individual key for - * both transmitting and receiving (keyidx 0) _unicast_ packets. Now, - * keyidx 0 is reserved for this unicast use and default keys can only - * use keyidx 1..3 (i.e., default key with keyidx 0 is not supported). - * This should be fine for more or less all cases, but for completeness - * sake, the driver could be enhanced to support the missing key. */ -#if 0 - if (addr == NULL) - os_memset(param->sta_addr, 0xff, ETH_ALEN); - else - os_memcpy(param->sta_addr, addr, ETH_ALEN); -#else - os_memset(param->sta_addr, 0xff, ETH_ALEN); -#endif - os_strlcpy((char *) param->u.crypt.alg, alg_name, - HOSTAP_CRYPT_ALG_NAME_LEN); - param->u.crypt.flags = set_tx ? HOSTAP_CRYPT_FLAG_SET_TX_KEY : 0; - param->u.crypt.idx = key_idx; - if (seq) - os_memcpy(param->u.crypt.seq, seq, seq_len); - param->u.crypt.key_len = key_len; - os_memcpy((u8 *) (param + 1), key, key_len); - - if (hostapd_ioctl(drv, param, blen, 1)) { - wpa_printf(MSG_WARNING, "Failed to set encryption."); - show_set_key_error(param); - ret = -1; - } - os_free(buf); - - return ret; -} - - -static int wpa_driver_hostap_set_countermeasures(void *priv, int enabled) -{ - struct wpa_driver_hostap_data *drv = priv; - wpa_printf(MSG_DEBUG, "%s: enabled=%d", __FUNCTION__, enabled); - return prism2param(drv, PRISM2_PARAM_TKIP_COUNTERMEASURES, enabled); -} - - -static int wpa_driver_hostap_reset(struct wpa_driver_hostap_data *drv, - int type) -{ - struct iwreq iwr; - int *i, ret = 0; - - wpa_printf(MSG_DEBUG, "%s: type=%d", __FUNCTION__, type); - - os_memset(&iwr, 0, sizeof(iwr)); - os_strlcpy(iwr.ifr_name, drv->ifname, IFNAMSIZ); - i = (int *) iwr.u.name; - *i++ = type; - - if (ioctl(drv->sock, PRISM2_IOCTL_RESET, &iwr) < 0) { - perror("ioctl[PRISM2_IOCTL_RESET]"); - ret = -1; - } - return ret; -} - - -static int wpa_driver_hostap_mlme(struct wpa_driver_hostap_data *drv, - const u8 *addr, int cmd, int reason_code) -{ - struct prism2_hostapd_param param; - int ret; - - /* There does not seem to be a better way of deauthenticating or - * disassociating with Prism2/2.5/3 than sending the management frame - * and then resetting the Port0 to make sure both the AP and the STA - * end up in disconnected state. */ - os_memset(¶m, 0, sizeof(param)); - param.cmd = PRISM2_HOSTAPD_MLME; - os_memcpy(param.sta_addr, addr, ETH_ALEN); - param.u.mlme.cmd = cmd; - param.u.mlme.reason_code = reason_code; - ret = hostapd_ioctl(drv, ¶m, sizeof(param), 1); - if (ret == 0) { - os_sleep(0, 100000); - ret = wpa_driver_hostap_reset(drv, 2); - } - return ret; -} - - -static int wpa_driver_hostap_deauthenticate(void *priv, const u8 *addr, - int reason_code) -{ - struct wpa_driver_hostap_data *drv = priv; - wpa_printf(MSG_DEBUG, "%s", __FUNCTION__); - return wpa_driver_hostap_mlme(drv, addr, MLME_STA_DEAUTH, - reason_code); -} - - -static int wpa_driver_hostap_disassociate(void *priv, const u8 *addr, - int reason_code) -{ - struct wpa_driver_hostap_data *drv = priv; - wpa_printf(MSG_DEBUG, "%s", __FUNCTION__); - return wpa_driver_hostap_mlme(drv, addr, MLME_STA_DISASSOC, - reason_code); -} - - -static int -wpa_driver_hostap_associate(void *priv, - struct wpa_driver_associate_params *params) -{ - struct wpa_driver_hostap_data *drv = priv; - int ret = 0; - int allow_unencrypted_eapol; - - wpa_printf(MSG_DEBUG, "%s", __FUNCTION__); - - if (prism2param(drv, PRISM2_PARAM_DROP_UNENCRYPTED, - params->drop_unencrypted) < 0) - ret = -1; - if (wpa_driver_hostap_set_auth_alg(drv, params->auth_alg) < 0) - ret = -1; - if (params->mode != drv->current_mode) { - /* At the moment, Host AP driver requires host_roaming=2 for - * infrastructure mode and host_roaming=0 for adhoc. */ - if (prism2param(drv, PRISM2_PARAM_HOST_ROAMING, - params->mode == IEEE80211_MODE_IBSS ? 0 : 2) < - 0) { - wpa_printf(MSG_DEBUG, "%s: failed to set host_roaming", - __func__); - } - drv->current_mode = params->mode; - } - - if (prism2param(drv, PRISM2_PARAM_PRIVACY_INVOKED, - params->key_mgmt_suite != KEY_MGMT_NONE) < 0) - ret = -1; - if (wpa_driver_hostap_set_wpa_ie(drv, params->wpa_ie, - params->wpa_ie_len) < 0) - ret = -1; - if (wpa_driver_wext_set_mode(drv->wext, params->mode) < 0) - ret = -1; - if (params->freq && - wpa_driver_wext_set_freq(drv->wext, params->freq) < 0) - ret = -1; - if (wpa_driver_wext_set_ssid(drv->wext, params->ssid, params->ssid_len) - < 0) - ret = -1; - if (wpa_driver_wext_set_bssid(drv->wext, params->bssid) < 0) - ret = -1; - - /* Allow unencrypted EAPOL messages even if pairwise keys are set when - * not using WPA. IEEE 802.1X specifies that these frames are not - * encrypted, but WPA encrypts them when pairwise keys are in use. */ - if (params->key_mgmt_suite == KEY_MGMT_802_1X || - params->key_mgmt_suite == KEY_MGMT_PSK) - allow_unencrypted_eapol = 0; - else - allow_unencrypted_eapol = 1; - - if (prism2param(drv, PRISM2_PARAM_IEEE_802_1X, - allow_unencrypted_eapol) < 0) { - wpa_printf(MSG_DEBUG, "hostap: Failed to configure " - "ieee_802_1x param"); - /* Ignore this error.. driver_hostap.c can also be used with - * other drivers that do not support this prism2_param. */ - } - - return ret; -} - - -static int wpa_driver_hostap_scan(void *priv, - struct wpa_driver_scan_params *params) -{ - struct wpa_driver_hostap_data *drv = priv; - struct prism2_hostapd_param param; - int ret; - const u8 *ssid = params->ssids[0].ssid; - size_t ssid_len = params->ssids[0].ssid_len; - - if (ssid == NULL) { - /* Use standard Linux Wireless Extensions ioctl if possible - * because some drivers using hostap code in wpa_supplicant - * might not support Host AP specific scan request (with SSID - * info). */ - return wpa_driver_wext_scan(drv->wext, params); - } - - if (ssid_len > 32) - ssid_len = 32; - - os_memset(¶m, 0, sizeof(param)); - param.cmd = PRISM2_HOSTAPD_SCAN_REQ; - param.u.scan_req.ssid_len = ssid_len; - os_memcpy(param.u.scan_req.ssid, ssid, ssid_len); - ret = hostapd_ioctl(drv, ¶m, sizeof(param), 1); - - /* Not all drivers generate "scan completed" wireless event, so try to - * read results after a timeout. */ - eloop_cancel_timeout(wpa_driver_wext_scan_timeout, drv->wext, - drv->ctx); - eloop_register_timeout(3, 0, wpa_driver_wext_scan_timeout, drv->wext, - drv->ctx); - - return ret; -} - - -static int wpa_driver_hostap_set_auth_alg(void *priv, int auth_alg) -{ - struct wpa_driver_hostap_data *drv = priv; - int algs = 0; - - if (auth_alg & WPA_AUTH_ALG_OPEN) - algs |= 1; - if (auth_alg & WPA_AUTH_ALG_SHARED) - algs |= 2; - if (auth_alg & WPA_AUTH_ALG_LEAP) - algs |= 4; - if (algs == 0) - algs = 1; /* at least one algorithm should be set */ - - return prism2param(drv, PRISM2_PARAM_AP_AUTH_ALGS, algs); -} - - -static int wpa_driver_hostap_get_bssid(void *priv, u8 *bssid) -{ - struct wpa_driver_hostap_data *drv = priv; - return wpa_driver_wext_get_bssid(drv->wext, bssid); -} - - -static int wpa_driver_hostap_get_ssid(void *priv, u8 *ssid) -{ - struct wpa_driver_hostap_data *drv = priv; - return wpa_driver_wext_get_ssid(drv->wext, ssid); -} - - -static struct wpa_scan_results * wpa_driver_hostap_get_scan_results(void *priv) -{ - struct wpa_driver_hostap_data *drv = priv; - return wpa_driver_wext_get_scan_results(drv->wext); -} - - -static int wpa_driver_hostap_set_operstate(void *priv, int state) -{ - struct wpa_driver_hostap_data *drv = priv; - return wpa_driver_wext_set_operstate(drv->wext, state); -} - - -static void * wpa_driver_hostap_init(void *ctx, const char *ifname) -{ - struct wpa_driver_hostap_data *drv; - - drv = os_zalloc(sizeof(*drv)); - if (drv == NULL) - return NULL; - drv->wext = wpa_driver_wext_init(ctx, ifname); - if (drv->wext == NULL) { - os_free(drv); - return NULL; - } - - drv->ctx = ctx; - os_strlcpy(drv->ifname, ifname, sizeof(drv->ifname)); - drv->sock = socket(PF_INET, SOCK_DGRAM, 0); - if (drv->sock < 0) { - perror("socket"); - wpa_driver_wext_deinit(drv->wext); - os_free(drv); - return NULL; - } - - if (os_strncmp(ifname, "wlan", 4) == 0) { - /* - * Host AP driver may use both wlan# and wifi# interface in - * wireless events. - */ - char ifname2[IFNAMSIZ + 1]; - os_strlcpy(ifname2, ifname, sizeof(ifname2)); - os_memcpy(ifname2, "wifi", 4); - wpa_driver_wext_alternative_ifindex(drv->wext, ifname2); - } - - wpa_driver_hostap_set_wpa(drv, 1); - - return drv; -} - - -static void wpa_driver_hostap_deinit(void *priv) -{ - struct wpa_driver_hostap_data *drv = priv; - wpa_driver_hostap_set_wpa(drv, 0); - wpa_driver_wext_deinit(drv->wext); - close(drv->sock); - os_free(drv); -} - -#endif /* HOSTAPD */ - - -const struct wpa_driver_ops wpa_driver_hostap_ops = { - .name = "hostap", - .desc = "Host AP driver (Intersil Prism2/2.5/3)", - .set_key = wpa_driver_hostap_set_key, -#ifdef HOSTAPD - .hapd_init = hostap_init, - .hapd_deinit = hostap_driver_deinit, - .set_ieee8021x = hostap_set_ieee8021x, - .set_privacy = hostap_set_privacy, - .get_seqnum = hostap_get_seqnum, - .flush = hostap_flush, - .set_generic_elem = hostap_set_generic_elem, - .read_sta_data = hostap_read_sta_data, - .hapd_send_eapol = hostap_send_eapol, - .sta_set_flags = hostap_sta_set_flags, - .sta_deauth = hostap_sta_deauth, - .sta_disassoc = hostap_sta_disassoc, - .sta_remove = hostap_sta_remove, - .hapd_set_ssid = hostap_set_ssid, - .send_mlme = hostap_send_mlme, - .sta_add = hostap_sta_add, - .get_inact_sec = hostap_get_inact_sec, - .sta_clear_stats = hostap_sta_clear_stats, - .get_hw_feature_data = hostap_get_hw_feature_data, - .set_ap_wps_ie = hostap_set_ap_wps_ie, -#else /* HOSTAPD */ - .get_bssid = wpa_driver_hostap_get_bssid, - .get_ssid = wpa_driver_hostap_get_ssid, - .set_countermeasures = wpa_driver_hostap_set_countermeasures, - .scan2 = wpa_driver_hostap_scan, - .get_scan_results2 = wpa_driver_hostap_get_scan_results, - .deauthenticate = wpa_driver_hostap_deauthenticate, - .disassociate = wpa_driver_hostap_disassociate, - .associate = wpa_driver_hostap_associate, - .init = wpa_driver_hostap_init, - .deinit = wpa_driver_hostap_deinit, - .set_operstate = wpa_driver_hostap_set_operstate, -#endif /* HOSTAPD */ -}; diff --git a/hostapd-0.8/src/drivers/driver_hostap.h b/hostapd-0.8/src/drivers/driver_hostap.h deleted file mode 100644 index 66b2bb3..0000000 --- a/hostapd-0.8/src/drivers/driver_hostap.h +++ /dev/null @@ -1,216 +0,0 @@ -/* - * Driver interaction with Linux Host AP driver - * Copyright (c) 2002-2006, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#ifndef HOSTAP_DRIVER_H -#define HOSTAP_DRIVER_H - -/* netdevice private ioctls (used, e.g., with iwpriv from user space) */ - -/* New wireless extensions API - SET/GET convention (even ioctl numbers are - * root only) - */ -#define PRISM2_IOCTL_PRISM2_PARAM (SIOCIWFIRSTPRIV + 0) -#define PRISM2_IOCTL_GET_PRISM2_PARAM (SIOCIWFIRSTPRIV + 1) -#define PRISM2_IOCTL_WRITEMIF (SIOCIWFIRSTPRIV + 2) -#define PRISM2_IOCTL_READMIF (SIOCIWFIRSTPRIV + 3) -#define PRISM2_IOCTL_MONITOR (SIOCIWFIRSTPRIV + 4) -#define PRISM2_IOCTL_RESET (SIOCIWFIRSTPRIV + 6) -#define PRISM2_IOCTL_INQUIRE (SIOCIWFIRSTPRIV + 8) -#define PRISM2_IOCTL_WDS_ADD (SIOCIWFIRSTPRIV + 10) -#define PRISM2_IOCTL_WDS_DEL (SIOCIWFIRSTPRIV + 12) -#define PRISM2_IOCTL_SET_RID_WORD (SIOCIWFIRSTPRIV + 14) -#define PRISM2_IOCTL_MACCMD (SIOCIWFIRSTPRIV + 16) -#define PRISM2_IOCTL_ADDMAC (SIOCIWFIRSTPRIV + 18) -#define PRISM2_IOCTL_DELMAC (SIOCIWFIRSTPRIV + 20) -#define PRISM2_IOCTL_KICKMAC (SIOCIWFIRSTPRIV + 22) - -/* following are not in SIOCGIWPRIV list; check permission in the driver code - */ -#define PRISM2_IOCTL_DOWNLOAD (SIOCDEVPRIVATE + 13) -#define PRISM2_IOCTL_HOSTAPD (SIOCDEVPRIVATE + 14) - - -/* PRISM2_IOCTL_PRISM2_PARAM ioctl() subtypes: */ -enum { - /* PRISM2_PARAM_PTYPE = 1, */ /* REMOVED 2003-10-22 */ - PRISM2_PARAM_TXRATECTRL = 2, - PRISM2_PARAM_BEACON_INT = 3, - PRISM2_PARAM_PSEUDO_IBSS = 4, - PRISM2_PARAM_ALC = 5, - /* PRISM2_PARAM_TXPOWER = 6, */ /* REMOVED 2003-10-22 */ - PRISM2_PARAM_DUMP = 7, - PRISM2_PARAM_OTHER_AP_POLICY = 8, - PRISM2_PARAM_AP_MAX_INACTIVITY = 9, - PRISM2_PARAM_AP_BRIDGE_PACKETS = 10, - PRISM2_PARAM_DTIM_PERIOD = 11, - PRISM2_PARAM_AP_NULLFUNC_ACK = 12, - PRISM2_PARAM_MAX_WDS = 13, - PRISM2_PARAM_AP_AUTOM_AP_WDS = 14, - PRISM2_PARAM_AP_AUTH_ALGS = 15, - PRISM2_PARAM_MONITOR_ALLOW_FCSERR = 16, - PRISM2_PARAM_HOST_ENCRYPT = 17, - PRISM2_PARAM_HOST_DECRYPT = 18, - PRISM2_PARAM_BUS_MASTER_THRESHOLD_RX = 19, - PRISM2_PARAM_BUS_MASTER_THRESHOLD_TX = 20, - PRISM2_PARAM_HOST_ROAMING = 21, - PRISM2_PARAM_BCRX_STA_KEY = 22, - PRISM2_PARAM_IEEE_802_1X = 23, - PRISM2_PARAM_ANTSEL_TX = 24, - PRISM2_PARAM_ANTSEL_RX = 25, - PRISM2_PARAM_MONITOR_TYPE = 26, - PRISM2_PARAM_WDS_TYPE = 27, - PRISM2_PARAM_HOSTSCAN = 28, - PRISM2_PARAM_AP_SCAN = 29, - PRISM2_PARAM_ENH_SEC = 30, - PRISM2_PARAM_IO_DEBUG = 31, - PRISM2_PARAM_BASIC_RATES = 32, - PRISM2_PARAM_OPER_RATES = 33, - PRISM2_PARAM_HOSTAPD = 34, - PRISM2_PARAM_HOSTAPD_STA = 35, - PRISM2_PARAM_WPA = 36, - PRISM2_PARAM_PRIVACY_INVOKED = 37, - PRISM2_PARAM_TKIP_COUNTERMEASURES = 38, - PRISM2_PARAM_DROP_UNENCRYPTED = 39, - PRISM2_PARAM_SCAN_CHANNEL_MASK = 40, -}; - -enum { HOSTAP_ANTSEL_DO_NOT_TOUCH = 0, HOSTAP_ANTSEL_DIVERSITY = 1, - HOSTAP_ANTSEL_LOW = 2, HOSTAP_ANTSEL_HIGH = 3 }; - - -/* PRISM2_IOCTL_MACCMD ioctl() subcommands: */ -enum { AP_MAC_CMD_POLICY_OPEN = 0, AP_MAC_CMD_POLICY_ALLOW = 1, - AP_MAC_CMD_POLICY_DENY = 2, AP_MAC_CMD_FLUSH = 3, - AP_MAC_CMD_KICKALL = 4 }; - - -/* PRISM2_IOCTL_DOWNLOAD ioctl() dl_cmd: */ -enum { - PRISM2_DOWNLOAD_VOLATILE = 1 /* RAM */, - /* Note! Old versions of prism2_srec have a fatal error in CRC-16 - * calculation, which will corrupt all non-volatile downloads. - * PRISM2_DOWNLOAD_NON_VOLATILE used to be 2, but it is now 3 to - * prevent use of old versions of prism2_srec for non-volatile - * download. */ - PRISM2_DOWNLOAD_NON_VOLATILE = 3 /* FLASH */, - PRISM2_DOWNLOAD_VOLATILE_GENESIS = 4 /* RAM in Genesis mode */, - /* Persistent versions of volatile download commands (keep firmware - * data in memory and automatically re-download after hw_reset */ - PRISM2_DOWNLOAD_VOLATILE_PERSISTENT = 5, - PRISM2_DOWNLOAD_VOLATILE_GENESIS_PERSISTENT = 6, -}; - -struct prism2_download_param { - u32 dl_cmd; - u32 start_addr; - u32 num_areas; - struct prism2_download_area { - u32 addr; /* wlan card address */ - u32 len; - caddr_t ptr; /* pointer to data in user space */ - } data[0]; -}; - -#define PRISM2_MAX_DOWNLOAD_AREA_LEN 131072 -#define PRISM2_MAX_DOWNLOAD_LEN 262144 - - -/* PRISM2_IOCTL_HOSTAPD ioctl() cmd: */ -enum { - PRISM2_HOSTAPD_FLUSH = 1, - PRISM2_HOSTAPD_ADD_STA = 2, - PRISM2_HOSTAPD_REMOVE_STA = 3, - PRISM2_HOSTAPD_GET_INFO_STA = 4, - /* REMOVED: PRISM2_HOSTAPD_RESET_TXEXC_STA = 5, */ - PRISM2_SET_ENCRYPTION = 6, - PRISM2_GET_ENCRYPTION = 7, - PRISM2_HOSTAPD_SET_FLAGS_STA = 8, - PRISM2_HOSTAPD_GET_RID = 9, - PRISM2_HOSTAPD_SET_RID = 10, - PRISM2_HOSTAPD_SET_ASSOC_AP_ADDR = 11, - PRISM2_HOSTAPD_SET_GENERIC_ELEMENT = 12, - PRISM2_HOSTAPD_MLME = 13, - PRISM2_HOSTAPD_SCAN_REQ = 14, - PRISM2_HOSTAPD_STA_CLEAR_STATS = 15, -}; - -#define PRISM2_HOSTAPD_MAX_BUF_SIZE 1024 -#define PRISM2_HOSTAPD_RID_HDR_LEN \ -((size_t) (&((struct prism2_hostapd_param *) 0)->u.rid.data)) -#define PRISM2_HOSTAPD_GENERIC_ELEMENT_HDR_LEN \ -((size_t) (&((struct prism2_hostapd_param *) 0)->u.generic_elem.data)) - -/* Maximum length for algorithm names (-1 for nul termination) used in ioctl() - */ -#define HOSTAP_CRYPT_ALG_NAME_LEN 16 - - -struct prism2_hostapd_param { - u32 cmd; - u8 sta_addr[ETH_ALEN]; - union { - struct { - u16 aid; - u16 capability; - u8 tx_supp_rates; - } add_sta; - struct { - u32 inactive_sec; - } get_info_sta; - struct { - u8 alg[HOSTAP_CRYPT_ALG_NAME_LEN]; - u32 flags; - u32 err; - u8 idx; - u8 seq[8]; /* sequence counter (set: RX, get: TX) */ - u16 key_len; - u8 key[0]; - } crypt; - struct { - u32 flags_and; - u32 flags_or; - } set_flags_sta; - struct { - u16 rid; - u16 len; - u8 data[0]; - } rid; - struct { - u8 len; - u8 data[0]; - } generic_elem; - struct { -#define MLME_STA_DEAUTH 0 -#define MLME_STA_DISASSOC 1 - u16 cmd; - u16 reason_code; - } mlme; - struct { - u8 ssid_len; - u8 ssid[32]; - } scan_req; - } u; -}; - -#define HOSTAP_CRYPT_FLAG_SET_TX_KEY BIT(0) -#define HOSTAP_CRYPT_FLAG_PERMANENT BIT(1) - -#define HOSTAP_CRYPT_ERR_UNKNOWN_ALG 2 -#define HOSTAP_CRYPT_ERR_UNKNOWN_ADDR 3 -#define HOSTAP_CRYPT_ERR_CRYPT_INIT_FAILED 4 -#define HOSTAP_CRYPT_ERR_KEY_SET_FAILED 5 -#define HOSTAP_CRYPT_ERR_TX_KEY_SET_FAILED 6 -#define HOSTAP_CRYPT_ERR_CARD_CONF_FAILED 7 - -#endif /* HOSTAP_DRIVER_H */ diff --git a/hostapd-0.8/src/drivers/driver_iphone.m b/hostapd-0.8/src/drivers/driver_iphone.m deleted file mode 100644 index 8213fda..0000000 --- a/hostapd-0.8/src/drivers/driver_iphone.m +++ /dev/null @@ -1,466 +0,0 @@ -/* - * WPA Supplicant - iPhone/iPod touch Apple80211 driver interface - * Copyright (c) 2007, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#include "includes.h" -#define Boolean __DummyBoolean -#include -#undef Boolean - -#include "common.h" -#include "driver.h" -#include "eloop.h" -#include "common/ieee802_11_defs.h" - -#include "MobileApple80211.h" - -struct wpa_driver_iphone_data { - void *ctx; - Apple80211Ref wireless_ctx; - CFArrayRef scan_results; - int ctrl_power; -}; - - -static const void * cfdict_get_key_str(CFDictionaryRef dict, const char *key) -{ - const void *res; - CFStringRef str = CFStringCreateWithCString(kCFAllocatorDefault, key, - kCFStringEncodingMacRoman); - if (str == NULL) - return NULL; - - res = CFDictionaryGetValue(dict, str); - CFRelease(str); - return res; -} - - -static int wpa_driver_iphone_get_ssid(void *priv, u8 *ssid) -{ - struct wpa_driver_iphone_data *drv = priv; - CFDataRef data; - int err, len; - - err = Apple80211CopyValue(drv->wireless_ctx, APPLE80211_VALUE_SSID, 0, - &data); - if (err != 0) { - wpa_printf(MSG_DEBUG, "iPhone: Apple80211CopyValue(SSID) " - "failed: %d", err); - return -1; - } - - len = CFDataGetLength(data); - if (len > 32) { - CFRelease(data); - return -1; - } - os_memcpy(ssid, CFDataGetBytePtr(data), len); - CFRelease(data); - - return len; -} - - -static int wpa_driver_iphone_get_bssid(void *priv, u8 *bssid) -{ - struct wpa_driver_iphone_data *drv = priv; - CFStringRef data; - int err; - int a1, a2, a3, a4, a5, a6; - - err = Apple80211CopyValue(drv->wireless_ctx, APPLE80211_VALUE_BSSID, 0, - &data); - if (err != 0) { - wpa_printf(MSG_DEBUG, "iPhone: Apple80211CopyValue(BSSID) " - "failed: %d", err); - return -1; - } - - sscanf(CFStringGetCStringPtr(data, kCFStringEncodingMacRoman), - "%x:%x:%x:%x:%x:%x", &a1, &a2, &a3, &a4, &a5, &a6); - bssid[0] = a1; - bssid[1] = a2; - bssid[2] = a3; - bssid[3] = a4; - bssid[4] = a5; - bssid[5] = a6; - - CFRelease(data); - - return 0; -} - - -static void wpa_driver_iphone_scan_timeout(void *eloop_ctx, void *timeout_ctx) -{ - wpa_supplicant_event(timeout_ctx, EVENT_SCAN_RESULTS, NULL); -} - - -static int wpa_driver_iphone_scan(void *priv, const u8 *ssid, size_t ssid_len) -{ - struct wpa_driver_iphone_data *drv = priv; - int err; - - if (drv->scan_results) { - CFRelease(drv->scan_results); - drv->scan_results = NULL; - } - - err = Apple80211Scan(drv->wireless_ctx, &drv->scan_results, NULL); - if (err) { - wpa_printf(MSG_DEBUG, "iPhone: Apple80211Scan failed: %d", - err); - return -1; - } - - eloop_register_timeout(0, 0, wpa_driver_iphone_scan_timeout, drv, - drv->ctx); - return 0; -} - - -static int wpa_driver_iphone_get_scan_results(void *priv, - struct wpa_scan_result *results, - size_t max_size) -{ - struct wpa_driver_iphone_data *drv = priv; - size_t i, num; - - if (drv->scan_results == NULL) - return 0; - - num = CFArrayGetCount(drv->scan_results); - if (num > max_size) - num = max_size; - os_memset(results, 0, num * sizeof(struct wpa_scan_result)); - - for (i = 0; i < num; i++) { - struct wpa_scan_result *res = &results[i]; - CFDictionaryRef dict = - CFArrayGetValueAtIndex(drv->scan_results, i); - CFDataRef data; - CFStringRef str; - CFNumberRef num; - int val; - - data = cfdict_get_key_str(dict, "SSID"); - if (data) { - res->ssid_len = CFDataGetLength(data); - if (res->ssid_len > 32) - res->ssid_len = 32; - os_memcpy(res->ssid, CFDataGetBytePtr(data), - res->ssid_len); - } - - str = cfdict_get_key_str(dict, "BSSID"); - if (str) { - int a1, a2, a3, a4, a5, a6; - sscanf(CFStringGetCStringPtr( - str, kCFStringEncodingMacRoman), - "%x:%x:%x:%x:%x:%x", - &a1, &a2, &a3, &a4, &a5, &a6); - res->bssid[0] = a1; - res->bssid[1] = a2; - res->bssid[2] = a3; - res->bssid[3] = a4; - res->bssid[4] = a5; - res->bssid[5] = a6; - } - - num = cfdict_get_key_str(dict, "CAPABILITIES"); - if (num) { - if (CFNumberGetValue(num, kCFNumberSInt32Type, &val)) - res->caps = val; - } - - num = cfdict_get_key_str(dict, "CHANNEL"); - if (num) { - if (CFNumberGetValue(num, kCFNumberSInt32Type, &val)) - res->freq = 2407 + val * 5; - } - - num = cfdict_get_key_str(dict, "RSSI"); - if (num) { - if (CFNumberGetValue(num, kCFNumberSInt32Type, &val)) - res->level = val; - } - - num = cfdict_get_key_str(dict, "NOISE"); - if (num) { - if (CFNumberGetValue(num, kCFNumberSInt32Type, &val)) - res->noise = val; - } - - data = cfdict_get_key_str(dict, "IE"); - if (data) { - u8 *ptr = (u8 *) CFDataGetBytePtr(data); - int len = CFDataGetLength(data); - u8 *pos = ptr, *end = ptr + len; - - while (pos + 2 < end) { - if (pos + 2 + pos[1] > end) - break; - if (pos[0] == WLAN_EID_RSN && - pos[1] <= SSID_MAX_WPA_IE_LEN) { - os_memcpy(res->rsn_ie, pos, - 2 + pos[1]); - res->rsn_ie_len = 2 + pos[1]; - } - if (pos[0] == WLAN_EID_VENDOR_SPECIFIC && - pos[1] > 4 && pos[2] == 0x00 && - pos[3] == 0x50 && pos[4] == 0xf2 && - pos[5] == 0x01) { - os_memcpy(res->wpa_ie, pos, - 2 + pos[1]); - res->wpa_ie_len = 2 + pos[1]; - } - - pos = pos + 2 + pos[1]; - } - } - } - - return num; -} - - -static void wpa_driver_iphone_assoc_timeout(void *eloop_ctx, void *timeout_ctx) -{ - struct wpa_driver_iphone_data *drv = eloop_ctx; - u8 bssid[ETH_ALEN]; - - if (wpa_driver_iphone_get_bssid(drv, bssid) != 0) { - eloop_register_timeout(1, 0, wpa_driver_iphone_assoc_timeout, - drv, drv->ctx); - return; - } - - wpa_supplicant_event(timeout_ctx, EVENT_ASSOC, NULL); -} - - -static int wpa_driver_iphone_associate( - void *priv, struct wpa_driver_associate_params *params) -{ - struct wpa_driver_iphone_data *drv = priv; - int i, num, err; - size_t ssid_len; - CFDictionaryRef bss = NULL; - - /* - * TODO: Consider generating parameters instead of just using an entry - * from scan results in order to support ap_scan=2. - */ - - if (drv->scan_results == NULL) { - wpa_printf(MSG_DEBUG, "iPhone: No scan results - cannot " - "associate"); - return -1; - } - - num = CFArrayGetCount(drv->scan_results); - - for (i = 0; i < num; i++) { - CFDictionaryRef dict = - CFArrayGetValueAtIndex(drv->scan_results, i); - CFDataRef data; - - data = cfdict_get_key_str(dict, "SSID"); - if (data == NULL) - continue; - - ssid_len = CFDataGetLength(data); - if (ssid_len != params->ssid_len || - os_memcmp(CFDataGetBytePtr(data), params->ssid, ssid_len) - != 0) - continue; - - bss = dict; - break; - } - - if (bss == NULL) { - wpa_printf(MSG_DEBUG, "iPhone: Could not find SSID from scan " - "results - cannot associate"); - return -1; - } - - wpa_printf(MSG_DEBUG, "iPhone: Trying to associate with a BSS found " - "from scan results"); - - err = Apple80211Associate(drv->wireless_ctx, bss, NULL); - if (err) { - wpa_printf(MSG_DEBUG, "iPhone: Apple80211Associate() failed: " - "%d", err); - return -1; - } - - /* - * Driver is actually already associated; report association from an - * eloop callback. - */ - eloop_cancel_timeout(wpa_driver_iphone_assoc_timeout, drv, drv->ctx); - eloop_register_timeout(0, 0, wpa_driver_iphone_assoc_timeout, drv, - drv->ctx); - - return 0; -} - - -static int wpa_driver_iphone_set_key(void *priv, wpa_alg alg, const u8 *addr, - int key_idx, int set_tx, const u8 *seq, - size_t seq_len, const u8 *key, - size_t key_len) -{ - /* - * TODO: Need to either support configuring PMK for 4-way handshake or - * PTK for TKIP/CCMP. - */ - return -1; -} - - -static int wpa_driver_iphone_get_capa(void *priv, struct wpa_driver_capa *capa) -{ - os_memset(capa, 0, sizeof(*capa)); - - capa->key_mgmt = WPA_DRIVER_CAPA_KEY_MGMT_WPA | - WPA_DRIVER_CAPA_KEY_MGMT_WPA2 | - WPA_DRIVER_CAPA_KEY_MGMT_WPA_PSK | - WPA_DRIVER_CAPA_KEY_MGMT_WPA2_PSK; - capa->enc = WPA_DRIVER_CAPA_ENC_WEP40 | WPA_DRIVER_CAPA_ENC_WEP104 | - WPA_DRIVER_CAPA_ENC_TKIP | WPA_DRIVER_CAPA_ENC_CCMP; - capa->auth = WPA_DRIVER_AUTH_OPEN | WPA_DRIVER_AUTH_SHARED | - WPA_DRIVER_AUTH_LEAP; - capa->flags = WPA_DRIVER_FLAGS_4WAY_HANDSHAKE; - - return 0; -} - - -static void * wpa_driver_iphone_init(void *ctx, const char *ifname) -{ - struct wpa_driver_iphone_data *drv; - int err; - char power; - CFStringRef name; - CFDictionaryRef dict; - - drv = os_zalloc(sizeof(*drv)); - if (drv == NULL) - return NULL; - drv->ctx = ctx; - err = Apple80211Open(&drv->wireless_ctx); - if (err) { - wpa_printf(MSG_ERROR, "iPhone: Apple80211Open failed: %d", - err); - os_free(drv); - return NULL; - } - - name = CFStringCreateWithCString(kCFAllocatorDefault, ifname, - kCFStringEncodingISOLatin1); - if (name == NULL) { - wpa_printf(MSG_ERROR, "iPhone: ifname -> CFString failed"); - Apple80211Close(drv->wireless_ctx); - os_free(drv); - return NULL; - } - - err = Apple80211BindToInterface(drv->wireless_ctx, name); - CFRelease(name); - - if (err) { - wpa_printf(MSG_ERROR, "iPhone: Apple80211BindToInterface " - "failed: %d", err); - Apple80211Close(drv->wireless_ctx); - os_free(drv); - return NULL; - } - - err = Apple80211GetPower(drv->wireless_ctx, &power); - if (err) - wpa_printf(MSG_DEBUG, "iPhone: Apple80211GetPower failed: %d", - err); - - wpa_printf(MSG_DEBUG, "iPhone: Power=%d", power); - - if (!power) { - drv->ctrl_power = 1; - err = Apple80211SetPower(drv->wireless_ctx, 1); - if (err) { - wpa_printf(MSG_DEBUG, "iPhone: Apple80211SetPower " - "failed: %d", err); - Apple80211Close(drv->wireless_ctx); - os_free(drv); - return NULL; - } - } - - err = Apple80211GetInfoCopy(drv->wireless_ctx, &dict); - if (err == 0) { - CFShow(dict); - CFRelease(dict); - } else { - printf("Apple80211GetInfoCopy: %d\n", err); - } - - return drv; -} - - -static void wpa_driver_iphone_deinit(void *priv) -{ - struct wpa_driver_iphone_data *drv = priv; - int err; - - eloop_cancel_timeout(wpa_driver_iphone_scan_timeout, drv, drv->ctx); - eloop_cancel_timeout(wpa_driver_iphone_assoc_timeout, drv, drv->ctx); - - if (drv->ctrl_power) { - wpa_printf(MSG_DEBUG, "iPhone: Power down the interface"); - err = Apple80211SetPower(drv->wireless_ctx, 0); - if (err) { - wpa_printf(MSG_DEBUG, "iPhone: Apple80211SetPower(0) " - "failed: %d", err); - } - } - - err = Apple80211Close(drv->wireless_ctx); - if (err) { - wpa_printf(MSG_DEBUG, "iPhone: Apple80211Close failed: %d", - err); - } - - if (drv->scan_results) - CFRelease(drv->scan_results); - - os_free(drv); -} - - -const struct wpa_driver_ops wpa_driver_iphone_ops = { - .name = "iphone", - .desc = "iPhone/iPod touch Apple80211 driver", - .get_ssid = wpa_driver_iphone_get_ssid, - .get_bssid = wpa_driver_iphone_get_bssid, - .init = wpa_driver_iphone_init, - .deinit = wpa_driver_iphone_deinit, - .scan = wpa_driver_iphone_scan, - .get_scan_results = wpa_driver_iphone_get_scan_results, - .associate = wpa_driver_iphone_associate, - .set_key = wpa_driver_iphone_set_key, - .get_capa = wpa_driver_iphone_get_capa, -}; diff --git a/hostapd-0.8/src/drivers/driver_madwifi.c b/hostapd-0.8/src/drivers/driver_madwifi.c deleted file mode 100644 index 630fbf4..0000000 --- a/hostapd-0.8/src/drivers/driver_madwifi.c +++ /dev/null @@ -1,1856 +0,0 @@ -/* - * WPA Supplicant - driver interaction with MADWIFI 802.11 driver - * Copyright (c) 2004, Sam Leffler - * Copyright (c) 2004, Video54 Technologies - * Copyright (c) 2004-2007, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - * - * While this driver wrapper supports both AP (hostapd) and station - * (wpa_supplicant) operations, the station side is deprecated and - * driver_wext.c should be used instead. This driver wrapper should only be - * used with hostapd for AP mode functionality. - */ - -#include "includes.h" -#include - -#include "common.h" -#include "driver.h" -#include "driver_wext.h" -#include "eloop.h" -#include "common/ieee802_11_defs.h" -#include "wireless_copy.h" - -/* - * Avoid conflicts with wpa_supplicant definitions by undefining a definition. - */ -#undef WME_OUI_TYPE - -#include -#include -#ifdef WME_NUM_AC -/* Assume this is built against BSD branch of madwifi driver. */ -#define MADWIFI_BSD -#include -#endif /* WME_NUM_AC */ -#include -#include - -#ifdef CONFIG_WPS -#ifdef IEEE80211_IOCTL_FILTERFRAME -#include - -#ifndef ETH_P_80211_RAW -#define ETH_P_80211_RAW 0x0019 -#endif -#endif /* IEEE80211_IOCTL_FILTERFRAME */ -#endif /* CONFIG_WPS */ - -/* - * Avoid conflicts with hostapd definitions by undefining couple of defines - * from madwifi header files. - */ -#undef RSN_VERSION -#undef WPA_VERSION -#undef WPA_OUI_TYPE -#undef WME_OUI_TYPE - - -#ifdef IEEE80211_IOCTL_SETWMMPARAMS -/* Assume this is built against madwifi-ng */ -#define MADWIFI_NG -#endif /* IEEE80211_IOCTL_SETWMMPARAMS */ - -#define WPA_KEY_RSC_LEN 8 - -#ifdef HOSTAPD - -#include "priv_netlink.h" -#include "netlink.h" -#include "linux_ioctl.h" -#include "l2_packet/l2_packet.h" - - -struct madwifi_driver_data { - struct hostapd_data *hapd; /* back pointer */ - - char iface[IFNAMSIZ + 1]; - int ifindex; - struct l2_packet_data *sock_xmit; /* raw packet xmit socket */ - struct l2_packet_data *sock_recv; /* raw packet recv socket */ - int ioctl_sock; /* socket for ioctl() use */ - struct netlink_data *netlink; - int we_version; - u8 acct_mac[ETH_ALEN]; - struct hostap_sta_driver_data acct_data; - - struct l2_packet_data *sock_raw; /* raw 802.11 management frames */ -}; - -static int madwifi_sta_deauth(void *priv, const u8 *own_addr, const u8 *addr, - int reason_code); - -static int -set80211priv(struct madwifi_driver_data *drv, int op, void *data, int len) -{ - struct iwreq iwr; - int do_inline = len < IFNAMSIZ; - - memset(&iwr, 0, sizeof(iwr)); - os_strlcpy(iwr.ifr_name, drv->iface, IFNAMSIZ); -#ifdef IEEE80211_IOCTL_FILTERFRAME - /* FILTERFRAME must be NOT inline, regardless of size. */ - if (op == IEEE80211_IOCTL_FILTERFRAME) - do_inline = 0; -#endif /* IEEE80211_IOCTL_FILTERFRAME */ - if (op == IEEE80211_IOCTL_SET_APPIEBUF) - do_inline = 0; - if (do_inline) { - /* - * Argument data fits inline; put it there. - */ - memcpy(iwr.u.name, data, len); - } else { - /* - * Argument data too big for inline transfer; setup a - * parameter block instead; the kernel will transfer - * the data for the driver. - */ - iwr.u.data.pointer = data; - iwr.u.data.length = len; - } - - if (ioctl(drv->ioctl_sock, op, &iwr) < 0) { -#ifdef MADWIFI_NG - int first = IEEE80211_IOCTL_SETPARAM; - static const char *opnames[] = { - "ioctl[IEEE80211_IOCTL_SETPARAM]", - "ioctl[IEEE80211_IOCTL_GETPARAM]", - "ioctl[IEEE80211_IOCTL_SETMODE]", - "ioctl[IEEE80211_IOCTL_GETMODE]", - "ioctl[IEEE80211_IOCTL_SETWMMPARAMS]", - "ioctl[IEEE80211_IOCTL_GETWMMPARAMS]", - "ioctl[IEEE80211_IOCTL_SETCHANLIST]", - "ioctl[IEEE80211_IOCTL_GETCHANLIST]", - "ioctl[IEEE80211_IOCTL_CHANSWITCH]", - "ioctl[IEEE80211_IOCTL_GET_APPIEBUF]", - "ioctl[IEEE80211_IOCTL_SET_APPIEBUF]", - "ioctl[IEEE80211_IOCTL_GETSCANRESULTS]", - "ioctl[IEEE80211_IOCTL_FILTERFRAME]", - "ioctl[IEEE80211_IOCTL_GETCHANINFO]", - "ioctl[IEEE80211_IOCTL_SETOPTIE]", - "ioctl[IEEE80211_IOCTL_GETOPTIE]", - "ioctl[IEEE80211_IOCTL_SETMLME]", - NULL, - "ioctl[IEEE80211_IOCTL_SETKEY]", - NULL, - "ioctl[IEEE80211_IOCTL_DELKEY]", - NULL, - "ioctl[IEEE80211_IOCTL_ADDMAC]", - NULL, - "ioctl[IEEE80211_IOCTL_DELMAC]", - NULL, - "ioctl[IEEE80211_IOCTL_WDSMAC]", - NULL, - "ioctl[IEEE80211_IOCTL_WDSDELMAC]", - NULL, - "ioctl[IEEE80211_IOCTL_KICKMAC]", - }; -#else /* MADWIFI_NG */ - int first = IEEE80211_IOCTL_SETPARAM; - static const char *opnames[] = { - "ioctl[IEEE80211_IOCTL_SETPARAM]", - "ioctl[IEEE80211_IOCTL_GETPARAM]", - "ioctl[IEEE80211_IOCTL_SETKEY]", - "ioctl[SIOCIWFIRSTPRIV+3]", - "ioctl[IEEE80211_IOCTL_DELKEY]", - "ioctl[SIOCIWFIRSTPRIV+5]", - "ioctl[IEEE80211_IOCTL_SETMLME]", - "ioctl[SIOCIWFIRSTPRIV+7]", - "ioctl[IEEE80211_IOCTL_SETOPTIE]", - "ioctl[IEEE80211_IOCTL_GETOPTIE]", - "ioctl[IEEE80211_IOCTL_ADDMAC]", - "ioctl[SIOCIWFIRSTPRIV+11]", - "ioctl[IEEE80211_IOCTL_DELMAC]", - "ioctl[SIOCIWFIRSTPRIV+13]", - "ioctl[IEEE80211_IOCTL_CHANLIST]", - "ioctl[SIOCIWFIRSTPRIV+15]", - "ioctl[IEEE80211_IOCTL_GETRSN]", - "ioctl[SIOCIWFIRSTPRIV+17]", - "ioctl[IEEE80211_IOCTL_GETKEY]", - }; -#endif /* MADWIFI_NG */ - int idx = op - first; - if (first <= op && - idx < (int) (sizeof(opnames) / sizeof(opnames[0])) && - opnames[idx]) - perror(opnames[idx]); - else - perror("ioctl[unknown???]"); - return -1; - } - return 0; -} - -static int -set80211param(struct madwifi_driver_data *drv, int op, int arg) -{ - struct iwreq iwr; - - memset(&iwr, 0, sizeof(iwr)); - os_strlcpy(iwr.ifr_name, drv->iface, IFNAMSIZ); - iwr.u.mode = op; - memcpy(iwr.u.name+sizeof(__u32), &arg, sizeof(arg)); - - if (ioctl(drv->ioctl_sock, IEEE80211_IOCTL_SETPARAM, &iwr) < 0) { - perror("ioctl[IEEE80211_IOCTL_SETPARAM]"); - wpa_printf(MSG_DEBUG, "%s: Failed to set parameter (op %d " - "arg %d)", __func__, op, arg); - return -1; - } - return 0; -} - -#ifndef CONFIG_NO_STDOUT_DEBUG -static const char * -ether_sprintf(const u8 *addr) -{ - static char buf[sizeof(MACSTR)]; - - if (addr != NULL) - snprintf(buf, sizeof(buf), MACSTR, MAC2STR(addr)); - else - snprintf(buf, sizeof(buf), MACSTR, 0,0,0,0,0,0); - return buf; -} -#endif /* CONFIG_NO_STDOUT_DEBUG */ - -/* - * Configure WPA parameters. - */ -static int -madwifi_configure_wpa(struct madwifi_driver_data *drv, - struct wpa_bss_params *params) -{ - int v; - - switch (params->wpa_group) { - case WPA_CIPHER_CCMP: - v = IEEE80211_CIPHER_AES_CCM; - break; - case WPA_CIPHER_TKIP: - v = IEEE80211_CIPHER_TKIP; - break; - case WPA_CIPHER_WEP104: - v = IEEE80211_CIPHER_WEP; - break; - case WPA_CIPHER_WEP40: - v = IEEE80211_CIPHER_WEP; - break; - case WPA_CIPHER_NONE: - v = IEEE80211_CIPHER_NONE; - break; - default: - wpa_printf(MSG_ERROR, "Unknown group key cipher %u", - params->wpa_group); - return -1; - } - wpa_printf(MSG_DEBUG, "%s: group key cipher=%d", __func__, v); - if (set80211param(drv, IEEE80211_PARAM_MCASTCIPHER, v)) { - printf("Unable to set group key cipher to %u\n", v); - return -1; - } - if (v == IEEE80211_CIPHER_WEP) { - /* key length is done only for specific ciphers */ - v = (params->wpa_group == WPA_CIPHER_WEP104 ? 13 : 5); - if (set80211param(drv, IEEE80211_PARAM_MCASTKEYLEN, v)) { - printf("Unable to set group key length to %u\n", v); - return -1; - } - } - - v = 0; - if (params->wpa_pairwise & WPA_CIPHER_CCMP) - v |= 1<wpa_pairwise & WPA_CIPHER_TKIP) - v |= 1<wpa_pairwise & WPA_CIPHER_NONE) - v |= 1<wpa_key_mgmt); - if (set80211param(drv, IEEE80211_PARAM_KEYMGTALGS, - params->wpa_key_mgmt)) { - printf("Unable to set key management algorithms to 0x%x\n", - params->wpa_key_mgmt); - return -1; - } - - v = 0; - if (params->rsn_preauth) - v |= BIT(0); - wpa_printf(MSG_DEBUG, "%s: rsn capabilities=0x%x", - __func__, params->rsn_preauth); - if (set80211param(drv, IEEE80211_PARAM_RSNCAPS, v)) { - printf("Unable to set RSN capabilities to 0x%x\n", v); - return -1; - } - - wpa_printf(MSG_DEBUG, "%s: enable WPA=0x%x", __func__, params->wpa); - if (set80211param(drv, IEEE80211_PARAM_WPA, params->wpa)) { - printf("Unable to set WPA to %u\n", params->wpa); - return -1; - } - return 0; -} - -static int -madwifi_set_ieee8021x(void *priv, struct wpa_bss_params *params) -{ - struct madwifi_driver_data *drv = priv; - - wpa_printf(MSG_DEBUG, "%s: enabled=%d", __func__, params->enabled); - - if (!params->enabled) { - /* XXX restore state */ - return set80211param(priv, IEEE80211_PARAM_AUTHMODE, - IEEE80211_AUTH_AUTO); - } - if (!params->wpa && !params->ieee802_1x) { - hostapd_logger(drv->hapd, NULL, HOSTAPD_MODULE_DRIVER, - HOSTAPD_LEVEL_WARNING, "No 802.1X or WPA enabled!"); - return -1; - } - if (params->wpa && madwifi_configure_wpa(drv, params) != 0) { - hostapd_logger(drv->hapd, NULL, HOSTAPD_MODULE_DRIVER, - HOSTAPD_LEVEL_WARNING, "Error configuring WPA state!"); - return -1; - } - if (set80211param(priv, IEEE80211_PARAM_AUTHMODE, - (params->wpa ? IEEE80211_AUTH_WPA : IEEE80211_AUTH_8021X))) { - hostapd_logger(drv->hapd, NULL, HOSTAPD_MODULE_DRIVER, - HOSTAPD_LEVEL_WARNING, "Error enabling WPA/802.1X!"); - return -1; - } - - return 0; -} - -static int -madwifi_set_privacy(void *priv, int enabled) -{ - struct madwifi_driver_data *drv = priv; - - wpa_printf(MSG_DEBUG, "%s: enabled=%d", __func__, enabled); - - return set80211param(drv, IEEE80211_PARAM_PRIVACY, enabled); -} - -static int -madwifi_set_sta_authorized(void *priv, const u8 *addr, int authorized) -{ - struct madwifi_driver_data *drv = priv; - struct ieee80211req_mlme mlme; - int ret; - - wpa_printf(MSG_DEBUG, "%s: addr=%s authorized=%d", - __func__, ether_sprintf(addr), authorized); - - if (authorized) - mlme.im_op = IEEE80211_MLME_AUTHORIZE; - else - mlme.im_op = IEEE80211_MLME_UNAUTHORIZE; - mlme.im_reason = 0; - memcpy(mlme.im_macaddr, addr, IEEE80211_ADDR_LEN); - ret = set80211priv(drv, IEEE80211_IOCTL_SETMLME, &mlme, sizeof(mlme)); - if (ret < 0) { - wpa_printf(MSG_DEBUG, "%s: Failed to %sauthorize STA " MACSTR, - __func__, authorized ? "" : "un", MAC2STR(addr)); - } - - return ret; -} - -static int -madwifi_sta_set_flags(void *priv, const u8 *addr, - int total_flags, int flags_or, int flags_and) -{ - /* For now, only support setting Authorized flag */ - if (flags_or & WPA_STA_AUTHORIZED) - return madwifi_set_sta_authorized(priv, addr, 1); - if (!(flags_and & WPA_STA_AUTHORIZED)) - return madwifi_set_sta_authorized(priv, addr, 0); - return 0; -} - -static int -madwifi_del_key(void *priv, const u8 *addr, int key_idx) -{ - struct madwifi_driver_data *drv = priv; - struct ieee80211req_del_key wk; - int ret; - - wpa_printf(MSG_DEBUG, "%s: addr=%s key_idx=%d", - __func__, ether_sprintf(addr), key_idx); - - memset(&wk, 0, sizeof(wk)); - if (addr != NULL) { - memcpy(wk.idk_macaddr, addr, IEEE80211_ADDR_LEN); - wk.idk_keyix = (u8) IEEE80211_KEYIX_NONE; - } else { - wk.idk_keyix = key_idx; - } - - ret = set80211priv(drv, IEEE80211_IOCTL_DELKEY, &wk, sizeof(wk)); - if (ret < 0) { - wpa_printf(MSG_DEBUG, "%s: Failed to delete key (addr %s" - " key_idx %d)", __func__, ether_sprintf(addr), - key_idx); - } - - return ret; -} - -static int -wpa_driver_madwifi_set_key(const char *ifname, void *priv, enum wpa_alg alg, - const u8 *addr, int key_idx, int set_tx, - const u8 *seq, size_t seq_len, - const u8 *key, size_t key_len) -{ - struct madwifi_driver_data *drv = priv; - struct ieee80211req_key wk; - u_int8_t cipher; - int ret; - - if (alg == WPA_ALG_NONE) - return madwifi_del_key(drv, addr, key_idx); - - wpa_printf(MSG_DEBUG, "%s: alg=%d addr=%s key_idx=%d", - __func__, alg, ether_sprintf(addr), key_idx); - - if (alg == WPA_ALG_WEP) - cipher = IEEE80211_CIPHER_WEP; - else if (alg == WPA_ALG_TKIP) - cipher = IEEE80211_CIPHER_TKIP; - else if (alg == WPA_ALG_CCMP) - cipher = IEEE80211_CIPHER_AES_CCM; - else { - printf("%s: unknown/unsupported algorithm %d\n", - __func__, alg); - return -1; - } - - if (key_len > sizeof(wk.ik_keydata)) { - printf("%s: key length %lu too big\n", __func__, - (unsigned long) key_len); - return -3; - } - - memset(&wk, 0, sizeof(wk)); - wk.ik_type = cipher; - wk.ik_flags = IEEE80211_KEY_RECV | IEEE80211_KEY_XMIT; - if (addr == NULL || is_broadcast_ether_addr(addr)) { - memset(wk.ik_macaddr, 0xff, IEEE80211_ADDR_LEN); - wk.ik_keyix = key_idx; - wk.ik_flags |= IEEE80211_KEY_DEFAULT; - } else { - memcpy(wk.ik_macaddr, addr, IEEE80211_ADDR_LEN); - wk.ik_keyix = IEEE80211_KEYIX_NONE; - } - wk.ik_keylen = key_len; - memcpy(wk.ik_keydata, key, key_len); - - ret = set80211priv(drv, IEEE80211_IOCTL_SETKEY, &wk, sizeof(wk)); - if (ret < 0) { - wpa_printf(MSG_DEBUG, "%s: Failed to set key (addr %s" - " key_idx %d alg %d key_len %lu set_tx %d)", - __func__, ether_sprintf(wk.ik_macaddr), key_idx, - alg, (unsigned long) key_len, set_tx); - } - - return ret; -} - - -static int -madwifi_get_seqnum(const char *ifname, void *priv, const u8 *addr, int idx, - u8 *seq) -{ - struct madwifi_driver_data *drv = priv; - struct ieee80211req_key wk; - - wpa_printf(MSG_DEBUG, "%s: addr=%s idx=%d", - __func__, ether_sprintf(addr), idx); - - memset(&wk, 0, sizeof(wk)); - if (addr == NULL) - memset(wk.ik_macaddr, 0xff, IEEE80211_ADDR_LEN); - else - memcpy(wk.ik_macaddr, addr, IEEE80211_ADDR_LEN); - wk.ik_keyix = idx; - - if (set80211priv(drv, IEEE80211_IOCTL_GETKEY, &wk, sizeof(wk))) { - wpa_printf(MSG_DEBUG, "%s: Failed to get encryption data " - "(addr " MACSTR " key_idx %d)", - __func__, MAC2STR(wk.ik_macaddr), idx); - return -1; - } - -#ifdef WORDS_BIGENDIAN - { - /* - * wk.ik_keytsc is in host byte order (big endian), need to - * swap it to match with the byte order used in WPA. - */ - int i; - u8 tmp[WPA_KEY_RSC_LEN]; - memcpy(tmp, &wk.ik_keytsc, sizeof(wk.ik_keytsc)); - for (i = 0; i < WPA_KEY_RSC_LEN; i++) { - seq[i] = tmp[WPA_KEY_RSC_LEN - i - 1]; - } - } -#else /* WORDS_BIGENDIAN */ - memcpy(seq, &wk.ik_keytsc, sizeof(wk.ik_keytsc)); -#endif /* WORDS_BIGENDIAN */ - return 0; -} - - -static int -madwifi_flush(void *priv) -{ -#ifdef MADWIFI_BSD - u8 allsta[IEEE80211_ADDR_LEN]; - memset(allsta, 0xff, IEEE80211_ADDR_LEN); - return madwifi_sta_deauth(priv, NULL, allsta, - IEEE80211_REASON_AUTH_LEAVE); -#else /* MADWIFI_BSD */ - return 0; /* XXX */ -#endif /* MADWIFI_BSD */ -} - - -static int -madwifi_read_sta_driver_data(void *priv, struct hostap_sta_driver_data *data, - const u8 *addr) -{ - struct madwifi_driver_data *drv = priv; - -#ifdef MADWIFI_BSD - struct ieee80211req_sta_stats stats; - - memset(data, 0, sizeof(*data)); - - /* - * Fetch statistics for station from the system. - */ - memset(&stats, 0, sizeof(stats)); - memcpy(stats.is_u.macaddr, addr, IEEE80211_ADDR_LEN); - if (set80211priv(drv, -#ifdef MADWIFI_NG - IEEE80211_IOCTL_STA_STATS, -#else /* MADWIFI_NG */ - IEEE80211_IOCTL_GETSTASTATS, -#endif /* MADWIFI_NG */ - &stats, sizeof(stats))) { - wpa_printf(MSG_DEBUG, "%s: Failed to fetch STA stats (addr " - MACSTR ")", __func__, MAC2STR(addr)); - if (memcmp(addr, drv->acct_mac, ETH_ALEN) == 0) { - memcpy(data, &drv->acct_data, sizeof(*data)); - return 0; - } - - printf("Failed to get station stats information element.\n"); - return -1; - } - - data->rx_packets = stats.is_stats.ns_rx_data; - data->rx_bytes = stats.is_stats.ns_rx_bytes; - data->tx_packets = stats.is_stats.ns_tx_data; - data->tx_bytes = stats.is_stats.ns_tx_bytes; - return 0; - -#else /* MADWIFI_BSD */ - - char buf[1024], line[128], *pos; - FILE *f; - unsigned long val; - - memset(data, 0, sizeof(*data)); - snprintf(buf, sizeof(buf), "/proc/net/madwifi/%s/" MACSTR, - drv->iface, MAC2STR(addr)); - - f = fopen(buf, "r"); - if (!f) { - if (memcmp(addr, drv->acct_mac, ETH_ALEN) != 0) - return -1; - memcpy(data, &drv->acct_data, sizeof(*data)); - return 0; - } - /* Need to read proc file with in one piece, so use large enough - * buffer. */ - setbuffer(f, buf, sizeof(buf)); - - while (fgets(line, sizeof(line), f)) { - pos = strchr(line, '='); - if (!pos) - continue; - *pos++ = '\0'; - val = strtoul(pos, NULL, 10); - if (strcmp(line, "rx_packets") == 0) - data->rx_packets = val; - else if (strcmp(line, "tx_packets") == 0) - data->tx_packets = val; - else if (strcmp(line, "rx_bytes") == 0) - data->rx_bytes = val; - else if (strcmp(line, "tx_bytes") == 0) - data->tx_bytes = val; - } - - fclose(f); - - return 0; -#endif /* MADWIFI_BSD */ -} - - -static int -madwifi_sta_clear_stats(void *priv, const u8 *addr) -{ -#if defined(MADWIFI_BSD) && defined(IEEE80211_MLME_CLEAR_STATS) - struct madwifi_driver_data *drv = priv; - struct ieee80211req_mlme mlme; - int ret; - - wpa_printf(MSG_DEBUG, "%s: addr=%s", __func__, ether_sprintf(addr)); - - mlme.im_op = IEEE80211_MLME_CLEAR_STATS; - memcpy(mlme.im_macaddr, addr, IEEE80211_ADDR_LEN); - ret = set80211priv(drv, IEEE80211_IOCTL_SETMLME, &mlme, - sizeof(mlme)); - if (ret < 0) { - wpa_printf(MSG_DEBUG, "%s: Failed to clear STA stats (addr " - MACSTR ")", __func__, MAC2STR(addr)); - } - - return ret; -#else /* MADWIFI_BSD && IEEE80211_MLME_CLEAR_STATS */ - return 0; /* FIX */ -#endif /* MADWIFI_BSD && IEEE80211_MLME_CLEAR_STATS */ -} - - -static int -madwifi_set_opt_ie(void *priv, const u8 *ie, size_t ie_len) -{ - /* - * Do nothing; we setup parameters at startup that define the - * contents of the beacon information element. - */ - return 0; -} - -static int -madwifi_sta_deauth(void *priv, const u8 *own_addr, const u8 *addr, - int reason_code) -{ - struct madwifi_driver_data *drv = priv; - struct ieee80211req_mlme mlme; - int ret; - - wpa_printf(MSG_DEBUG, "%s: addr=%s reason_code=%d", - __func__, ether_sprintf(addr), reason_code); - - mlme.im_op = IEEE80211_MLME_DEAUTH; - mlme.im_reason = reason_code; - memcpy(mlme.im_macaddr, addr, IEEE80211_ADDR_LEN); - ret = set80211priv(drv, IEEE80211_IOCTL_SETMLME, &mlme, sizeof(mlme)); - if (ret < 0) { - wpa_printf(MSG_DEBUG, "%s: Failed to deauth STA (addr " MACSTR - " reason %d)", - __func__, MAC2STR(addr), reason_code); - } - - return ret; -} - -static int -madwifi_sta_disassoc(void *priv, const u8 *own_addr, const u8 *addr, - int reason_code) -{ - struct madwifi_driver_data *drv = priv; - struct ieee80211req_mlme mlme; - int ret; - - wpa_printf(MSG_DEBUG, "%s: addr=%s reason_code=%d", - __func__, ether_sprintf(addr), reason_code); - - mlme.im_op = IEEE80211_MLME_DISASSOC; - mlme.im_reason = reason_code; - memcpy(mlme.im_macaddr, addr, IEEE80211_ADDR_LEN); - ret = set80211priv(drv, IEEE80211_IOCTL_SETMLME, &mlme, sizeof(mlme)); - if (ret < 0) { - wpa_printf(MSG_DEBUG, "%s: Failed to disassoc STA (addr " - MACSTR " reason %d)", - __func__, MAC2STR(addr), reason_code); - } - - return ret; -} - -#ifdef CONFIG_WPS -#ifdef IEEE80211_IOCTL_FILTERFRAME -static void madwifi_raw_receive(void *ctx, const u8 *src_addr, const u8 *buf, - size_t len) -{ - struct madwifi_driver_data *drv = ctx; - const struct ieee80211_mgmt *mgmt; - u16 fc; - union wpa_event_data event; - - /* Send Probe Request information to WPS processing */ - - if (len < IEEE80211_HDRLEN + sizeof(mgmt->u.probe_req)) - return; - mgmt = (const struct ieee80211_mgmt *) buf; - - fc = le_to_host16(mgmt->frame_control); - if (WLAN_FC_GET_TYPE(fc) != WLAN_FC_TYPE_MGMT || - WLAN_FC_GET_STYPE(fc) != WLAN_FC_STYPE_PROBE_REQ) - return; - - os_memset(&event, 0, sizeof(event)); - event.rx_probe_req.sa = mgmt->sa; - event.rx_probe_req.ie = mgmt->u.probe_req.variable; - event.rx_probe_req.ie_len = - len - (IEEE80211_HDRLEN + sizeof(mgmt->u.probe_req)); - wpa_supplicant_event(drv->hapd, EVENT_RX_PROBE_REQ, &event); -} -#endif /* IEEE80211_IOCTL_FILTERFRAME */ -#endif /* CONFIG_WPS */ - -static int madwifi_receive_probe_req(struct madwifi_driver_data *drv) -{ - int ret = 0; -#ifdef CONFIG_WPS -#ifdef IEEE80211_IOCTL_FILTERFRAME - struct ieee80211req_set_filter filt; - - wpa_printf(MSG_DEBUG, "%s Enter", __func__); - filt.app_filterype = IEEE80211_FILTER_TYPE_PROBE_REQ; - - ret = set80211priv(drv, IEEE80211_IOCTL_FILTERFRAME, &filt, - sizeof(struct ieee80211req_set_filter)); - if (ret) - return ret; - - drv->sock_raw = l2_packet_init(drv->iface, NULL, ETH_P_80211_RAW, - madwifi_raw_receive, drv, 1); - if (drv->sock_raw == NULL) - return -1; -#endif /* IEEE80211_IOCTL_FILTERFRAME */ -#endif /* CONFIG_WPS */ - return ret; -} - -#ifdef CONFIG_WPS -static int -madwifi_set_wps_ie(void *priv, const u8 *ie, size_t len, u32 frametype) -{ - struct madwifi_driver_data *drv = priv; - u8 buf[256]; - struct ieee80211req_getset_appiebuf *beac_ie; - - wpa_printf(MSG_DEBUG, "%s buflen = %lu", __func__, - (unsigned long) len); - - beac_ie = (struct ieee80211req_getset_appiebuf *) buf; - beac_ie->app_frmtype = frametype; - beac_ie->app_buflen = len; - memcpy(&(beac_ie->app_buf[0]), ie, len); - - return set80211priv(drv, IEEE80211_IOCTL_SET_APPIEBUF, beac_ie, - sizeof(struct ieee80211req_getset_appiebuf) + len); -} - -static int -madwifi_set_ap_wps_ie(void *priv, const struct wpabuf *beacon, - const struct wpabuf *proberesp, - const struct wpabuf *assocresp) -{ - if (madwifi_set_wps_ie(priv, beacon ? wpabuf_head(beacon) : NULL, - beacon ? wpabuf_len(beacon) : 0, - IEEE80211_APPIE_FRAME_BEACON) < 0) - return -1; - return madwifi_set_wps_ie(priv, - proberesp ? wpabuf_head(proberesp) : NULL, - proberesp ? wpabuf_len(proberesp) : 0, - IEEE80211_APPIE_FRAME_PROBE_RESP); -} -#else /* CONFIG_WPS */ -#define madwifi_set_ap_wps_ie NULL -#endif /* CONFIG_WPS */ - -static void -madwifi_new_sta(struct madwifi_driver_data *drv, u8 addr[IEEE80211_ADDR_LEN]) -{ - struct hostapd_data *hapd = drv->hapd; - struct ieee80211req_wpaie ie; - int ielen = 0; - u8 *iebuf = NULL; - - /* - * Fetch negotiated WPA/RSN parameters from the system. - */ - memset(&ie, 0, sizeof(ie)); - memcpy(ie.wpa_macaddr, addr, IEEE80211_ADDR_LEN); - if (set80211priv(drv, IEEE80211_IOCTL_GETWPAIE, &ie, sizeof(ie))) { - wpa_printf(MSG_DEBUG, "%s: Failed to get WPA/RSN IE", - __func__); - goto no_ie; - } - wpa_hexdump(MSG_MSGDUMP, "madwifi req WPA IE", - ie.wpa_ie, IEEE80211_MAX_OPT_IE); - iebuf = ie.wpa_ie; - /* madwifi seems to return some random data if WPA/RSN IE is not set. - * Assume the IE was not included if the IE type is unknown. */ - if (iebuf[0] != WLAN_EID_VENDOR_SPECIFIC) - iebuf[1] = 0; -#ifdef MADWIFI_NG - wpa_hexdump(MSG_MSGDUMP, "madwifi req RSN IE", - ie.rsn_ie, IEEE80211_MAX_OPT_IE); - if (iebuf[1] == 0 && ie.rsn_ie[1] > 0) { - /* madwifi-ng svn #1453 added rsn_ie. Use it, if wpa_ie was not - * set. This is needed for WPA2. */ - iebuf = ie.rsn_ie; - if (iebuf[0] != WLAN_EID_RSN) - iebuf[1] = 0; - } -#endif /* MADWIFI_NG */ - - ielen = iebuf[1]; - if (ielen == 0) - iebuf = NULL; - else - ielen += 2; - -no_ie: - drv_event_assoc(hapd, addr, iebuf, ielen, 0); - - if (memcmp(addr, drv->acct_mac, ETH_ALEN) == 0) { - /* Cached accounting data is not valid anymore. */ - memset(drv->acct_mac, 0, ETH_ALEN); - memset(&drv->acct_data, 0, sizeof(drv->acct_data)); - } -} - -static void -madwifi_wireless_event_wireless_custom(struct madwifi_driver_data *drv, - char *custom) -{ - wpa_printf(MSG_DEBUG, "Custom wireless event: '%s'", custom); - - if (strncmp(custom, "MLME-MICHAELMICFAILURE.indication", 33) == 0) { - char *pos; - u8 addr[ETH_ALEN]; - pos = strstr(custom, "addr="); - if (pos == NULL) { - wpa_printf(MSG_DEBUG, - "MLME-MICHAELMICFAILURE.indication " - "without sender address ignored"); - return; - } - pos += 5; - if (hwaddr_aton(pos, addr) == 0) { - union wpa_event_data data; - os_memset(&data, 0, sizeof(data)); - data.michael_mic_failure.unicast = 1; - data.michael_mic_failure.src = addr; - wpa_supplicant_event(drv->hapd, - EVENT_MICHAEL_MIC_FAILURE, &data); - } else { - wpa_printf(MSG_DEBUG, - "MLME-MICHAELMICFAILURE.indication " - "with invalid MAC address"); - } - } else if (strncmp(custom, "STA-TRAFFIC-STAT", 16) == 0) { - char *key, *value; - u32 val; - key = custom; - while ((key = strchr(key, '\n')) != NULL) { - key++; - value = strchr(key, '='); - if (value == NULL) - continue; - *value++ = '\0'; - val = strtoul(value, NULL, 10); - if (strcmp(key, "mac") == 0) - hwaddr_aton(value, drv->acct_mac); - else if (strcmp(key, "rx_packets") == 0) - drv->acct_data.rx_packets = val; - else if (strcmp(key, "tx_packets") == 0) - drv->acct_data.tx_packets = val; - else if (strcmp(key, "rx_bytes") == 0) - drv->acct_data.rx_bytes = val; - else if (strcmp(key, "tx_bytes") == 0) - drv->acct_data.tx_bytes = val; - key = value; - } - } -} - -static void -madwifi_wireless_event_wireless(struct madwifi_driver_data *drv, - char *data, int len) -{ - struct iw_event iwe_buf, *iwe = &iwe_buf; - char *pos, *end, *custom, *buf; - - pos = data; - end = data + len; - - while (pos + IW_EV_LCP_LEN <= end) { - /* Event data may be unaligned, so make a local, aligned copy - * before processing. */ - memcpy(&iwe_buf, pos, IW_EV_LCP_LEN); - wpa_printf(MSG_MSGDUMP, "Wireless event: cmd=0x%x len=%d", - iwe->cmd, iwe->len); - if (iwe->len <= IW_EV_LCP_LEN) - return; - - custom = pos + IW_EV_POINT_LEN; - if (drv->we_version > 18 && - (iwe->cmd == IWEVMICHAELMICFAILURE || - iwe->cmd == IWEVCUSTOM)) { - /* WE-19 removed the pointer from struct iw_point */ - char *dpos = (char *) &iwe_buf.u.data.length; - int dlen = dpos - (char *) &iwe_buf; - memcpy(dpos, pos + IW_EV_LCP_LEN, - sizeof(struct iw_event) - dlen); - } else { - memcpy(&iwe_buf, pos, sizeof(struct iw_event)); - custom += IW_EV_POINT_OFF; - } - - switch (iwe->cmd) { - case IWEVEXPIRED: - drv_event_disassoc(drv->hapd, - (u8 *) iwe->u.addr.sa_data); - break; - case IWEVREGISTERED: - madwifi_new_sta(drv, (u8 *) iwe->u.addr.sa_data); - break; - case IWEVCUSTOM: - if (custom + iwe->u.data.length > end) - return; - buf = malloc(iwe->u.data.length + 1); - if (buf == NULL) - return; /* XXX */ - memcpy(buf, custom, iwe->u.data.length); - buf[iwe->u.data.length] = '\0'; - madwifi_wireless_event_wireless_custom(drv, buf); - free(buf); - break; - } - - pos += iwe->len; - } -} - - -static void -madwifi_wireless_event_rtm_newlink(void *ctx, struct ifinfomsg *ifi, - u8 *buf, size_t len) -{ - struct madwifi_driver_data *drv = ctx; - int attrlen, rta_len; - struct rtattr *attr; - - if (ifi->ifi_index != drv->ifindex) - return; - - attrlen = len; - attr = (struct rtattr *) buf; - - rta_len = RTA_ALIGN(sizeof(struct rtattr)); - while (RTA_OK(attr, attrlen)) { - if (attr->rta_type == IFLA_WIRELESS) { - madwifi_wireless_event_wireless( - drv, ((char *) attr) + rta_len, - attr->rta_len - rta_len); - } - attr = RTA_NEXT(attr, attrlen); - } -} - - -static int -madwifi_get_we_version(struct madwifi_driver_data *drv) -{ - struct iw_range *range; - struct iwreq iwr; - int minlen; - size_t buflen; - - drv->we_version = 0; - - /* - * Use larger buffer than struct iw_range in order to allow the - * structure to grow in the future. - */ - buflen = sizeof(struct iw_range) + 500; - range = os_zalloc(buflen); - if (range == NULL) - return -1; - - memset(&iwr, 0, sizeof(iwr)); - os_strlcpy(iwr.ifr_name, drv->iface, IFNAMSIZ); - iwr.u.data.pointer = (caddr_t) range; - iwr.u.data.length = buflen; - - minlen = ((char *) &range->enc_capa) - (char *) range + - sizeof(range->enc_capa); - - if (ioctl(drv->ioctl_sock, SIOCGIWRANGE, &iwr) < 0) { - perror("ioctl[SIOCGIWRANGE]"); - free(range); - return -1; - } else if (iwr.u.data.length >= minlen && - range->we_version_compiled >= 18) { - wpa_printf(MSG_DEBUG, "SIOCGIWRANGE: WE(compiled)=%d " - "WE(source)=%d enc_capa=0x%x", - range->we_version_compiled, - range->we_version_source, - range->enc_capa); - drv->we_version = range->we_version_compiled; - } - - free(range); - return 0; -} - - -static int -madwifi_wireless_event_init(struct madwifi_driver_data *drv) -{ - struct netlink_config *cfg; - - madwifi_get_we_version(drv); - - cfg = os_zalloc(sizeof(*cfg)); - if (cfg == NULL) - return -1; - cfg->ctx = drv; - cfg->newlink_cb = madwifi_wireless_event_rtm_newlink; - drv->netlink = netlink_init(cfg); - if (drv->netlink == NULL) { - os_free(cfg); - return -1; - } - - return 0; -} - - -static int -madwifi_send_eapol(void *priv, const u8 *addr, const u8 *data, size_t data_len, - int encrypt, const u8 *own_addr, u32 flags) -{ - struct madwifi_driver_data *drv = priv; - unsigned char buf[3000]; - unsigned char *bp = buf; - struct l2_ethhdr *eth; - size_t len; - int status; - - /* - * Prepend the Ethernet header. If the caller left us - * space at the front we could just insert it but since - * we don't know we copy to a local buffer. Given the frequency - * and size of frames this probably doesn't matter. - */ - len = data_len + sizeof(struct l2_ethhdr); - if (len > sizeof(buf)) { - bp = malloc(len); - if (bp == NULL) { - printf("EAPOL frame discarded, cannot malloc temp " - "buffer of size %lu!\n", (unsigned long) len); - return -1; - } - } - eth = (struct l2_ethhdr *) bp; - memcpy(eth->h_dest, addr, ETH_ALEN); - memcpy(eth->h_source, own_addr, ETH_ALEN); - eth->h_proto = host_to_be16(ETH_P_EAPOL); - memcpy(eth+1, data, data_len); - - wpa_hexdump(MSG_MSGDUMP, "TX EAPOL", bp, len); - - status = l2_packet_send(drv->sock_xmit, addr, ETH_P_EAPOL, bp, len); - - if (bp != buf) - free(bp); - return status; -} - -static void -handle_read(void *ctx, const u8 *src_addr, const u8 *buf, size_t len) -{ - struct madwifi_driver_data *drv = ctx; - drv_event_eapol_rx(drv->hapd, src_addr, buf + sizeof(struct l2_ethhdr), - len - sizeof(struct l2_ethhdr)); -} - -static void * -madwifi_init(struct hostapd_data *hapd, struct wpa_init_params *params) -{ - struct madwifi_driver_data *drv; - struct ifreq ifr; - struct iwreq iwr; - char brname[IFNAMSIZ]; - - drv = os_zalloc(sizeof(struct madwifi_driver_data)); - if (drv == NULL) { - printf("Could not allocate memory for madwifi driver data\n"); - return NULL; - } - - drv->hapd = hapd; - drv->ioctl_sock = socket(PF_INET, SOCK_DGRAM, 0); - if (drv->ioctl_sock < 0) { - perror("socket[PF_INET,SOCK_DGRAM]"); - goto bad; - } - memcpy(drv->iface, params->ifname, sizeof(drv->iface)); - - memset(&ifr, 0, sizeof(ifr)); - os_strlcpy(ifr.ifr_name, drv->iface, sizeof(ifr.ifr_name)); - if (ioctl(drv->ioctl_sock, SIOCGIFINDEX, &ifr) != 0) { - perror("ioctl(SIOCGIFINDEX)"); - goto bad; - } - drv->ifindex = ifr.ifr_ifindex; - - drv->sock_xmit = l2_packet_init(drv->iface, NULL, ETH_P_EAPOL, - handle_read, drv, 1); - if (drv->sock_xmit == NULL) - goto bad; - if (l2_packet_get_own_addr(drv->sock_xmit, params->own_addr)) - goto bad; - if (params->bridge[0]) { - wpa_printf(MSG_DEBUG, "Configure bridge %s for EAPOL traffic.", - params->bridge[0]); - drv->sock_recv = l2_packet_init(params->bridge[0], NULL, - ETH_P_EAPOL, handle_read, drv, - 1); - if (drv->sock_recv == NULL) - goto bad; - } else if (linux_br_get(brname, drv->iface) == 0) { - wpa_printf(MSG_DEBUG, "Interface in bridge %s; configure for " - "EAPOL receive", brname); - drv->sock_recv = l2_packet_init(brname, NULL, ETH_P_EAPOL, - handle_read, drv, 1); - if (drv->sock_recv == NULL) - goto bad; - } else - drv->sock_recv = drv->sock_xmit; - - memset(&iwr, 0, sizeof(iwr)); - os_strlcpy(iwr.ifr_name, drv->iface, IFNAMSIZ); - - iwr.u.mode = IW_MODE_MASTER; - - if (ioctl(drv->ioctl_sock, SIOCSIWMODE, &iwr) < 0) { - perror("ioctl[SIOCSIWMODE]"); - printf("Could not set interface to master mode!\n"); - goto bad; - } - - /* mark down during setup */ - linux_set_iface_flags(drv->ioctl_sock, drv->iface, 0); - madwifi_set_privacy(drv, 0); /* default to no privacy */ - - madwifi_receive_probe_req(drv); - - if (madwifi_wireless_event_init(drv)) - goto bad; - - return drv; -bad: - if (drv->sock_xmit != NULL) - l2_packet_deinit(drv->sock_xmit); - if (drv->ioctl_sock >= 0) - close(drv->ioctl_sock); - if (drv != NULL) - free(drv); - return NULL; -} - - -static void -madwifi_deinit(void *priv) -{ - struct madwifi_driver_data *drv = priv; - - netlink_deinit(drv->netlink); - (void) linux_set_iface_flags(drv->ioctl_sock, drv->iface, 0); - if (drv->ioctl_sock >= 0) - close(drv->ioctl_sock); - if (drv->sock_recv != NULL && drv->sock_recv != drv->sock_xmit) - l2_packet_deinit(drv->sock_recv); - if (drv->sock_xmit != NULL) - l2_packet_deinit(drv->sock_xmit); - if (drv->sock_raw) - l2_packet_deinit(drv->sock_raw); - free(drv); -} - -static int -madwifi_set_ssid(void *priv, const u8 *buf, int len) -{ - struct madwifi_driver_data *drv = priv; - struct iwreq iwr; - - memset(&iwr, 0, sizeof(iwr)); - os_strlcpy(iwr.ifr_name, drv->iface, IFNAMSIZ); - iwr.u.essid.flags = 1; /* SSID active */ - iwr.u.essid.pointer = (caddr_t) buf; - iwr.u.essid.length = len + 1; - - if (ioctl(drv->ioctl_sock, SIOCSIWESSID, &iwr) < 0) { - perror("ioctl[SIOCSIWESSID]"); - printf("len=%d\n", len); - return -1; - } - return 0; -} - -static int -madwifi_get_ssid(void *priv, u8 *buf, int len) -{ - struct madwifi_driver_data *drv = priv; - struct iwreq iwr; - int ret = 0; - - memset(&iwr, 0, sizeof(iwr)); - os_strlcpy(iwr.ifr_name, drv->iface, IFNAMSIZ); - iwr.u.essid.pointer = (caddr_t) buf; - iwr.u.essid.length = len; - - if (ioctl(drv->ioctl_sock, SIOCGIWESSID, &iwr) < 0) { - perror("ioctl[SIOCGIWESSID]"); - ret = -1; - } else - ret = iwr.u.essid.length; - - return ret; -} - -static int -madwifi_set_countermeasures(void *priv, int enabled) -{ - struct madwifi_driver_data *drv = priv; - wpa_printf(MSG_DEBUG, "%s: enabled=%d", __FUNCTION__, enabled); - return set80211param(drv, IEEE80211_PARAM_COUNTERMEASURES, enabled); -} - -static int -madwifi_commit(void *priv) -{ - struct madwifi_driver_data *drv = priv; - return linux_set_iface_flags(drv->ioctl_sock, drv->iface, 1); -} - -#else /* HOSTAPD */ - -struct wpa_driver_madwifi_data { - void *wext; /* private data for driver_wext */ - void *ctx; - char ifname[IFNAMSIZ + 1]; - int sock; -}; - -static int wpa_driver_madwifi_set_auth_alg(void *priv, int auth_alg); -static int wpa_driver_madwifi_set_probe_req_ie(void *priv, const u8 *ies, - size_t ies_len); - - -static int -set80211priv(struct wpa_driver_madwifi_data *drv, int op, void *data, int len, - int show_err) -{ - struct iwreq iwr; - - os_memset(&iwr, 0, sizeof(iwr)); - os_strlcpy(iwr.ifr_name, drv->ifname, IFNAMSIZ); - if (len < IFNAMSIZ && - op != IEEE80211_IOCTL_SET_APPIEBUF) { - /* - * Argument data fits inline; put it there. - */ - os_memcpy(iwr.u.name, data, len); - } else { - /* - * Argument data too big for inline transfer; setup a - * parameter block instead; the kernel will transfer - * the data for the driver. - */ - iwr.u.data.pointer = data; - iwr.u.data.length = len; - } - - if (ioctl(drv->sock, op, &iwr) < 0) { - if (show_err) { -#ifdef MADWIFI_NG - int first = IEEE80211_IOCTL_SETPARAM; - int last = IEEE80211_IOCTL_KICKMAC; - static const char *opnames[] = { - "ioctl[IEEE80211_IOCTL_SETPARAM]", - "ioctl[IEEE80211_IOCTL_GETPARAM]", - "ioctl[IEEE80211_IOCTL_SETMODE]", - "ioctl[IEEE80211_IOCTL_GETMODE]", - "ioctl[IEEE80211_IOCTL_SETWMMPARAMS]", - "ioctl[IEEE80211_IOCTL_GETWMMPARAMS]", - "ioctl[IEEE80211_IOCTL_SETCHANLIST]", - "ioctl[IEEE80211_IOCTL_GETCHANLIST]", - "ioctl[IEEE80211_IOCTL_CHANSWITCH]", - NULL, - "ioctl[IEEE80211_IOCTL_SET_APPIEBUF]", - "ioctl[IEEE80211_IOCTL_GETSCANRESULTS]", - NULL, - "ioctl[IEEE80211_IOCTL_GETCHANINFO]", - "ioctl[IEEE80211_IOCTL_SETOPTIE]", - "ioctl[IEEE80211_IOCTL_GETOPTIE]", - "ioctl[IEEE80211_IOCTL_SETMLME]", - NULL, - "ioctl[IEEE80211_IOCTL_SETKEY]", - NULL, - "ioctl[IEEE80211_IOCTL_DELKEY]", - NULL, - "ioctl[IEEE80211_IOCTL_ADDMAC]", - NULL, - "ioctl[IEEE80211_IOCTL_DELMAC]", - NULL, - "ioctl[IEEE80211_IOCTL_WDSMAC]", - NULL, - "ioctl[IEEE80211_IOCTL_WDSDELMAC]", - NULL, - "ioctl[IEEE80211_IOCTL_KICKMAC]", - }; -#else /* MADWIFI_NG */ - int first = IEEE80211_IOCTL_SETPARAM; - int last = IEEE80211_IOCTL_CHANLIST; - static const char *opnames[] = { - "ioctl[IEEE80211_IOCTL_SETPARAM]", - "ioctl[IEEE80211_IOCTL_GETPARAM]", - "ioctl[IEEE80211_IOCTL_SETKEY]", - "ioctl[IEEE80211_IOCTL_GETKEY]", - "ioctl[IEEE80211_IOCTL_DELKEY]", - NULL, - "ioctl[IEEE80211_IOCTL_SETMLME]", - NULL, - "ioctl[IEEE80211_IOCTL_SETOPTIE]", - "ioctl[IEEE80211_IOCTL_GETOPTIE]", - "ioctl[IEEE80211_IOCTL_ADDMAC]", - NULL, - "ioctl[IEEE80211_IOCTL_DELMAC]", - NULL, - "ioctl[IEEE80211_IOCTL_CHANLIST]", - }; -#endif /* MADWIFI_NG */ - int idx = op - first; - if (first <= op && op <= last && - idx < (int) (sizeof(opnames) / sizeof(opnames[0])) - && opnames[idx]) - perror(opnames[idx]); - else - perror("ioctl[unknown???]"); - } - return -1; - } - return 0; -} - -static int -set80211param(struct wpa_driver_madwifi_data *drv, int op, int arg, - int show_err) -{ - struct iwreq iwr; - - os_memset(&iwr, 0, sizeof(iwr)); - os_strlcpy(iwr.ifr_name, drv->ifname, IFNAMSIZ); - iwr.u.mode = op; - os_memcpy(iwr.u.name+sizeof(u32), &arg, sizeof(arg)); - - if (ioctl(drv->sock, IEEE80211_IOCTL_SETPARAM, &iwr) < 0) { - if (show_err) - perror("ioctl[IEEE80211_IOCTL_SETPARAM]"); - return -1; - } - return 0; -} - -static int -wpa_driver_madwifi_set_wpa_ie(struct wpa_driver_madwifi_data *drv, - const u8 *wpa_ie, size_t wpa_ie_len) -{ - struct iwreq iwr; - - os_memset(&iwr, 0, sizeof(iwr)); - os_strlcpy(iwr.ifr_name, drv->ifname, IFNAMSIZ); - /* NB: SETOPTIE is not fixed-size so must not be inlined */ - iwr.u.data.pointer = (void *) wpa_ie; - iwr.u.data.length = wpa_ie_len; - - if (ioctl(drv->sock, IEEE80211_IOCTL_SETOPTIE, &iwr) < 0) { - perror("ioctl[IEEE80211_IOCTL_SETOPTIE]"); - return -1; - } - return 0; -} - -static int -wpa_driver_madwifi_del_key(struct wpa_driver_madwifi_data *drv, int key_idx, - const u8 *addr) -{ - struct ieee80211req_del_key wk; - - wpa_printf(MSG_DEBUG, "%s: keyidx=%d", __FUNCTION__, key_idx); - os_memset(&wk, 0, sizeof(wk)); - wk.idk_keyix = key_idx; - if (addr != NULL) - os_memcpy(wk.idk_macaddr, addr, IEEE80211_ADDR_LEN); - - return set80211priv(drv, IEEE80211_IOCTL_DELKEY, &wk, sizeof(wk), 1); -} - -static int -wpa_driver_madwifi_set_key(const char *ifname, void *priv, enum wpa_alg alg, - const u8 *addr, int key_idx, int set_tx, - const u8 *seq, size_t seq_len, - const u8 *key, size_t key_len) -{ - struct wpa_driver_madwifi_data *drv = priv; - struct ieee80211req_key wk; - char *alg_name; - u_int8_t cipher; - - if (alg == WPA_ALG_NONE) - return wpa_driver_madwifi_del_key(drv, key_idx, addr); - - switch (alg) { - case WPA_ALG_WEP: - if (addr == NULL || os_memcmp(addr, "\xff\xff\xff\xff\xff\xff", - ETH_ALEN) == 0) { - /* - * madwifi did not seem to like static WEP key - * configuration with IEEE80211_IOCTL_SETKEY, so use - * Linux wireless extensions ioctl for this. - */ - return wpa_driver_wext_set_key(ifname, drv->wext, alg, - addr, key_idx, set_tx, - seq, seq_len, - key, key_len); - } - alg_name = "WEP"; - cipher = IEEE80211_CIPHER_WEP; - break; - case WPA_ALG_TKIP: - alg_name = "TKIP"; - cipher = IEEE80211_CIPHER_TKIP; - break; - case WPA_ALG_CCMP: - alg_name = "CCMP"; - cipher = IEEE80211_CIPHER_AES_CCM; - break; - default: - wpa_printf(MSG_DEBUG, "%s: unknown/unsupported algorithm %d", - __FUNCTION__, alg); - return -1; - } - - wpa_printf(MSG_DEBUG, "%s: alg=%s key_idx=%d set_tx=%d seq_len=%lu " - "key_len=%lu", __FUNCTION__, alg_name, key_idx, set_tx, - (unsigned long) seq_len, (unsigned long) key_len); - - if (seq_len > sizeof(u_int64_t)) { - wpa_printf(MSG_DEBUG, "%s: seq_len %lu too big", - __FUNCTION__, (unsigned long) seq_len); - return -2; - } - if (key_len > sizeof(wk.ik_keydata)) { - wpa_printf(MSG_DEBUG, "%s: key length %lu too big", - __FUNCTION__, (unsigned long) key_len); - return -3; - } - - os_memset(&wk, 0, sizeof(wk)); - wk.ik_type = cipher; - wk.ik_flags = IEEE80211_KEY_RECV; - if (addr == NULL || - os_memcmp(addr, "\xff\xff\xff\xff\xff\xff", ETH_ALEN) == 0) - wk.ik_flags |= IEEE80211_KEY_GROUP; - if (set_tx) { - wk.ik_flags |= IEEE80211_KEY_XMIT | IEEE80211_KEY_DEFAULT; - os_memcpy(wk.ik_macaddr, addr, IEEE80211_ADDR_LEN); - } else - os_memset(wk.ik_macaddr, 0, IEEE80211_ADDR_LEN); - wk.ik_keyix = key_idx; - wk.ik_keylen = key_len; -#ifdef WORDS_BIGENDIAN - if (seq) { - size_t i; - u8 tmp[WPA_KEY_RSC_LEN]; - os_memset(tmp, 0, sizeof(tmp)); - for (i = 0; i < seq_len; i++) - tmp[WPA_KEY_RSC_LEN - i - 1] = seq[i]; - os_memcpy(&wk.ik_keyrsc, tmp, WPA_KEY_RSC_LEN); - } -#else /* WORDS_BIGENDIAN */ - if (seq) - os_memcpy(&wk.ik_keyrsc, seq, seq_len); -#endif /* WORDS_BIGENDIAN */ - os_memcpy(wk.ik_keydata, key, key_len); - - return set80211priv(drv, IEEE80211_IOCTL_SETKEY, &wk, sizeof(wk), 1); -} - -static int -wpa_driver_madwifi_set_countermeasures(void *priv, int enabled) -{ - struct wpa_driver_madwifi_data *drv = priv; - wpa_printf(MSG_DEBUG, "%s: enabled=%d", __FUNCTION__, enabled); - return set80211param(drv, IEEE80211_PARAM_COUNTERMEASURES, enabled, 1); -} - -static int -wpa_driver_madwifi_deauthenticate(void *priv, const u8 *addr, int reason_code) -{ - struct wpa_driver_madwifi_data *drv = priv; - struct ieee80211req_mlme mlme; - - wpa_printf(MSG_DEBUG, "%s", __FUNCTION__); - mlme.im_op = IEEE80211_MLME_DEAUTH; - mlme.im_reason = reason_code; - os_memcpy(mlme.im_macaddr, addr, IEEE80211_ADDR_LEN); - return set80211priv(drv, IEEE80211_IOCTL_SETMLME, &mlme, sizeof(mlme), 1); -} - -static int -wpa_driver_madwifi_disassociate(void *priv, const u8 *addr, int reason_code) -{ - struct wpa_driver_madwifi_data *drv = priv; - struct ieee80211req_mlme mlme; - - wpa_printf(MSG_DEBUG, "%s", __FUNCTION__); - mlme.im_op = IEEE80211_MLME_DISASSOC; - mlme.im_reason = reason_code; - os_memcpy(mlme.im_macaddr, addr, IEEE80211_ADDR_LEN); - return set80211priv(drv, IEEE80211_IOCTL_SETMLME, &mlme, sizeof(mlme), 1); -} - -static int -wpa_driver_madwifi_associate(void *priv, - struct wpa_driver_associate_params *params) -{ - struct wpa_driver_madwifi_data *drv = priv; - struct ieee80211req_mlme mlme; - int ret = 0, privacy = 1; - - wpa_printf(MSG_DEBUG, "%s", __FUNCTION__); - - if (set80211param(drv, IEEE80211_PARAM_DROPUNENCRYPTED, - params->drop_unencrypted, 1) < 0) - ret = -1; - if (wpa_driver_madwifi_set_auth_alg(drv, params->auth_alg) < 0) - ret = -1; - - /* - * NB: Don't need to set the freq or cipher-related state as - * this is implied by the bssid which is used to locate - * the scanned node state which holds it. The ssid is - * needed to disambiguate an AP that broadcasts multiple - * ssid's but uses the same bssid. - */ - /* XXX error handling is wrong but unclear what to do... */ - if (wpa_driver_madwifi_set_wpa_ie(drv, params->wpa_ie, - params->wpa_ie_len) < 0) - ret = -1; - - if (params->pairwise_suite == CIPHER_NONE && - params->group_suite == CIPHER_NONE && - params->key_mgmt_suite == KEY_MGMT_NONE && - params->wpa_ie_len == 0) - privacy = 0; - - if (set80211param(drv, IEEE80211_PARAM_PRIVACY, privacy, 1) < 0) - ret = -1; - - if (params->wpa_ie_len && - set80211param(drv, IEEE80211_PARAM_WPA, - params->wpa_ie[0] == WLAN_EID_RSN ? 2 : 1, 1) < 0) - ret = -1; - - if (params->bssid == NULL) { - /* ap_scan=2 mode - driver takes care of AP selection and - * roaming */ - /* FIX: this does not seem to work; would probably need to - * change something in the driver */ - if (set80211param(drv, IEEE80211_PARAM_ROAMING, 0, 1) < 0) - ret = -1; - - if (wpa_driver_wext_set_ssid(drv->wext, params->ssid, - params->ssid_len) < 0) - ret = -1; - } else { - if (set80211param(drv, IEEE80211_PARAM_ROAMING, 2, 1) < 0) - ret = -1; - if (wpa_driver_wext_set_ssid(drv->wext, params->ssid, - params->ssid_len) < 0) - ret = -1; - os_memset(&mlme, 0, sizeof(mlme)); - mlme.im_op = IEEE80211_MLME_ASSOC; - os_memcpy(mlme.im_macaddr, params->bssid, IEEE80211_ADDR_LEN); - if (set80211priv(drv, IEEE80211_IOCTL_SETMLME, &mlme, - sizeof(mlme), 1) < 0) { - wpa_printf(MSG_DEBUG, "%s: SETMLME[ASSOC] failed", - __func__); - ret = -1; - } - } - - return ret; -} - -static int -wpa_driver_madwifi_set_auth_alg(void *priv, int auth_alg) -{ - struct wpa_driver_madwifi_data *drv = priv; - int authmode; - - if ((auth_alg & WPA_AUTH_ALG_OPEN) && - (auth_alg & WPA_AUTH_ALG_SHARED)) - authmode = IEEE80211_AUTH_AUTO; - else if (auth_alg & WPA_AUTH_ALG_SHARED) - authmode = IEEE80211_AUTH_SHARED; - else - authmode = IEEE80211_AUTH_OPEN; - - return set80211param(drv, IEEE80211_PARAM_AUTHMODE, authmode, 1); -} - -static int -wpa_driver_madwifi_scan(void *priv, struct wpa_driver_scan_params *params) -{ - struct wpa_driver_madwifi_data *drv = priv; - struct iwreq iwr; - int ret = 0; - const u8 *ssid = params->ssids[0].ssid; - size_t ssid_len = params->ssids[0].ssid_len; - - wpa_driver_madwifi_set_probe_req_ie(drv, params->extra_ies, - params->extra_ies_len); - - os_memset(&iwr, 0, sizeof(iwr)); - os_strlcpy(iwr.ifr_name, drv->ifname, IFNAMSIZ); - - /* set desired ssid before scan */ - /* FIX: scan should not break the current association, so using - * set_ssid may not be the best way of doing this.. */ - if (wpa_driver_wext_set_ssid(drv->wext, ssid, ssid_len) < 0) - ret = -1; - - if (ioctl(drv->sock, SIOCSIWSCAN, &iwr) < 0) { - perror("ioctl[SIOCSIWSCAN]"); - ret = -1; - } - - /* - * madwifi delivers a scan complete event so no need to poll, but - * register a backup timeout anyway to make sure that we recover even - * if the driver does not send this event for any reason. This timeout - * will only be used if the event is not delivered (event handler will - * cancel the timeout). - */ - eloop_cancel_timeout(wpa_driver_wext_scan_timeout, drv->wext, - drv->ctx); - eloop_register_timeout(30, 0, wpa_driver_wext_scan_timeout, drv->wext, - drv->ctx); - - return ret; -} - -static int wpa_driver_madwifi_get_bssid(void *priv, u8 *bssid) -{ - struct wpa_driver_madwifi_data *drv = priv; - return wpa_driver_wext_get_bssid(drv->wext, bssid); -} - - -static int wpa_driver_madwifi_get_ssid(void *priv, u8 *ssid) -{ - struct wpa_driver_madwifi_data *drv = priv; - return wpa_driver_wext_get_ssid(drv->wext, ssid); -} - - -static struct wpa_scan_results * -wpa_driver_madwifi_get_scan_results(void *priv) -{ - struct wpa_driver_madwifi_data *drv = priv; - return wpa_driver_wext_get_scan_results(drv->wext); -} - - -static int wpa_driver_madwifi_set_operstate(void *priv, int state) -{ - struct wpa_driver_madwifi_data *drv = priv; - return wpa_driver_wext_set_operstate(drv->wext, state); -} - - -static int wpa_driver_madwifi_set_probe_req_ie(void *priv, const u8 *ies, - size_t ies_len) -{ - struct ieee80211req_getset_appiebuf *probe_req_ie; - int ret; - - probe_req_ie = os_malloc(sizeof(*probe_req_ie) + ies_len); - if (probe_req_ie == NULL) - return -1; - - probe_req_ie->app_frmtype = IEEE80211_APPIE_FRAME_PROBE_REQ; - probe_req_ie->app_buflen = ies_len; - os_memcpy(probe_req_ie->app_buf, ies, ies_len); - - ret = set80211priv(priv, IEEE80211_IOCTL_SET_APPIEBUF, probe_req_ie, - sizeof(struct ieee80211req_getset_appiebuf) + - ies_len, 1); - - os_free(probe_req_ie); - - return ret; -} - - -static void * wpa_driver_madwifi_init(void *ctx, const char *ifname) -{ - struct wpa_driver_madwifi_data *drv; - - drv = os_zalloc(sizeof(*drv)); - if (drv == NULL) - return NULL; - drv->wext = wpa_driver_wext_init(ctx, ifname); - if (drv->wext == NULL) - goto fail; - - drv->ctx = ctx; - os_strlcpy(drv->ifname, ifname, sizeof(drv->ifname)); - drv->sock = socket(PF_INET, SOCK_DGRAM, 0); - if (drv->sock < 0) - goto fail2; - - if (set80211param(drv, IEEE80211_PARAM_ROAMING, 2, 1) < 0) { - wpa_printf(MSG_DEBUG, "%s: failed to set wpa_supplicant-based " - "roaming", __FUNCTION__); - goto fail3; - } - - if (set80211param(drv, IEEE80211_PARAM_WPA, 3, 1) < 0) { - wpa_printf(MSG_DEBUG, "%s: failed to enable WPA support", - __FUNCTION__); - goto fail3; - } - - return drv; - -fail3: - close(drv->sock); -fail2: - wpa_driver_wext_deinit(drv->wext); -fail: - os_free(drv); - return NULL; -} - - -static void wpa_driver_madwifi_deinit(void *priv) -{ - struct wpa_driver_madwifi_data *drv = priv; - - if (wpa_driver_madwifi_set_wpa_ie(drv, NULL, 0) < 0) { - wpa_printf(MSG_DEBUG, "%s: failed to clear WPA IE", - __FUNCTION__); - } - if (set80211param(drv, IEEE80211_PARAM_ROAMING, 0, 1) < 0) { - wpa_printf(MSG_DEBUG, "%s: failed to enable driver-based " - "roaming", __FUNCTION__); - } - if (set80211param(drv, IEEE80211_PARAM_PRIVACY, 0, 1) < 0) { - wpa_printf(MSG_DEBUG, "%s: failed to disable forced Privacy " - "flag", __FUNCTION__); - } - if (set80211param(drv, IEEE80211_PARAM_WPA, 0, 1) < 0) { - wpa_printf(MSG_DEBUG, "%s: failed to disable WPA", - __FUNCTION__); - } - - wpa_driver_wext_deinit(drv->wext); - - close(drv->sock); - os_free(drv); -} - -#endif /* HOSTAPD */ - - -const struct wpa_driver_ops wpa_driver_madwifi_ops = { - .name = "madwifi", - .desc = "MADWIFI 802.11 support (Atheros, etc.)", - .set_key = wpa_driver_madwifi_set_key, -#ifdef HOSTAPD - .hapd_init = madwifi_init, - .hapd_deinit = madwifi_deinit, - .set_ieee8021x = madwifi_set_ieee8021x, - .set_privacy = madwifi_set_privacy, - .get_seqnum = madwifi_get_seqnum, - .flush = madwifi_flush, - .set_generic_elem = madwifi_set_opt_ie, - .sta_set_flags = madwifi_sta_set_flags, - .read_sta_data = madwifi_read_sta_driver_data, - .hapd_send_eapol = madwifi_send_eapol, - .sta_disassoc = madwifi_sta_disassoc, - .sta_deauth = madwifi_sta_deauth, - .hapd_set_ssid = madwifi_set_ssid, - .hapd_get_ssid = madwifi_get_ssid, - .hapd_set_countermeasures = madwifi_set_countermeasures, - .sta_clear_stats = madwifi_sta_clear_stats, - .commit = madwifi_commit, - .set_ap_wps_ie = madwifi_set_ap_wps_ie, -#else /* HOSTAPD */ - .get_bssid = wpa_driver_madwifi_get_bssid, - .get_ssid = wpa_driver_madwifi_get_ssid, - .init = wpa_driver_madwifi_init, - .deinit = wpa_driver_madwifi_deinit, - .set_countermeasures = wpa_driver_madwifi_set_countermeasures, - .scan2 = wpa_driver_madwifi_scan, - .get_scan_results2 = wpa_driver_madwifi_get_scan_results, - .deauthenticate = wpa_driver_madwifi_deauthenticate, - .disassociate = wpa_driver_madwifi_disassociate, - .associate = wpa_driver_madwifi_associate, - .set_operstate = wpa_driver_madwifi_set_operstate, -#endif /* HOSTAPD */ -}; diff --git a/hostapd-0.8/src/drivers/driver_ndis.c b/hostapd-0.8/src/drivers/driver_ndis.c deleted file mode 100644 index aeb7304..0000000 --- a/hostapd-0.8/src/drivers/driver_ndis.c +++ /dev/null @@ -1,3331 +0,0 @@ -/* - * WPA Supplicant - Windows/NDIS driver interface - * Copyright (c) 2004-2007, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#ifdef __CYGWIN__ -/* Avoid some header file conflicts by not including standard headers for - * cygwin builds when Packet32.h is included. */ -#include "build_config.h" -int close(int fd); -#else /* __CYGWIN__ */ -#include "includes.h" -#endif /* __CYGWIN__ */ -#ifdef CONFIG_USE_NDISUIO -#include -#else /* CONFIG_USE_NDISUIO */ -#include -#endif /* CONFIG_USE_NDISUIO */ -#ifdef __MINGW32_VERSION -#include -#else /* __MINGW32_VERSION */ -#include -#endif /* __MINGW32_VERSION */ - -#ifdef _WIN32_WCE -#include -#include -#include -#endif /* _WIN32_WCE */ - -#include "common.h" -#include "driver.h" -#include "eloop.h" -#include "common/ieee802_11_defs.h" -#include "driver_ndis.h" - -int wpa_driver_register_event_cb(struct wpa_driver_ndis_data *drv); -#ifdef CONFIG_NDIS_EVENTS_INTEGRATED -void wpa_driver_ndis_event_pipe_cb(void *eloop_data, void *user_data); -#endif /* CONFIG_NDIS_EVENTS_INTEGRATED */ - -static void wpa_driver_ndis_deinit(void *priv); -static void wpa_driver_ndis_poll(void *drv); -static void wpa_driver_ndis_poll_timeout(void *eloop_ctx, void *timeout_ctx); -static int wpa_driver_ndis_adapter_init(struct wpa_driver_ndis_data *drv); -static int wpa_driver_ndis_adapter_open(struct wpa_driver_ndis_data *drv); -static void wpa_driver_ndis_adapter_close(struct wpa_driver_ndis_data *drv); - - -static const u8 pae_group_addr[ETH_ALEN] = -{ 0x01, 0x80, 0xc2, 0x00, 0x00, 0x03 }; - - -/* FIX: to be removed once this can be compiled with the complete NDIS - * header files */ -#ifndef OID_802_11_BSSID -#define OID_802_11_BSSID 0x0d010101 -#define OID_802_11_SSID 0x0d010102 -#define OID_802_11_INFRASTRUCTURE_MODE 0x0d010108 -#define OID_802_11_ADD_WEP 0x0D010113 -#define OID_802_11_REMOVE_WEP 0x0D010114 -#define OID_802_11_DISASSOCIATE 0x0D010115 -#define OID_802_11_BSSID_LIST 0x0d010217 -#define OID_802_11_AUTHENTICATION_MODE 0x0d010118 -#define OID_802_11_PRIVACY_FILTER 0x0d010119 -#define OID_802_11_BSSID_LIST_SCAN 0x0d01011A -#define OID_802_11_WEP_STATUS 0x0d01011B -#define OID_802_11_ENCRYPTION_STATUS OID_802_11_WEP_STATUS -#define OID_802_11_ADD_KEY 0x0d01011D -#define OID_802_11_REMOVE_KEY 0x0d01011E -#define OID_802_11_ASSOCIATION_INFORMATION 0x0d01011F -#define OID_802_11_TEST 0x0d010120 -#define OID_802_11_CAPABILITY 0x0d010122 -#define OID_802_11_PMKID 0x0d010123 - -#define NDIS_802_11_LENGTH_SSID 32 -#define NDIS_802_11_LENGTH_RATES 8 -#define NDIS_802_11_LENGTH_RATES_EX 16 - -typedef UCHAR NDIS_802_11_MAC_ADDRESS[6]; - -typedef struct NDIS_802_11_SSID { - ULONG SsidLength; - UCHAR Ssid[NDIS_802_11_LENGTH_SSID]; -} NDIS_802_11_SSID; - -typedef LONG NDIS_802_11_RSSI; - -typedef enum NDIS_802_11_NETWORK_TYPE { - Ndis802_11FH, - Ndis802_11DS, - Ndis802_11OFDM5, - Ndis802_11OFDM24, - Ndis802_11NetworkTypeMax -} NDIS_802_11_NETWORK_TYPE; - -typedef struct NDIS_802_11_CONFIGURATION_FH { - ULONG Length; - ULONG HopPattern; - ULONG HopSet; - ULONG DwellTime; -} NDIS_802_11_CONFIGURATION_FH; - -typedef struct NDIS_802_11_CONFIGURATION { - ULONG Length; - ULONG BeaconPeriod; - ULONG ATIMWindow; - ULONG DSConfig; - NDIS_802_11_CONFIGURATION_FH FHConfig; -} NDIS_802_11_CONFIGURATION; - -typedef enum NDIS_802_11_NETWORK_INFRASTRUCTURE { - Ndis802_11IBSS, - Ndis802_11Infrastructure, - Ndis802_11AutoUnknown, - Ndis802_11InfrastructureMax -} NDIS_802_11_NETWORK_INFRASTRUCTURE; - -typedef enum NDIS_802_11_AUTHENTICATION_MODE { - Ndis802_11AuthModeOpen, - Ndis802_11AuthModeShared, - Ndis802_11AuthModeAutoSwitch, - Ndis802_11AuthModeWPA, - Ndis802_11AuthModeWPAPSK, - Ndis802_11AuthModeWPANone, - Ndis802_11AuthModeWPA2, - Ndis802_11AuthModeWPA2PSK, - Ndis802_11AuthModeMax -} NDIS_802_11_AUTHENTICATION_MODE; - -typedef enum NDIS_802_11_WEP_STATUS { - Ndis802_11WEPEnabled, - Ndis802_11Encryption1Enabled = Ndis802_11WEPEnabled, - Ndis802_11WEPDisabled, - Ndis802_11EncryptionDisabled = Ndis802_11WEPDisabled, - Ndis802_11WEPKeyAbsent, - Ndis802_11Encryption1KeyAbsent = Ndis802_11WEPKeyAbsent, - Ndis802_11WEPNotSupported, - Ndis802_11EncryptionNotSupported = Ndis802_11WEPNotSupported, - Ndis802_11Encryption2Enabled, - Ndis802_11Encryption2KeyAbsent, - Ndis802_11Encryption3Enabled, - Ndis802_11Encryption3KeyAbsent -} NDIS_802_11_WEP_STATUS, NDIS_802_11_ENCRYPTION_STATUS; - -typedef enum NDIS_802_11_PRIVACY_FILTER { - Ndis802_11PrivFilterAcceptAll, - Ndis802_11PrivFilter8021xWEP -} NDIS_802_11_PRIVACY_FILTER; - -typedef UCHAR NDIS_802_11_RATES[NDIS_802_11_LENGTH_RATES]; -typedef UCHAR NDIS_802_11_RATES_EX[NDIS_802_11_LENGTH_RATES_EX]; - -typedef struct NDIS_WLAN_BSSID_EX { - ULONG Length; - NDIS_802_11_MAC_ADDRESS MacAddress; /* BSSID */ - UCHAR Reserved[2]; - NDIS_802_11_SSID Ssid; - ULONG Privacy; - NDIS_802_11_RSSI Rssi; - NDIS_802_11_NETWORK_TYPE NetworkTypeInUse; - NDIS_802_11_CONFIGURATION Configuration; - NDIS_802_11_NETWORK_INFRASTRUCTURE InfrastructureMode; - NDIS_802_11_RATES_EX SupportedRates; - ULONG IELength; - UCHAR IEs[1]; -} NDIS_WLAN_BSSID_EX; - -typedef struct NDIS_802_11_BSSID_LIST_EX { - ULONG NumberOfItems; - NDIS_WLAN_BSSID_EX Bssid[1]; -} NDIS_802_11_BSSID_LIST_EX; - -typedef struct NDIS_802_11_FIXED_IEs { - UCHAR Timestamp[8]; - USHORT BeaconInterval; - USHORT Capabilities; -} NDIS_802_11_FIXED_IEs; - -typedef struct NDIS_802_11_WEP { - ULONG Length; - ULONG KeyIndex; - ULONG KeyLength; - UCHAR KeyMaterial[1]; -} NDIS_802_11_WEP; - -typedef ULONG NDIS_802_11_KEY_INDEX; -typedef ULONGLONG NDIS_802_11_KEY_RSC; - -typedef struct NDIS_802_11_KEY { - ULONG Length; - ULONG KeyIndex; - ULONG KeyLength; - NDIS_802_11_MAC_ADDRESS BSSID; - NDIS_802_11_KEY_RSC KeyRSC; - UCHAR KeyMaterial[1]; -} NDIS_802_11_KEY; - -typedef struct NDIS_802_11_REMOVE_KEY { - ULONG Length; - ULONG KeyIndex; - NDIS_802_11_MAC_ADDRESS BSSID; -} NDIS_802_11_REMOVE_KEY; - -typedef struct NDIS_802_11_AI_REQFI { - USHORT Capabilities; - USHORT ListenInterval; - NDIS_802_11_MAC_ADDRESS CurrentAPAddress; -} NDIS_802_11_AI_REQFI; - -typedef struct NDIS_802_11_AI_RESFI { - USHORT Capabilities; - USHORT StatusCode; - USHORT AssociationId; -} NDIS_802_11_AI_RESFI; - -typedef struct NDIS_802_11_ASSOCIATION_INFORMATION { - ULONG Length; - USHORT AvailableRequestFixedIEs; - NDIS_802_11_AI_REQFI RequestFixedIEs; - ULONG RequestIELength; - ULONG OffsetRequestIEs; - USHORT AvailableResponseFixedIEs; - NDIS_802_11_AI_RESFI ResponseFixedIEs; - ULONG ResponseIELength; - ULONG OffsetResponseIEs; -} NDIS_802_11_ASSOCIATION_INFORMATION; - -typedef struct NDIS_802_11_AUTHENTICATION_ENCRYPTION { - NDIS_802_11_AUTHENTICATION_MODE AuthModeSupported; - NDIS_802_11_ENCRYPTION_STATUS EncryptStatusSupported; -} NDIS_802_11_AUTHENTICATION_ENCRYPTION; - -typedef struct NDIS_802_11_CAPABILITY { - ULONG Length; - ULONG Version; - ULONG NoOfPMKIDs; - ULONG NoOfAuthEncryptPairsSupported; - NDIS_802_11_AUTHENTICATION_ENCRYPTION - AuthenticationEncryptionSupported[1]; -} NDIS_802_11_CAPABILITY; - -typedef UCHAR NDIS_802_11_PMKID_VALUE[16]; - -typedef struct BSSID_INFO { - NDIS_802_11_MAC_ADDRESS BSSID; - NDIS_802_11_PMKID_VALUE PMKID; -} BSSID_INFO; - -typedef struct NDIS_802_11_PMKID { - ULONG Length; - ULONG BSSIDInfoCount; - BSSID_INFO BSSIDInfo[1]; -} NDIS_802_11_PMKID; - -typedef enum NDIS_802_11_STATUS_TYPE { - Ndis802_11StatusType_Authentication, - Ndis802_11StatusType_PMKID_CandidateList = 2, - Ndis802_11StatusTypeMax -} NDIS_802_11_STATUS_TYPE; - -typedef struct NDIS_802_11_STATUS_INDICATION { - NDIS_802_11_STATUS_TYPE StatusType; -} NDIS_802_11_STATUS_INDICATION; - -typedef struct PMKID_CANDIDATE { - NDIS_802_11_MAC_ADDRESS BSSID; - ULONG Flags; -} PMKID_CANDIDATE; - -#define NDIS_802_11_PMKID_CANDIDATE_PREAUTH_ENABLED 0x01 - -typedef struct NDIS_802_11_PMKID_CANDIDATE_LIST { - ULONG Version; - ULONG NumCandidates; - PMKID_CANDIDATE CandidateList[1]; -} NDIS_802_11_PMKID_CANDIDATE_LIST; - -typedef struct NDIS_802_11_AUTHENTICATION_REQUEST { - ULONG Length; - NDIS_802_11_MAC_ADDRESS Bssid; - ULONG Flags; -} NDIS_802_11_AUTHENTICATION_REQUEST; - -#define NDIS_802_11_AUTH_REQUEST_REAUTH 0x01 -#define NDIS_802_11_AUTH_REQUEST_KEYUPDATE 0x02 -#define NDIS_802_11_AUTH_REQUEST_PAIRWISE_ERROR 0x06 -#define NDIS_802_11_AUTH_REQUEST_GROUP_ERROR 0x0E - -#endif /* OID_802_11_BSSID */ - - -#ifndef OID_802_11_PMKID -/* Platform SDK for XP did not include WPA2, so add needed definitions */ - -#define OID_802_11_CAPABILITY 0x0d010122 -#define OID_802_11_PMKID 0x0d010123 - -#define Ndis802_11AuthModeWPA2 6 -#define Ndis802_11AuthModeWPA2PSK 7 - -#define Ndis802_11StatusType_PMKID_CandidateList 2 - -typedef struct NDIS_802_11_AUTHENTICATION_ENCRYPTION { - NDIS_802_11_AUTHENTICATION_MODE AuthModeSupported; - NDIS_802_11_ENCRYPTION_STATUS EncryptStatusSupported; -} NDIS_802_11_AUTHENTICATION_ENCRYPTION; - -typedef struct NDIS_802_11_CAPABILITY { - ULONG Length; - ULONG Version; - ULONG NoOfPMKIDs; - ULONG NoOfAuthEncryptPairsSupported; - NDIS_802_11_AUTHENTICATION_ENCRYPTION - AuthenticationEncryptionSupported[1]; -} NDIS_802_11_CAPABILITY; - -typedef UCHAR NDIS_802_11_PMKID_VALUE[16]; - -typedef struct BSSID_INFO { - NDIS_802_11_MAC_ADDRESS BSSID; - NDIS_802_11_PMKID_VALUE PMKID; -} BSSID_INFO; - -typedef struct NDIS_802_11_PMKID { - ULONG Length; - ULONG BSSIDInfoCount; - BSSID_INFO BSSIDInfo[1]; -} NDIS_802_11_PMKID; - -typedef struct PMKID_CANDIDATE { - NDIS_802_11_MAC_ADDRESS BSSID; - ULONG Flags; -} PMKID_CANDIDATE; - -#define NDIS_802_11_PMKID_CANDIDATE_PREAUTH_ENABLED 0x01 - -typedef struct NDIS_802_11_PMKID_CANDIDATE_LIST { - ULONG Version; - ULONG NumCandidates; - PMKID_CANDIDATE CandidateList[1]; -} NDIS_802_11_PMKID_CANDIDATE_LIST; - -#endif /* OID_802_11_CAPABILITY */ - - -#ifndef OID_DOT11_CURRENT_OPERATION_MODE -/* Native 802.11 OIDs */ -#define OID_DOT11_NDIS_START 0x0D010300 -#define OID_DOT11_CURRENT_OPERATION_MODE (OID_DOT11_NDIS_START + 8) -#define OID_DOT11_SCAN_REQUEST (OID_DOT11_NDIS_START + 11) - -typedef enum _DOT11_BSS_TYPE { - dot11_BSS_type_infrastructure = 1, - dot11_BSS_type_independent = 2, - dot11_BSS_type_any = 3 -} DOT11_BSS_TYPE, * PDOT11_BSS_TYPE; - -typedef UCHAR DOT11_MAC_ADDRESS[6]; -typedef DOT11_MAC_ADDRESS * PDOT11_MAC_ADDRESS; - -typedef enum _DOT11_SCAN_TYPE { - dot11_scan_type_active = 1, - dot11_scan_type_passive = 2, - dot11_scan_type_auto = 3, - dot11_scan_type_forced = 0x80000000 -} DOT11_SCAN_TYPE, * PDOT11_SCAN_TYPE; - -typedef struct _DOT11_SCAN_REQUEST_V2 { - DOT11_BSS_TYPE dot11BSSType; - DOT11_MAC_ADDRESS dot11BSSID; - DOT11_SCAN_TYPE dot11ScanType; - BOOLEAN bRestrictedScan; - ULONG udot11SSIDsOffset; - ULONG uNumOfdot11SSIDs; - BOOLEAN bUseRequestIE; - ULONG uRequestIDsOffset; - ULONG uNumOfRequestIDs; - ULONG uPhyTypeInfosOffset; - ULONG uNumOfPhyTypeInfos; - ULONG uIEsOffset; - ULONG uIEsLength; - UCHAR ucBuffer[1]; -} DOT11_SCAN_REQUEST_V2, * PDOT11_SCAN_REQUEST_V2; - -#endif /* OID_DOT11_CURRENT_OPERATION_MODE */ - -#ifdef CONFIG_USE_NDISUIO -#ifndef _WIN32_WCE -#ifdef __MINGW32_VERSION -typedef ULONG NDIS_OID; -#endif /* __MINGW32_VERSION */ -/* from nuiouser.h */ -#define FSCTL_NDISUIO_BASE FILE_DEVICE_NETWORK - -#define _NDISUIO_CTL_CODE(_Function, _Method, _Access) \ - CTL_CODE(FSCTL_NDISUIO_BASE, _Function, _Method, _Access) - -#define IOCTL_NDISUIO_OPEN_DEVICE \ - _NDISUIO_CTL_CODE(0x200, METHOD_BUFFERED, \ - FILE_READ_ACCESS | FILE_WRITE_ACCESS) - -#define IOCTL_NDISUIO_QUERY_OID_VALUE \ - _NDISUIO_CTL_CODE(0x201, METHOD_BUFFERED, \ - FILE_READ_ACCESS | FILE_WRITE_ACCESS) - -#define IOCTL_NDISUIO_SET_OID_VALUE \ - _NDISUIO_CTL_CODE(0x205, METHOD_BUFFERED, \ - FILE_READ_ACCESS | FILE_WRITE_ACCESS) - -#define IOCTL_NDISUIO_SET_ETHER_TYPE \ - _NDISUIO_CTL_CODE(0x202, METHOD_BUFFERED, \ - FILE_READ_ACCESS | FILE_WRITE_ACCESS) - -#define IOCTL_NDISUIO_QUERY_BINDING \ - _NDISUIO_CTL_CODE(0x203, METHOD_BUFFERED, \ - FILE_READ_ACCESS | FILE_WRITE_ACCESS) - -#define IOCTL_NDISUIO_BIND_WAIT \ - _NDISUIO_CTL_CODE(0x204, METHOD_BUFFERED, \ - FILE_READ_ACCESS | FILE_WRITE_ACCESS) - -typedef struct _NDISUIO_QUERY_OID -{ - NDIS_OID Oid; - UCHAR Data[sizeof(ULONG)]; -} NDISUIO_QUERY_OID, *PNDISUIO_QUERY_OID; - -typedef struct _NDISUIO_SET_OID -{ - NDIS_OID Oid; - UCHAR Data[sizeof(ULONG)]; -} NDISUIO_SET_OID, *PNDISUIO_SET_OID; - -typedef struct _NDISUIO_QUERY_BINDING -{ - ULONG BindingIndex; - ULONG DeviceNameOffset; - ULONG DeviceNameLength; - ULONG DeviceDescrOffset; - ULONG DeviceDescrLength; -} NDISUIO_QUERY_BINDING, *PNDISUIO_QUERY_BINDING; -#endif /* _WIN32_WCE */ -#endif /* CONFIG_USE_NDISUIO */ - - -static int ndis_get_oid(struct wpa_driver_ndis_data *drv, unsigned int oid, - char *data, size_t len) -{ -#ifdef CONFIG_USE_NDISUIO - NDISUIO_QUERY_OID *o; - size_t buflen = sizeof(*o) + len; - DWORD written; - int ret; - size_t hdrlen; - - o = os_zalloc(buflen); - if (o == NULL) - return -1; - o->Oid = oid; -#ifdef _WIN32_WCE - o->ptcDeviceName = drv->adapter_name; -#endif /* _WIN32_WCE */ - if (!DeviceIoControl(drv->ndisuio, IOCTL_NDISUIO_QUERY_OID_VALUE, - o, sizeof(NDISUIO_QUERY_OID), o, buflen, &written, - NULL)) { - wpa_printf(MSG_DEBUG, "NDIS: IOCTL_NDISUIO_QUERY_OID_VALUE " - "failed (oid=%08x): %d", oid, (int) GetLastError()); - os_free(o); - return -1; - } - hdrlen = sizeof(NDISUIO_QUERY_OID) - sizeof(o->Data); - if (written < hdrlen) { - wpa_printf(MSG_DEBUG, "NDIS: query oid=%08x written (%d); " - "too short", oid, (unsigned int) written); - os_free(o); - return -1; - } - written -= hdrlen; - if (written > len) { - wpa_printf(MSG_DEBUG, "NDIS: query oid=%08x written (%d) > " - "len (%d)",oid, (unsigned int) written, len); - os_free(o); - return -1; - } - os_memcpy(data, o->Data, written); - ret = written; - os_free(o); - return ret; -#else /* CONFIG_USE_NDISUIO */ - char *buf; - PACKET_OID_DATA *o; - int ret; - - buf = os_zalloc(sizeof(*o) + len); - if (buf == NULL) - return -1; - o = (PACKET_OID_DATA *) buf; - o->Oid = oid; - o->Length = len; - - if (!PacketRequest(drv->adapter, FALSE, o)) { - wpa_printf(MSG_DEBUG, "%s: oid=0x%x len (%d) failed", - __func__, oid, len); - os_free(buf); - return -1; - } - if (o->Length > len) { - wpa_printf(MSG_DEBUG, "%s: oid=0x%x Length (%d) > len (%d)", - __func__, oid, (unsigned int) o->Length, len); - os_free(buf); - return -1; - } - os_memcpy(data, o->Data, o->Length); - ret = o->Length; - os_free(buf); - return ret; -#endif /* CONFIG_USE_NDISUIO */ -} - - -static int ndis_set_oid(struct wpa_driver_ndis_data *drv, unsigned int oid, - const char *data, size_t len) -{ -#ifdef CONFIG_USE_NDISUIO - NDISUIO_SET_OID *o; - size_t buflen, reallen; - DWORD written; - char txt[50]; - - os_snprintf(txt, sizeof(txt), "NDIS: Set OID %08x", oid); - wpa_hexdump_key(MSG_MSGDUMP, txt, (const u8 *) data, len); - - buflen = sizeof(*o) + len; - reallen = buflen - sizeof(o->Data); - o = os_zalloc(buflen); - if (o == NULL) - return -1; - o->Oid = oid; -#ifdef _WIN32_WCE - o->ptcDeviceName = drv->adapter_name; -#endif /* _WIN32_WCE */ - if (data) - os_memcpy(o->Data, data, len); - if (!DeviceIoControl(drv->ndisuio, IOCTL_NDISUIO_SET_OID_VALUE, - o, reallen, NULL, 0, &written, NULL)) { - wpa_printf(MSG_DEBUG, "NDIS: IOCTL_NDISUIO_SET_OID_VALUE " - "(oid=%08x) failed: %d", oid, (int) GetLastError()); - os_free(o); - return -1; - } - os_free(o); - return 0; -#else /* CONFIG_USE_NDISUIO */ - char *buf; - PACKET_OID_DATA *o; - char txt[50]; - - os_snprintf(txt, sizeof(txt), "NDIS: Set OID %08x", oid); - wpa_hexdump_key(MSG_MSGDUMP, txt, (const u8 *) data, len); - - buf = os_zalloc(sizeof(*o) + len); - if (buf == NULL) - return -1; - o = (PACKET_OID_DATA *) buf; - o->Oid = oid; - o->Length = len; - if (data) - os_memcpy(o->Data, data, len); - - if (!PacketRequest(drv->adapter, TRUE, o)) { - wpa_printf(MSG_DEBUG, "%s: oid=0x%x len (%d) failed", - __func__, oid, len); - os_free(buf); - return -1; - } - os_free(buf); - return 0; -#endif /* CONFIG_USE_NDISUIO */ -} - - -static int ndis_set_auth_mode(struct wpa_driver_ndis_data *drv, int mode) -{ - u32 auth_mode = mode; - if (ndis_set_oid(drv, OID_802_11_AUTHENTICATION_MODE, - (char *) &auth_mode, sizeof(auth_mode)) < 0) { - wpa_printf(MSG_DEBUG, "NDIS: Failed to set " - "OID_802_11_AUTHENTICATION_MODE (%d)", - (int) auth_mode); - return -1; - } - return 0; -} - - -static int ndis_get_auth_mode(struct wpa_driver_ndis_data *drv) -{ - u32 auth_mode; - int res; - res = ndis_get_oid(drv, OID_802_11_AUTHENTICATION_MODE, - (char *) &auth_mode, sizeof(auth_mode)); - if (res != sizeof(auth_mode)) { - wpa_printf(MSG_DEBUG, "NDIS: Failed to get " - "OID_802_11_AUTHENTICATION_MODE"); - return -1; - } - return auth_mode; -} - - -static int ndis_set_encr_status(struct wpa_driver_ndis_data *drv, int encr) -{ - u32 encr_status = encr; - if (ndis_set_oid(drv, OID_802_11_ENCRYPTION_STATUS, - (char *) &encr_status, sizeof(encr_status)) < 0) { - wpa_printf(MSG_DEBUG, "NDIS: Failed to set " - "OID_802_11_ENCRYPTION_STATUS (%d)", encr); - return -1; - } - return 0; -} - - -static int ndis_get_encr_status(struct wpa_driver_ndis_data *drv) -{ - u32 encr; - int res; - res = ndis_get_oid(drv, OID_802_11_ENCRYPTION_STATUS, - (char *) &encr, sizeof(encr)); - if (res != sizeof(encr)) { - wpa_printf(MSG_DEBUG, "NDIS: Failed to get " - "OID_802_11_ENCRYPTION_STATUS"); - return -1; - } - return encr; -} - - -static int wpa_driver_ndis_get_bssid(void *priv, u8 *bssid) -{ - struct wpa_driver_ndis_data *drv = priv; - - if (drv->wired) { - /* - * Report PAE group address as the "BSSID" for wired - * connection. - */ - os_memcpy(bssid, pae_group_addr, ETH_ALEN); - return 0; - } - - return ndis_get_oid(drv, OID_802_11_BSSID, (char *) bssid, ETH_ALEN) < - 0 ? -1 : 0; -} - - -static int wpa_driver_ndis_get_ssid(void *priv, u8 *ssid) -{ - struct wpa_driver_ndis_data *drv = priv; - NDIS_802_11_SSID buf; - int res; - - res = ndis_get_oid(drv, OID_802_11_SSID, (char *) &buf, sizeof(buf)); - if (res < 4) { - wpa_printf(MSG_DEBUG, "NDIS: Failed to get SSID"); - if (drv->wired) { - wpa_printf(MSG_DEBUG, "NDIS: Allow get_ssid failure " - "with a wired interface"); - return 0; - } - return -1; - } - os_memcpy(ssid, buf.Ssid, buf.SsidLength); - return buf.SsidLength; -} - - -static int wpa_driver_ndis_set_ssid(struct wpa_driver_ndis_data *drv, - const u8 *ssid, size_t ssid_len) -{ - NDIS_802_11_SSID buf; - - os_memset(&buf, 0, sizeof(buf)); - buf.SsidLength = ssid_len; - os_memcpy(buf.Ssid, ssid, ssid_len); - /* - * Make sure radio is marked enabled here so that scan request will not - * force SSID to be changed to a random one in order to enable radio at - * that point. - */ - drv->radio_enabled = 1; - return ndis_set_oid(drv, OID_802_11_SSID, (char *) &buf, sizeof(buf)); -} - - -/* Disconnect using OID_802_11_DISASSOCIATE. This will also turn the radio off. - */ -static int wpa_driver_ndis_radio_off(struct wpa_driver_ndis_data *drv) -{ - drv->radio_enabled = 0; - return ndis_set_oid(drv, OID_802_11_DISASSOCIATE, " ", 4); -} - - -/* Disconnect by setting SSID to random (i.e., likely not used). */ -static int wpa_driver_ndis_disconnect(struct wpa_driver_ndis_data *drv) -{ - char ssid[32]; - int i; - for (i = 0; i < 32; i++) - ssid[i] = rand() & 0xff; - return wpa_driver_ndis_set_ssid(drv, (u8 *) ssid, 32); -} - - -static int wpa_driver_ndis_deauthenticate(void *priv, const u8 *addr, - int reason_code) -{ - struct wpa_driver_ndis_data *drv = priv; - return wpa_driver_ndis_disconnect(drv); -} - - -static int wpa_driver_ndis_disassociate(void *priv, const u8 *addr, - int reason_code) -{ - struct wpa_driver_ndis_data *drv = priv; - return wpa_driver_ndis_disconnect(drv); -} - - -static void wpa_driver_ndis_scan_timeout(void *eloop_ctx, void *timeout_ctx) -{ - wpa_printf(MSG_DEBUG, "Scan timeout - try to get results"); - wpa_supplicant_event(timeout_ctx, EVENT_SCAN_RESULTS, NULL); -} - - -static int wpa_driver_ndis_scan_native80211( - struct wpa_driver_ndis_data *drv, - struct wpa_driver_scan_params *params) -{ - DOT11_SCAN_REQUEST_V2 req; - int res; - - os_memset(&req, 0, sizeof(req)); - req.dot11BSSType = dot11_BSS_type_any; - os_memset(req.dot11BSSID, 0xff, ETH_ALEN); - req.dot11ScanType = dot11_scan_type_auto; - res = ndis_set_oid(drv, OID_DOT11_SCAN_REQUEST, (char *) &req, - sizeof(req)); - eloop_cancel_timeout(wpa_driver_ndis_scan_timeout, drv, drv->ctx); - eloop_register_timeout(7, 0, wpa_driver_ndis_scan_timeout, drv, - drv->ctx); - return res; -} - - -static int wpa_driver_ndis_scan(void *priv, - struct wpa_driver_scan_params *params) -{ - struct wpa_driver_ndis_data *drv = priv; - int res; - - if (drv->native80211) - return wpa_driver_ndis_scan_native80211(drv, params); - - if (!drv->radio_enabled) { - wpa_printf(MSG_DEBUG, "NDIS: turning radio on before the first" - " scan"); - if (wpa_driver_ndis_disconnect(drv) < 0) { - wpa_printf(MSG_DEBUG, "NDIS: failed to enable radio"); - } - drv->radio_enabled = 1; - } - - res = ndis_set_oid(drv, OID_802_11_BSSID_LIST_SCAN, " ", 4); - eloop_cancel_timeout(wpa_driver_ndis_scan_timeout, drv, drv->ctx); - eloop_register_timeout(7, 0, wpa_driver_ndis_scan_timeout, drv, - drv->ctx); - return res; -} - - -static const u8 * wpa_scan_get_ie(const struct wpa_scan_res *res, u8 ie) -{ - const u8 *end, *pos; - - pos = (const u8 *) (res + 1); - end = pos + res->ie_len; - - while (pos + 1 < end) { - if (pos + 2 + pos[1] > end) - break; - if (pos[0] == ie) - return pos; - pos += 2 + pos[1]; - } - - return NULL; -} - - -static struct wpa_scan_res * wpa_driver_ndis_add_scan_ssid( - struct wpa_scan_res *r, NDIS_802_11_SSID *ssid) -{ - struct wpa_scan_res *nr; - u8 *pos; - - if (wpa_scan_get_ie(r, WLAN_EID_SSID)) - return r; /* SSID IE already present */ - - if (ssid->SsidLength == 0 || ssid->SsidLength > 32) - return r; /* No valid SSID inside scan data */ - - nr = os_realloc(r, sizeof(*r) + r->ie_len + 2 + ssid->SsidLength); - if (nr == NULL) - return r; - - pos = ((u8 *) (nr + 1)) + nr->ie_len; - *pos++ = WLAN_EID_SSID; - *pos++ = ssid->SsidLength; - os_memcpy(pos, ssid->Ssid, ssid->SsidLength); - nr->ie_len += 2 + ssid->SsidLength; - - return nr; -} - - -static struct wpa_scan_results * wpa_driver_ndis_get_scan_results(void *priv) -{ - struct wpa_driver_ndis_data *drv = priv; - NDIS_802_11_BSSID_LIST_EX *b; - size_t blen, count, i; - int len; - char *pos; - struct wpa_scan_results *results; - struct wpa_scan_res *r; - - blen = 65535; - b = os_zalloc(blen); - if (b == NULL) - return NULL; - len = ndis_get_oid(drv, OID_802_11_BSSID_LIST, (char *) b, blen); - if (len < 0) { - wpa_printf(MSG_DEBUG, "NDIS: failed to get scan results"); - os_free(b); - return NULL; - } - count = b->NumberOfItems; - - results = os_zalloc(sizeof(*results)); - if (results == NULL) { - os_free(b); - return NULL; - } - results->res = os_zalloc(count * sizeof(struct wpa_scan_res *)); - if (results->res == NULL) { - os_free(results); - os_free(b); - return NULL; - } - - pos = (char *) &b->Bssid[0]; - for (i = 0; i < count; i++) { - NDIS_WLAN_BSSID_EX *bss = (NDIS_WLAN_BSSID_EX *) pos; - NDIS_802_11_FIXED_IEs *fixed; - - if (bss->IELength < sizeof(NDIS_802_11_FIXED_IEs)) { - wpa_printf(MSG_DEBUG, "NDIS: too small IELength=%d", - (int) bss->IELength); - break; - } - if (((char *) bss->IEs) + bss->IELength > (char *) b + blen) { - /* - * Some NDIS drivers have been reported to include an - * entry with an invalid IELength in scan results and - * this has crashed wpa_supplicant, so validate the - * returned value before using it. - */ - wpa_printf(MSG_DEBUG, "NDIS: skipped invalid scan " - "result IE (BSSID=" MACSTR ") IELength=%d", - MAC2STR(bss->MacAddress), - (int) bss->IELength); - break; - } - - r = os_zalloc(sizeof(*r) + bss->IELength - - sizeof(NDIS_802_11_FIXED_IEs)); - if (r == NULL) - break; - - os_memcpy(r->bssid, bss->MacAddress, ETH_ALEN); - r->level = (int) bss->Rssi; - r->freq = bss->Configuration.DSConfig / 1000; - fixed = (NDIS_802_11_FIXED_IEs *) bss->IEs; - r->beacon_int = WPA_GET_LE16((u8 *) &fixed->BeaconInterval); - r->caps = WPA_GET_LE16((u8 *) &fixed->Capabilities); - r->tsf = WPA_GET_LE64(fixed->Timestamp); - os_memcpy(r + 1, bss->IEs + sizeof(NDIS_802_11_FIXED_IEs), - bss->IELength - sizeof(NDIS_802_11_FIXED_IEs)); - r->ie_len = bss->IELength - sizeof(NDIS_802_11_FIXED_IEs); - r = wpa_driver_ndis_add_scan_ssid(r, &bss->Ssid); - - results->res[results->num++] = r; - - pos += bss->Length; - if (pos > (char *) b + blen) - break; - } - - os_free(b); - - return results; -} - - -static int wpa_driver_ndis_remove_key(struct wpa_driver_ndis_data *drv, - int key_idx, const u8 *addr, - const u8 *bssid, int pairwise) -{ - NDIS_802_11_REMOVE_KEY rkey; - NDIS_802_11_KEY_INDEX index; - int res, res2; - - os_memset(&rkey, 0, sizeof(rkey)); - - rkey.Length = sizeof(rkey); - rkey.KeyIndex = key_idx; - if (pairwise) - rkey.KeyIndex |= 1 << 30; - os_memcpy(rkey.BSSID, bssid, ETH_ALEN); - - res = ndis_set_oid(drv, OID_802_11_REMOVE_KEY, (char *) &rkey, - sizeof(rkey)); - if (!pairwise) { - index = key_idx; - res2 = ndis_set_oid(drv, OID_802_11_REMOVE_WEP, - (char *) &index, sizeof(index)); - } else - res2 = 0; - - if (res < 0 && res2 < 0) - return -1; - return 0; -} - - -static int wpa_driver_ndis_add_wep(struct wpa_driver_ndis_data *drv, - int pairwise, int key_idx, int set_tx, - const u8 *key, size_t key_len) -{ - NDIS_802_11_WEP *wep; - size_t len; - int res; - - len = 12 + key_len; - wep = os_zalloc(len); - if (wep == NULL) - return -1; - wep->Length = len; - wep->KeyIndex = key_idx; - if (set_tx) - wep->KeyIndex |= 1 << 31; -#if 0 /* Setting bit30 does not seem to work with some NDIS drivers */ - if (pairwise) - wep->KeyIndex |= 1 << 30; -#endif - wep->KeyLength = key_len; - os_memcpy(wep->KeyMaterial, key, key_len); - - wpa_hexdump_key(MSG_MSGDUMP, "NDIS: OID_802_11_ADD_WEP", - (u8 *) wep, len); - res = ndis_set_oid(drv, OID_802_11_ADD_WEP, (char *) wep, len); - - os_free(wep); - - return res; -} - - -static int wpa_driver_ndis_set_key(const char *ifname, void *priv, - enum wpa_alg alg, const u8 *addr, - int key_idx, int set_tx, - const u8 *seq, size_t seq_len, - const u8 *key, size_t key_len) -{ - struct wpa_driver_ndis_data *drv = priv; - size_t len, i; - NDIS_802_11_KEY *nkey; - int res, pairwise; - u8 bssid[ETH_ALEN]; - - if (addr == NULL || is_broadcast_ether_addr(addr)) { - /* Group Key */ - pairwise = 0; - if (wpa_driver_ndis_get_bssid(drv, bssid) < 0) - os_memset(bssid, 0xff, ETH_ALEN); - } else { - /* Pairwise Key */ - pairwise = 1; - os_memcpy(bssid, addr, ETH_ALEN); - } - - if (alg == WPA_ALG_NONE || key_len == 0) { - return wpa_driver_ndis_remove_key(drv, key_idx, addr, bssid, - pairwise); - } - - if (alg == WPA_ALG_WEP) { - return wpa_driver_ndis_add_wep(drv, pairwise, key_idx, set_tx, - key, key_len); - } - - len = 12 + 6 + 6 + 8 + key_len; - - nkey = os_zalloc(len); - if (nkey == NULL) - return -1; - - nkey->Length = len; - nkey->KeyIndex = key_idx; - if (set_tx) - nkey->KeyIndex |= 1 << 31; - if (pairwise) - nkey->KeyIndex |= 1 << 30; - if (seq && seq_len) - nkey->KeyIndex |= 1 << 29; - nkey->KeyLength = key_len; - os_memcpy(nkey->BSSID, bssid, ETH_ALEN); - if (seq && seq_len) { - for (i = 0; i < seq_len; i++) - nkey->KeyRSC |= (ULONGLONG) seq[i] << (i * 8); - } - if (alg == WPA_ALG_TKIP && key_len == 32) { - os_memcpy(nkey->KeyMaterial, key, 16); - os_memcpy(nkey->KeyMaterial + 16, key + 24, 8); - os_memcpy(nkey->KeyMaterial + 24, key + 16, 8); - } else { - os_memcpy(nkey->KeyMaterial, key, key_len); - } - - wpa_hexdump_key(MSG_MSGDUMP, "NDIS: OID_802_11_ADD_KEY", - (u8 *) nkey, len); - res = ndis_set_oid(drv, OID_802_11_ADD_KEY, (char *) nkey, len); - os_free(nkey); - - return res; -} - - -static int -wpa_driver_ndis_associate(void *priv, - struct wpa_driver_associate_params *params) -{ - struct wpa_driver_ndis_data *drv = priv; - u32 auth_mode, encr, priv_mode, mode; - u8 bcast[ETH_ALEN] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; - - drv->mode = params->mode; - - /* Note: Setting OID_802_11_INFRASTRUCTURE_MODE clears current keys, - * so static WEP keys needs to be set again after this. */ - if (params->mode == IEEE80211_MODE_IBSS) { - mode = Ndis802_11IBSS; - /* Need to make sure that BSSID polling is enabled for - * IBSS mode. */ - eloop_cancel_timeout(wpa_driver_ndis_poll_timeout, drv, NULL); - eloop_register_timeout(1, 0, wpa_driver_ndis_poll_timeout, - drv, NULL); - } else - mode = Ndis802_11Infrastructure; - if (ndis_set_oid(drv, OID_802_11_INFRASTRUCTURE_MODE, - (char *) &mode, sizeof(mode)) < 0) { - wpa_printf(MSG_DEBUG, "NDIS: Failed to set " - "OID_802_11_INFRASTRUCTURE_MODE (%d)", - (int) mode); - /* Try to continue anyway */ - } - - if (params->key_mgmt_suite == KEY_MGMT_NONE || - params->key_mgmt_suite == KEY_MGMT_802_1X_NO_WPA) { - /* Re-set WEP keys if static WEP configuration is used. */ - int i; - for (i = 0; i < 4; i++) { - if (!params->wep_key[i]) - continue; - wpa_printf(MSG_DEBUG, "NDIS: Re-setting static WEP " - "key %d", i); - wpa_driver_ndis_set_key(drv->ifname, drv, WPA_ALG_WEP, - bcast, i, - i == params->wep_tx_keyidx, - NULL, 0, params->wep_key[i], - params->wep_key_len[i]); - } - } - - if (params->wpa_ie == NULL || params->wpa_ie_len == 0) { - if (params->auth_alg & WPA_AUTH_ALG_SHARED) { - if (params->auth_alg & WPA_AUTH_ALG_OPEN) - auth_mode = Ndis802_11AuthModeAutoSwitch; - else - auth_mode = Ndis802_11AuthModeShared; - } else - auth_mode = Ndis802_11AuthModeOpen; - priv_mode = Ndis802_11PrivFilterAcceptAll; - } else if (params->wpa_ie[0] == WLAN_EID_RSN) { - priv_mode = Ndis802_11PrivFilter8021xWEP; - if (params->key_mgmt_suite == KEY_MGMT_PSK) - auth_mode = Ndis802_11AuthModeWPA2PSK; - else - auth_mode = Ndis802_11AuthModeWPA2; -#ifdef CONFIG_WPS - } else if (params->key_mgmt_suite == KEY_MGMT_WPS) { - auth_mode = Ndis802_11AuthModeOpen; - priv_mode = Ndis802_11PrivFilterAcceptAll; - if (params->wps == WPS_MODE_PRIVACY) { - u8 dummy_key[5] = { 0x11, 0x22, 0x33, 0x44, 0x55 }; - /* - * Some NDIS drivers refuse to associate in open mode - * configuration due to Privacy field mismatch, so use - * a workaround to make the configuration look like - * matching one for WPS provisioning. - */ - wpa_printf(MSG_DEBUG, "NDIS: Set dummy WEP key as a " - "workaround to allow driver to associate " - "for WPS"); - wpa_driver_ndis_set_key(drv->ifname, drv, WPA_ALG_WEP, - bcast, 0, 1, - NULL, 0, dummy_key, - sizeof(dummy_key)); - } -#endif /* CONFIG_WPS */ - } else { - priv_mode = Ndis802_11PrivFilter8021xWEP; - if (params->key_mgmt_suite == KEY_MGMT_WPA_NONE) - auth_mode = Ndis802_11AuthModeWPANone; - else if (params->key_mgmt_suite == KEY_MGMT_PSK) - auth_mode = Ndis802_11AuthModeWPAPSK; - else - auth_mode = Ndis802_11AuthModeWPA; - } - - switch (params->pairwise_suite) { - case CIPHER_CCMP: - encr = Ndis802_11Encryption3Enabled; - break; - case CIPHER_TKIP: - encr = Ndis802_11Encryption2Enabled; - break; - case CIPHER_WEP40: - case CIPHER_WEP104: - encr = Ndis802_11Encryption1Enabled; - break; - case CIPHER_NONE: -#ifdef CONFIG_WPS - if (params->wps == WPS_MODE_PRIVACY) { - encr = Ndis802_11Encryption1Enabled; - break; - } -#endif /* CONFIG_WPS */ - if (params->group_suite == CIPHER_CCMP) - encr = Ndis802_11Encryption3Enabled; - else if (params->group_suite == CIPHER_TKIP) - encr = Ndis802_11Encryption2Enabled; - else - encr = Ndis802_11EncryptionDisabled; - break; - default: -#ifdef CONFIG_WPS - if (params->wps == WPS_MODE_PRIVACY) { - encr = Ndis802_11Encryption1Enabled; - break; - } -#endif /* CONFIG_WPS */ - encr = Ndis802_11EncryptionDisabled; - break; - }; - - if (ndis_set_oid(drv, OID_802_11_PRIVACY_FILTER, - (char *) &priv_mode, sizeof(priv_mode)) < 0) { - wpa_printf(MSG_DEBUG, "NDIS: Failed to set " - "OID_802_11_PRIVACY_FILTER (%d)", - (int) priv_mode); - /* Try to continue anyway */ - } - - ndis_set_auth_mode(drv, auth_mode); - ndis_set_encr_status(drv, encr); - - if (params->bssid) { - ndis_set_oid(drv, OID_802_11_BSSID, (char *) params->bssid, - ETH_ALEN); - drv->oid_bssid_set = 1; - } else if (drv->oid_bssid_set) { - ndis_set_oid(drv, OID_802_11_BSSID, "\xff\xff\xff\xff\xff\xff", - ETH_ALEN); - drv->oid_bssid_set = 0; - } - - return wpa_driver_ndis_set_ssid(drv, params->ssid, params->ssid_len); -} - - -static int wpa_driver_ndis_set_pmkid(struct wpa_driver_ndis_data *drv) -{ - int len, count, i, ret; - struct ndis_pmkid_entry *entry; - NDIS_802_11_PMKID *p; - - count = 0; - entry = drv->pmkid; - while (entry) { - count++; - if (count >= drv->no_of_pmkid) - break; - entry = entry->next; - } - len = 8 + count * sizeof(BSSID_INFO); - p = os_zalloc(len); - if (p == NULL) - return -1; - - p->Length = len; - p->BSSIDInfoCount = count; - entry = drv->pmkid; - for (i = 0; i < count; i++) { - os_memcpy(&p->BSSIDInfo[i].BSSID, entry->bssid, ETH_ALEN); - os_memcpy(&p->BSSIDInfo[i].PMKID, entry->pmkid, 16); - entry = entry->next; - } - wpa_hexdump(MSG_MSGDUMP, "NDIS: OID_802_11_PMKID", (u8 *) p, len); - ret = ndis_set_oid(drv, OID_802_11_PMKID, (char *) p, len); - os_free(p); - return ret; -} - - -static int wpa_driver_ndis_add_pmkid(void *priv, const u8 *bssid, - const u8 *pmkid) -{ - struct wpa_driver_ndis_data *drv = priv; - struct ndis_pmkid_entry *entry, *prev; - - if (drv->no_of_pmkid == 0) - return 0; - - prev = NULL; - entry = drv->pmkid; - while (entry) { - if (os_memcmp(entry->bssid, bssid, ETH_ALEN) == 0) - break; - prev = entry; - entry = entry->next; - } - - if (entry) { - /* Replace existing entry for this BSSID and move it into the - * beginning of the list. */ - os_memcpy(entry->pmkid, pmkid, 16); - if (prev) { - prev->next = entry->next; - entry->next = drv->pmkid; - drv->pmkid = entry; - } - } else { - entry = os_malloc(sizeof(*entry)); - if (entry) { - os_memcpy(entry->bssid, bssid, ETH_ALEN); - os_memcpy(entry->pmkid, pmkid, 16); - entry->next = drv->pmkid; - drv->pmkid = entry; - } - } - - return wpa_driver_ndis_set_pmkid(drv); -} - - -static int wpa_driver_ndis_remove_pmkid(void *priv, const u8 *bssid, - const u8 *pmkid) -{ - struct wpa_driver_ndis_data *drv = priv; - struct ndis_pmkid_entry *entry, *prev; - - if (drv->no_of_pmkid == 0) - return 0; - - entry = drv->pmkid; - prev = NULL; - while (entry) { - if (os_memcmp(entry->bssid, bssid, ETH_ALEN) == 0 && - os_memcmp(entry->pmkid, pmkid, 16) == 0) { - if (prev) - prev->next = entry->next; - else - drv->pmkid = entry->next; - os_free(entry); - break; - } - prev = entry; - entry = entry->next; - } - return wpa_driver_ndis_set_pmkid(drv); -} - - -static int wpa_driver_ndis_flush_pmkid(void *priv) -{ - struct wpa_driver_ndis_data *drv = priv; - NDIS_802_11_PMKID p; - struct ndis_pmkid_entry *pmkid, *prev; - int prev_authmode, ret; - - if (drv->no_of_pmkid == 0) - return 0; - - pmkid = drv->pmkid; - drv->pmkid = NULL; - while (pmkid) { - prev = pmkid; - pmkid = pmkid->next; - os_free(prev); - } - - /* - * Some drivers may refuse OID_802_11_PMKID if authMode is not set to - * WPA2, so change authMode temporarily, if needed. - */ - prev_authmode = ndis_get_auth_mode(drv); - if (prev_authmode != Ndis802_11AuthModeWPA2) - ndis_set_auth_mode(drv, Ndis802_11AuthModeWPA2); - - os_memset(&p, 0, sizeof(p)); - p.Length = 8; - p.BSSIDInfoCount = 0; - wpa_hexdump(MSG_MSGDUMP, "NDIS: OID_802_11_PMKID (flush)", - (u8 *) &p, 8); - ret = ndis_set_oid(drv, OID_802_11_PMKID, (char *) &p, 8); - - if (prev_authmode != Ndis802_11AuthModeWPA2) - ndis_set_auth_mode(drv, prev_authmode); - - return ret; -} - - -static int wpa_driver_ndis_get_associnfo(struct wpa_driver_ndis_data *drv) -{ - char buf[512], *pos; - NDIS_802_11_ASSOCIATION_INFORMATION *ai; - int len; - union wpa_event_data data; - NDIS_802_11_BSSID_LIST_EX *b; - size_t blen, i; - - len = ndis_get_oid(drv, OID_802_11_ASSOCIATION_INFORMATION, buf, - sizeof(buf)); - if (len < 0) { - wpa_printf(MSG_DEBUG, "NDIS: failed to get association " - "information"); - return -1; - } - if (len > sizeof(buf)) { - /* Some drivers seem to be producing incorrect length for this - * data. Limit the length to the current buffer size to avoid - * crashing in hexdump. The data seems to be otherwise valid, - * so better try to use it. */ - wpa_printf(MSG_DEBUG, "NDIS: ignored bogus association " - "information length %d", len); - len = ndis_get_oid(drv, OID_802_11_ASSOCIATION_INFORMATION, - buf, sizeof(buf)); - if (len < -1) { - wpa_printf(MSG_DEBUG, "NDIS: re-reading association " - "information failed"); - return -1; - } - if (len > sizeof(buf)) { - wpa_printf(MSG_DEBUG, "NDIS: ignored bogus association" - " information length %d (re-read)", len); - len = sizeof(buf); - } - } - wpa_hexdump(MSG_MSGDUMP, "NDIS: association information", - (u8 *) buf, len); - if (len < sizeof(*ai)) { - wpa_printf(MSG_DEBUG, "NDIS: too short association " - "information"); - return -1; - } - ai = (NDIS_802_11_ASSOCIATION_INFORMATION *) buf; - wpa_printf(MSG_DEBUG, "NDIS: ReqFixed=0x%x RespFixed=0x%x off_req=%d " - "off_resp=%d len_req=%d len_resp=%d", - ai->AvailableRequestFixedIEs, ai->AvailableResponseFixedIEs, - (int) ai->OffsetRequestIEs, (int) ai->OffsetResponseIEs, - (int) ai->RequestIELength, (int) ai->ResponseIELength); - - if (ai->OffsetRequestIEs + ai->RequestIELength > (unsigned) len || - ai->OffsetResponseIEs + ai->ResponseIELength > (unsigned) len) { - wpa_printf(MSG_DEBUG, "NDIS: association information - " - "IE overflow"); - return -1; - } - - wpa_hexdump(MSG_MSGDUMP, "NDIS: Request IEs", - (u8 *) buf + ai->OffsetRequestIEs, ai->RequestIELength); - wpa_hexdump(MSG_MSGDUMP, "NDIS: Response IEs", - (u8 *) buf + ai->OffsetResponseIEs, ai->ResponseIELength); - - os_memset(&data, 0, sizeof(data)); - data.assoc_info.req_ies = (u8 *) buf + ai->OffsetRequestIEs; - data.assoc_info.req_ies_len = ai->RequestIELength; - data.assoc_info.resp_ies = (u8 *) buf + ai->OffsetResponseIEs; - data.assoc_info.resp_ies_len = ai->ResponseIELength; - - blen = 65535; - b = os_zalloc(blen); - if (b == NULL) - goto skip_scan_results; - len = ndis_get_oid(drv, OID_802_11_BSSID_LIST, (char *) b, blen); - if (len < 0) { - wpa_printf(MSG_DEBUG, "NDIS: failed to get scan results"); - os_free(b); - b = NULL; - goto skip_scan_results; - } - wpa_printf(MSG_DEBUG, "NDIS: %d BSSID items to process for AssocInfo", - (unsigned int) b->NumberOfItems); - - pos = (char *) &b->Bssid[0]; - for (i = 0; i < b->NumberOfItems; i++) { - NDIS_WLAN_BSSID_EX *bss = (NDIS_WLAN_BSSID_EX *) pos; - if (os_memcmp(drv->bssid, bss->MacAddress, ETH_ALEN) == 0 && - bss->IELength > sizeof(NDIS_802_11_FIXED_IEs)) { - data.assoc_info.beacon_ies = - ((u8 *) bss->IEs) + - sizeof(NDIS_802_11_FIXED_IEs); - data.assoc_info.beacon_ies_len = - bss->IELength - sizeof(NDIS_802_11_FIXED_IEs); - wpa_hexdump(MSG_MSGDUMP, "NDIS: Beacon IEs", - data.assoc_info.beacon_ies, - data.assoc_info.beacon_ies_len); - break; - } - pos += bss->Length; - if (pos > (char *) b + blen) - break; - } - -skip_scan_results: - wpa_supplicant_event(drv->ctx, EVENT_ASSOCINFO, &data); - - os_free(b); - - return 0; -} - - -static void wpa_driver_ndis_poll_timeout(void *eloop_ctx, void *timeout_ctx) -{ - struct wpa_driver_ndis_data *drv = eloop_ctx; - u8 bssid[ETH_ALEN]; - int poll; - - if (drv->wired) - return; - - if (wpa_driver_ndis_get_bssid(drv, bssid)) { - /* Disconnected */ - if (!is_zero_ether_addr(drv->bssid)) { - os_memset(drv->bssid, 0, ETH_ALEN); - wpa_supplicant_event(drv->ctx, EVENT_DISASSOC, NULL); - } - } else { - /* Connected */ - if (os_memcmp(drv->bssid, bssid, ETH_ALEN) != 0) { - os_memcpy(drv->bssid, bssid, ETH_ALEN); - wpa_driver_ndis_get_associnfo(drv); - wpa_supplicant_event(drv->ctx, EVENT_ASSOC, NULL); - } - } - - /* When using integrated NDIS event receiver, we can skip BSSID - * polling when using infrastructure network. However, when using - * IBSS mode, many driver do not seem to generate connection event, - * so we need to enable BSSID polling to figure out when IBSS network - * has been formed. - */ - poll = drv->mode == IEEE80211_MODE_IBSS; -#ifndef CONFIG_NDIS_EVENTS_INTEGRATED -#ifndef _WIN32_WCE - poll = 1; -#endif /* _WIN32_WCE */ -#endif /* CONFIG_NDIS_EVENTS_INTEGRATED */ - - if (poll) { - eloop_register_timeout(1, 0, wpa_driver_ndis_poll_timeout, - drv, NULL); - } -} - - -static void wpa_driver_ndis_poll(void *priv) -{ - struct wpa_driver_ndis_data *drv = priv; - eloop_cancel_timeout(wpa_driver_ndis_poll_timeout, drv, NULL); - wpa_driver_ndis_poll_timeout(drv, NULL); -} - - -/* Called when driver generates Media Connect Event by calling - * NdisMIndicateStatus() with NDIS_STATUS_MEDIA_CONNECT */ -void wpa_driver_ndis_event_connect(struct wpa_driver_ndis_data *drv) -{ - wpa_printf(MSG_DEBUG, "NDIS: Media Connect Event"); - if (wpa_driver_ndis_get_bssid(drv, drv->bssid) == 0) { - wpa_driver_ndis_get_associnfo(drv); - wpa_supplicant_event(drv->ctx, EVENT_ASSOC, NULL); - } -} - - -/* Called when driver generates Media Disconnect Event by calling - * NdisMIndicateStatus() with NDIS_STATUS_MEDIA_DISCONNECT */ -void wpa_driver_ndis_event_disconnect(struct wpa_driver_ndis_data *drv) -{ - wpa_printf(MSG_DEBUG, "NDIS: Media Disconnect Event"); - os_memset(drv->bssid, 0, ETH_ALEN); - wpa_supplicant_event(drv->ctx, EVENT_DISASSOC, NULL); -} - - -static void wpa_driver_ndis_event_auth(struct wpa_driver_ndis_data *drv, - const u8 *data, size_t data_len) -{ - NDIS_802_11_AUTHENTICATION_REQUEST *req; - int pairwise = 0, group = 0; - union wpa_event_data event; - - if (data_len < sizeof(*req)) { - wpa_printf(MSG_DEBUG, "NDIS: Too short Authentication Request " - "Event (len=%d)", data_len); - return; - } - req = (NDIS_802_11_AUTHENTICATION_REQUEST *) data; - - wpa_printf(MSG_DEBUG, "NDIS: Authentication Request Event: " - "Bssid " MACSTR " Flags 0x%x", - MAC2STR(req->Bssid), (int) req->Flags); - - if ((req->Flags & NDIS_802_11_AUTH_REQUEST_PAIRWISE_ERROR) == - NDIS_802_11_AUTH_REQUEST_PAIRWISE_ERROR) - pairwise = 1; - else if ((req->Flags & NDIS_802_11_AUTH_REQUEST_GROUP_ERROR) == - NDIS_802_11_AUTH_REQUEST_GROUP_ERROR) - group = 1; - - if (pairwise || group) { - os_memset(&event, 0, sizeof(event)); - event.michael_mic_failure.unicast = pairwise; - wpa_supplicant_event(drv->ctx, EVENT_MICHAEL_MIC_FAILURE, - &event); - } -} - - -static void wpa_driver_ndis_event_pmkid(struct wpa_driver_ndis_data *drv, - const u8 *data, size_t data_len) -{ - NDIS_802_11_PMKID_CANDIDATE_LIST *pmkid; - size_t i; - union wpa_event_data event; - - if (data_len < 8) { - wpa_printf(MSG_DEBUG, "NDIS: Too short PMKID Candidate List " - "Event (len=%d)", data_len); - return; - } - pmkid = (NDIS_802_11_PMKID_CANDIDATE_LIST *) data; - wpa_printf(MSG_DEBUG, "NDIS: PMKID Candidate List Event - Version %d " - "NumCandidates %d", - (int) pmkid->Version, (int) pmkid->NumCandidates); - - if (pmkid->Version != 1) { - wpa_printf(MSG_DEBUG, "NDIS: Unsupported PMKID Candidate List " - "Version %d", (int) pmkid->Version); - return; - } - - if (data_len < 8 + pmkid->NumCandidates * sizeof(PMKID_CANDIDATE)) { - wpa_printf(MSG_DEBUG, "NDIS: PMKID Candidate List underflow"); - return; - } - - os_memset(&event, 0, sizeof(event)); - for (i = 0; i < pmkid->NumCandidates; i++) { - PMKID_CANDIDATE *p = &pmkid->CandidateList[i]; - wpa_printf(MSG_DEBUG, "NDIS: %d: " MACSTR " Flags 0x%x", - i, MAC2STR(p->BSSID), (int) p->Flags); - os_memcpy(event.pmkid_candidate.bssid, p->BSSID, ETH_ALEN); - event.pmkid_candidate.index = i; - event.pmkid_candidate.preauth = - p->Flags & NDIS_802_11_PMKID_CANDIDATE_PREAUTH_ENABLED; - wpa_supplicant_event(drv->ctx, EVENT_PMKID_CANDIDATE, - &event); - } -} - - -/* Called when driver calls NdisMIndicateStatus() with - * NDIS_STATUS_MEDIA_SPECIFIC_INDICATION */ -void wpa_driver_ndis_event_media_specific(struct wpa_driver_ndis_data *drv, - const u8 *data, size_t data_len) -{ - NDIS_802_11_STATUS_INDICATION *status; - - if (data == NULL || data_len < sizeof(*status)) - return; - - wpa_hexdump(MSG_DEBUG, "NDIS: Media Specific Indication", - data, data_len); - - status = (NDIS_802_11_STATUS_INDICATION *) data; - data += sizeof(status); - data_len -= sizeof(status); - - switch (status->StatusType) { - case Ndis802_11StatusType_Authentication: - wpa_driver_ndis_event_auth(drv, data, data_len); - break; - case Ndis802_11StatusType_PMKID_CandidateList: - wpa_driver_ndis_event_pmkid(drv, data, data_len); - break; - default: - wpa_printf(MSG_DEBUG, "NDIS: Unknown StatusType %d", - (int) status->StatusType); - break; - } -} - - -/* Called when an adapter is added */ -void wpa_driver_ndis_event_adapter_arrival(struct wpa_driver_ndis_data *drv) -{ - union wpa_event_data event; - int i; - - wpa_printf(MSG_DEBUG, "NDIS: Notify Adapter Arrival"); - - for (i = 0; i < 30; i++) { - /* Re-open Packet32/NDISUIO connection */ - wpa_driver_ndis_adapter_close(drv); - if (wpa_driver_ndis_adapter_init(drv) < 0 || - wpa_driver_ndis_adapter_open(drv) < 0) { - wpa_printf(MSG_DEBUG, "NDIS: Driver re-initialization " - "(%d) failed", i); - os_sleep(1, 0); - } else { - wpa_printf(MSG_DEBUG, "NDIS: Driver re-initialized"); - break; - } - } - - os_memset(&event, 0, sizeof(event)); - os_strlcpy(event.interface_status.ifname, drv->ifname, - sizeof(event.interface_status.ifname)); - event.interface_status.ievent = EVENT_INTERFACE_ADDED; - wpa_supplicant_event(drv->ctx, EVENT_INTERFACE_STATUS, &event); -} - - -/* Called when an adapter is removed */ -void wpa_driver_ndis_event_adapter_removal(struct wpa_driver_ndis_data *drv) -{ - union wpa_event_data event; - - wpa_printf(MSG_DEBUG, "NDIS: Notify Adapter Removal"); - os_memset(&event, 0, sizeof(event)); - os_strlcpy(event.interface_status.ifname, drv->ifname, - sizeof(event.interface_status.ifname)); - event.interface_status.ievent = EVENT_INTERFACE_REMOVED; - wpa_supplicant_event(drv->ctx, EVENT_INTERFACE_STATUS, &event); -} - - -static void -wpa_driver_ndis_get_wpa_capability(struct wpa_driver_ndis_data *drv) -{ - wpa_printf(MSG_DEBUG, "NDIS: verifying driver WPA capability"); - - if (ndis_set_auth_mode(drv, Ndis802_11AuthModeWPA) == 0 && - ndis_get_auth_mode(drv) == Ndis802_11AuthModeWPA) { - wpa_printf(MSG_DEBUG, "NDIS: WPA key management supported"); - drv->capa.key_mgmt |= WPA_DRIVER_CAPA_KEY_MGMT_WPA; - } - - if (ndis_set_auth_mode(drv, Ndis802_11AuthModeWPAPSK) == 0 && - ndis_get_auth_mode(drv) == Ndis802_11AuthModeWPAPSK) { - wpa_printf(MSG_DEBUG, "NDIS: WPA-PSK key management " - "supported"); - drv->capa.key_mgmt |= WPA_DRIVER_CAPA_KEY_MGMT_WPA_PSK; - } - - if (ndis_set_encr_status(drv, Ndis802_11Encryption3Enabled) == 0 && - ndis_get_encr_status(drv) == Ndis802_11Encryption3KeyAbsent) { - wpa_printf(MSG_DEBUG, "NDIS: CCMP encryption supported"); - drv->capa.enc |= WPA_DRIVER_CAPA_ENC_CCMP; - } - - if (ndis_set_encr_status(drv, Ndis802_11Encryption2Enabled) == 0 && - ndis_get_encr_status(drv) == Ndis802_11Encryption2KeyAbsent) { - wpa_printf(MSG_DEBUG, "NDIS: TKIP encryption supported"); - drv->capa.enc |= WPA_DRIVER_CAPA_ENC_TKIP; - } - - if (ndis_set_encr_status(drv, Ndis802_11Encryption1Enabled) == 0 && - ndis_get_encr_status(drv) == Ndis802_11Encryption1KeyAbsent) { - wpa_printf(MSG_DEBUG, "NDIS: WEP encryption supported"); - drv->capa.enc |= WPA_DRIVER_CAPA_ENC_WEP40 | - WPA_DRIVER_CAPA_ENC_WEP104; - } - - if (ndis_set_auth_mode(drv, Ndis802_11AuthModeShared) == 0 && - ndis_get_auth_mode(drv) == Ndis802_11AuthModeShared) { - drv->capa.auth |= WPA_DRIVER_AUTH_SHARED; - } - - if (ndis_set_auth_mode(drv, Ndis802_11AuthModeOpen) == 0 && - ndis_get_auth_mode(drv) == Ndis802_11AuthModeOpen) { - drv->capa.auth |= WPA_DRIVER_AUTH_OPEN; - } - - ndis_set_encr_status(drv, Ndis802_11EncryptionDisabled); - - /* Could also verify OID_802_11_ADD_KEY error reporting and - * support for OID_802_11_ASSOCIATION_INFORMATION. */ - - if (drv->capa.key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_WPA && - drv->capa.enc & (WPA_DRIVER_CAPA_ENC_TKIP | - WPA_DRIVER_CAPA_ENC_CCMP)) { - wpa_printf(MSG_DEBUG, "NDIS: driver supports WPA"); - drv->has_capability = 1; - } else { - wpa_printf(MSG_DEBUG, "NDIS: no WPA support found"); - } - - wpa_printf(MSG_DEBUG, "NDIS: driver capabilities: key_mgmt 0x%x " - "enc 0x%x auth 0x%x", - drv->capa.key_mgmt, drv->capa.enc, drv->capa.auth); -} - - -static void wpa_driver_ndis_get_capability(struct wpa_driver_ndis_data *drv) -{ - char buf[512]; - int len; - size_t i; - NDIS_802_11_CAPABILITY *c; - - drv->capa.flags = WPA_DRIVER_FLAGS_DRIVER_IE; - - len = ndis_get_oid(drv, OID_802_11_CAPABILITY, buf, sizeof(buf)); - if (len < 0) { - wpa_driver_ndis_get_wpa_capability(drv); - return; - } - - wpa_hexdump(MSG_MSGDUMP, "OID_802_11_CAPABILITY", (u8 *) buf, len); - c = (NDIS_802_11_CAPABILITY *) buf; - if (len < sizeof(*c) || c->Version != 2) { - wpa_printf(MSG_DEBUG, "NDIS: unsupported " - "OID_802_11_CAPABILITY data"); - return; - } - wpa_printf(MSG_DEBUG, "NDIS: Driver supports OID_802_11_CAPABILITY - " - "NoOfPMKIDs %d NoOfAuthEncrPairs %d", - (int) c->NoOfPMKIDs, - (int) c->NoOfAuthEncryptPairsSupported); - drv->has_capability = 1; - drv->no_of_pmkid = c->NoOfPMKIDs; - for (i = 0; i < c->NoOfAuthEncryptPairsSupported; i++) { - NDIS_802_11_AUTHENTICATION_ENCRYPTION *ae; - ae = &c->AuthenticationEncryptionSupported[i]; - if ((char *) (ae + 1) > buf + len) { - wpa_printf(MSG_DEBUG, "NDIS: auth/encr pair list " - "overflow"); - break; - } - wpa_printf(MSG_MSGDUMP, "NDIS: %d - auth %d encr %d", - i, (int) ae->AuthModeSupported, - (int) ae->EncryptStatusSupported); - switch (ae->AuthModeSupported) { - case Ndis802_11AuthModeOpen: - drv->capa.auth |= WPA_DRIVER_AUTH_OPEN; - break; - case Ndis802_11AuthModeShared: - drv->capa.auth |= WPA_DRIVER_AUTH_SHARED; - break; - case Ndis802_11AuthModeWPA: - drv->capa.key_mgmt |= WPA_DRIVER_CAPA_KEY_MGMT_WPA; - break; - case Ndis802_11AuthModeWPAPSK: - drv->capa.key_mgmt |= WPA_DRIVER_CAPA_KEY_MGMT_WPA_PSK; - break; - case Ndis802_11AuthModeWPA2: - drv->capa.key_mgmt |= WPA_DRIVER_CAPA_KEY_MGMT_WPA2; - break; - case Ndis802_11AuthModeWPA2PSK: - drv->capa.key_mgmt |= - WPA_DRIVER_CAPA_KEY_MGMT_WPA2_PSK; - break; - case Ndis802_11AuthModeWPANone: - drv->capa.key_mgmt |= - WPA_DRIVER_CAPA_KEY_MGMT_WPA_NONE; - break; - default: - break; - } - switch (ae->EncryptStatusSupported) { - case Ndis802_11Encryption1Enabled: - drv->capa.enc |= WPA_DRIVER_CAPA_ENC_WEP40; - drv->capa.enc |= WPA_DRIVER_CAPA_ENC_WEP104; - break; - case Ndis802_11Encryption2Enabled: - drv->capa.enc |= WPA_DRIVER_CAPA_ENC_TKIP; - break; - case Ndis802_11Encryption3Enabled: - drv->capa.enc |= WPA_DRIVER_CAPA_ENC_CCMP; - break; - default: - break; - } - } - - wpa_printf(MSG_DEBUG, "NDIS: driver capabilities: key_mgmt 0x%x " - "enc 0x%x auth 0x%x", - drv->capa.key_mgmt, drv->capa.enc, drv->capa.auth); -} - - -static int wpa_driver_ndis_get_capa(void *priv, struct wpa_driver_capa *capa) -{ - struct wpa_driver_ndis_data *drv = priv; - if (!drv->has_capability) - return -1; - os_memcpy(capa, &drv->capa, sizeof(*capa)); - return 0; -} - - -static const char * wpa_driver_ndis_get_ifname(void *priv) -{ - struct wpa_driver_ndis_data *drv = priv; - return drv->ifname; -} - - -static const u8 * wpa_driver_ndis_get_mac_addr(void *priv) -{ - struct wpa_driver_ndis_data *drv = priv; - return drv->own_addr; -} - - -#ifdef _WIN32_WCE - -#define NDISUIO_MSG_SIZE (sizeof(NDISUIO_DEVICE_NOTIFICATION) + 512) - -static void ndisuio_notification_receive(void *eloop_data, void *user_ctx) -{ - struct wpa_driver_ndis_data *drv = eloop_data; - NDISUIO_DEVICE_NOTIFICATION *hdr; - u8 buf[NDISUIO_MSG_SIZE]; - DWORD len, flags; - - if (!ReadMsgQueue(drv->event_queue, buf, NDISUIO_MSG_SIZE, &len, 0, - &flags)) { - wpa_printf(MSG_DEBUG, "ndisuio_notification_receive: " - "ReadMsgQueue failed: %d", (int) GetLastError()); - return; - } - - if (len < sizeof(NDISUIO_DEVICE_NOTIFICATION)) { - wpa_printf(MSG_DEBUG, "ndisuio_notification_receive: " - "Too short message (len=%d)", (int) len); - return; - } - - hdr = (NDISUIO_DEVICE_NOTIFICATION *) buf; - wpa_printf(MSG_DEBUG, "NDIS: Notification received: len=%d type=0x%x", - (int) len, hdr->dwNotificationType); - - switch (hdr->dwNotificationType) { -#ifdef NDISUIO_NOTIFICATION_ADAPTER_ARRIVAL - case NDISUIO_NOTIFICATION_ADAPTER_ARRIVAL: - wpa_printf(MSG_DEBUG, "NDIS: ADAPTER_ARRIVAL"); - wpa_driver_ndis_event_adapter_arrival(drv); - break; -#endif -#ifdef NDISUIO_NOTIFICATION_ADAPTER_REMOVAL - case NDISUIO_NOTIFICATION_ADAPTER_REMOVAL: - wpa_printf(MSG_DEBUG, "NDIS: ADAPTER_REMOVAL"); - wpa_driver_ndis_event_adapter_removal(drv); - break; -#endif - case NDISUIO_NOTIFICATION_MEDIA_CONNECT: - wpa_printf(MSG_DEBUG, "NDIS: MEDIA_CONNECT"); - SetEvent(drv->connected_event); - wpa_driver_ndis_event_connect(drv); - break; - case NDISUIO_NOTIFICATION_MEDIA_DISCONNECT: - ResetEvent(drv->connected_event); - wpa_printf(MSG_DEBUG, "NDIS: MEDIA_DISCONNECT"); - wpa_driver_ndis_event_disconnect(drv); - break; - case NDISUIO_NOTIFICATION_MEDIA_SPECIFIC_NOTIFICATION: - wpa_printf(MSG_DEBUG, "NDIS: MEDIA_SPECIFIC_NOTIFICATION"); -#if _WIN32_WCE == 420 || _WIN32_WCE == 0x420 - wpa_driver_ndis_event_media_specific( - drv, hdr->pvStatusBuffer, hdr->uiStatusBufferSize); -#else - wpa_driver_ndis_event_media_specific( - drv, ((const u8 *) hdr) + hdr->uiOffsetToStatusBuffer, - (size_t) hdr->uiStatusBufferSize); -#endif - break; - default: - wpa_printf(MSG_DEBUG, "NDIS: Unknown notification type 0x%x", - hdr->dwNotificationType); - break; - } -} - - -static void ndisuio_notification_deinit(struct wpa_driver_ndis_data *drv) -{ - NDISUIO_REQUEST_NOTIFICATION req; - - memset(&req, 0, sizeof(req)); - req.hMsgQueue = drv->event_queue; - req.dwNotificationTypes = 0; - - if (!DeviceIoControl(drv->ndisuio, IOCTL_NDISUIO_REQUEST_NOTIFICATION, - &req, sizeof(req), NULL, 0, NULL, NULL)) { - wpa_printf(MSG_INFO, "ndisuio_notification_deinit: " - "IOCTL_NDISUIO_REQUEST_NOTIFICATION failed: %d", - (int) GetLastError()); - } - - if (!DeviceIoControl(drv->ndisuio, IOCTL_NDISUIO_CANCEL_NOTIFICATION, - NULL, 0, NULL, 0, NULL, NULL)) { - wpa_printf(MSG_INFO, "ndisuio_notification_deinit: " - "IOCTL_NDISUIO_CANCEL_NOTIFICATION failed: %d", - (int) GetLastError()); - } - - if (drv->event_queue) { - eloop_unregister_event(drv->event_queue, - sizeof(drv->event_queue)); - CloseHandle(drv->event_queue); - drv->event_queue = NULL; - } - - if (drv->connected_event) { - CloseHandle(drv->connected_event); - drv->connected_event = NULL; - } -} - - -static int ndisuio_notification_init(struct wpa_driver_ndis_data *drv) -{ - MSGQUEUEOPTIONS opt; - NDISUIO_REQUEST_NOTIFICATION req; - - drv->connected_event = - CreateEvent(NULL, TRUE, FALSE, TEXT("WpaSupplicantConnected")); - if (drv->connected_event == NULL) { - wpa_printf(MSG_INFO, "ndisuio_notification_init: " - "CreateEvent failed: %d", - (int) GetLastError()); - return -1; - } - - memset(&opt, 0, sizeof(opt)); - opt.dwSize = sizeof(opt); - opt.dwMaxMessages = 5; - opt.cbMaxMessage = NDISUIO_MSG_SIZE; - opt.bReadAccess = TRUE; - - drv->event_queue = CreateMsgQueue(NULL, &opt); - if (drv->event_queue == NULL) { - wpa_printf(MSG_INFO, "ndisuio_notification_init: " - "CreateMsgQueue failed: %d", - (int) GetLastError()); - ndisuio_notification_deinit(drv); - return -1; - } - - memset(&req, 0, sizeof(req)); - req.hMsgQueue = drv->event_queue; - req.dwNotificationTypes = -#ifdef NDISUIO_NOTIFICATION_ADAPTER_ARRIVAL - NDISUIO_NOTIFICATION_ADAPTER_ARRIVAL | -#endif -#ifdef NDISUIO_NOTIFICATION_ADAPTER_REMOVAL - NDISUIO_NOTIFICATION_ADAPTER_REMOVAL | -#endif - NDISUIO_NOTIFICATION_MEDIA_CONNECT | - NDISUIO_NOTIFICATION_MEDIA_DISCONNECT | - NDISUIO_NOTIFICATION_MEDIA_SPECIFIC_NOTIFICATION; - - if (!DeviceIoControl(drv->ndisuio, IOCTL_NDISUIO_REQUEST_NOTIFICATION, - &req, sizeof(req), NULL, 0, NULL, NULL)) { - wpa_printf(MSG_INFO, "ndisuio_notification_init: " - "IOCTL_NDISUIO_REQUEST_NOTIFICATION failed: %d", - (int) GetLastError()); - ndisuio_notification_deinit(drv); - return -1; - } - - eloop_register_event(drv->event_queue, sizeof(drv->event_queue), - ndisuio_notification_receive, drv, NULL); - - return 0; -} -#endif /* _WIN32_WCE */ - - -static int wpa_driver_ndis_get_names(struct wpa_driver_ndis_data *drv) -{ -#ifdef CONFIG_USE_NDISUIO - NDISUIO_QUERY_BINDING *b; - size_t blen = sizeof(*b) + 1024; - int i, error, found = 0; - DWORD written; - char name[256], desc[256], *dpos; - WCHAR *pos; - size_t j, len, dlen; - - b = os_malloc(blen); - if (b == NULL) - return -1; - - for (i = 0; ; i++) { - os_memset(b, 0, blen); - b->BindingIndex = i; - if (!DeviceIoControl(drv->ndisuio, IOCTL_NDISUIO_QUERY_BINDING, - b, sizeof(NDISUIO_QUERY_BINDING), b, blen, - &written, NULL)) { - error = (int) GetLastError(); - if (error == ERROR_NO_MORE_ITEMS) - break; - wpa_printf(MSG_DEBUG, "IOCTL_NDISUIO_QUERY_BINDING " - "failed: %d", error); - break; - } - - pos = (WCHAR *) ((char *) b + b->DeviceNameOffset); - len = b->DeviceNameLength; - if (len >= sizeof(name)) - len = sizeof(name) - 1; - for (j = 0; j < len; j++) - name[j] = (char) pos[j]; - name[len] = '\0'; - - pos = (WCHAR *) ((char *) b + b->DeviceDescrOffset); - len = b->DeviceDescrLength; - if (len >= sizeof(desc)) - len = sizeof(desc) - 1; - for (j = 0; j < len; j++) - desc[j] = (char) pos[j]; - desc[len] = '\0'; - - wpa_printf(MSG_DEBUG, "NDIS: %d - %s - %s", i, name, desc); - - if (os_strstr(name, drv->ifname)) { - wpa_printf(MSG_DEBUG, "NDIS: Interface name match"); - found = 1; - break; - } - - if (os_strncmp(desc, drv->ifname, os_strlen(drv->ifname)) == 0) - { - wpa_printf(MSG_DEBUG, "NDIS: Interface description " - "match"); - found = 1; - break; - } - } - - if (!found) { - wpa_printf(MSG_DEBUG, "NDIS: Could not find interface '%s'", - drv->ifname); - os_free(b); - return -1; - } - - os_strlcpy(drv->ifname, - os_strncmp(name, "\\DEVICE\\", 8) == 0 ? name + 8 : name, - sizeof(drv->ifname)); -#ifdef _WIN32_WCE - drv->adapter_name = wpa_strdup_tchar(drv->ifname); - if (drv->adapter_name == NULL) { - wpa_printf(MSG_ERROR, "NDIS: Failed to allocate memory for " - "adapter name"); - os_free(b); - return -1; - } -#endif /* _WIN32_WCE */ - - dpos = os_strstr(desc, " - "); - if (dpos) - dlen = dpos - desc; - else - dlen = os_strlen(desc); - drv->adapter_desc = os_malloc(dlen + 1); - if (drv->adapter_desc) { - os_memcpy(drv->adapter_desc, desc, dlen); - drv->adapter_desc[dlen] = '\0'; - } - - os_free(b); - - if (drv->adapter_desc == NULL) - return -1; - - wpa_printf(MSG_DEBUG, "NDIS: Adapter description prefix '%s'", - drv->adapter_desc); - - return 0; -#else /* CONFIG_USE_NDISUIO */ - PTSTR _names; - char *names, *pos, *pos2; - ULONG len; - BOOLEAN res; -#define MAX_ADAPTERS 32 - char *name[MAX_ADAPTERS]; - char *desc[MAX_ADAPTERS]; - int num_name, num_desc, i, found_name, found_desc; - size_t dlen; - - wpa_printf(MSG_DEBUG, "NDIS: Packet.dll version: %s", - PacketGetVersion()); - - len = 8192; - _names = os_zalloc(len); - if (_names == NULL) - return -1; - - res = PacketGetAdapterNames(_names, &len); - if (!res && len > 8192) { - os_free(_names); - _names = os_zalloc(len); - if (_names == NULL) - return -1; - res = PacketGetAdapterNames(_names, &len); - } - - if (!res) { - wpa_printf(MSG_ERROR, "NDIS: Failed to get adapter list " - "(PacketGetAdapterNames)"); - os_free(_names); - return -1; - } - - names = (char *) _names; - if (names[0] && names[1] == '\0' && names[2] && names[3] == '\0') { - wpa_printf(MSG_DEBUG, "NDIS: Looks like adapter names are in " - "UNICODE"); - /* Convert to ASCII */ - pos2 = pos = names; - while (pos2 < names + len) { - if (pos2[0] == '\0' && pos2[1] == '\0' && - pos2[2] == '\0' && pos2[3] == '\0') { - pos2 += 4; - break; - } - *pos++ = pos2[0]; - pos2 += 2; - } - os_memcpy(pos + 2, names, pos - names); - pos += 2; - } else - pos = names; - - num_name = 0; - while (pos < names + len) { - name[num_name] = pos; - while (*pos && pos < names + len) - pos++; - if (pos + 1 >= names + len) { - os_free(names); - return -1; - } - pos++; - num_name++; - if (num_name >= MAX_ADAPTERS) { - wpa_printf(MSG_DEBUG, "NDIS: Too many adapters"); - os_free(names); - return -1; - } - if (*pos == '\0') { - wpa_printf(MSG_DEBUG, "NDIS: %d adapter names found", - num_name); - pos++; - break; - } - } - - num_desc = 0; - while (pos < names + len) { - desc[num_desc] = pos; - while (*pos && pos < names + len) - pos++; - if (pos + 1 >= names + len) { - os_free(names); - return -1; - } - pos++; - num_desc++; - if (num_desc >= MAX_ADAPTERS) { - wpa_printf(MSG_DEBUG, "NDIS: Too many adapter " - "descriptions"); - os_free(names); - return -1; - } - if (*pos == '\0') { - wpa_printf(MSG_DEBUG, "NDIS: %d adapter descriptions " - "found", num_name); - pos++; - break; - } - } - - /* - * Windows 98 with Packet.dll 3.0 alpha3 does not include adapter - * descriptions. Fill in dummy descriptors to work around this. - */ - while (num_desc < num_name) - desc[num_desc++] = "dummy description"; - - if (num_name != num_desc) { - wpa_printf(MSG_DEBUG, "NDIS: mismatch in adapter name and " - "description counts (%d != %d)", - num_name, num_desc); - os_free(names); - return -1; - } - - found_name = found_desc = -1; - for (i = 0; i < num_name; i++) { - wpa_printf(MSG_DEBUG, "NDIS: %d - %s - %s", - i, name[i], desc[i]); - if (found_name == -1 && os_strstr(name[i], drv->ifname)) - found_name = i; - if (found_desc == -1 && - os_strncmp(desc[i], drv->ifname, os_strlen(drv->ifname)) == - 0) - found_desc = i; - } - - if (found_name < 0 && found_desc >= 0) { - wpa_printf(MSG_DEBUG, "NDIS: Matched interface '%s' based on " - "description '%s'", - name[found_desc], desc[found_desc]); - found_name = found_desc; - os_strlcpy(drv->ifname, - os_strncmp(name[found_desc], "\\Device\\NPF_", 12) - == 0 ? name[found_desc] + 12 : name[found_desc], - sizeof(drv->ifname)); - } - - if (found_name < 0) { - wpa_printf(MSG_DEBUG, "NDIS: Could not find interface '%s'", - drv->ifname); - os_free(names); - return -1; - } - - i = found_name; - pos = os_strrchr(desc[i], '('); - if (pos) { - dlen = pos - desc[i]; - pos--; - if (pos > desc[i] && *pos == ' ') - dlen--; - } else { - dlen = os_strlen(desc[i]); - } - drv->adapter_desc = os_malloc(dlen + 1); - if (drv->adapter_desc) { - os_memcpy(drv->adapter_desc, desc[i], dlen); - drv->adapter_desc[dlen] = '\0'; - } - - os_free(names); - - if (drv->adapter_desc == NULL) - return -1; - - wpa_printf(MSG_DEBUG, "NDIS: Adapter description prefix '%s'", - drv->adapter_desc); - - return 0; -#endif /* CONFIG_USE_NDISUIO */ -} - - -#if defined(CONFIG_NATIVE_WINDOWS) || defined(__CYGWIN__) -#ifndef _WIN32_WCE -/* - * These structures are undocumented for WinXP; only WinCE version is - * documented. These would be included wzcsapi.h if it were available. Some - * changes here have been needed to make the structures match with WinXP SP2. - * It is unclear whether these work with any other version. - */ - -typedef struct { - LPWSTR wszGuid; -} INTF_KEY_ENTRY, *PINTF_KEY_ENTRY; - -typedef struct { - DWORD dwNumIntfs; - PINTF_KEY_ENTRY pIntfs; -} INTFS_KEY_TABLE, *PINTFS_KEY_TABLE; - -typedef struct { - DWORD dwDataLen; - LPBYTE pData; -} RAW_DATA, *PRAW_DATA; - -typedef struct { - LPWSTR wszGuid; - LPWSTR wszDescr; - ULONG ulMediaState; - ULONG ulMediaType; - ULONG ulPhysicalMediaType; - INT nInfraMode; - INT nAuthMode; - INT nWepStatus; -#ifndef _WIN32_WCE - u8 pad[2]; /* why is this needed? */ -#endif /* _WIN32_WCE */ - DWORD dwCtlFlags; - DWORD dwCapabilities; /* something added for WinXP SP2(?) */ - RAW_DATA rdSSID; - RAW_DATA rdBSSID; - RAW_DATA rdBSSIDList; - RAW_DATA rdStSSIDList; - RAW_DATA rdCtrlData; -#ifdef UNDER_CE - BOOL bInitialized; -#endif - DWORD nWPAMCastCipher; - /* add some extra buffer for later additions since this interface is - * far from stable */ - u8 later_additions[100]; -} INTF_ENTRY, *PINTF_ENTRY; - -#define INTF_ALL 0xffffffff -#define INTF_ALL_FLAGS 0x0000ffff -#define INTF_CTLFLAGS 0x00000010 -#define INTFCTL_ENABLED 0x8000 -#endif /* _WIN32_WCE */ - - -#ifdef _WIN32_WCE -static int wpa_driver_ndis_rebind_adapter(struct wpa_driver_ndis_data *drv) -{ - HANDLE ndis; - TCHAR multi[100]; - int len; - - len = _tcslen(drv->adapter_name); - if (len > 80) - return -1; - - ndis = CreateFile(DD_NDIS_DEVICE_NAME, GENERIC_READ | GENERIC_WRITE, - 0, NULL, OPEN_EXISTING, 0, NULL); - if (ndis == INVALID_HANDLE_VALUE) { - wpa_printf(MSG_DEBUG, "NDIS: Failed to open file to NDIS " - "device: %d", (int) GetLastError()); - return -1; - } - - len++; - memcpy(multi, drv->adapter_name, len * sizeof(TCHAR)); - memcpy(&multi[len], TEXT("NDISUIO\0"), 9 * sizeof(TCHAR)); - len += 9; - - if (!DeviceIoControl(ndis, IOCTL_NDIS_REBIND_ADAPTER, - multi, len * sizeof(TCHAR), NULL, 0, NULL, NULL)) - { - wpa_printf(MSG_DEBUG, "NDIS: IOCTL_NDIS_REBIND_ADAPTER " - "failed: 0x%x", (int) GetLastError()); - wpa_hexdump_ascii(MSG_DEBUG, "NDIS: rebind multi_sz", - (u8 *) multi, len * sizeof(TCHAR)); - CloseHandle(ndis); - return -1; - } - - CloseHandle(ndis); - - wpa_printf(MSG_DEBUG, "NDIS: Requested NDIS rebind of NDISUIO " - "protocol"); - - return 0; -} -#endif /* _WIN32_WCE */ - - -static int wpa_driver_ndis_set_wzc(struct wpa_driver_ndis_data *drv, - int enable) -{ -#ifdef _WIN32_WCE - HKEY hk, hk2; - LONG ret; - DWORD i, hnd, len; - TCHAR keyname[256], devname[256]; - -#define WZC_DRIVER TEXT("Drivers\\BuiltIn\\ZeroConfig") - - if (enable) { - HANDLE h; - h = ActivateDeviceEx(WZC_DRIVER, NULL, 0, NULL); - if (h == INVALID_HANDLE_VALUE || h == 0) { - wpa_printf(MSG_DEBUG, "NDIS: Failed to re-enable WZC " - "- ActivateDeviceEx failed: %d", - (int) GetLastError()); - return -1; - } - - wpa_printf(MSG_DEBUG, "NDIS: WZC re-enabled"); - return wpa_driver_ndis_rebind_adapter(drv); - } - - /* - * Unfortunately, just disabling the WZC for an interface is not enough - * to free NDISUIO for us, so need to disable and unload WZC completely - * for now when using WinCE with NDISUIO. In addition, must request - * NDISUIO protocol to be rebound to the adapter in order to free the - * NDISUIO binding that WZC hold before us. - */ - - /* Enumerate HKLM\Drivers\Active\* to find a handle to WZC. */ - ret = RegOpenKeyEx(HKEY_LOCAL_MACHINE, DEVLOAD_ACTIVE_KEY, 0, 0, &hk); - if (ret != ERROR_SUCCESS) { - wpa_printf(MSG_DEBUG, "NDIS: RegOpenKeyEx(DEVLOAD_ACTIVE_KEY) " - "failed: %d %d", (int) ret, (int) GetLastError()); - return -1; - } - - for (i = 0; ; i++) { - len = sizeof(keyname); - ret = RegEnumKeyEx(hk, i, keyname, &len, NULL, NULL, NULL, - NULL); - if (ret != ERROR_SUCCESS) { - wpa_printf(MSG_DEBUG, "NDIS: Could not find active " - "WZC - assuming it is not running."); - RegCloseKey(hk); - return -1; - } - - ret = RegOpenKeyEx(hk, keyname, 0, 0, &hk2); - if (ret != ERROR_SUCCESS) { - wpa_printf(MSG_DEBUG, "NDIS: RegOpenKeyEx(active dev) " - "failed: %d %d", - (int) ret, (int) GetLastError()); - continue; - } - - len = sizeof(devname); - ret = RegQueryValueEx(hk2, DEVLOAD_DEVKEY_VALNAME, NULL, NULL, - (LPBYTE) devname, &len); - if (ret != ERROR_SUCCESS) { - wpa_printf(MSG_DEBUG, "NDIS: RegQueryValueEx(" - "DEVKEY_VALNAME) failed: %d %d", - (int) ret, (int) GetLastError()); - RegCloseKey(hk2); - continue; - } - - if (_tcscmp(devname, WZC_DRIVER) == 0) - break; - - RegCloseKey(hk2); - } - - RegCloseKey(hk); - - /* Found WZC - get handle to it. */ - len = sizeof(hnd); - ret = RegQueryValueEx(hk2, DEVLOAD_HANDLE_VALNAME, NULL, NULL, - (PUCHAR) &hnd, &len); - if (ret != ERROR_SUCCESS) { - wpa_printf(MSG_DEBUG, "NDIS: RegQueryValueEx(HANDLE_VALNAME) " - "failed: %d %d", (int) ret, (int) GetLastError()); - RegCloseKey(hk2); - return -1; - } - - RegCloseKey(hk2); - - /* Deactivate WZC */ - if (!DeactivateDevice((HANDLE) hnd)) { - wpa_printf(MSG_DEBUG, "NDIS: DeactivateDevice failed: %d", - (int) GetLastError()); - return -1; - } - - wpa_printf(MSG_DEBUG, "NDIS: Disabled WZC temporarily"); - drv->wzc_disabled = 1; - return wpa_driver_ndis_rebind_adapter(drv); - -#else /* _WIN32_WCE */ - - HMODULE hm; - DWORD (WINAPI *wzc_enum_interf)(LPWSTR pSrvAddr, - PINTFS_KEY_TABLE pIntfs); - DWORD (WINAPI *wzc_query_interf)(LPWSTR pSrvAddr, DWORD dwInFlags, - PINTF_ENTRY pIntf, - LPDWORD pdwOutFlags); - DWORD (WINAPI *wzc_set_interf)(LPWSTR pSrvAddr, DWORD dwInFlags, - PINTF_ENTRY pIntf, LPDWORD pdwOutFlags); - int ret = -1, j; - DWORD res; - INTFS_KEY_TABLE guids; - INTF_ENTRY intf; - char guid[128]; - WCHAR *pos; - DWORD flags, i; - - hm = LoadLibrary(TEXT("wzcsapi.dll")); - if (hm == NULL) { - wpa_printf(MSG_DEBUG, "NDIS: Failed to load wzcsapi.dll (%u) " - "- WZC probably not running", - (unsigned int) GetLastError()); - return -1; - } - -#ifdef _WIN32_WCE - wzc_enum_interf = (void *) GetProcAddressA(hm, "WZCEnumInterfaces"); - wzc_query_interf = (void *) GetProcAddressA(hm, "WZCQueryInterface"); - wzc_set_interf = (void *) GetProcAddressA(hm, "WZCSetInterface"); -#else /* _WIN32_WCE */ - wzc_enum_interf = (void *) GetProcAddress(hm, "WZCEnumInterfaces"); - wzc_query_interf = (void *) GetProcAddress(hm, "WZCQueryInterface"); - wzc_set_interf = (void *) GetProcAddress(hm, "WZCSetInterface"); -#endif /* _WIN32_WCE */ - - if (wzc_enum_interf == NULL || wzc_query_interf == NULL || - wzc_set_interf == NULL) { - wpa_printf(MSG_DEBUG, "NDIS: WZCEnumInterfaces, " - "WZCQueryInterface, or WZCSetInterface not found " - "in wzcsapi.dll"); - goto fail; - } - - os_memset(&guids, 0, sizeof(guids)); - res = wzc_enum_interf(NULL, &guids); - if (res != 0) { - wpa_printf(MSG_DEBUG, "NDIS: WZCEnumInterfaces failed: %d; " - "WZC service is apparently not running", - (int) res); - goto fail; - } - - wpa_printf(MSG_DEBUG, "NDIS: WZCEnumInterfaces: %d interfaces", - (int) guids.dwNumIntfs); - - for (i = 0; i < guids.dwNumIntfs; i++) { - pos = guids.pIntfs[i].wszGuid; - for (j = 0; j < sizeof(guid); j++) { - guid[j] = (char) *pos; - if (*pos == 0) - break; - pos++; - } - guid[sizeof(guid) - 1] = '\0'; - wpa_printf(MSG_DEBUG, "NDIS: intfs %d GUID '%s'", - (int) i, guid); - if (os_strstr(drv->ifname, guid) == NULL) - continue; - - wpa_printf(MSG_DEBUG, "NDIS: Current interface found from " - "WZC"); - break; - } - - if (i >= guids.dwNumIntfs) { - wpa_printf(MSG_DEBUG, "NDIS: Current interface not found from " - "WZC"); - goto fail; - } - - os_memset(&intf, 0, sizeof(intf)); - intf.wszGuid = guids.pIntfs[i].wszGuid; - /* Set flags to verify that the structure has not changed. */ - intf.dwCtlFlags = -1; - flags = 0; - res = wzc_query_interf(NULL, INTFCTL_ENABLED, &intf, &flags); - if (res != 0) { - wpa_printf(MSG_DEBUG, "NDIS: Could not query flags for the " - "WZC interface: %d (0x%x)", - (int) res, (int) res); - wpa_printf(MSG_DEBUG, "NDIS: GetLastError: %u", - (unsigned int) GetLastError()); - goto fail; - } - - wpa_printf(MSG_DEBUG, "NDIS: WZC interface flags 0x%x dwCtlFlags 0x%x", - (int) flags, (int) intf.dwCtlFlags); - - if (intf.dwCtlFlags == -1) { - wpa_printf(MSG_DEBUG, "NDIS: Looks like wzcsapi has changed " - "again - could not disable WZC"); - wpa_hexdump(MSG_MSGDUMP, "NDIS: intf", - (u8 *) &intf, sizeof(intf)); - goto fail; - } - - if (enable) { - if (!(intf.dwCtlFlags & INTFCTL_ENABLED)) { - wpa_printf(MSG_DEBUG, "NDIS: Enabling WZC for this " - "interface"); - intf.dwCtlFlags |= INTFCTL_ENABLED; - res = wzc_set_interf(NULL, INTFCTL_ENABLED, &intf, - &flags); - if (res != 0) { - wpa_printf(MSG_DEBUG, "NDIS: Failed to enable " - "WZC: %d (0x%x)", - (int) res, (int) res); - wpa_printf(MSG_DEBUG, "NDIS: GetLastError: %u", - (unsigned int) GetLastError()); - goto fail; - } - wpa_printf(MSG_DEBUG, "NDIS: Re-enabled WZC for this " - "interface"); - drv->wzc_disabled = 0; - } - } else { - if (intf.dwCtlFlags & INTFCTL_ENABLED) { - wpa_printf(MSG_DEBUG, "NDIS: Disabling WZC for this " - "interface"); - intf.dwCtlFlags &= ~INTFCTL_ENABLED; - res = wzc_set_interf(NULL, INTFCTL_ENABLED, &intf, - &flags); - if (res != 0) { - wpa_printf(MSG_DEBUG, "NDIS: Failed to " - "disable WZC: %d (0x%x)", - (int) res, (int) res); - wpa_printf(MSG_DEBUG, "NDIS: GetLastError: %u", - (unsigned int) GetLastError()); - goto fail; - } - wpa_printf(MSG_DEBUG, "NDIS: Disabled WZC temporarily " - "for this interface"); - drv->wzc_disabled = 1; - } else { - wpa_printf(MSG_DEBUG, "NDIS: WZC was not enabled for " - "this interface"); - } - } - - ret = 0; - -fail: - FreeLibrary(hm); - - return ret; -#endif /* _WIN32_WCE */ -} - -#else /* CONFIG_NATIVE_WINDOWS || __CYGWIN__ */ - -static int wpa_driver_ndis_set_wzc(struct wpa_driver_ndis_data *drv, - int enable) -{ - return 0; -} - -#endif /* CONFIG_NATIVE_WINDOWS || __CYGWIN__ */ - - -#ifdef CONFIG_USE_NDISUIO -/* - * l2_packet_ndis.c is sharing the same handle to NDISUIO, so we must be able - * to export this handle. This is somewhat ugly, but there is no better - * mechanism available to pass data from driver interface to l2_packet wrapper. - */ -static HANDLE driver_ndis_ndisuio_handle = INVALID_HANDLE_VALUE; - -HANDLE driver_ndis_get_ndisuio_handle(void) -{ - return driver_ndis_ndisuio_handle; -} -#endif /* CONFIG_USE_NDISUIO */ - - -static int wpa_driver_ndis_adapter_init(struct wpa_driver_ndis_data *drv) -{ -#ifdef CONFIG_USE_NDISUIO -#ifndef _WIN32_WCE -#define NDISUIO_DEVICE_NAME TEXT("\\\\.\\\\Ndisuio") - DWORD written; -#endif /* _WIN32_WCE */ - drv->ndisuio = CreateFile(NDISUIO_DEVICE_NAME, - GENERIC_READ | GENERIC_WRITE, 0, NULL, - OPEN_EXISTING, - FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED, - INVALID_HANDLE_VALUE); - if (drv->ndisuio == INVALID_HANDLE_VALUE) { - wpa_printf(MSG_ERROR, "NDIS: Failed to open connection to " - "NDISUIO: %d", (int) GetLastError()); - return -1; - } - driver_ndis_ndisuio_handle = drv->ndisuio; - -#ifndef _WIN32_WCE - if (!DeviceIoControl(drv->ndisuio, IOCTL_NDISUIO_BIND_WAIT, NULL, 0, - NULL, 0, &written, NULL)) { - wpa_printf(MSG_ERROR, "NDIS: IOCTL_NDISUIO_BIND_WAIT failed: " - "%d", (int) GetLastError()); - CloseHandle(drv->ndisuio); - drv->ndisuio = INVALID_HANDLE_VALUE; - return -1; - } -#endif /* _WIN32_WCE */ - - return 0; -#else /* CONFIG_USE_NDISUIO */ - return 0; -#endif /* CONFIG_USE_NDISUIO */ -} - - -static int wpa_driver_ndis_adapter_open(struct wpa_driver_ndis_data *drv) -{ -#ifdef CONFIG_USE_NDISUIO - DWORD written; -#define MAX_NDIS_DEVICE_NAME_LEN 256 - WCHAR ifname[MAX_NDIS_DEVICE_NAME_LEN]; - size_t len, i, pos; - const char *prefix = "\\DEVICE\\"; - -#ifdef _WIN32_WCE - pos = 0; -#else /* _WIN32_WCE */ - pos = 8; -#endif /* _WIN32_WCE */ - len = pos + os_strlen(drv->ifname); - if (len >= MAX_NDIS_DEVICE_NAME_LEN) - return -1; - for (i = 0; i < pos; i++) - ifname[i] = (WCHAR) prefix[i]; - for (i = pos; i < len; i++) - ifname[i] = (WCHAR) drv->ifname[i - pos]; - ifname[i] = L'\0'; - - if (!DeviceIoControl(drv->ndisuio, IOCTL_NDISUIO_OPEN_DEVICE, - ifname, len * sizeof(WCHAR), NULL, 0, &written, - NULL)) { - wpa_printf(MSG_ERROR, "NDIS: IOCTL_NDISUIO_OPEN_DEVICE " - "failed: %d", (int) GetLastError()); - wpa_hexdump_ascii(MSG_DEBUG, "NDIS: ifname", - (const u8 *) ifname, len * sizeof(WCHAR)); - CloseHandle(drv->ndisuio); - drv->ndisuio = INVALID_HANDLE_VALUE; - return -1; - } - - wpa_printf(MSG_DEBUG, "NDIS: Opened NDISUIO device successfully"); - - return 0; -#else /* CONFIG_USE_NDISUIO */ - char ifname[128]; - os_snprintf(ifname, sizeof(ifname), "\\Device\\NPF_%s", drv->ifname); - drv->adapter = PacketOpenAdapter(ifname); - if (drv->adapter == NULL) { - wpa_printf(MSG_DEBUG, "NDIS: PacketOpenAdapter failed for " - "'%s'", ifname); - return -1; - } - return 0; -#endif /* CONFIG_USE_NDISUIO */ -} - - -static void wpa_driver_ndis_adapter_close(struct wpa_driver_ndis_data *drv) -{ -#ifdef CONFIG_USE_NDISUIO - driver_ndis_ndisuio_handle = INVALID_HANDLE_VALUE; - if (drv->ndisuio != INVALID_HANDLE_VALUE) - CloseHandle(drv->ndisuio); -#else /* CONFIG_USE_NDISUIO */ - if (drv->adapter) - PacketCloseAdapter(drv->adapter); -#endif /* CONFIG_USE_NDISUIO */ -} - - -static int ndis_add_multicast(struct wpa_driver_ndis_data *drv) -{ - if (ndis_set_oid(drv, OID_802_3_MULTICAST_LIST, - (const char *) pae_group_addr, ETH_ALEN) < 0) { - wpa_printf(MSG_DEBUG, "NDIS: Failed to add PAE group address " - "to the multicast list"); - return -1; - } - - return 0; -} - - -static void * wpa_driver_ndis_init(void *ctx, const char *ifname) -{ - struct wpa_driver_ndis_data *drv; - u32 mode; - - drv = os_zalloc(sizeof(*drv)); - if (drv == NULL) - return NULL; - drv->ctx = ctx; - /* - * Compatibility code to strip possible prefix from the GUID. Previous - * versions include \Device\NPF_ prefix for all names, but the internal - * interface name is now only the GUI. Both Packet32 and NDISUIO - * prefixes are supported. - */ - if (os_strncmp(ifname, "\\Device\\NPF_", 12) == 0) - ifname += 12; - else if (os_strncmp(ifname, "\\DEVICE\\", 8) == 0) - ifname += 8; - os_strlcpy(drv->ifname, ifname, sizeof(drv->ifname)); - - if (wpa_driver_ndis_adapter_init(drv) < 0) { - os_free(drv); - return NULL; - } - - if (wpa_driver_ndis_get_names(drv) < 0) { - wpa_driver_ndis_adapter_close(drv); - os_free(drv); - return NULL; - } - - wpa_driver_ndis_set_wzc(drv, 0); - - if (wpa_driver_ndis_adapter_open(drv) < 0) { - wpa_driver_ndis_adapter_close(drv); - os_free(drv); - return NULL; - } - - if (ndis_get_oid(drv, OID_802_3_CURRENT_ADDRESS, - (char *) drv->own_addr, ETH_ALEN) < 0) { - wpa_printf(MSG_DEBUG, "NDIS: Get OID_802_3_CURRENT_ADDRESS " - "failed"); - wpa_driver_ndis_adapter_close(drv); - os_free(drv); - return NULL; - } - wpa_driver_ndis_get_capability(drv); - - /* Make sure that the driver does not have any obsolete PMKID entries. - */ - wpa_driver_ndis_flush_pmkid(drv); - - /* - * Disconnect to make sure that driver re-associates if it was - * connected. - */ - wpa_driver_ndis_disconnect(drv); - - eloop_register_timeout(1, 0, wpa_driver_ndis_poll_timeout, drv, NULL); - -#ifdef CONFIG_NDIS_EVENTS_INTEGRATED - drv->events = ndis_events_init(&drv->events_pipe, &drv->event_avail, - drv->ifname, drv->adapter_desc); - if (drv->events == NULL) { - wpa_driver_ndis_deinit(drv); - return NULL; - } - eloop_register_event(drv->event_avail, sizeof(drv->event_avail), - wpa_driver_ndis_event_pipe_cb, drv, NULL); -#endif /* CONFIG_NDIS_EVENTS_INTEGRATED */ - -#ifdef _WIN32_WCE - if (ndisuio_notification_init(drv) < 0) { - wpa_driver_ndis_deinit(drv); - return NULL; - } -#endif /* _WIN32_WCE */ - - /* Set mode here in case card was configured for ad-hoc mode - * previously. */ - mode = Ndis802_11Infrastructure; - if (ndis_set_oid(drv, OID_802_11_INFRASTRUCTURE_MODE, - (char *) &mode, sizeof(mode)) < 0) { - char buf[8]; - int res; - wpa_printf(MSG_DEBUG, "NDIS: Failed to set " - "OID_802_11_INFRASTRUCTURE_MODE (%d)", - (int) mode); - /* Try to continue anyway */ - - res = ndis_get_oid(drv, OID_DOT11_CURRENT_OPERATION_MODE, buf, - sizeof(buf)); - if (res > 0) { - wpa_printf(MSG_INFO, "NDIS: The driver seems to use " - "Native 802.11 OIDs. These are not yet " - "fully supported."); - drv->native80211 = 1; - } else if (!drv->has_capability || drv->capa.enc == 0) { - /* - * Note: This will also happen with NDIS 6 drivers with - * Vista. - */ - wpa_printf(MSG_DEBUG, "NDIS: Driver did not provide " - "any wireless capabilities - assume it is " - "a wired interface"); - drv->wired = 1; - drv->capa.flags |= WPA_DRIVER_FLAGS_WIRED; - drv->has_capability = 1; - ndis_add_multicast(drv); - } - } - - return drv; -} - - -static void wpa_driver_ndis_deinit(void *priv) -{ - struct wpa_driver_ndis_data *drv = priv; - -#ifdef CONFIG_NDIS_EVENTS_INTEGRATED - if (drv->events) { - eloop_unregister_event(drv->event_avail, - sizeof(drv->event_avail)); - ndis_events_deinit(drv->events); - } -#endif /* CONFIG_NDIS_EVENTS_INTEGRATED */ - -#ifdef _WIN32_WCE - ndisuio_notification_deinit(drv); -#endif /* _WIN32_WCE */ - - eloop_cancel_timeout(wpa_driver_ndis_scan_timeout, drv, drv->ctx); - eloop_cancel_timeout(wpa_driver_ndis_poll_timeout, drv, NULL); - wpa_driver_ndis_flush_pmkid(drv); - wpa_driver_ndis_disconnect(drv); - if (wpa_driver_ndis_radio_off(drv) < 0) { - wpa_printf(MSG_DEBUG, "NDIS: failed to disassociate and turn " - "radio off"); - } - - wpa_driver_ndis_adapter_close(drv); - - if (drv->wzc_disabled) - wpa_driver_ndis_set_wzc(drv, 1); - -#ifdef _WIN32_WCE - os_free(drv->adapter_name); -#endif /* _WIN32_WCE */ - os_free(drv->adapter_desc); - os_free(drv); -} - - -static struct wpa_interface_info * -wpa_driver_ndis_get_interfaces(void *global_priv) -{ - struct wpa_interface_info *iface = NULL, *niface; - -#ifdef CONFIG_USE_NDISUIO - NDISUIO_QUERY_BINDING *b; - size_t blen = sizeof(*b) + 1024; - int i, error; - DWORD written; - char name[256], desc[256]; - WCHAR *pos; - size_t j, len; - HANDLE ndisuio; - - ndisuio = CreateFile(NDISUIO_DEVICE_NAME, - GENERIC_READ | GENERIC_WRITE, 0, NULL, - OPEN_EXISTING, - FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED, - INVALID_HANDLE_VALUE); - if (ndisuio == INVALID_HANDLE_VALUE) { - wpa_printf(MSG_ERROR, "NDIS: Failed to open connection to " - "NDISUIO: %d", (int) GetLastError()); - return NULL; - } - -#ifndef _WIN32_WCE - if (!DeviceIoControl(ndisuio, IOCTL_NDISUIO_BIND_WAIT, NULL, 0, - NULL, 0, &written, NULL)) { - wpa_printf(MSG_ERROR, "NDIS: IOCTL_NDISUIO_BIND_WAIT failed: " - "%d", (int) GetLastError()); - CloseHandle(ndisuio); - return NULL; - } -#endif /* _WIN32_WCE */ - - b = os_malloc(blen); - if (b == NULL) { - CloseHandle(ndisuio); - return NULL; - } - - for (i = 0; ; i++) { - os_memset(b, 0, blen); - b->BindingIndex = i; - if (!DeviceIoControl(ndisuio, IOCTL_NDISUIO_QUERY_BINDING, - b, sizeof(NDISUIO_QUERY_BINDING), b, blen, - &written, NULL)) { - error = (int) GetLastError(); - if (error == ERROR_NO_MORE_ITEMS) - break; - wpa_printf(MSG_DEBUG, "IOCTL_NDISUIO_QUERY_BINDING " - "failed: %d", error); - break; - } - - pos = (WCHAR *) ((char *) b + b->DeviceNameOffset); - len = b->DeviceNameLength; - if (len >= sizeof(name)) - len = sizeof(name) - 1; - for (j = 0; j < len; j++) - name[j] = (char) pos[j]; - name[len] = '\0'; - - pos = (WCHAR *) ((char *) b + b->DeviceDescrOffset); - len = b->DeviceDescrLength; - if (len >= sizeof(desc)) - len = sizeof(desc) - 1; - for (j = 0; j < len; j++) - desc[j] = (char) pos[j]; - desc[len] = '\0'; - - wpa_printf(MSG_DEBUG, "NDIS: %d - %s - %s", i, name, desc); - - niface = os_zalloc(sizeof(*niface)); - if (niface == NULL) - break; - niface->drv_name = "ndis"; - if (os_strncmp(name, "\\DEVICE\\", 8) == 0) - niface->ifname = os_strdup(name + 8); - else - niface->ifname = os_strdup(name); - if (niface->ifname == NULL) { - os_free(niface); - break; - } - niface->desc = os_strdup(desc); - niface->next = iface; - iface = niface; - } - - os_free(b); - CloseHandle(ndisuio); -#else /* CONFIG_USE_NDISUIO */ - PTSTR _names; - char *names, *pos, *pos2; - ULONG len; - BOOLEAN res; - char *name[MAX_ADAPTERS]; - char *desc[MAX_ADAPTERS]; - int num_name, num_desc, i; - - wpa_printf(MSG_DEBUG, "NDIS: Packet.dll version: %s", - PacketGetVersion()); - - len = 8192; - _names = os_zalloc(len); - if (_names == NULL) - return NULL; - - res = PacketGetAdapterNames(_names, &len); - if (!res && len > 8192) { - os_free(_names); - _names = os_zalloc(len); - if (_names == NULL) - return NULL; - res = PacketGetAdapterNames(_names, &len); - } - - if (!res) { - wpa_printf(MSG_ERROR, "NDIS: Failed to get adapter list " - "(PacketGetAdapterNames)"); - os_free(_names); - return NULL; - } - - names = (char *) _names; - if (names[0] && names[1] == '\0' && names[2] && names[3] == '\0') { - wpa_printf(MSG_DEBUG, "NDIS: Looks like adapter names are in " - "UNICODE"); - /* Convert to ASCII */ - pos2 = pos = names; - while (pos2 < names + len) { - if (pos2[0] == '\0' && pos2[1] == '\0' && - pos2[2] == '\0' && pos2[3] == '\0') { - pos2 += 4; - break; - } - *pos++ = pos2[0]; - pos2 += 2; - } - os_memcpy(pos + 2, names, pos - names); - pos += 2; - } else - pos = names; - - num_name = 0; - while (pos < names + len) { - name[num_name] = pos; - while (*pos && pos < names + len) - pos++; - if (pos + 1 >= names + len) { - os_free(names); - return NULL; - } - pos++; - num_name++; - if (num_name >= MAX_ADAPTERS) { - wpa_printf(MSG_DEBUG, "NDIS: Too many adapters"); - os_free(names); - return NULL; - } - if (*pos == '\0') { - wpa_printf(MSG_DEBUG, "NDIS: %d adapter names found", - num_name); - pos++; - break; - } - } - - num_desc = 0; - while (pos < names + len) { - desc[num_desc] = pos; - while (*pos && pos < names + len) - pos++; - if (pos + 1 >= names + len) { - os_free(names); - return NULL; - } - pos++; - num_desc++; - if (num_desc >= MAX_ADAPTERS) { - wpa_printf(MSG_DEBUG, "NDIS: Too many adapter " - "descriptions"); - os_free(names); - return NULL; - } - if (*pos == '\0') { - wpa_printf(MSG_DEBUG, "NDIS: %d adapter descriptions " - "found", num_name); - pos++; - break; - } - } - - /* - * Windows 98 with Packet.dll 3.0 alpha3 does not include adapter - * descriptions. Fill in dummy descriptors to work around this. - */ - while (num_desc < num_name) - desc[num_desc++] = "dummy description"; - - if (num_name != num_desc) { - wpa_printf(MSG_DEBUG, "NDIS: mismatch in adapter name and " - "description counts (%d != %d)", - num_name, num_desc); - os_free(names); - return NULL; - } - - for (i = 0; i < num_name; i++) { - niface = os_zalloc(sizeof(*niface)); - if (niface == NULL) - break; - niface->drv_name = "ndis"; - if (os_strncmp(name[i], "\\Device\\NPF_", 12) == 0) - niface->ifname = os_strdup(name[i] + 12); - else - niface->ifname = os_strdup(name[i]); - if (niface->ifname == NULL) { - os_free(niface); - break; - } - niface->desc = os_strdup(desc[i]); - niface->next = iface; - iface = niface; - } - -#endif /* CONFIG_USE_NDISUIO */ - - return iface; -} - - -const struct wpa_driver_ops wpa_driver_ndis_ops = { - "ndis", - "Windows NDIS driver", - wpa_driver_ndis_get_bssid, - wpa_driver_ndis_get_ssid, - wpa_driver_ndis_set_key, - wpa_driver_ndis_init, - wpa_driver_ndis_deinit, - NULL /* set_param */, - NULL /* set_countermeasures */, - wpa_driver_ndis_deauthenticate, - wpa_driver_ndis_disassociate, - wpa_driver_ndis_associate, - wpa_driver_ndis_add_pmkid, - wpa_driver_ndis_remove_pmkid, - wpa_driver_ndis_flush_pmkid, - wpa_driver_ndis_get_capa, - wpa_driver_ndis_poll, - wpa_driver_ndis_get_ifname, - wpa_driver_ndis_get_mac_addr, - NULL /* send_eapol */, - NULL /* set_operstate */, - NULL /* mlme_setprotection */, - NULL /* get_hw_feature_data */, - NULL /* set_channel */, - NULL /* set_ssid */, - NULL /* set_bssid */, - NULL /* send_mlme */, - NULL /* mlme_add_sta */, - NULL /* mlme_remove_sta */, - NULL /* update_ft_ies */, - NULL /* send_ft_action */, - wpa_driver_ndis_get_scan_results, - NULL /* set_country */, - NULL /* global_init */, - NULL /* global_deinit */, - NULL /* init2 */, - wpa_driver_ndis_get_interfaces, - wpa_driver_ndis_scan, - NULL /* authenticate */, - NULL /* set_beacon */, - NULL /* hapd_init */, - NULL /* hapd_deinit */, - NULL /* set_ieee8021x */, - NULL /* set_privacy */, - NULL /* get_seqnum */, - NULL /* flush */, - NULL /* set_generic_elem */, - NULL /* read_sta_data */, - NULL /* hapd_send_eapol */, - NULL /* sta_deauth */, - NULL /* sta_disassoc */, - NULL /* sta_remove */, - NULL /* hapd_get_ssid */, - NULL /* hapd_set_ssid */, - NULL /* hapd_set_countermeasures */, - NULL /* sta_add */, - NULL /* get_inact_sec */, - NULL /* sta_clear_stats */, - NULL /* set_freq */, - NULL /* set_rts */, - NULL /* set_frag */, - NULL /* sta_set_flags */, - NULL /* set_rate_sets */, - NULL /* set_cts_protect */, - NULL /* set_preamble */, - NULL /* set_short_slot_time */, - NULL /* set_tx_queue_params */, - NULL /* valid_bss_mask */, - NULL /* if_add */, - NULL /* if_remove */, - NULL /* set_sta_vlan */, - NULL /* commit */, - NULL /* send_ether */, - NULL /* set_radius_acl_auth */, - NULL /* set_radius_acl_expire */, - NULL /* set_ht_params */, - NULL /* set_ap_wps_ie */, - NULL /* set_supp_port */, - NULL /* set_wds_sta */, - NULL /* send_action */, - NULL /* send_action_cancel_wait */, - NULL /* remain_on_channel */, - NULL /* cancel_remain_on_channel */, - NULL /* probe_req_report */, - NULL /* disable_11b_rates */, - NULL /* deinit_ap */, - NULL /* suspend */, - NULL /* resume */, - NULL /* signal_monitor */, - NULL /* send_frame */, - NULL /* shared_freq */, - NULL /* get_noa */, - NULL /* set_noa */, - NULL /* set_p2p_powersave */, - NULL /* ampdu */, - NULL /* set_intra_bss */, - NULL /* get_radio_name */, - NULL /* p2p_find */, - NULL /* p2p_stop_find */, - NULL /* p2p_listen */, - NULL /* p2p_connect */, - NULL /* wps_success_cb */, - NULL /* p2p_group_formation_failed */, - NULL /* p2p_set_params */, - NULL /* p2p_prov_disc_req */, - NULL /* p2p_sd_request */, - NULL /* p2p_sd_cancel_request */, - NULL /* p2p_sd_response */, - NULL /* p2p_service_update */, - NULL /* p2p_reject */, - NULL /* p2p_invite */, - NULL /* send_tdls_mgmt */, - NULL /* tdls_oper */, - NULL /* signal_poll */ -}; diff --git a/hostapd-0.8/src/drivers/driver_ndis.h b/hostapd-0.8/src/drivers/driver_ndis.h deleted file mode 100644 index f263f0e..0000000 --- a/hostapd-0.8/src/drivers/driver_ndis.h +++ /dev/null @@ -1,65 +0,0 @@ -/* - * WPA Supplicant - Windows/NDIS driver interface - * Copyright (c) 2004-2006, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#ifndef DRIVER_NDIS_H -#define DRIVER_NDIS_H - -#ifdef CONFIG_NDIS_EVENTS_INTEGRATED -struct ndis_events_data; -struct ndis_events_data * ndis_events_init(HANDLE *read_pipe, HANDLE *event, - const char *ifname, - const char *desc); -void ndis_events_deinit(struct ndis_events_data *events); -#endif /* CONFIG_NDIS_EVENTS_INTEGRATED */ - -struct ndis_pmkid_entry { - struct ndis_pmkid_entry *next; - u8 bssid[ETH_ALEN]; - u8 pmkid[16]; -}; - -struct wpa_driver_ndis_data { - void *ctx; - char ifname[100]; /* GUID: {7EE3EFE5-C165-472F-986D-F6FBEDFE8C8D} */ -#ifdef _WIN32_WCE - TCHAR *adapter_name; - HANDLE event_queue; /* NDISUIO notifier MsgQueue */ - HANDLE connected_event; /* WpaSupplicantConnected event */ -#endif /* _WIN32_WCE */ - u8 own_addr[ETH_ALEN]; -#ifdef CONFIG_USE_NDISUIO - HANDLE ndisuio; -#else /* CONFIG_USE_NDISUIO */ - LPADAPTER adapter; -#endif /* CONFIG_USE_NDISUIO */ - u8 bssid[ETH_ALEN]; - - int has_capability; - int no_of_pmkid; - int radio_enabled; - struct wpa_driver_capa capa; - struct ndis_pmkid_entry *pmkid; - char *adapter_desc; - int wired; - int native80211; - int mode; - int wzc_disabled; - int oid_bssid_set; -#ifdef CONFIG_NDIS_EVENTS_INTEGRATED - HANDLE events_pipe, event_avail; - struct ndis_events_data *events; -#endif /* CONFIG_NDIS_EVENTS_INTEGRATED */ -}; - -#endif /* DRIVER_NDIS_H */ diff --git a/hostapd-0.8/src/drivers/driver_ndis_.c b/hostapd-0.8/src/drivers/driver_ndis_.c deleted file mode 100644 index 4bee9aa..0000000 --- a/hostapd-0.8/src/drivers/driver_ndis_.c +++ /dev/null @@ -1,105 +0,0 @@ -/* - * WPA Supplicant - Windows/NDIS driver interface - event processing - * Copyright (c) 2004-2005, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#include "includes.h" - -#include "common.h" -#include "driver.h" -#include "eloop.h" - -/* Keep this event processing in a separate file and without WinPcap headers to - * avoid conflicts with some of the header files. */ -struct _ADAPTER; -typedef struct _ADAPTER * LPADAPTER; -#include "driver_ndis.h" - - -void wpa_driver_ndis_event_connect(struct wpa_driver_ndis_data *drv); -void wpa_driver_ndis_event_disconnect(struct wpa_driver_ndis_data *drv); -void wpa_driver_ndis_event_media_specific(struct wpa_driver_ndis_data *drv, - const u8 *data, size_t data_len); -void wpa_driver_ndis_event_adapter_arrival(struct wpa_driver_ndis_data *drv); -void wpa_driver_ndis_event_adapter_removal(struct wpa_driver_ndis_data *drv); - - -enum event_types { EVENT_CONNECT, EVENT_DISCONNECT, - EVENT_MEDIA_SPECIFIC, EVENT_ADAPTER_ARRIVAL, - EVENT_ADAPTER_REMOVAL }; - -/* Event data: - * enum event_types (as int, i.e., 4 octets) - * data length (2 octets (big endian), optional) - * data (variable len, optional) - */ - - -static void wpa_driver_ndis_event_process(struct wpa_driver_ndis_data *drv, - u8 *buf, size_t len) -{ - u8 *pos, *data = NULL; - enum event_types type; - size_t data_len = 0; - - wpa_hexdump(MSG_MSGDUMP, "NDIS: received event data", buf, len); - if (len < sizeof(int)) - return; - type = *((int *) buf); - pos = buf + sizeof(int); - wpa_printf(MSG_DEBUG, "NDIS: event - type %d", type); - - if (buf + len - pos > 2) { - data_len = (int) *pos++ << 8; - data_len += *pos++; - if (data_len > (size_t) (buf + len - pos)) { - wpa_printf(MSG_DEBUG, "NDIS: event data overflow"); - return; - } - data = pos; - wpa_hexdump(MSG_MSGDUMP, "NDIS: event data", data, data_len); - } - - switch (type) { - case EVENT_CONNECT: - wpa_driver_ndis_event_connect(drv); - break; - case EVENT_DISCONNECT: - wpa_driver_ndis_event_disconnect(drv); - break; - case EVENT_MEDIA_SPECIFIC: - wpa_driver_ndis_event_media_specific(drv, data, data_len); - break; - case EVENT_ADAPTER_ARRIVAL: - wpa_driver_ndis_event_adapter_arrival(drv); - break; - case EVENT_ADAPTER_REMOVAL: - wpa_driver_ndis_event_adapter_removal(drv); - break; - } -} - - -void wpa_driver_ndis_event_pipe_cb(void *eloop_data, void *user_data) -{ - struct wpa_driver_ndis_data *drv = eloop_data; - u8 buf[512]; - DWORD len; - - ResetEvent(drv->event_avail); - if (ReadFile(drv->events_pipe, buf, sizeof(buf), &len, NULL)) - wpa_driver_ndis_event_process(drv, buf, len); - else { - wpa_printf(MSG_DEBUG, "%s: ReadFile() failed: %d", __func__, - (int) GetLastError()); - } -} diff --git a/hostapd-0.8/src/drivers/driver_nl80211.c b/hostapd-0.8/src/drivers/driver_nl80211.c deleted file mode 100644 index 90b3f20..0000000 --- a/hostapd-0.8/src/drivers/driver_nl80211.c +++ /dev/null @@ -1,6550 +0,0 @@ -/* - * Driver interaction with Linux nl80211/cfg80211 - * Copyright (c) 2002-2010, Jouni Malinen - * Copyright (c) 2003-2004, Instant802 Networks, Inc. - * Copyright (c) 2005-2006, Devicescape Software, Inc. - * Copyright (c) 2007, Johannes Berg - * Copyright (c) 2009-2010, Atheros Communications - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#include "includes.h" -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "nl80211_copy.h" - -#include "common.h" -#include "eloop.h" -#include "utils/list.h" -#include "common/ieee802_11_defs.h" -#include "netlink.h" -#include "linux_ioctl.h" -#include "radiotap.h" -#include "radiotap_iter.h" -#include "rfkill.h" -#include "driver.h" - -#ifdef CONFIG_LIBNL20 -/* libnl 2.0 compatibility code */ -#define nl_handle nl_sock -#define nl80211_handle_alloc nl_socket_alloc_cb -#define nl80211_handle_destroy nl_socket_free -#else -/* - * libnl 1.1 has a bug, it tries to allocate socket numbers densely - * but when you free a socket again it will mess up its bitmap and - * and use the wrong number the next time it needs a socket ID. - * Therefore, we wrap the handle alloc/destroy and add our own pid - * accounting. - */ -static uint32_t port_bitmap[32] = { 0 }; - -static struct nl_handle *nl80211_handle_alloc(void *cb) -{ - struct nl_handle *handle; - uint32_t pid = getpid() & 0x3FFFFF; - int i; - - handle = nl_handle_alloc_cb(cb); - - for (i = 0; i < 1024; i++) { - if (port_bitmap[i / 32] & (1 << (i % 32))) - continue; - port_bitmap[i / 32] |= 1 << (i % 32); - pid += i << 22; - break; - } - - nl_socket_set_local_port(handle, pid); - - return handle; -} - -static void nl80211_handle_destroy(struct nl_handle *handle) -{ - uint32_t port = nl_socket_get_local_port(handle); - - port >>= 22; - port_bitmap[port / 32] &= ~(1 << (port % 32)); - - nl_handle_destroy(handle); -} -#endif /* CONFIG_LIBNL20 */ - - -#ifndef IFF_LOWER_UP -#define IFF_LOWER_UP 0x10000 /* driver signals L1 up */ -#endif -#ifndef IFF_DORMANT -#define IFF_DORMANT 0x20000 /* driver signals dormant */ -#endif - -#ifndef IF_OPER_DORMANT -#define IF_OPER_DORMANT 5 -#endif -#ifndef IF_OPER_UP -#define IF_OPER_UP 6 -#endif - -struct nl80211_global { - struct dl_list interfaces; -}; - -struct i802_bss { - struct wpa_driver_nl80211_data *drv; - struct i802_bss *next; - int ifindex; - char ifname[IFNAMSIZ + 1]; - char brname[IFNAMSIZ]; - unsigned int beacon_set:1; - unsigned int added_if_into_bridge:1; - unsigned int added_bridge:1; -}; - -struct wpa_driver_nl80211_data { - struct nl80211_global *global; - struct dl_list list; - u8 addr[ETH_ALEN]; - char phyname[32]; - void *ctx; - struct netlink_data *netlink; - int ioctl_sock; /* socket for ioctl() use */ - int ifindex; - int if_removed; - int if_disabled; - struct rfkill_data *rfkill; - struct wpa_driver_capa capa; - int has_capability; - - int operstate; - - int scan_complete_events; - - struct nl_handle *nl_handle; - struct nl_handle *nl_handle_event; - struct nl_handle *nl_handle_preq; - struct nl_cache *nl_cache; - struct nl_cache *nl_cache_event; - struct nl_cache *nl_cache_preq; - struct nl_cb *nl_cb; - struct genl_family *nl80211; - - u8 auth_bssid[ETH_ALEN]; - u8 bssid[ETH_ALEN]; - int associated; - u8 ssid[32]; - size_t ssid_len; - int nlmode; - int ap_scan_as_station; - unsigned int assoc_freq; - - int monitor_sock; - int monitor_ifidx; - int disable_11b_rates; - - unsigned int pending_remain_on_chan:1; - - u64 remain_on_chan_cookie; - u64 send_action_cookie; - - unsigned int last_mgmt_freq; - - struct wpa_driver_scan_filter *filter_ssids; - size_t num_filter_ssids; - - struct i802_bss first_bss; - -#ifdef HOSTAPD - int eapol_sock; /* socket for EAPOL frames */ - - int default_if_indices[16]; - int *if_indices; - int num_if_indices; - - int last_freq; - int last_freq_ht; -#endif /* HOSTAPD */ -}; - - -static void wpa_driver_nl80211_scan_timeout(void *eloop_ctx, - void *timeout_ctx); -static int wpa_driver_nl80211_set_mode(void *priv, int mode); -static int -wpa_driver_nl80211_finish_drv_init(struct wpa_driver_nl80211_data *drv); -static int wpa_driver_nl80211_mlme(struct wpa_driver_nl80211_data *drv, - const u8 *addr, int cmd, u16 reason_code, - int local_state_change); -static void nl80211_remove_monitor_interface( - struct wpa_driver_nl80211_data *drv); -static int nl80211_send_frame_cmd(struct wpa_driver_nl80211_data *drv, - unsigned int freq, unsigned int wait, - const u8 *buf, size_t buf_len, u64 *cookie); -static int wpa_driver_nl80211_probe_req_report(void *priv, int report); - -#ifdef HOSTAPD -static void add_ifidx(struct wpa_driver_nl80211_data *drv, int ifidx); -static void del_ifidx(struct wpa_driver_nl80211_data *drv, int ifidx); -static int have_ifidx(struct wpa_driver_nl80211_data *drv, int ifidx); -static int wpa_driver_nl80211_if_remove(void *priv, - enum wpa_driver_if_type type, - const char *ifname); -#else /* HOSTAPD */ -static int have_ifidx(struct wpa_driver_nl80211_data *drv, int ifidx) -{ - return 0; -} -#endif /* HOSTAPD */ - -static int i802_set_freq(void *priv, struct hostapd_freq_params *freq); -static int nl80211_disable_11b_rates(struct wpa_driver_nl80211_data *drv, - int ifindex, int disabled); - -static int nl80211_leave_ibss(struct wpa_driver_nl80211_data *drv); - - -/* nl80211 code */ -static int ack_handler(struct nl_msg *msg, void *arg) -{ - int *err = arg; - *err = 0; - return NL_STOP; -} - -static int finish_handler(struct nl_msg *msg, void *arg) -{ - int *ret = arg; - *ret = 0; - return NL_SKIP; -} - -static int error_handler(struct sockaddr_nl *nla, struct nlmsgerr *err, - void *arg) -{ - int *ret = arg; - *ret = err->error; - return NL_SKIP; -} - - -static int no_seq_check(struct nl_msg *msg, void *arg) -{ - return NL_OK; -} - - -static int send_and_recv(struct wpa_driver_nl80211_data *drv, - struct nl_handle *nl_handle, struct nl_msg *msg, - int (*valid_handler)(struct nl_msg *, void *), - void *valid_data) -{ - struct nl_cb *cb; - int err = -ENOMEM; - - cb = nl_cb_clone(drv->nl_cb); - if (!cb) - goto out; - - err = nl_send_auto_complete(nl_handle, msg); - if (err < 0) - goto out; - - err = 1; - - nl_cb_err(cb, NL_CB_CUSTOM, error_handler, &err); - nl_cb_set(cb, NL_CB_FINISH, NL_CB_CUSTOM, finish_handler, &err); - nl_cb_set(cb, NL_CB_ACK, NL_CB_CUSTOM, ack_handler, &err); - - if (valid_handler) - nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, - valid_handler, valid_data); - - while (err > 0) - nl_recvmsgs(nl_handle, cb); - out: - nl_cb_put(cb); - nlmsg_free(msg); - return err; -} - - -static int send_and_recv_msgs(struct wpa_driver_nl80211_data *drv, - struct nl_msg *msg, - int (*valid_handler)(struct nl_msg *, void *), - void *valid_data) -{ - return send_and_recv(drv, drv->nl_handle, msg, valid_handler, - valid_data); -} - - -struct family_data { - const char *group; - int id; -}; - - -static int family_handler(struct nl_msg *msg, void *arg) -{ - struct family_data *res = arg; - struct nlattr *tb[CTRL_ATTR_MAX + 1]; - struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg)); - struct nlattr *mcgrp; - int i; - - nla_parse(tb, CTRL_ATTR_MAX, genlmsg_attrdata(gnlh, 0), - genlmsg_attrlen(gnlh, 0), NULL); - if (!tb[CTRL_ATTR_MCAST_GROUPS]) - return NL_SKIP; - - nla_for_each_nested(mcgrp, tb[CTRL_ATTR_MCAST_GROUPS], i) { - struct nlattr *tb2[CTRL_ATTR_MCAST_GRP_MAX + 1]; - nla_parse(tb2, CTRL_ATTR_MCAST_GRP_MAX, nla_data(mcgrp), - nla_len(mcgrp), NULL); - if (!tb2[CTRL_ATTR_MCAST_GRP_NAME] || - !tb2[CTRL_ATTR_MCAST_GRP_ID] || - os_strncmp(nla_data(tb2[CTRL_ATTR_MCAST_GRP_NAME]), - res->group, - nla_len(tb2[CTRL_ATTR_MCAST_GRP_NAME])) != 0) - continue; - res->id = nla_get_u32(tb2[CTRL_ATTR_MCAST_GRP_ID]); - break; - }; - - return NL_SKIP; -} - - -static int nl_get_multicast_id(struct wpa_driver_nl80211_data *drv, - const char *family, const char *group) -{ - struct nl_msg *msg; - int ret = -1; - struct family_data res = { group, -ENOENT }; - - msg = nlmsg_alloc(); - if (!msg) - return -ENOMEM; - genlmsg_put(msg, 0, 0, genl_ctrl_resolve(drv->nl_handle, "nlctrl"), - 0, 0, CTRL_CMD_GETFAMILY, 0); - NLA_PUT_STRING(msg, CTRL_ATTR_FAMILY_NAME, family); - - ret = send_and_recv_msgs(drv, msg, family_handler, &res); - msg = NULL; - if (ret == 0) - ret = res.id; - -nla_put_failure: - nlmsg_free(msg); - return ret; -} - - -static int wpa_driver_nl80211_get_bssid(void *priv, u8 *bssid) -{ - struct i802_bss *bss = priv; - struct wpa_driver_nl80211_data *drv = bss->drv; - if (!drv->associated) - return -1; - os_memcpy(bssid, drv->bssid, ETH_ALEN); - return 0; -} - - -static int wpa_driver_nl80211_get_ssid(void *priv, u8 *ssid) -{ - struct i802_bss *bss = priv; - struct wpa_driver_nl80211_data *drv = bss->drv; - if (!drv->associated) - return -1; - os_memcpy(ssid, drv->ssid, drv->ssid_len); - return drv->ssid_len; -} - - -static void wpa_driver_nl80211_event_link(struct wpa_driver_nl80211_data *drv, - char *buf, size_t len, int del) -{ - union wpa_event_data event; - - os_memset(&event, 0, sizeof(event)); - if (len > sizeof(event.interface_status.ifname)) - len = sizeof(event.interface_status.ifname) - 1; - os_memcpy(event.interface_status.ifname, buf, len); - event.interface_status.ievent = del ? EVENT_INTERFACE_REMOVED : - EVENT_INTERFACE_ADDED; - - wpa_printf(MSG_DEBUG, "RTM_%sLINK, IFLA_IFNAME: Interface '%s' %s", - del ? "DEL" : "NEW", - event.interface_status.ifname, - del ? "removed" : "added"); - - if (os_strcmp(drv->first_bss.ifname, event.interface_status.ifname) == 0) { - if (del) - drv->if_removed = 1; - else - drv->if_removed = 0; - } - - wpa_supplicant_event(drv->ctx, EVENT_INTERFACE_STATUS, &event); -} - - -static int wpa_driver_nl80211_own_ifname(struct wpa_driver_nl80211_data *drv, - u8 *buf, size_t len) -{ - int attrlen, rta_len; - struct rtattr *attr; - - attrlen = len; - attr = (struct rtattr *) buf; - - rta_len = RTA_ALIGN(sizeof(struct rtattr)); - while (RTA_OK(attr, attrlen)) { - if (attr->rta_type == IFLA_IFNAME) { - if (os_strcmp(((char *) attr) + rta_len, drv->first_bss.ifname) - == 0) - return 1; - else - break; - } - attr = RTA_NEXT(attr, attrlen); - } - - return 0; -} - - -static int wpa_driver_nl80211_own_ifindex(struct wpa_driver_nl80211_data *drv, - int ifindex, u8 *buf, size_t len) -{ - if (drv->ifindex == ifindex) - return 1; - - if (drv->if_removed && wpa_driver_nl80211_own_ifname(drv, buf, len)) { - drv->first_bss.ifindex = if_nametoindex(drv->first_bss.ifname); - wpa_printf(MSG_DEBUG, "nl80211: Update ifindex for a removed " - "interface"); - wpa_driver_nl80211_finish_drv_init(drv); - return 1; - } - - return 0; -} - - -static void wpa_driver_nl80211_event_rtm_newlink(void *ctx, - struct ifinfomsg *ifi, - u8 *buf, size_t len) -{ - struct wpa_driver_nl80211_data *drv = ctx; - int attrlen, rta_len; - struct rtattr *attr; - u32 brid = 0; - - if (!wpa_driver_nl80211_own_ifindex(drv, ifi->ifi_index, buf, len) && - !have_ifidx(drv, ifi->ifi_index)) { - wpa_printf(MSG_DEBUG, "nl80211: Ignore event for foreign " - "ifindex %d", ifi->ifi_index); - return; - } - - wpa_printf(MSG_DEBUG, "RTM_NEWLINK: operstate=%d ifi_flags=0x%x " - "(%s%s%s%s)", - drv->operstate, ifi->ifi_flags, - (ifi->ifi_flags & IFF_UP) ? "[UP]" : "", - (ifi->ifi_flags & IFF_RUNNING) ? "[RUNNING]" : "", - (ifi->ifi_flags & IFF_LOWER_UP) ? "[LOWER_UP]" : "", - (ifi->ifi_flags & IFF_DORMANT) ? "[DORMANT]" : ""); - - if (!drv->if_disabled && !(ifi->ifi_flags & IFF_UP)) { - wpa_printf(MSG_DEBUG, "nl80211: Interface down"); - drv->if_disabled = 1; - wpa_supplicant_event(drv->ctx, EVENT_INTERFACE_DISABLED, NULL); - } - - if (drv->if_disabled && (ifi->ifi_flags & IFF_UP)) { - wpa_printf(MSG_DEBUG, "nl80211: Interface up"); - drv->if_disabled = 0; - wpa_supplicant_event(drv->ctx, EVENT_INTERFACE_ENABLED, NULL); - } - - /* - * Some drivers send the association event before the operup event--in - * this case, lifting operstate in wpa_driver_nl80211_set_operstate() - * fails. This will hit us when wpa_supplicant does not need to do - * IEEE 802.1X authentication - */ - if (drv->operstate == 1 && - (ifi->ifi_flags & (IFF_LOWER_UP | IFF_DORMANT)) == IFF_LOWER_UP && - !(ifi->ifi_flags & IFF_RUNNING)) - netlink_send_oper_ifla(drv->netlink, drv->ifindex, - -1, IF_OPER_UP); - - attrlen = len; - attr = (struct rtattr *) buf; - rta_len = RTA_ALIGN(sizeof(struct rtattr)); - while (RTA_OK(attr, attrlen)) { - if (attr->rta_type == IFLA_IFNAME) { - wpa_driver_nl80211_event_link( - drv, - ((char *) attr) + rta_len, - attr->rta_len - rta_len, 0); - } else if (attr->rta_type == IFLA_MASTER) - brid = nla_get_u32((struct nlattr *) attr); - attr = RTA_NEXT(attr, attrlen); - } - -#ifdef HOSTAPD - if (ifi->ifi_family == AF_BRIDGE && brid) { - /* device has been added to bridge */ - char namebuf[IFNAMSIZ]; - if_indextoname(brid, namebuf); - wpa_printf(MSG_DEBUG, "nl80211: Add ifindex %u for bridge %s", - brid, namebuf); - add_ifidx(drv, brid); - } -#endif /* HOSTAPD */ -} - - -static void wpa_driver_nl80211_event_rtm_dellink(void *ctx, - struct ifinfomsg *ifi, - u8 *buf, size_t len) -{ - struct wpa_driver_nl80211_data *drv = ctx; - int attrlen, rta_len; - struct rtattr *attr; - u32 brid = 0; - - attrlen = len; - attr = (struct rtattr *) buf; - - rta_len = RTA_ALIGN(sizeof(struct rtattr)); - while (RTA_OK(attr, attrlen)) { - if (attr->rta_type == IFLA_IFNAME) { - wpa_driver_nl80211_event_link( - drv, - ((char *) attr) + rta_len, - attr->rta_len - rta_len, 1); - } else if (attr->rta_type == IFLA_MASTER) - brid = nla_get_u32((struct nlattr *) attr); - attr = RTA_NEXT(attr, attrlen); - } - -#ifdef HOSTAPD - if (ifi->ifi_family == AF_BRIDGE && brid) { - /* device has been removed from bridge */ - char namebuf[IFNAMSIZ]; - if_indextoname(brid, namebuf); - wpa_printf(MSG_DEBUG, "nl80211: Remove ifindex %u for bridge " - "%s", brid, namebuf); - del_ifidx(drv, brid); - } -#endif /* HOSTAPD */ -} - - -static void mlme_event_auth(struct wpa_driver_nl80211_data *drv, - const u8 *frame, size_t len) -{ - const struct ieee80211_mgmt *mgmt; - union wpa_event_data event; - - mgmt = (const struct ieee80211_mgmt *) frame; - if (len < 24 + sizeof(mgmt->u.auth)) { - wpa_printf(MSG_DEBUG, "nl80211: Too short association event " - "frame"); - return; - } - - os_memcpy(drv->auth_bssid, mgmt->sa, ETH_ALEN); - os_memset(&event, 0, sizeof(event)); - os_memcpy(event.auth.peer, mgmt->sa, ETH_ALEN); - event.auth.auth_type = le_to_host16(mgmt->u.auth.auth_alg); - event.auth.status_code = le_to_host16(mgmt->u.auth.status_code); - if (len > 24 + sizeof(mgmt->u.auth)) { - event.auth.ies = mgmt->u.auth.variable; - event.auth.ies_len = len - 24 - sizeof(mgmt->u.auth); - } - - wpa_supplicant_event(drv->ctx, EVENT_AUTH, &event); -} - - -static void mlme_event_assoc(struct wpa_driver_nl80211_data *drv, - const u8 *frame, size_t len) -{ - const struct ieee80211_mgmt *mgmt; - union wpa_event_data event; - u16 status; - - mgmt = (const struct ieee80211_mgmt *) frame; - if (len < 24 + sizeof(mgmt->u.assoc_resp)) { - wpa_printf(MSG_DEBUG, "nl80211: Too short association event " - "frame"); - return; - } - - status = le_to_host16(mgmt->u.assoc_resp.status_code); - if (status != WLAN_STATUS_SUCCESS) { - os_memset(&event, 0, sizeof(event)); - event.assoc_reject.bssid = mgmt->bssid; - if (len > 24 + sizeof(mgmt->u.assoc_resp)) { - event.assoc_reject.resp_ies = - (u8 *) mgmt->u.assoc_resp.variable; - event.assoc_reject.resp_ies_len = - len - 24 - sizeof(mgmt->u.assoc_resp); - } - event.assoc_reject.status_code = status; - - wpa_supplicant_event(drv->ctx, EVENT_ASSOC_REJECT, &event); - return; - } - - drv->associated = 1; - os_memcpy(drv->bssid, mgmt->sa, ETH_ALEN); - - os_memset(&event, 0, sizeof(event)); - if (len > 24 + sizeof(mgmt->u.assoc_resp)) { - event.assoc_info.resp_ies = (u8 *) mgmt->u.assoc_resp.variable; - event.assoc_info.resp_ies_len = - len - 24 - sizeof(mgmt->u.assoc_resp); - } - - event.assoc_info.freq = drv->assoc_freq; - - wpa_supplicant_event(drv->ctx, EVENT_ASSOC, &event); -} - - -static void mlme_event_connect(struct wpa_driver_nl80211_data *drv, - enum nl80211_commands cmd, struct nlattr *status, - struct nlattr *addr, struct nlattr *req_ie, - struct nlattr *resp_ie) -{ - union wpa_event_data event; - - if (drv->capa.flags & WPA_DRIVER_FLAGS_SME) { - /* - * Avoid reporting two association events that would confuse - * the core code. - */ - wpa_printf(MSG_DEBUG, "nl80211: Ignore connect event (cmd=%d) " - "when using userspace SME", cmd); - return; - } - - os_memset(&event, 0, sizeof(event)); - if (cmd == NL80211_CMD_CONNECT && - nla_get_u16(status) != WLAN_STATUS_SUCCESS) { - if (addr) - event.assoc_reject.bssid = nla_data(addr); - if (resp_ie) { - event.assoc_reject.resp_ies = nla_data(resp_ie); - event.assoc_reject.resp_ies_len = nla_len(resp_ie); - } - event.assoc_reject.status_code = nla_get_u16(status); - wpa_supplicant_event(drv->ctx, EVENT_ASSOC_REJECT, &event); - return; - } - - drv->associated = 1; - if (addr) - os_memcpy(drv->bssid, nla_data(addr), ETH_ALEN); - - if (req_ie) { - event.assoc_info.req_ies = nla_data(req_ie); - event.assoc_info.req_ies_len = nla_len(req_ie); - } - if (resp_ie) { - event.assoc_info.resp_ies = nla_data(resp_ie); - event.assoc_info.resp_ies_len = nla_len(resp_ie); - } - - wpa_supplicant_event(drv->ctx, EVENT_ASSOC, &event); -} - - -static void mlme_timeout_event(struct wpa_driver_nl80211_data *drv, - enum nl80211_commands cmd, struct nlattr *addr) -{ - union wpa_event_data event; - enum wpa_event_type ev; - - if (nla_len(addr) != ETH_ALEN) - return; - - wpa_printf(MSG_DEBUG, "nl80211: MLME event %d; timeout with " MACSTR, - cmd, MAC2STR((u8 *) nla_data(addr))); - - if (cmd == NL80211_CMD_AUTHENTICATE) - ev = EVENT_AUTH_TIMED_OUT; - else if (cmd == NL80211_CMD_ASSOCIATE) - ev = EVENT_ASSOC_TIMED_OUT; - else - return; - - os_memset(&event, 0, sizeof(event)); - os_memcpy(event.timeout_event.addr, nla_data(addr), ETH_ALEN); - wpa_supplicant_event(drv->ctx, ev, &event); -} - - -static void mlme_event_mgmt(struct wpa_driver_nl80211_data *drv, - struct nlattr *freq, const u8 *frame, size_t len) -{ - const struct ieee80211_mgmt *mgmt; - union wpa_event_data event; - u16 fc, stype; - - mgmt = (const struct ieee80211_mgmt *) frame; - if (len < 24) { - wpa_printf(MSG_DEBUG, "nl80211: Too short action frame"); - return; - } - - fc = le_to_host16(mgmt->frame_control); - stype = WLAN_FC_GET_STYPE(fc); - - os_memset(&event, 0, sizeof(event)); - if (freq) { - event.rx_action.freq = nla_get_u32(freq); - drv->last_mgmt_freq = event.rx_action.freq; - } - if (stype == WLAN_FC_STYPE_ACTION) { - event.rx_action.da = mgmt->da; - event.rx_action.sa = mgmt->sa; - event.rx_action.bssid = mgmt->bssid; - event.rx_action.category = mgmt->u.action.category; - event.rx_action.data = &mgmt->u.action.category + 1; - event.rx_action.len = frame + len - event.rx_action.data; - wpa_supplicant_event(drv->ctx, EVENT_RX_ACTION, &event); - } else { - event.rx_mgmt.frame = frame; - event.rx_mgmt.frame_len = len; - wpa_supplicant_event(drv->ctx, EVENT_RX_MGMT, &event); - } -} - - -static void mlme_event_action_tx_status(struct wpa_driver_nl80211_data *drv, - struct nlattr *cookie, const u8 *frame, - size_t len, struct nlattr *ack) -{ - union wpa_event_data event; - const struct ieee80211_hdr *hdr; - u16 fc; - u64 cookie_val; - - if (!cookie) - return; - - cookie_val = nla_get_u64(cookie); - wpa_printf(MSG_DEBUG, "nl80211: Action TX status: cookie=0%llx%s " - "(ack=%d)", - (long long unsigned int) cookie_val, - cookie_val == drv->send_action_cookie ? - " (match)" : " (unknown)", ack != NULL); - if (cookie_val != drv->send_action_cookie) - return; - - hdr = (const struct ieee80211_hdr *) frame; - fc = le_to_host16(hdr->frame_control); - - os_memset(&event, 0, sizeof(event)); - event.tx_status.type = WLAN_FC_GET_TYPE(fc); - event.tx_status.stype = WLAN_FC_GET_STYPE(fc); - event.tx_status.dst = hdr->addr1; - event.tx_status.data = frame; - event.tx_status.data_len = len; - event.tx_status.ack = ack != NULL; - wpa_supplicant_event(drv->ctx, EVENT_TX_STATUS, &event); -} - - -static void mlme_event_deauth_disassoc(struct wpa_driver_nl80211_data *drv, - enum wpa_event_type type, - const u8 *frame, size_t len) -{ - const struct ieee80211_mgmt *mgmt; - union wpa_event_data event; - const u8 *bssid = NULL; - u16 reason_code = 0; - - mgmt = (const struct ieee80211_mgmt *) frame; - if (len >= 24) { - bssid = mgmt->bssid; - - if (drv->associated != 0 && - os_memcmp(bssid, drv->bssid, ETH_ALEN) != 0 && - os_memcmp(bssid, drv->auth_bssid, ETH_ALEN) != 0) { - /* - * We have presumably received this deauth as a - * response to a clear_state_mismatch() outgoing - * deauth. Don't let it take us offline! - */ - wpa_printf(MSG_DEBUG, "nl80211: Deauth received " - "from Unknown BSSID " MACSTR " -- ignoring", - MAC2STR(bssid)); - return; - } - } - - drv->associated = 0; - os_memset(&event, 0, sizeof(event)); - - /* Note: Same offset for Reason Code in both frame subtypes */ - if (len >= 24 + sizeof(mgmt->u.deauth)) - reason_code = le_to_host16(mgmt->u.deauth.reason_code); - - if (type == EVENT_DISASSOC) { - event.disassoc_info.addr = bssid; - event.disassoc_info.reason_code = reason_code; - if (frame + len > mgmt->u.disassoc.variable) { - event.disassoc_info.ie = mgmt->u.disassoc.variable; - event.disassoc_info.ie_len = frame + len - - mgmt->u.disassoc.variable; - } - } else { - event.deauth_info.addr = bssid; - event.deauth_info.reason_code = reason_code; - if (frame + len > mgmt->u.deauth.variable) { - event.deauth_info.ie = mgmt->u.deauth.variable; - event.deauth_info.ie_len = frame + len - - mgmt->u.deauth.variable; - } - } - - wpa_supplicant_event(drv->ctx, type, &event); -} - - -static void mlme_event_unprot_disconnect(struct wpa_driver_nl80211_data *drv, - enum wpa_event_type type, - const u8 *frame, size_t len) -{ - const struct ieee80211_mgmt *mgmt; - union wpa_event_data event; - u16 reason_code = 0; - - if (len < 24) - return; - - mgmt = (const struct ieee80211_mgmt *) frame; - - os_memset(&event, 0, sizeof(event)); - /* Note: Same offset for Reason Code in both frame subtypes */ - if (len >= 24 + sizeof(mgmt->u.deauth)) - reason_code = le_to_host16(mgmt->u.deauth.reason_code); - - if (type == EVENT_UNPROT_DISASSOC) { - event.unprot_disassoc.sa = mgmt->sa; - event.unprot_disassoc.da = mgmt->da; - event.unprot_disassoc.reason_code = reason_code; - } else { - event.unprot_deauth.sa = mgmt->sa; - event.unprot_deauth.da = mgmt->da; - event.unprot_deauth.reason_code = reason_code; - } - - wpa_supplicant_event(drv->ctx, type, &event); -} - - -static void mlme_event(struct wpa_driver_nl80211_data *drv, - enum nl80211_commands cmd, struct nlattr *frame, - struct nlattr *addr, struct nlattr *timed_out, - struct nlattr *freq, struct nlattr *ack, - struct nlattr *cookie) -{ - if (timed_out && addr) { - mlme_timeout_event(drv, cmd, addr); - return; - } - - if (frame == NULL) { - wpa_printf(MSG_DEBUG, "nl80211: MLME event %d without frame " - "data", cmd); - return; - } - - wpa_printf(MSG_DEBUG, "nl80211: MLME event %d", cmd); - wpa_hexdump(MSG_MSGDUMP, "nl80211: MLME event frame", - nla_data(frame), nla_len(frame)); - - switch (cmd) { - case NL80211_CMD_AUTHENTICATE: - mlme_event_auth(drv, nla_data(frame), nla_len(frame)); - break; - case NL80211_CMD_ASSOCIATE: - mlme_event_assoc(drv, nla_data(frame), nla_len(frame)); - break; - case NL80211_CMD_DEAUTHENTICATE: - mlme_event_deauth_disassoc(drv, EVENT_DEAUTH, - nla_data(frame), nla_len(frame)); - break; - case NL80211_CMD_DISASSOCIATE: - mlme_event_deauth_disassoc(drv, EVENT_DISASSOC, - nla_data(frame), nla_len(frame)); - break; - case NL80211_CMD_FRAME: - mlme_event_mgmt(drv, freq, nla_data(frame), nla_len(frame)); - break; - case NL80211_CMD_FRAME_TX_STATUS: - mlme_event_action_tx_status(drv, cookie, nla_data(frame), - nla_len(frame), ack); - break; - case NL80211_CMD_UNPROT_DEAUTHENTICATE: - mlme_event_unprot_disconnect(drv, EVENT_UNPROT_DEAUTH, - nla_data(frame), nla_len(frame)); - break; - case NL80211_CMD_UNPROT_DISASSOCIATE: - mlme_event_unprot_disconnect(drv, EVENT_UNPROT_DISASSOC, - nla_data(frame), nla_len(frame)); - break; - default: - break; - } -} - - -static void mlme_event_michael_mic_failure(struct wpa_driver_nl80211_data *drv, - struct nlattr *tb[]) -{ - union wpa_event_data data; - - wpa_printf(MSG_DEBUG, "nl80211: MLME event Michael MIC failure"); - os_memset(&data, 0, sizeof(data)); - if (tb[NL80211_ATTR_MAC]) { - wpa_hexdump(MSG_DEBUG, "nl80211: Source MAC address", - nla_data(tb[NL80211_ATTR_MAC]), - nla_len(tb[NL80211_ATTR_MAC])); - data.michael_mic_failure.src = nla_data(tb[NL80211_ATTR_MAC]); - } - if (tb[NL80211_ATTR_KEY_SEQ]) { - wpa_hexdump(MSG_DEBUG, "nl80211: TSC", - nla_data(tb[NL80211_ATTR_KEY_SEQ]), - nla_len(tb[NL80211_ATTR_KEY_SEQ])); - } - if (tb[NL80211_ATTR_KEY_TYPE]) { - enum nl80211_key_type key_type = - nla_get_u32(tb[NL80211_ATTR_KEY_TYPE]); - wpa_printf(MSG_DEBUG, "nl80211: Key Type %d", key_type); - if (key_type == NL80211_KEYTYPE_PAIRWISE) - data.michael_mic_failure.unicast = 1; - } else - data.michael_mic_failure.unicast = 1; - - if (tb[NL80211_ATTR_KEY_IDX]) { - u8 key_id = nla_get_u8(tb[NL80211_ATTR_KEY_IDX]); - wpa_printf(MSG_DEBUG, "nl80211: Key Id %d", key_id); - } - - wpa_supplicant_event(drv->ctx, EVENT_MICHAEL_MIC_FAILURE, &data); -} - - -static void mlme_event_join_ibss(struct wpa_driver_nl80211_data *drv, - struct nlattr *tb[]) -{ - if (tb[NL80211_ATTR_MAC] == NULL) { - wpa_printf(MSG_DEBUG, "nl80211: No address in IBSS joined " - "event"); - return; - } - os_memcpy(drv->bssid, nla_data(tb[NL80211_ATTR_MAC]), ETH_ALEN); - drv->associated = 1; - wpa_printf(MSG_DEBUG, "nl80211: IBSS " MACSTR " joined", - MAC2STR(drv->bssid)); - - wpa_supplicant_event(drv->ctx, EVENT_ASSOC, NULL); -} - - -static void mlme_event_remain_on_channel(struct wpa_driver_nl80211_data *drv, - int cancel_event, struct nlattr *tb[]) -{ - unsigned int freq, chan_type, duration; - union wpa_event_data data; - u64 cookie; - - if (tb[NL80211_ATTR_WIPHY_FREQ]) - freq = nla_get_u32(tb[NL80211_ATTR_WIPHY_FREQ]); - else - freq = 0; - - if (tb[NL80211_ATTR_WIPHY_CHANNEL_TYPE]) - chan_type = nla_get_u32(tb[NL80211_ATTR_WIPHY_CHANNEL_TYPE]); - else - chan_type = 0; - - if (tb[NL80211_ATTR_DURATION]) - duration = nla_get_u32(tb[NL80211_ATTR_DURATION]); - else - duration = 0; - - if (tb[NL80211_ATTR_COOKIE]) - cookie = nla_get_u64(tb[NL80211_ATTR_COOKIE]); - else - cookie = 0; - - wpa_printf(MSG_DEBUG, "nl80211: Remain-on-channel event (cancel=%d " - "freq=%u channel_type=%u duration=%u cookie=0x%llx (%s))", - cancel_event, freq, chan_type, duration, - (long long unsigned int) cookie, - cookie == drv->remain_on_chan_cookie ? "match" : "unknown"); - - if (cookie != drv->remain_on_chan_cookie) - return; /* not for us */ - - drv->pending_remain_on_chan = !cancel_event; - - os_memset(&data, 0, sizeof(data)); - data.remain_on_channel.freq = freq; - data.remain_on_channel.duration = duration; - wpa_supplicant_event(drv->ctx, cancel_event ? - EVENT_CANCEL_REMAIN_ON_CHANNEL : - EVENT_REMAIN_ON_CHANNEL, &data); -} - - -static void send_scan_event(struct wpa_driver_nl80211_data *drv, int aborted, - struct nlattr *tb[]) -{ - union wpa_event_data event; - struct nlattr *nl; - int rem; - struct scan_info *info; -#define MAX_REPORT_FREQS 50 - int freqs[MAX_REPORT_FREQS]; - int num_freqs = 0; - - os_memset(&event, 0, sizeof(event)); - info = &event.scan_info; - info->aborted = aborted; - - if (tb[NL80211_ATTR_SCAN_SSIDS]) { - nla_for_each_nested(nl, tb[NL80211_ATTR_SCAN_SSIDS], rem) { - struct wpa_driver_scan_ssid *s = - &info->ssids[info->num_ssids]; - s->ssid = nla_data(nl); - s->ssid_len = nla_len(nl); - info->num_ssids++; - if (info->num_ssids == WPAS_MAX_SCAN_SSIDS) - break; - } - } - if (tb[NL80211_ATTR_SCAN_FREQUENCIES]) { - nla_for_each_nested(nl, tb[NL80211_ATTR_SCAN_FREQUENCIES], rem) - { - freqs[num_freqs] = nla_get_u32(nl); - num_freqs++; - if (num_freqs == MAX_REPORT_FREQS - 1) - break; - } - info->freqs = freqs; - info->num_freqs = num_freqs; - } - wpa_supplicant_event(drv->ctx, EVENT_SCAN_RESULTS, &event); -} - - -static int get_link_signal(struct nl_msg *msg, void *arg) -{ - struct nlattr *tb[NL80211_ATTR_MAX + 1]; - struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg)); - struct nlattr *sinfo[NL80211_STA_INFO_MAX + 1]; - static struct nla_policy policy[NL80211_STA_INFO_MAX + 1] = { - [NL80211_STA_INFO_SIGNAL] = { .type = NLA_U8 }, - }; - struct nlattr *rinfo[NL80211_RATE_INFO_MAX + 1]; - static struct nla_policy rate_policy[NL80211_RATE_INFO_MAX + 1] = { - [NL80211_RATE_INFO_BITRATE] = { .type = NLA_U16 }, - [NL80211_RATE_INFO_MCS] = { .type = NLA_U8 }, - [NL80211_RATE_INFO_40_MHZ_WIDTH] = { .type = NLA_FLAG }, - [NL80211_RATE_INFO_SHORT_GI] = { .type = NLA_FLAG }, - }; - struct wpa_signal_info *sig_change = arg; - - nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0), - genlmsg_attrlen(gnlh, 0), NULL); - if (!tb[NL80211_ATTR_STA_INFO] || - nla_parse_nested(sinfo, NL80211_STA_INFO_MAX, - tb[NL80211_ATTR_STA_INFO], policy)) - return NL_SKIP; - if (!sinfo[NL80211_STA_INFO_SIGNAL]) - return NL_SKIP; - - sig_change->current_signal = - (s8) nla_get_u8(sinfo[NL80211_STA_INFO_SIGNAL]); - - if (sinfo[NL80211_STA_INFO_TX_BITRATE]) { - if (nla_parse_nested(rinfo, NL80211_RATE_INFO_MAX, - sinfo[NL80211_STA_INFO_TX_BITRATE], - rate_policy)) { - sig_change->current_txrate = 0; - } else { - if (rinfo[NL80211_RATE_INFO_BITRATE]) { - sig_change->current_txrate = - nla_get_u16(rinfo[ - NL80211_RATE_INFO_BITRATE]) * 100; - } - } - } - - return NL_SKIP; -} - - -static int nl80211_get_link_signal(struct wpa_driver_nl80211_data *drv, - struct wpa_signal_info *sig) -{ - struct nl_msg *msg; - - sig->current_signal = -9999; - sig->current_txrate = 0; - - msg = nlmsg_alloc(); - if (!msg) - return -ENOMEM; - - genlmsg_put(msg, 0, 0, genl_family_get_id(drv->nl80211), 0, - 0, NL80211_CMD_GET_STATION, 0); - - NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, drv->ifindex); - NLA_PUT(msg, NL80211_ATTR_MAC, ETH_ALEN, drv->bssid); - - return send_and_recv_msgs(drv, msg, get_link_signal, sig); - nla_put_failure: - return -ENOBUFS; -} - - -static int get_link_noise(struct nl_msg *msg, void *arg) -{ - struct nlattr *tb[NL80211_ATTR_MAX + 1]; - struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg)); - struct nlattr *sinfo[NL80211_SURVEY_INFO_MAX + 1]; - static struct nla_policy survey_policy[NL80211_SURVEY_INFO_MAX + 1] = { - [NL80211_SURVEY_INFO_FREQUENCY] = { .type = NLA_U32 }, - [NL80211_SURVEY_INFO_NOISE] = { .type = NLA_U8 }, - }; - struct wpa_signal_info *sig_change = arg; - - nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0), - genlmsg_attrlen(gnlh, 0), NULL); - - if (!tb[NL80211_ATTR_SURVEY_INFO]) { - wpa_printf(MSG_DEBUG, "nl80211: survey data missing!"); - return NL_SKIP; - } - - if (nla_parse_nested(sinfo, NL80211_SURVEY_INFO_MAX, - tb[NL80211_ATTR_SURVEY_INFO], - survey_policy)) { - wpa_printf(MSG_DEBUG, "nl80211: failed to parse nested " - "attributes!"); - return NL_SKIP; - } - - if (!sinfo[NL80211_SURVEY_INFO_FREQUENCY]) - return NL_SKIP; - - if (nla_get_u32(sinfo[NL80211_SURVEY_INFO_FREQUENCY]) != - sig_change->frequency) - return NL_SKIP; - - if (!sinfo[NL80211_SURVEY_INFO_NOISE]) - return NL_SKIP; - - sig_change->current_noise = - (s8) nla_get_u8(sinfo[NL80211_SURVEY_INFO_NOISE]); - - return NL_SKIP; -} - - -static int nl80211_get_link_noise(struct wpa_driver_nl80211_data *drv, - struct wpa_signal_info *sig_change) -{ - struct nl_msg *msg; - - sig_change->current_noise = 9999; - sig_change->frequency = drv->assoc_freq; - - msg = nlmsg_alloc(); - if (!msg) - return -ENOMEM; - - genlmsg_put(msg, 0, 0, genl_family_get_id(drv->nl80211), 0, - NLM_F_DUMP, NL80211_CMD_GET_SURVEY, 0); - - NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, drv->ifindex); - - return send_and_recv_msgs(drv, msg, get_link_noise, sig_change); - nla_put_failure: - return -ENOBUFS; -} - - -static void nl80211_cqm_event(struct wpa_driver_nl80211_data *drv, - struct nlattr *tb[]) -{ - static struct nla_policy cqm_policy[NL80211_ATTR_CQM_MAX + 1] = { - [NL80211_ATTR_CQM_RSSI_THOLD] = { .type = NLA_U32 }, - [NL80211_ATTR_CQM_RSSI_HYST] = { .type = NLA_U8 }, - [NL80211_ATTR_CQM_RSSI_THRESHOLD_EVENT] = { .type = NLA_U32 }, - [NL80211_ATTR_CQM_PKT_LOSS_EVENT] = { .type = NLA_U32 }, - }; - struct nlattr *cqm[NL80211_ATTR_CQM_MAX + 1]; - enum nl80211_cqm_rssi_threshold_event event; - union wpa_event_data ed; - struct wpa_signal_info sig; - int res; - - if (tb[NL80211_ATTR_CQM] == NULL || - nla_parse_nested(cqm, NL80211_ATTR_CQM_MAX, tb[NL80211_ATTR_CQM], - cqm_policy)) { - wpa_printf(MSG_DEBUG, "nl80211: Ignore invalid CQM event"); - return; - } - - os_memset(&ed, 0, sizeof(ed)); - - if (cqm[NL80211_ATTR_CQM_PKT_LOSS_EVENT]) { - if (!tb[NL80211_ATTR_MAC]) - return; - os_memcpy(ed.low_ack.addr, nla_data(tb[NL80211_ATTR_MAC]), - ETH_ALEN); - wpa_supplicant_event(drv->ctx, EVENT_STATION_LOW_ACK, &ed); - return; - } - - if (cqm[NL80211_ATTR_CQM_RSSI_THRESHOLD_EVENT] == NULL) - return; - event = nla_get_u32(cqm[NL80211_ATTR_CQM_RSSI_THRESHOLD_EVENT]); - - if (event == NL80211_CQM_RSSI_THRESHOLD_EVENT_HIGH) { - wpa_printf(MSG_DEBUG, "nl80211: Connection quality monitor " - "event: RSSI high"); - ed.signal_change.above_threshold = 1; - } else if (event == NL80211_CQM_RSSI_THRESHOLD_EVENT_LOW) { - wpa_printf(MSG_DEBUG, "nl80211: Connection quality monitor " - "event: RSSI low"); - ed.signal_change.above_threshold = 0; - } else - return; - - res = nl80211_get_link_signal(drv, &sig); - if (res == 0) { - ed.signal_change.current_signal = sig.current_signal; - ed.signal_change.current_txrate = sig.current_txrate; - wpa_printf(MSG_DEBUG, "nl80211: Signal: %d dBm txrate: %d", - sig.current_signal, sig.current_txrate); - } - - res = nl80211_get_link_noise(drv, &sig); - if (res == 0) { - ed.signal_change.current_noise = sig.current_noise; - wpa_printf(MSG_DEBUG, "nl80211: Noise: %d dBm", - sig.current_noise); - } - - wpa_supplicant_event(drv->ctx, EVENT_SIGNAL_CHANGE, &ed); -} - - -static void nl80211_new_station_event(struct wpa_driver_nl80211_data *drv, - struct nlattr **tb) -{ - u8 *addr; - union wpa_event_data data; - - if (tb[NL80211_ATTR_MAC] == NULL) - return; - addr = nla_data(tb[NL80211_ATTR_MAC]); - wpa_printf(MSG_DEBUG, "nl80211: New station " MACSTR, MAC2STR(addr)); - if (drv->nlmode != NL80211_IFTYPE_ADHOC) - return; - - os_memset(&data, 0, sizeof(data)); - os_memcpy(data.ibss_rsn_start.peer, addr, ETH_ALEN); - wpa_supplicant_event(drv->ctx, EVENT_IBSS_RSN_START, &data); -} - - -static void nl80211_del_station_event(struct wpa_driver_nl80211_data *drv, - struct nlattr **tb) -{ - u8 *addr; - union wpa_event_data data; - - if (tb[NL80211_ATTR_MAC] == NULL) - return; - addr = nla_data(tb[NL80211_ATTR_MAC]); - wpa_printf(MSG_DEBUG, "nl80211: Delete station " MACSTR, - MAC2STR(addr)); - if (drv->nlmode != NL80211_IFTYPE_ADHOC) - return; - - os_memset(&data, 0, sizeof(data)); - os_memcpy(data.ibss_peer_lost.peer, addr, ETH_ALEN); - wpa_supplicant_event(drv->ctx, EVENT_IBSS_PEER_LOST, &data); -} - - -static int process_event(struct nl_msg *msg, void *arg) -{ - struct wpa_driver_nl80211_data *drv = arg; - struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg)); - struct nlattr *tb[NL80211_ATTR_MAX + 1]; - union wpa_event_data data; - - nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0), - genlmsg_attrlen(gnlh, 0), NULL); - - if (tb[NL80211_ATTR_IFINDEX]) { - int ifindex = nla_get_u32(tb[NL80211_ATTR_IFINDEX]); - if (ifindex != drv->ifindex && !have_ifidx(drv, ifindex)) { - wpa_printf(MSG_DEBUG, "nl80211: Ignored event (cmd=%d)" - " for foreign interface (ifindex %d)", - gnlh->cmd, ifindex); - return NL_SKIP; - } - } - - if (drv->ap_scan_as_station && - (gnlh->cmd == NL80211_CMD_NEW_SCAN_RESULTS || - gnlh->cmd == NL80211_CMD_SCAN_ABORTED)) { - wpa_driver_nl80211_set_mode(&drv->first_bss, - IEEE80211_MODE_AP); - drv->ap_scan_as_station = 0; - } - - switch (gnlh->cmd) { - case NL80211_CMD_TRIGGER_SCAN: - wpa_printf(MSG_DEBUG, "nl80211: Scan trigger"); - break; - case NL80211_CMD_NEW_SCAN_RESULTS: - wpa_printf(MSG_DEBUG, "nl80211: New scan results available"); - drv->scan_complete_events = 1; - eloop_cancel_timeout(wpa_driver_nl80211_scan_timeout, drv, - drv->ctx); - send_scan_event(drv, 0, tb); - break; - case NL80211_CMD_SCAN_ABORTED: - wpa_printf(MSG_DEBUG, "nl80211: Scan aborted"); - /* - * Need to indicate that scan results are available in order - * not to make wpa_supplicant stop its scanning. - */ - eloop_cancel_timeout(wpa_driver_nl80211_scan_timeout, drv, - drv->ctx); - send_scan_event(drv, 1, tb); - break; - case NL80211_CMD_AUTHENTICATE: - case NL80211_CMD_ASSOCIATE: - case NL80211_CMD_DEAUTHENTICATE: - case NL80211_CMD_DISASSOCIATE: - case NL80211_CMD_FRAME: - case NL80211_CMD_FRAME_TX_STATUS: - case NL80211_CMD_UNPROT_DEAUTHENTICATE: - case NL80211_CMD_UNPROT_DISASSOCIATE: - mlme_event(drv, gnlh->cmd, tb[NL80211_ATTR_FRAME], - tb[NL80211_ATTR_MAC], tb[NL80211_ATTR_TIMED_OUT], - tb[NL80211_ATTR_WIPHY_FREQ], tb[NL80211_ATTR_ACK], - tb[NL80211_ATTR_COOKIE]); - break; - case NL80211_CMD_CONNECT: - case NL80211_CMD_ROAM: - mlme_event_connect(drv, gnlh->cmd, - tb[NL80211_ATTR_STATUS_CODE], - tb[NL80211_ATTR_MAC], - tb[NL80211_ATTR_REQ_IE], - tb[NL80211_ATTR_RESP_IE]); - break; - case NL80211_CMD_DISCONNECT: - if (drv->capa.flags & WPA_DRIVER_FLAGS_SME) { - /* - * Avoid reporting two disassociation events that could - * confuse the core code. - */ - wpa_printf(MSG_DEBUG, "nl80211: Ignore disconnect " - "event when using userspace SME"); - break; - } - drv->associated = 0; - os_memset(&data, 0, sizeof(data)); - if (tb[NL80211_ATTR_REASON_CODE]) - data.disassoc_info.reason_code = - nla_get_u16(tb[NL80211_ATTR_REASON_CODE]); - wpa_supplicant_event(drv->ctx, EVENT_DISASSOC, &data); - break; - case NL80211_CMD_MICHAEL_MIC_FAILURE: - mlme_event_michael_mic_failure(drv, tb); - break; - case NL80211_CMD_JOIN_IBSS: - mlme_event_join_ibss(drv, tb); - break; - case NL80211_CMD_REMAIN_ON_CHANNEL: - mlme_event_remain_on_channel(drv, 0, tb); - break; - case NL80211_CMD_CANCEL_REMAIN_ON_CHANNEL: - mlme_event_remain_on_channel(drv, 1, tb); - break; - case NL80211_CMD_NOTIFY_CQM: - nl80211_cqm_event(drv, tb); - break; - case NL80211_CMD_REG_CHANGE: - wpa_printf(MSG_DEBUG, "nl80211: Regulatory domain change"); - wpa_supplicant_event(drv->ctx, EVENT_CHANNEL_LIST_CHANGED, - NULL); - break; - case NL80211_CMD_REG_BEACON_HINT: - wpa_printf(MSG_DEBUG, "nl80211: Regulatory beacon hint"); - wpa_supplicant_event(drv->ctx, EVENT_CHANNEL_LIST_CHANGED, - NULL); - break; - case NL80211_CMD_NEW_STATION: - nl80211_new_station_event(drv, tb); - break; - case NL80211_CMD_DEL_STATION: - nl80211_del_station_event(drv, tb); - break; - default: - wpa_printf(MSG_DEBUG, "nl80211: Ignored unknown event " - "(cmd=%d)", gnlh->cmd); - break; - } - - return NL_SKIP; -} - - -static void wpa_driver_nl80211_event_receive(int sock, void *eloop_ctx, - void *handle) -{ - struct nl_cb *cb; - struct wpa_driver_nl80211_data *drv = eloop_ctx; - - wpa_printf(MSG_DEBUG, "nl80211: Event message available"); - - cb = nl_cb_clone(drv->nl_cb); - if (!cb) - return; - nl_cb_set(cb, NL_CB_SEQ_CHECK, NL_CB_CUSTOM, no_seq_check, NULL); - nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, process_event, drv); - nl_recvmsgs(handle, cb); - nl_cb_put(cb); -} - - -/** - * wpa_driver_nl80211_set_country - ask nl80211 to set the regulatory domain - * @priv: driver_nl80211 private data - * @alpha2_arg: country to which to switch to - * Returns: 0 on success, -1 on failure - * - * This asks nl80211 to set the regulatory domain for given - * country ISO / IEC alpha2. - */ -static int wpa_driver_nl80211_set_country(void *priv, const char *alpha2_arg) -{ - struct i802_bss *bss = priv; - struct wpa_driver_nl80211_data *drv = bss->drv; - char alpha2[3]; - struct nl_msg *msg; - - msg = nlmsg_alloc(); - if (!msg) - return -ENOMEM; - - alpha2[0] = alpha2_arg[0]; - alpha2[1] = alpha2_arg[1]; - alpha2[2] = '\0'; - - genlmsg_put(msg, 0, 0, genl_family_get_id(drv->nl80211), 0, - 0, NL80211_CMD_REQ_SET_REG, 0); - - NLA_PUT_STRING(msg, NL80211_ATTR_REG_ALPHA2, alpha2); - if (send_and_recv_msgs(drv, msg, NULL, NULL)) - return -EINVAL; - return 0; -nla_put_failure: - return -EINVAL; -} - - -struct wiphy_info_data { - int max_scan_ssids; - int ap_supported; - int p2p_supported; - int auth_supported; - int connect_supported; - int offchan_tx_supported; - int max_remain_on_chan; -}; - - -static int wiphy_info_handler(struct nl_msg *msg, void *arg) -{ - struct nlattr *tb[NL80211_ATTR_MAX + 1]; - struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg)); - struct wiphy_info_data *info = arg; - int p2p_go_supported = 0, p2p_client_supported = 0; - - nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0), - genlmsg_attrlen(gnlh, 0), NULL); - - if (tb[NL80211_ATTR_MAX_NUM_SCAN_SSIDS]) - info->max_scan_ssids = - nla_get_u8(tb[NL80211_ATTR_MAX_NUM_SCAN_SSIDS]); - - if (tb[NL80211_ATTR_SUPPORTED_IFTYPES]) { - struct nlattr *nl_mode; - int i; - nla_for_each_nested(nl_mode, - tb[NL80211_ATTR_SUPPORTED_IFTYPES], i) { - switch (nla_type(nl_mode)) { - case NL80211_IFTYPE_AP: - info->ap_supported = 1; - break; - case NL80211_IFTYPE_P2P_GO: - p2p_go_supported = 1; - break; - case NL80211_IFTYPE_P2P_CLIENT: - p2p_client_supported = 1; - break; - } - } - } - - info->p2p_supported = p2p_go_supported && p2p_client_supported; - - if (tb[NL80211_ATTR_SUPPORTED_COMMANDS]) { - struct nlattr *nl_cmd; - int i; - - nla_for_each_nested(nl_cmd, - tb[NL80211_ATTR_SUPPORTED_COMMANDS], i) { - u32 cmd = nla_get_u32(nl_cmd); - if (cmd == NL80211_CMD_AUTHENTICATE) - info->auth_supported = 1; - else if (cmd == NL80211_CMD_CONNECT) - info->connect_supported = 1; - } - } - - if (tb[NL80211_ATTR_OFFCHANNEL_TX_OK]) - info->offchan_tx_supported = 1; - - if (tb[NL80211_ATTR_MAX_REMAIN_ON_CHANNEL_DURATION]) - info->max_remain_on_chan = - nla_get_u32(tb[NL80211_ATTR_MAX_REMAIN_ON_CHANNEL_DURATION]); - - return NL_SKIP; -} - - -static int wpa_driver_nl80211_get_info(struct wpa_driver_nl80211_data *drv, - struct wiphy_info_data *info) -{ - struct nl_msg *msg; - - os_memset(info, 0, sizeof(*info)); - - /* default to 5000 since early versions of mac80211 don't set it */ - info->max_remain_on_chan = 5000; - - msg = nlmsg_alloc(); - if (!msg) - return -1; - - genlmsg_put(msg, 0, 0, genl_family_get_id(drv->nl80211), 0, - 0, NL80211_CMD_GET_WIPHY, 0); - - NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, drv->first_bss.ifindex); - - if (send_and_recv_msgs(drv, msg, wiphy_info_handler, info) == 0) - return 0; - msg = NULL; -nla_put_failure: - nlmsg_free(msg); - return -1; -} - - -static int wpa_driver_nl80211_capa(struct wpa_driver_nl80211_data *drv) -{ - struct wiphy_info_data info; - if (wpa_driver_nl80211_get_info(drv, &info)) - return -1; - drv->has_capability = 1; - /* For now, assume TKIP, CCMP, WPA, WPA2 are supported */ - drv->capa.key_mgmt = WPA_DRIVER_CAPA_KEY_MGMT_WPA | - WPA_DRIVER_CAPA_KEY_MGMT_WPA_PSK | - WPA_DRIVER_CAPA_KEY_MGMT_WPA2 | - WPA_DRIVER_CAPA_KEY_MGMT_WPA2_PSK; - drv->capa.enc = WPA_DRIVER_CAPA_ENC_WEP40 | - WPA_DRIVER_CAPA_ENC_WEP104 | - WPA_DRIVER_CAPA_ENC_TKIP | - WPA_DRIVER_CAPA_ENC_CCMP; - drv->capa.auth = WPA_DRIVER_AUTH_OPEN | - WPA_DRIVER_AUTH_SHARED | - WPA_DRIVER_AUTH_LEAP; - - drv->capa.max_scan_ssids = info.max_scan_ssids; - if (info.ap_supported) - drv->capa.flags |= WPA_DRIVER_FLAGS_AP; - - if (info.auth_supported) - drv->capa.flags |= WPA_DRIVER_FLAGS_SME; - else if (!info.connect_supported) { - wpa_printf(MSG_INFO, "nl80211: Driver does not support " - "authentication/association or connect commands"); - return -1; - } - - if (info.offchan_tx_supported) { - wpa_printf(MSG_DEBUG, "nl80211: Using driver-based " - "off-channel TX"); - drv->capa.flags |= WPA_DRIVER_FLAGS_OFFCHANNEL_TX; - } - - drv->capa.flags |= WPA_DRIVER_FLAGS_SANE_ERROR_CODES; - drv->capa.flags |= WPA_DRIVER_FLAGS_SET_KEYS_AFTER_ASSOC_DONE; - if (info.p2p_supported) - drv->capa.flags |= WPA_DRIVER_FLAGS_P2P_CAPABLE; - drv->capa.flags |= WPA_DRIVER_FLAGS_EAPOL_TX_STATUS; - drv->capa.max_remain_on_chan = info.max_remain_on_chan; - - return 0; -} - - -static int wpa_driver_nl80211_init_nl(struct wpa_driver_nl80211_data *drv) -{ - int ret; - - /* Initialize generic netlink and nl80211 */ - - drv->nl_cb = nl_cb_alloc(NL_CB_DEFAULT); - if (drv->nl_cb == NULL) { - wpa_printf(MSG_ERROR, "nl80211: Failed to allocate netlink " - "callbacks"); - goto err1; - } - - drv->nl_handle = nl80211_handle_alloc(drv->nl_cb); - if (drv->nl_handle == NULL) { - wpa_printf(MSG_ERROR, "nl80211: Failed to allocate netlink " - "callbacks"); - goto err2; - } - - drv->nl_handle_event = nl80211_handle_alloc(drv->nl_cb); - if (drv->nl_handle_event == NULL) { - wpa_printf(MSG_ERROR, "nl80211: Failed to allocate netlink " - "callbacks (event)"); - goto err2b; - } - - if (genl_connect(drv->nl_handle)) { - wpa_printf(MSG_ERROR, "nl80211: Failed to connect to generic " - "netlink"); - goto err3; - } - - if (genl_connect(drv->nl_handle_event)) { - wpa_printf(MSG_ERROR, "nl80211: Failed to connect to generic " - "netlink (event)"); - goto err3; - } - -#ifdef CONFIG_LIBNL20 - if (genl_ctrl_alloc_cache(drv->nl_handle, &drv->nl_cache) < 0) { - wpa_printf(MSG_ERROR, "nl80211: Failed to allocate generic " - "netlink cache"); - goto err3; - } - if (genl_ctrl_alloc_cache(drv->nl_handle_event, &drv->nl_cache_event) < - 0) { - wpa_printf(MSG_ERROR, "nl80211: Failed to allocate generic " - "netlink cache (event)"); - goto err3b; - } -#else /* CONFIG_LIBNL20 */ - drv->nl_cache = genl_ctrl_alloc_cache(drv->nl_handle); - if (drv->nl_cache == NULL) { - wpa_printf(MSG_ERROR, "nl80211: Failed to allocate generic " - "netlink cache"); - goto err3; - } - drv->nl_cache_event = genl_ctrl_alloc_cache(drv->nl_handle_event); - if (drv->nl_cache_event == NULL) { - wpa_printf(MSG_ERROR, "nl80211: Failed to allocate generic " - "netlink cache (event)"); - goto err3b; - } -#endif /* CONFIG_LIBNL20 */ - - drv->nl80211 = genl_ctrl_search_by_name(drv->nl_cache, "nl80211"); - if (drv->nl80211 == NULL) { - wpa_printf(MSG_ERROR, "nl80211: 'nl80211' generic netlink not " - "found"); - goto err4; - } - - ret = nl_get_multicast_id(drv, "nl80211", "scan"); - if (ret >= 0) - ret = nl_socket_add_membership(drv->nl_handle_event, ret); - if (ret < 0) { - wpa_printf(MSG_ERROR, "nl80211: Could not add multicast " - "membership for scan events: %d (%s)", - ret, strerror(-ret)); - goto err4; - } - - ret = nl_get_multicast_id(drv, "nl80211", "mlme"); - if (ret >= 0) - ret = nl_socket_add_membership(drv->nl_handle_event, ret); - if (ret < 0) { - wpa_printf(MSG_ERROR, "nl80211: Could not add multicast " - "membership for mlme events: %d (%s)", - ret, strerror(-ret)); - goto err4; - } - - ret = nl_get_multicast_id(drv, "nl80211", "regulatory"); - if (ret >= 0) - ret = nl_socket_add_membership(drv->nl_handle_event, ret); - if (ret < 0) { - wpa_printf(MSG_DEBUG, "nl80211: Could not add multicast " - "membership for regulatory events: %d (%s)", - ret, strerror(-ret)); - /* Continue without regulatory events */ - } - - eloop_register_read_sock(nl_socket_get_fd(drv->nl_handle_event), - wpa_driver_nl80211_event_receive, drv, - drv->nl_handle_event); - - return 0; - -err4: - nl_cache_free(drv->nl_cache_event); -err3b: - nl_cache_free(drv->nl_cache); -err3: - nl80211_handle_destroy(drv->nl_handle_event); -err2b: - nl80211_handle_destroy(drv->nl_handle); -err2: - nl_cb_put(drv->nl_cb); -err1: - return -1; -} - - -static void wpa_driver_nl80211_rfkill_blocked(void *ctx) -{ - wpa_printf(MSG_DEBUG, "nl80211: RFKILL blocked"); - /* - * This may be for any interface; use ifdown event to disable - * interface. - */ -} - - -static void wpa_driver_nl80211_rfkill_unblocked(void *ctx) -{ - struct wpa_driver_nl80211_data *drv = ctx; - wpa_printf(MSG_DEBUG, "nl80211: RFKILL unblocked"); - if (linux_set_iface_flags(drv->ioctl_sock, drv->first_bss.ifname, 1)) { - wpa_printf(MSG_DEBUG, "nl80211: Could not set interface UP " - "after rfkill unblock"); - return; - } - /* rtnetlink ifup handler will report interface as enabled */ -} - - -static void nl80211_get_phy_name(struct wpa_driver_nl80211_data *drv) -{ - /* Find phy (radio) to which this interface belongs */ - char buf[90], *pos; - int f, rv; - - drv->phyname[0] = '\0'; - snprintf(buf, sizeof(buf) - 1, "/sys/class/net/%s/phy80211/name", - drv->first_bss.ifname); - f = open(buf, O_RDONLY); - if (f < 0) { - wpa_printf(MSG_DEBUG, "Could not open file %s: %s", - buf, strerror(errno)); - return; - } - - rv = read(f, drv->phyname, sizeof(drv->phyname) - 1); - close(f); - if (rv < 0) { - wpa_printf(MSG_DEBUG, "Could not read file %s: %s", - buf, strerror(errno)); - return; - } - - drv->phyname[rv] = '\0'; - pos = os_strchr(drv->phyname, '\n'); - if (pos) - *pos = '\0'; - wpa_printf(MSG_DEBUG, "nl80211: interface %s in phy %s", - drv->first_bss.ifname, drv->phyname); -} - - -/** - * wpa_driver_nl80211_init - Initialize nl80211 driver interface - * @ctx: context to be used when calling wpa_supplicant functions, - * e.g., wpa_supplicant_event() - * @ifname: interface name, e.g., wlan0 - * @global_priv: private driver global data from global_init() - * Returns: Pointer to private data, %NULL on failure - */ -static void * wpa_driver_nl80211_init(void *ctx, const char *ifname, - void *global_priv) -{ - struct wpa_driver_nl80211_data *drv; - struct netlink_config *cfg; - struct rfkill_config *rcfg; - struct i802_bss *bss; - - drv = os_zalloc(sizeof(*drv)); - if (drv == NULL) - return NULL; - drv->global = global_priv; - drv->ctx = ctx; - bss = &drv->first_bss; - bss->drv = drv; - os_strlcpy(bss->ifname, ifname, sizeof(bss->ifname)); - drv->monitor_ifidx = -1; - drv->monitor_sock = -1; - drv->ioctl_sock = -1; - - if (wpa_driver_nl80211_init_nl(drv)) { - os_free(drv); - return NULL; - } - - nl80211_get_phy_name(drv); - - drv->ioctl_sock = socket(PF_INET, SOCK_DGRAM, 0); - if (drv->ioctl_sock < 0) { - perror("socket(PF_INET,SOCK_DGRAM)"); - goto failed; - } - - cfg = os_zalloc(sizeof(*cfg)); - if (cfg == NULL) - goto failed; - cfg->ctx = drv; - cfg->newlink_cb = wpa_driver_nl80211_event_rtm_newlink; - cfg->dellink_cb = wpa_driver_nl80211_event_rtm_dellink; - drv->netlink = netlink_init(cfg); - if (drv->netlink == NULL) { - os_free(cfg); - goto failed; - } - - rcfg = os_zalloc(sizeof(*rcfg)); - if (rcfg == NULL) - goto failed; - rcfg->ctx = drv; - os_strlcpy(rcfg->ifname, ifname, sizeof(rcfg->ifname)); - rcfg->blocked_cb = wpa_driver_nl80211_rfkill_blocked; - rcfg->unblocked_cb = wpa_driver_nl80211_rfkill_unblocked; - drv->rfkill = rfkill_init(rcfg); - if (drv->rfkill == NULL) { - wpa_printf(MSG_DEBUG, "nl80211: RFKILL status not available"); - os_free(rcfg); - } - - if (wpa_driver_nl80211_finish_drv_init(drv)) - goto failed; - - if (drv->global) - dl_list_add(&drv->global->interfaces, &drv->list); - - return bss; - -failed: - rfkill_deinit(drv->rfkill); - netlink_deinit(drv->netlink); - if (drv->ioctl_sock >= 0) - close(drv->ioctl_sock); - - genl_family_put(drv->nl80211); - nl_cache_free(drv->nl_cache); - nl80211_handle_destroy(drv->nl_handle); - nl_cb_put(drv->nl_cb); - eloop_unregister_read_sock(nl_socket_get_fd(drv->nl_handle_event)); - - os_free(drv); - return NULL; -} - - -static int nl80211_register_frame(struct wpa_driver_nl80211_data *drv, - struct nl_handle *nl_handle, - u16 type, const u8 *match, size_t match_len) -{ - struct nl_msg *msg; - int ret = -1; - - msg = nlmsg_alloc(); - if (!msg) - return -1; - - genlmsg_put(msg, 0, 0, genl_family_get_id(drv->nl80211), 0, 0, - NL80211_CMD_REGISTER_ACTION, 0); - - NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, drv->ifindex); - NLA_PUT_U16(msg, NL80211_ATTR_FRAME_TYPE, type); - NLA_PUT(msg, NL80211_ATTR_FRAME_MATCH, match_len, match); - - ret = send_and_recv(drv, nl_handle, msg, NULL, NULL); - msg = NULL; - if (ret) { - wpa_printf(MSG_DEBUG, "nl80211: Register frame command " - "failed (type=%u): ret=%d (%s)", - type, ret, strerror(-ret)); - wpa_hexdump(MSG_DEBUG, "nl80211: Register frame match", - match, match_len); - goto nla_put_failure; - } - ret = 0; -nla_put_failure: - nlmsg_free(msg); - return ret; -} - - -static int nl80211_register_action_frame(struct wpa_driver_nl80211_data *drv, - const u8 *match, size_t match_len) -{ - u16 type = (WLAN_FC_TYPE_MGMT << 2) | (WLAN_FC_STYPE_ACTION << 4); - return nl80211_register_frame(drv, drv->nl_handle_event, - type, match, match_len); -} - - -static int nl80211_register_action_frames(struct wpa_driver_nl80211_data *drv) -{ -#ifdef CONFIG_P2P - /* GAS Initial Request */ - if (nl80211_register_action_frame(drv, (u8 *) "\x04\x0a", 2) < 0) - return -1; - /* GAS Initial Response */ - if (nl80211_register_action_frame(drv, (u8 *) "\x04\x0b", 2) < 0) - return -1; - /* GAS Comeback Request */ - if (nl80211_register_action_frame(drv, (u8 *) "\x04\x0c", 2) < 0) - return -1; - /* GAS Comeback Response */ - if (nl80211_register_action_frame(drv, (u8 *) "\x04\x0d", 2) < 0) - return -1; - /* P2P Public Action */ - if (nl80211_register_action_frame(drv, - (u8 *) "\x04\x09\x50\x6f\x9a\x09", - 6) < 0) - return -1; - /* P2P Action */ - if (nl80211_register_action_frame(drv, - (u8 *) "\x7f\x50\x6f\x9a\x09", - 5) < 0) - return -1; -#endif /* CONFIG_P2P */ -#ifdef CONFIG_IEEE80211W - /* SA Query Response */ - if (nl80211_register_action_frame(drv, (u8 *) "\x08\x01", 2) < 0) - return -1; -#endif /* CONFIG_IEEE80211W */ - - /* FT Action frames */ - if (nl80211_register_action_frame(drv, (u8 *) "\x06", 1) < 0) - return -1; - else - drv->capa.key_mgmt |= WPA_DRIVER_CAPA_KEY_MGMT_FT | - WPA_DRIVER_CAPA_KEY_MGMT_FT_PSK; - - return 0; -} - - -static void wpa_driver_nl80211_send_rfkill(void *eloop_ctx, void *timeout_ctx) -{ - wpa_supplicant_event(timeout_ctx, EVENT_INTERFACE_DISABLED, NULL); -} - - -static int -wpa_driver_nl80211_finish_drv_init(struct wpa_driver_nl80211_data *drv) -{ - struct i802_bss *bss = &drv->first_bss; - int send_rfkill_event = 0; - - drv->ifindex = if_nametoindex(bss->ifname); - drv->first_bss.ifindex = drv->ifindex; - -#ifndef HOSTAPD - if (wpa_driver_nl80211_set_mode(bss, IEEE80211_MODE_INFRA) < 0) { - wpa_printf(MSG_DEBUG, "nl80211: Could not configure driver to " - "use managed mode"); - } - - if (linux_set_iface_flags(drv->ioctl_sock, bss->ifname, 1)) { - if (rfkill_is_blocked(drv->rfkill)) { - wpa_printf(MSG_DEBUG, "nl80211: Could not yet enable " - "interface '%s' due to rfkill", - bss->ifname); - drv->if_disabled = 1; - send_rfkill_event = 1; - } else { - wpa_printf(MSG_ERROR, "nl80211: Could not set " - "interface '%s' UP", bss->ifname); - return -1; - } - } - - netlink_send_oper_ifla(drv->netlink, drv->ifindex, - 1, IF_OPER_DORMANT); -#endif /* HOSTAPD */ - - if (wpa_driver_nl80211_capa(drv)) - return -1; - - if (linux_get_ifhwaddr(drv->ioctl_sock, bss->ifname, drv->addr)) - return -1; - - if (nl80211_register_action_frames(drv) < 0) { - wpa_printf(MSG_DEBUG, "nl80211: Failed to register Action " - "frame processing - ignore for now"); - /* - * Older kernel versions did not support this, so ignore the - * error for now. Some functionality may not be available - * because of this. - */ - } - - if (send_rfkill_event) { - eloop_register_timeout(0, 0, wpa_driver_nl80211_send_rfkill, - drv, drv->ctx); - } - - return 0; -} - - -static int wpa_driver_nl80211_del_beacon(struct wpa_driver_nl80211_data *drv) -{ - struct nl_msg *msg; - - msg = nlmsg_alloc(); - if (!msg) - return -ENOMEM; - - genlmsg_put(msg, 0, 0, genl_family_get_id(drv->nl80211), 0, - 0, NL80211_CMD_DEL_BEACON, 0); - NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, drv->ifindex); - - return send_and_recv_msgs(drv, msg, NULL, NULL); - nla_put_failure: - return -ENOBUFS; -} - - -/** - * wpa_driver_nl80211_deinit - Deinitialize nl80211 driver interface - * @priv: Pointer to private nl80211 data from wpa_driver_nl80211_init() - * - * Shut down driver interface and processing of driver events. Free - * private data buffer if one was allocated in wpa_driver_nl80211_init(). - */ -static void wpa_driver_nl80211_deinit(void *priv) -{ - struct i802_bss *bss = priv; - struct wpa_driver_nl80211_data *drv = bss->drv; - - if (drv->nl_handle_preq) - wpa_driver_nl80211_probe_req_report(bss, 0); - if (bss->added_if_into_bridge) { - if (linux_br_del_if(drv->ioctl_sock, bss->brname, bss->ifname) - < 0) - wpa_printf(MSG_INFO, "nl80211: Failed to remove " - "interface %s from bridge %s: %s", - bss->ifname, bss->brname, strerror(errno)); - } - if (bss->added_bridge) { - if (linux_br_del(drv->ioctl_sock, bss->brname) < 0) - wpa_printf(MSG_INFO, "nl80211: Failed to remove " - "bridge %s: %s", - bss->brname, strerror(errno)); - } - - nl80211_remove_monitor_interface(drv); - - if (drv->nlmode == NL80211_IFTYPE_AP) - wpa_driver_nl80211_del_beacon(drv); - -#ifdef HOSTAPD - if (drv->last_freq_ht) { - /* Clear HT flags from the driver */ - struct hostapd_freq_params freq; - os_memset(&freq, 0, sizeof(freq)); - freq.freq = drv->last_freq; - i802_set_freq(priv, &freq); - } - - if (drv->eapol_sock >= 0) { - eloop_unregister_read_sock(drv->eapol_sock); - close(drv->eapol_sock); - } - - if (drv->if_indices != drv->default_if_indices) - os_free(drv->if_indices); -#endif /* HOSTAPD */ - - if (drv->disable_11b_rates) - nl80211_disable_11b_rates(drv, drv->ifindex, 0); - - netlink_send_oper_ifla(drv->netlink, drv->ifindex, 0, IF_OPER_UP); - netlink_deinit(drv->netlink); - rfkill_deinit(drv->rfkill); - - eloop_cancel_timeout(wpa_driver_nl80211_scan_timeout, drv, drv->ctx); - - (void) linux_set_iface_flags(drv->ioctl_sock, bss->ifname, 0); - wpa_driver_nl80211_set_mode(bss, IEEE80211_MODE_INFRA); - - if (drv->ioctl_sock >= 0) - close(drv->ioctl_sock); - - eloop_unregister_read_sock(nl_socket_get_fd(drv->nl_handle_event)); - genl_family_put(drv->nl80211); - nl_cache_free(drv->nl_cache); - nl_cache_free(drv->nl_cache_event); - nl80211_handle_destroy(drv->nl_handle); - nl80211_handle_destroy(drv->nl_handle_event); - nl_cb_put(drv->nl_cb); - - os_free(drv->filter_ssids); - - if (drv->global) - dl_list_del(&drv->list); - - os_free(drv); -} - - -/** - * wpa_driver_nl80211_scan_timeout - Scan timeout to report scan completion - * @eloop_ctx: Driver private data - * @timeout_ctx: ctx argument given to wpa_driver_nl80211_init() - * - * This function can be used as registered timeout when starting a scan to - * generate a scan completed event if the driver does not report this. - */ -static void wpa_driver_nl80211_scan_timeout(void *eloop_ctx, void *timeout_ctx) -{ - struct wpa_driver_nl80211_data *drv = eloop_ctx; - if (drv->ap_scan_as_station) { - wpa_driver_nl80211_set_mode(&drv->first_bss, - IEEE80211_MODE_AP); - drv->ap_scan_as_station = 0; - } - wpa_printf(MSG_DEBUG, "Scan timeout - try to get results"); - wpa_supplicant_event(timeout_ctx, EVENT_SCAN_RESULTS, NULL); -} - - -/** - * wpa_driver_nl80211_scan - Request the driver to initiate scan - * @priv: Pointer to private driver data from wpa_driver_nl80211_init() - * @params: Scan parameters - * Returns: 0 on success, -1 on failure - */ -static int wpa_driver_nl80211_scan(void *priv, - struct wpa_driver_scan_params *params) -{ - struct i802_bss *bss = priv; - struct wpa_driver_nl80211_data *drv = bss->drv; - int ret = 0, timeout; - struct nl_msg *msg, *ssids, *freqs; - size_t i; - - msg = nlmsg_alloc(); - ssids = nlmsg_alloc(); - freqs = nlmsg_alloc(); - if (!msg || !ssids || !freqs) { - nlmsg_free(msg); - nlmsg_free(ssids); - nlmsg_free(freqs); - return -1; - } - - os_free(drv->filter_ssids); - drv->filter_ssids = params->filter_ssids; - params->filter_ssids = NULL; - drv->num_filter_ssids = params->num_filter_ssids; - - genlmsg_put(msg, 0, 0, genl_family_get_id(drv->nl80211), 0, 0, - NL80211_CMD_TRIGGER_SCAN, 0); - - NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, drv->ifindex); - - for (i = 0; i < params->num_ssids; i++) { - wpa_hexdump_ascii(MSG_MSGDUMP, "nl80211: Scan SSID", - params->ssids[i].ssid, - params->ssids[i].ssid_len); - NLA_PUT(ssids, i + 1, params->ssids[i].ssid_len, - params->ssids[i].ssid); - } - if (params->num_ssids) - nla_put_nested(msg, NL80211_ATTR_SCAN_SSIDS, ssids); - - if (params->extra_ies) { - wpa_hexdump_ascii(MSG_MSGDUMP, "nl80211: Scan extra IEs", - params->extra_ies, params->extra_ies_len); - NLA_PUT(msg, NL80211_ATTR_IE, params->extra_ies_len, - params->extra_ies); - } - - if (params->freqs) { - for (i = 0; params->freqs[i]; i++) { - wpa_printf(MSG_MSGDUMP, "nl80211: Scan frequency %u " - "MHz", params->freqs[i]); - NLA_PUT_U32(freqs, i + 1, params->freqs[i]); - } - nla_put_nested(msg, NL80211_ATTR_SCAN_FREQUENCIES, freqs); - } - - ret = send_and_recv_msgs(drv, msg, NULL, NULL); - msg = NULL; - if (ret) { - wpa_printf(MSG_DEBUG, "nl80211: Scan trigger failed: ret=%d " - "(%s)", ret, strerror(-ret)); -#ifdef HOSTAPD - if (drv->nlmode == NL80211_IFTYPE_AP) { - /* - * mac80211 does not allow scan requests in AP mode, so - * try to do this in station mode. - */ - if (wpa_driver_nl80211_set_mode(bss, - IEEE80211_MODE_INFRA)) - goto nla_put_failure; - - if (wpa_driver_nl80211_scan(drv, params)) { - wpa_driver_nl80211_set_mode(bss, - IEEE80211_MODE_AP); - goto nla_put_failure; - } - - /* Restore AP mode when processing scan results */ - drv->ap_scan_as_station = 1; - ret = 0; - } else - goto nla_put_failure; -#else /* HOSTAPD */ - goto nla_put_failure; -#endif /* HOSTAPD */ - } - - /* Not all drivers generate "scan completed" wireless event, so try to - * read results after a timeout. */ - timeout = 10; - if (drv->scan_complete_events) { - /* - * The driver seems to deliver events to notify when scan is - * complete, so use longer timeout to avoid race conditions - * with scanning and following association request. - */ - timeout = 30; - } - wpa_printf(MSG_DEBUG, "Scan requested (ret=%d) - scan timeout %d " - "seconds", ret, timeout); - eloop_cancel_timeout(wpa_driver_nl80211_scan_timeout, drv, drv->ctx); - eloop_register_timeout(timeout, 0, wpa_driver_nl80211_scan_timeout, - drv, drv->ctx); - -nla_put_failure: - nlmsg_free(ssids); - nlmsg_free(msg); - nlmsg_free(freqs); - return ret; -} - - -static const u8 * nl80211_get_ie(const u8 *ies, size_t ies_len, u8 ie) -{ - const u8 *end, *pos; - - if (ies == NULL) - return NULL; - - pos = ies; - end = ies + ies_len; - - while (pos + 1 < end) { - if (pos + 2 + pos[1] > end) - break; - if (pos[0] == ie) - return pos; - pos += 2 + pos[1]; - } - - return NULL; -} - - -static int nl80211_scan_filtered(struct wpa_driver_nl80211_data *drv, - const u8 *ie, size_t ie_len) -{ - const u8 *ssid; - size_t i; - - if (drv->filter_ssids == NULL) - return 0; - - ssid = nl80211_get_ie(ie, ie_len, WLAN_EID_SSID); - if (ssid == NULL) - return 1; - - for (i = 0; i < drv->num_filter_ssids; i++) { - if (ssid[1] == drv->filter_ssids[i].ssid_len && - os_memcmp(ssid + 2, drv->filter_ssids[i].ssid, ssid[1]) == - 0) - return 0; - } - - return 1; -} - - -struct nl80211_bss_info_arg { - struct wpa_driver_nl80211_data *drv; - struct wpa_scan_results *res; -}; - -static int bss_info_handler(struct nl_msg *msg, void *arg) -{ - struct nlattr *tb[NL80211_ATTR_MAX + 1]; - struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg)); - struct nlattr *bss[NL80211_BSS_MAX + 1]; - static struct nla_policy bss_policy[NL80211_BSS_MAX + 1] = { - [NL80211_BSS_BSSID] = { .type = NLA_UNSPEC }, - [NL80211_BSS_FREQUENCY] = { .type = NLA_U32 }, - [NL80211_BSS_TSF] = { .type = NLA_U64 }, - [NL80211_BSS_BEACON_INTERVAL] = { .type = NLA_U16 }, - [NL80211_BSS_CAPABILITY] = { .type = NLA_U16 }, - [NL80211_BSS_INFORMATION_ELEMENTS] = { .type = NLA_UNSPEC }, - [NL80211_BSS_SIGNAL_MBM] = { .type = NLA_U32 }, - [NL80211_BSS_SIGNAL_UNSPEC] = { .type = NLA_U8 }, - [NL80211_BSS_STATUS] = { .type = NLA_U32 }, - [NL80211_BSS_SEEN_MS_AGO] = { .type = NLA_U32 }, - [NL80211_BSS_BEACON_IES] = { .type = NLA_UNSPEC }, - }; - struct nl80211_bss_info_arg *_arg = arg; - struct wpa_scan_results *res = _arg->res; - struct wpa_scan_res **tmp; - struct wpa_scan_res *r; - const u8 *ie, *beacon_ie; - size_t ie_len, beacon_ie_len; - u8 *pos; - - nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0), - genlmsg_attrlen(gnlh, 0), NULL); - if (!tb[NL80211_ATTR_BSS]) - return NL_SKIP; - if (nla_parse_nested(bss, NL80211_BSS_MAX, tb[NL80211_ATTR_BSS], - bss_policy)) - return NL_SKIP; - if (bss[NL80211_BSS_INFORMATION_ELEMENTS]) { - ie = nla_data(bss[NL80211_BSS_INFORMATION_ELEMENTS]); - ie_len = nla_len(bss[NL80211_BSS_INFORMATION_ELEMENTS]); - } else { - ie = NULL; - ie_len = 0; - } - if (bss[NL80211_BSS_BEACON_IES]) { - beacon_ie = nla_data(bss[NL80211_BSS_BEACON_IES]); - beacon_ie_len = nla_len(bss[NL80211_BSS_BEACON_IES]); - } else { - beacon_ie = NULL; - beacon_ie_len = 0; - } - - if (nl80211_scan_filtered(_arg->drv, ie ? ie : beacon_ie, - ie ? ie_len : beacon_ie_len)) - return NL_SKIP; - - r = os_zalloc(sizeof(*r) + ie_len + beacon_ie_len); - if (r == NULL) - return NL_SKIP; - if (bss[NL80211_BSS_BSSID]) - os_memcpy(r->bssid, nla_data(bss[NL80211_BSS_BSSID]), - ETH_ALEN); - if (bss[NL80211_BSS_FREQUENCY]) - r->freq = nla_get_u32(bss[NL80211_BSS_FREQUENCY]); - if (bss[NL80211_BSS_BEACON_INTERVAL]) - r->beacon_int = nla_get_u16(bss[NL80211_BSS_BEACON_INTERVAL]); - if (bss[NL80211_BSS_CAPABILITY]) - r->caps = nla_get_u16(bss[NL80211_BSS_CAPABILITY]); - r->flags |= WPA_SCAN_NOISE_INVALID; - if (bss[NL80211_BSS_SIGNAL_MBM]) { - r->level = nla_get_u32(bss[NL80211_BSS_SIGNAL_MBM]); - r->level /= 100; /* mBm to dBm */ - r->flags |= WPA_SCAN_LEVEL_DBM | WPA_SCAN_QUAL_INVALID; - } else if (bss[NL80211_BSS_SIGNAL_UNSPEC]) { - r->level = nla_get_u8(bss[NL80211_BSS_SIGNAL_UNSPEC]); - r->flags |= WPA_SCAN_LEVEL_INVALID; - } else - r->flags |= WPA_SCAN_LEVEL_INVALID | WPA_SCAN_QUAL_INVALID; - if (bss[NL80211_BSS_TSF]) - r->tsf = nla_get_u64(bss[NL80211_BSS_TSF]); - if (bss[NL80211_BSS_SEEN_MS_AGO]) - r->age = nla_get_u32(bss[NL80211_BSS_SEEN_MS_AGO]); - r->ie_len = ie_len; - pos = (u8 *) (r + 1); - if (ie) { - os_memcpy(pos, ie, ie_len); - pos += ie_len; - } - r->beacon_ie_len = beacon_ie_len; - if (beacon_ie) - os_memcpy(pos, beacon_ie, beacon_ie_len); - - if (bss[NL80211_BSS_STATUS]) { - enum nl80211_bss_status status; - status = nla_get_u32(bss[NL80211_BSS_STATUS]); - switch (status) { - case NL80211_BSS_STATUS_AUTHENTICATED: - r->flags |= WPA_SCAN_AUTHENTICATED; - break; - case NL80211_BSS_STATUS_ASSOCIATED: - r->flags |= WPA_SCAN_ASSOCIATED; - break; - default: - break; - } - } - - tmp = os_realloc(res->res, - (res->num + 1) * sizeof(struct wpa_scan_res *)); - if (tmp == NULL) { - os_free(r); - return NL_SKIP; - } - tmp[res->num++] = r; - res->res = tmp; - - return NL_SKIP; -} - - -static void clear_state_mismatch(struct wpa_driver_nl80211_data *drv, - const u8 *addr) -{ - if (drv->capa.flags & WPA_DRIVER_FLAGS_SME) { - wpa_printf(MSG_DEBUG, "nl80211: Clear possible state " - "mismatch (" MACSTR ")", MAC2STR(addr)); - wpa_driver_nl80211_mlme(drv, addr, - NL80211_CMD_DEAUTHENTICATE, - WLAN_REASON_PREV_AUTH_NOT_VALID, 1); - } -} - - -static void wpa_driver_nl80211_check_bss_status( - struct wpa_driver_nl80211_data *drv, struct wpa_scan_results *res) -{ - size_t i; - - for (i = 0; i < res->num; i++) { - struct wpa_scan_res *r = res->res[i]; - if (r->flags & WPA_SCAN_AUTHENTICATED) { - wpa_printf(MSG_DEBUG, "nl80211: Scan results " - "indicates BSS status with " MACSTR - " as authenticated", - MAC2STR(r->bssid)); - if (drv->nlmode == NL80211_IFTYPE_STATION && - os_memcmp(r->bssid, drv->bssid, ETH_ALEN) != 0 && - os_memcmp(r->bssid, drv->auth_bssid, ETH_ALEN) != - 0) { - wpa_printf(MSG_DEBUG, "nl80211: Unknown BSSID" - " in local state (auth=" MACSTR - " assoc=" MACSTR ")", - MAC2STR(drv->auth_bssid), - MAC2STR(drv->bssid)); - clear_state_mismatch(drv, r->bssid); - } - } - - if (r->flags & WPA_SCAN_ASSOCIATED) { - wpa_printf(MSG_DEBUG, "nl80211: Scan results " - "indicate BSS status with " MACSTR - " as associated", - MAC2STR(r->bssid)); - if (drv->nlmode == NL80211_IFTYPE_STATION && - !drv->associated) { - wpa_printf(MSG_DEBUG, "nl80211: Local state " - "(not associated) does not match " - "with BSS state"); - clear_state_mismatch(drv, r->bssid); - } else if (drv->nlmode == NL80211_IFTYPE_STATION && - os_memcmp(drv->bssid, r->bssid, ETH_ALEN) != - 0) { - wpa_printf(MSG_DEBUG, "nl80211: Local state " - "(associated with " MACSTR ") does " - "not match with BSS state", - MAC2STR(drv->bssid)); - clear_state_mismatch(drv, r->bssid); - clear_state_mismatch(drv, drv->bssid); - } - } - } -} - - -static void wpa_scan_results_free(struct wpa_scan_results *res) -{ - size_t i; - - if (res == NULL) - return; - - for (i = 0; i < res->num; i++) - os_free(res->res[i]); - os_free(res->res); - os_free(res); -} - - -static struct wpa_scan_results * -nl80211_get_scan_results(struct wpa_driver_nl80211_data *drv) -{ - struct nl_msg *msg; - struct wpa_scan_results *res; - int ret; - struct nl80211_bss_info_arg arg; - - res = os_zalloc(sizeof(*res)); - if (res == NULL) - return NULL; - msg = nlmsg_alloc(); - if (!msg) - goto nla_put_failure; - - genlmsg_put(msg, 0, 0, genl_family_get_id(drv->nl80211), 0, NLM_F_DUMP, - NL80211_CMD_GET_SCAN, 0); - NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, drv->ifindex); - - arg.drv = drv; - arg.res = res; - ret = send_and_recv_msgs(drv, msg, bss_info_handler, &arg); - msg = NULL; - if (ret == 0) { - wpa_printf(MSG_DEBUG, "Received scan results (%lu BSSes)", - (unsigned long) res->num); - return res; - } - wpa_printf(MSG_DEBUG, "nl80211: Scan result fetch failed: ret=%d " - "(%s)", ret, strerror(-ret)); -nla_put_failure: - nlmsg_free(msg); - wpa_scan_results_free(res); - return NULL; -} - - -/** - * wpa_driver_nl80211_get_scan_results - Fetch the latest scan results - * @priv: Pointer to private wext data from wpa_driver_nl80211_init() - * Returns: Scan results on success, -1 on failure - */ -static struct wpa_scan_results * -wpa_driver_nl80211_get_scan_results(void *priv) -{ - struct i802_bss *bss = priv; - struct wpa_driver_nl80211_data *drv = bss->drv; - struct wpa_scan_results *res; - - res = nl80211_get_scan_results(drv); - if (res) - wpa_driver_nl80211_check_bss_status(drv, res); - return res; -} - - -static void nl80211_dump_scan(struct wpa_driver_nl80211_data *drv) -{ - struct wpa_scan_results *res; - size_t i; - - res = nl80211_get_scan_results(drv); - if (res == NULL) { - wpa_printf(MSG_DEBUG, "nl80211: Failed to get scan results"); - return; - } - - wpa_printf(MSG_DEBUG, "nl80211: Scan result dump"); - for (i = 0; i < res->num; i++) { - struct wpa_scan_res *r = res->res[i]; - wpa_printf(MSG_DEBUG, "nl80211: %d/%d " MACSTR "%s%s", - (int) i, (int) res->num, MAC2STR(r->bssid), - r->flags & WPA_SCAN_AUTHENTICATED ? " [auth]" : "", - r->flags & WPA_SCAN_ASSOCIATED ? " [assoc]" : ""); - } - - wpa_scan_results_free(res); -} - - -static int wpa_driver_nl80211_set_key(const char *ifname, void *priv, - enum wpa_alg alg, const u8 *addr, - int key_idx, int set_tx, - const u8 *seq, size_t seq_len, - const u8 *key, size_t key_len) -{ - struct i802_bss *bss = priv; - struct wpa_driver_nl80211_data *drv = bss->drv; - int ifindex = if_nametoindex(ifname); - struct nl_msg *msg; - int ret; - - wpa_printf(MSG_DEBUG, "%s: ifindex=%d alg=%d addr=%p key_idx=%d " - "set_tx=%d seq_len=%lu key_len=%lu", - __func__, ifindex, alg, addr, key_idx, set_tx, - (unsigned long) seq_len, (unsigned long) key_len); - - msg = nlmsg_alloc(); - if (!msg) - return -ENOMEM; - - if (alg == WPA_ALG_NONE) { - genlmsg_put(msg, 0, 0, genl_family_get_id(drv->nl80211), 0, - 0, NL80211_CMD_DEL_KEY, 0); - } else { - genlmsg_put(msg, 0, 0, genl_family_get_id(drv->nl80211), 0, - 0, NL80211_CMD_NEW_KEY, 0); - NLA_PUT(msg, NL80211_ATTR_KEY_DATA, key_len, key); - switch (alg) { - case WPA_ALG_WEP: - if (key_len == 5) - NLA_PUT_U32(msg, NL80211_ATTR_KEY_CIPHER, - WLAN_CIPHER_SUITE_WEP40); - else - NLA_PUT_U32(msg, NL80211_ATTR_KEY_CIPHER, - WLAN_CIPHER_SUITE_WEP104); - break; - case WPA_ALG_TKIP: - NLA_PUT_U32(msg, NL80211_ATTR_KEY_CIPHER, - WLAN_CIPHER_SUITE_TKIP); - break; - case WPA_ALG_CCMP: - NLA_PUT_U32(msg, NL80211_ATTR_KEY_CIPHER, - WLAN_CIPHER_SUITE_CCMP); - break; - case WPA_ALG_IGTK: - NLA_PUT_U32(msg, NL80211_ATTR_KEY_CIPHER, - WLAN_CIPHER_SUITE_AES_CMAC); - break; - default: - wpa_printf(MSG_ERROR, "%s: Unsupported encryption " - "algorithm %d", __func__, alg); - nlmsg_free(msg); - return -1; - } - } - - if (seq && seq_len) - NLA_PUT(msg, NL80211_ATTR_KEY_SEQ, seq_len, seq); - - if (addr && !is_broadcast_ether_addr(addr)) { - wpa_printf(MSG_DEBUG, " addr=" MACSTR, MAC2STR(addr)); - NLA_PUT(msg, NL80211_ATTR_MAC, ETH_ALEN, addr); - - if (alg != WPA_ALG_WEP && key_idx && !set_tx) { - wpa_printf(MSG_DEBUG, " RSN IBSS RX GTK"); - NLA_PUT_U32(msg, NL80211_ATTR_KEY_TYPE, - NL80211_KEYTYPE_GROUP); - } - } else if (addr && is_broadcast_ether_addr(addr)) { - struct nl_msg *types; - int err; - wpa_printf(MSG_DEBUG, " broadcast key"); - types = nlmsg_alloc(); - if (!types) - goto nla_put_failure; - NLA_PUT_FLAG(types, NL80211_KEY_DEFAULT_TYPE_MULTICAST); - err = nla_put_nested(msg, NL80211_ATTR_KEY_DEFAULT_TYPES, - types); - nlmsg_free(types); - if (err) - goto nla_put_failure; - } - NLA_PUT_U8(msg, NL80211_ATTR_KEY_IDX, key_idx); - NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, ifindex); - - ret = send_and_recv_msgs(drv, msg, NULL, NULL); - if ((ret == -ENOENT || ret == -ENOLINK) && alg == WPA_ALG_NONE) - ret = 0; - if (ret) - wpa_printf(MSG_DEBUG, "nl80211: set_key failed; err=%d %s)", - ret, strerror(-ret)); - - /* - * If we failed or don't need to set the default TX key (below), - * we're done here. - */ - if (ret || !set_tx || alg == WPA_ALG_NONE) - return ret; - if (drv->nlmode == NL80211_IFTYPE_AP && addr && - !is_broadcast_ether_addr(addr)) - return ret; - - msg = nlmsg_alloc(); - if (!msg) - return -ENOMEM; - - genlmsg_put(msg, 0, 0, genl_family_get_id(drv->nl80211), 0, - 0, NL80211_CMD_SET_KEY, 0); - NLA_PUT_U8(msg, NL80211_ATTR_KEY_IDX, key_idx); - NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, ifindex); - if (alg == WPA_ALG_IGTK) - NLA_PUT_FLAG(msg, NL80211_ATTR_KEY_DEFAULT_MGMT); - else - NLA_PUT_FLAG(msg, NL80211_ATTR_KEY_DEFAULT); - if (addr && is_broadcast_ether_addr(addr)) { - struct nl_msg *types; - int err; - types = nlmsg_alloc(); - if (!types) - goto nla_put_failure; - NLA_PUT_FLAG(types, NL80211_KEY_DEFAULT_TYPE_MULTICAST); - err = nla_put_nested(msg, NL80211_ATTR_KEY_DEFAULT_TYPES, - types); - nlmsg_free(types); - if (err) - goto nla_put_failure; - } else if (addr) { - struct nl_msg *types; - int err; - types = nlmsg_alloc(); - if (!types) - goto nla_put_failure; - NLA_PUT_FLAG(types, NL80211_KEY_DEFAULT_TYPE_UNICAST); - err = nla_put_nested(msg, NL80211_ATTR_KEY_DEFAULT_TYPES, - types); - nlmsg_free(types); - if (err) - goto nla_put_failure; - } - - ret = send_and_recv_msgs(drv, msg, NULL, NULL); - if (ret == -ENOENT) - ret = 0; - if (ret) - wpa_printf(MSG_DEBUG, "nl80211: set_key default failed; " - "err=%d %s)", ret, strerror(-ret)); - return ret; - -nla_put_failure: - return -ENOBUFS; -} - - -static int nl_add_key(struct nl_msg *msg, enum wpa_alg alg, - int key_idx, int defkey, - const u8 *seq, size_t seq_len, - const u8 *key, size_t key_len) -{ - struct nlattr *key_attr = nla_nest_start(msg, NL80211_ATTR_KEY); - if (!key_attr) - return -1; - - if (defkey && alg == WPA_ALG_IGTK) - NLA_PUT_FLAG(msg, NL80211_KEY_DEFAULT_MGMT); - else if (defkey) - NLA_PUT_FLAG(msg, NL80211_KEY_DEFAULT); - - NLA_PUT_U8(msg, NL80211_KEY_IDX, key_idx); - - switch (alg) { - case WPA_ALG_WEP: - if (key_len == 5) - NLA_PUT_U32(msg, NL80211_KEY_CIPHER, - WLAN_CIPHER_SUITE_WEP40); - else - NLA_PUT_U32(msg, NL80211_KEY_CIPHER, - WLAN_CIPHER_SUITE_WEP104); - break; - case WPA_ALG_TKIP: - NLA_PUT_U32(msg, NL80211_KEY_CIPHER, WLAN_CIPHER_SUITE_TKIP); - break; - case WPA_ALG_CCMP: - NLA_PUT_U32(msg, NL80211_KEY_CIPHER, WLAN_CIPHER_SUITE_CCMP); - break; - case WPA_ALG_IGTK: - NLA_PUT_U32(msg, NL80211_KEY_CIPHER, - WLAN_CIPHER_SUITE_AES_CMAC); - break; - default: - wpa_printf(MSG_ERROR, "%s: Unsupported encryption " - "algorithm %d", __func__, alg); - return -1; - } - - if (seq && seq_len) - NLA_PUT(msg, NL80211_KEY_SEQ, seq_len, seq); - - NLA_PUT(msg, NL80211_KEY_DATA, key_len, key); - - nla_nest_end(msg, key_attr); - - return 0; - nla_put_failure: - return -1; -} - - -static int nl80211_set_conn_keys(struct wpa_driver_associate_params *params, - struct nl_msg *msg) -{ - int i, privacy = 0; - struct nlattr *nl_keys, *nl_key; - - for (i = 0; i < 4; i++) { - if (!params->wep_key[i]) - continue; - privacy = 1; - break; - } - if (params->wps == WPS_MODE_PRIVACY) - privacy = 1; - if (params->pairwise_suite && - params->pairwise_suite != WPA_CIPHER_NONE) - privacy = 1; - - if (!privacy) - return 0; - - NLA_PUT_FLAG(msg, NL80211_ATTR_PRIVACY); - - nl_keys = nla_nest_start(msg, NL80211_ATTR_KEYS); - if (!nl_keys) - goto nla_put_failure; - - for (i = 0; i < 4; i++) { - if (!params->wep_key[i]) - continue; - - nl_key = nla_nest_start(msg, i); - if (!nl_key) - goto nla_put_failure; - - NLA_PUT(msg, NL80211_KEY_DATA, params->wep_key_len[i], - params->wep_key[i]); - if (params->wep_key_len[i] == 5) - NLA_PUT_U32(msg, NL80211_KEY_CIPHER, - WLAN_CIPHER_SUITE_WEP40); - else - NLA_PUT_U32(msg, NL80211_KEY_CIPHER, - WLAN_CIPHER_SUITE_WEP104); - - NLA_PUT_U8(msg, NL80211_KEY_IDX, i); - - if (i == params->wep_tx_keyidx) - NLA_PUT_FLAG(msg, NL80211_KEY_DEFAULT); - - nla_nest_end(msg, nl_key); - } - nla_nest_end(msg, nl_keys); - - return 0; - -nla_put_failure: - return -ENOBUFS; -} - - -static int wpa_driver_nl80211_mlme(struct wpa_driver_nl80211_data *drv, - const u8 *addr, int cmd, u16 reason_code, - int local_state_change) -{ - int ret = -1; - struct nl_msg *msg; - - msg = nlmsg_alloc(); - if (!msg) - return -1; - - genlmsg_put(msg, 0, 0, genl_family_get_id(drv->nl80211), 0, 0, cmd, 0); - - NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, drv->ifindex); - NLA_PUT_U16(msg, NL80211_ATTR_REASON_CODE, reason_code); - NLA_PUT(msg, NL80211_ATTR_MAC, ETH_ALEN, addr); - if (local_state_change) - NLA_PUT_FLAG(msg, NL80211_ATTR_LOCAL_STATE_CHANGE); - - ret = send_and_recv_msgs(drv, msg, NULL, NULL); - msg = NULL; - if (ret) { - wpa_printf(MSG_DEBUG, "nl80211: MLME command failed: ret=%d " - "(%s)", ret, strerror(-ret)); - goto nla_put_failure; - } - ret = 0; - -nla_put_failure: - nlmsg_free(msg); - return ret; -} - - -static int wpa_driver_nl80211_disconnect(struct wpa_driver_nl80211_data *drv, - const u8 *addr, int reason_code) -{ - wpa_printf(MSG_DEBUG, "%s(addr=" MACSTR " reason_code=%d)", - __func__, MAC2STR(addr), reason_code); - drv->associated = 0; - return wpa_driver_nl80211_mlme(drv, addr, NL80211_CMD_DISCONNECT, - reason_code, 0); -} - - -static int wpa_driver_nl80211_deauthenticate(void *priv, const u8 *addr, - int reason_code) -{ - struct i802_bss *bss = priv; - struct wpa_driver_nl80211_data *drv = bss->drv; - if (!(drv->capa.flags & WPA_DRIVER_FLAGS_SME)) - return wpa_driver_nl80211_disconnect(drv, addr, reason_code); - wpa_printf(MSG_DEBUG, "%s(addr=" MACSTR " reason_code=%d)", - __func__, MAC2STR(addr), reason_code); - drv->associated = 0; - if (drv->nlmode == NL80211_IFTYPE_ADHOC) - return nl80211_leave_ibss(drv); - return wpa_driver_nl80211_mlme(drv, addr, NL80211_CMD_DEAUTHENTICATE, - reason_code, 0); -} - - -static int wpa_driver_nl80211_disassociate(void *priv, const u8 *addr, - int reason_code) -{ - struct i802_bss *bss = priv; - struct wpa_driver_nl80211_data *drv = bss->drv; - if (!(drv->capa.flags & WPA_DRIVER_FLAGS_SME)) - return wpa_driver_nl80211_disconnect(drv, addr, reason_code); - wpa_printf(MSG_DEBUG, "%s", __func__); - drv->associated = 0; - return wpa_driver_nl80211_mlme(drv, addr, NL80211_CMD_DISASSOCIATE, - reason_code, 0); -} - - -static int wpa_driver_nl80211_authenticate( - void *priv, struct wpa_driver_auth_params *params) -{ - struct i802_bss *bss = priv; - struct wpa_driver_nl80211_data *drv = bss->drv; - int ret = -1, i; - struct nl_msg *msg; - enum nl80211_auth_type type; - int count = 0; - - drv->associated = 0; - os_memset(drv->auth_bssid, 0, ETH_ALEN); - /* FIX: IBSS mode */ - if (drv->nlmode != NL80211_IFTYPE_STATION && - wpa_driver_nl80211_set_mode(priv, IEEE80211_MODE_INFRA) < 0) - return -1; - -retry: - msg = nlmsg_alloc(); - if (!msg) - return -1; - - wpa_printf(MSG_DEBUG, "nl80211: Authenticate (ifindex=%d)", - drv->ifindex); - - genlmsg_put(msg, 0, 0, genl_family_get_id(drv->nl80211), 0, 0, - NL80211_CMD_AUTHENTICATE, 0); - - for (i = 0; i < 4; i++) { - if (!params->wep_key[i]) - continue; - wpa_driver_nl80211_set_key(bss->ifname, priv, WPA_ALG_WEP, - NULL, i, - i == params->wep_tx_keyidx, NULL, 0, - params->wep_key[i], - params->wep_key_len[i]); - if (params->wep_tx_keyidx != i) - continue; - if (nl_add_key(msg, WPA_ALG_WEP, i, 1, NULL, 0, - params->wep_key[i], params->wep_key_len[i])) { - nlmsg_free(msg); - return -1; - } - } - - NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, drv->ifindex); - if (params->bssid) { - wpa_printf(MSG_DEBUG, " * bssid=" MACSTR, - MAC2STR(params->bssid)); - NLA_PUT(msg, NL80211_ATTR_MAC, ETH_ALEN, params->bssid); - } - if (params->freq) { - wpa_printf(MSG_DEBUG, " * freq=%d", params->freq); - NLA_PUT_U32(msg, NL80211_ATTR_WIPHY_FREQ, params->freq); - } - if (params->ssid) { - wpa_hexdump_ascii(MSG_DEBUG, " * SSID", - params->ssid, params->ssid_len); - NLA_PUT(msg, NL80211_ATTR_SSID, params->ssid_len, - params->ssid); - } - wpa_hexdump(MSG_DEBUG, " * IEs", params->ie, params->ie_len); - if (params->ie) - NLA_PUT(msg, NL80211_ATTR_IE, params->ie_len, params->ie); - if (params->auth_alg & WPA_AUTH_ALG_OPEN) - type = NL80211_AUTHTYPE_OPEN_SYSTEM; - else if (params->auth_alg & WPA_AUTH_ALG_SHARED) - type = NL80211_AUTHTYPE_SHARED_KEY; - else if (params->auth_alg & WPA_AUTH_ALG_LEAP) - type = NL80211_AUTHTYPE_NETWORK_EAP; - else if (params->auth_alg & WPA_AUTH_ALG_FT) - type = NL80211_AUTHTYPE_FT; - else - goto nla_put_failure; - wpa_printf(MSG_DEBUG, " * Auth Type %d", type); - NLA_PUT_U32(msg, NL80211_ATTR_AUTH_TYPE, type); - if (params->local_state_change) { - wpa_printf(MSG_DEBUG, " * Local state change only"); - NLA_PUT_FLAG(msg, NL80211_ATTR_LOCAL_STATE_CHANGE); - } - - ret = send_and_recv_msgs(drv, msg, NULL, NULL); - msg = NULL; - if (ret) { - wpa_printf(MSG_DEBUG, "nl80211: MLME command failed: ret=%d " - "(%s)", ret, strerror(-ret)); - count++; - if (ret == -EALREADY && count == 1 && params->bssid && - !params->local_state_change) { - /* - * mac80211 does not currently accept new - * authentication if we are already authenticated. As a - * workaround, force deauthentication and try again. - */ - wpa_printf(MSG_DEBUG, "nl80211: Retry authentication " - "after forced deauthentication"); - wpa_driver_nl80211_deauthenticate( - bss, params->bssid, - WLAN_REASON_PREV_AUTH_NOT_VALID); - nlmsg_free(msg); - goto retry; - } - goto nla_put_failure; - } - ret = 0; - wpa_printf(MSG_DEBUG, "nl80211: Authentication request send " - "successfully"); - -nla_put_failure: - nlmsg_free(msg); - return ret; -} - - -struct phy_info_arg { - u16 *num_modes; - struct hostapd_hw_modes *modes; -}; - -static int phy_info_handler(struct nl_msg *msg, void *arg) -{ - struct nlattr *tb_msg[NL80211_ATTR_MAX + 1]; - struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg)); - struct phy_info_arg *phy_info = arg; - - struct nlattr *tb_band[NL80211_BAND_ATTR_MAX + 1]; - - struct nlattr *tb_freq[NL80211_FREQUENCY_ATTR_MAX + 1]; - static struct nla_policy freq_policy[NL80211_FREQUENCY_ATTR_MAX + 1] = { - [NL80211_FREQUENCY_ATTR_FREQ] = { .type = NLA_U32 }, - [NL80211_FREQUENCY_ATTR_DISABLED] = { .type = NLA_FLAG }, - [NL80211_FREQUENCY_ATTR_PASSIVE_SCAN] = { .type = NLA_FLAG }, - [NL80211_FREQUENCY_ATTR_NO_IBSS] = { .type = NLA_FLAG }, - [NL80211_FREQUENCY_ATTR_RADAR] = { .type = NLA_FLAG }, - [NL80211_FREQUENCY_ATTR_MAX_TX_POWER] = { .type = NLA_U32 }, - }; - - struct nlattr *tb_rate[NL80211_BITRATE_ATTR_MAX + 1]; - static struct nla_policy rate_policy[NL80211_BITRATE_ATTR_MAX + 1] = { - [NL80211_BITRATE_ATTR_RATE] = { .type = NLA_U32 }, - [NL80211_BITRATE_ATTR_2GHZ_SHORTPREAMBLE] = { .type = NLA_FLAG }, - }; - - struct nlattr *nl_band; - struct nlattr *nl_freq; - struct nlattr *nl_rate; - int rem_band, rem_freq, rem_rate; - struct hostapd_hw_modes *mode; - int idx, mode_is_set; - - nla_parse(tb_msg, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0), - genlmsg_attrlen(gnlh, 0), NULL); - - if (!tb_msg[NL80211_ATTR_WIPHY_BANDS]) - return NL_SKIP; - - nla_for_each_nested(nl_band, tb_msg[NL80211_ATTR_WIPHY_BANDS], rem_band) { - mode = os_realloc(phy_info->modes, (*phy_info->num_modes + 1) * sizeof(*mode)); - if (!mode) - return NL_SKIP; - phy_info->modes = mode; - - mode_is_set = 0; - - mode = &phy_info->modes[*(phy_info->num_modes)]; - memset(mode, 0, sizeof(*mode)); - *(phy_info->num_modes) += 1; - - nla_parse(tb_band, NL80211_BAND_ATTR_MAX, nla_data(nl_band), - nla_len(nl_band), NULL); - - if (tb_band[NL80211_BAND_ATTR_HT_CAPA]) { - mode->ht_capab = nla_get_u16( - tb_band[NL80211_BAND_ATTR_HT_CAPA]); - } - - if (tb_band[NL80211_BAND_ATTR_HT_AMPDU_FACTOR]) { - mode->a_mpdu_params |= nla_get_u8( - tb_band[NL80211_BAND_ATTR_HT_AMPDU_FACTOR]) & - 0x03; - } - - if (tb_band[NL80211_BAND_ATTR_HT_AMPDU_DENSITY]) { - mode->a_mpdu_params |= nla_get_u8( - tb_band[NL80211_BAND_ATTR_HT_AMPDU_DENSITY]) << - 2; - } - - if (tb_band[NL80211_BAND_ATTR_HT_MCS_SET] && - nla_len(tb_band[NL80211_BAND_ATTR_HT_MCS_SET])) { - u8 *mcs; - mcs = nla_data(tb_band[NL80211_BAND_ATTR_HT_MCS_SET]); - os_memcpy(mode->mcs_set, mcs, 16); - } - - nla_for_each_nested(nl_freq, tb_band[NL80211_BAND_ATTR_FREQS], rem_freq) { - nla_parse(tb_freq, NL80211_FREQUENCY_ATTR_MAX, nla_data(nl_freq), - nla_len(nl_freq), freq_policy); - if (!tb_freq[NL80211_FREQUENCY_ATTR_FREQ]) - continue; - mode->num_channels++; - } - - mode->channels = os_zalloc(mode->num_channels * sizeof(struct hostapd_channel_data)); - if (!mode->channels) - return NL_SKIP; - - idx = 0; - - nla_for_each_nested(nl_freq, tb_band[NL80211_BAND_ATTR_FREQS], rem_freq) { - nla_parse(tb_freq, NL80211_FREQUENCY_ATTR_MAX, nla_data(nl_freq), - nla_len(nl_freq), freq_policy); - if (!tb_freq[NL80211_FREQUENCY_ATTR_FREQ]) - continue; - - mode->channels[idx].freq = nla_get_u32(tb_freq[NL80211_FREQUENCY_ATTR_FREQ]); - mode->channels[idx].flag = 0; - - if (!mode_is_set) { - /* crude heuristic */ - if (mode->channels[idx].freq < 4000) - mode->mode = HOSTAPD_MODE_IEEE80211B; - else - mode->mode = HOSTAPD_MODE_IEEE80211A; - mode_is_set = 1; - } - - /* crude heuristic */ - if (mode->channels[idx].freq < 4000) - if (mode->channels[idx].freq == 2484) - mode->channels[idx].chan = 14; - else - mode->channels[idx].chan = (mode->channels[idx].freq - 2407) / 5; - else - mode->channels[idx].chan = mode->channels[idx].freq/5 - 1000; - - if (tb_freq[NL80211_FREQUENCY_ATTR_DISABLED]) - mode->channels[idx].flag |= - HOSTAPD_CHAN_DISABLED; - if (tb_freq[NL80211_FREQUENCY_ATTR_PASSIVE_SCAN]) - mode->channels[idx].flag |= - HOSTAPD_CHAN_PASSIVE_SCAN; - if (tb_freq[NL80211_FREQUENCY_ATTR_NO_IBSS]) - mode->channels[idx].flag |= - HOSTAPD_CHAN_NO_IBSS; - if (tb_freq[NL80211_FREQUENCY_ATTR_RADAR]) - mode->channels[idx].flag |= - HOSTAPD_CHAN_RADAR; - - if (tb_freq[NL80211_FREQUENCY_ATTR_MAX_TX_POWER] && - !tb_freq[NL80211_FREQUENCY_ATTR_DISABLED]) - mode->channels[idx].max_tx_power = - nla_get_u32(tb_freq[NL80211_FREQUENCY_ATTR_MAX_TX_POWER]) / 100; - - idx++; - } - - nla_for_each_nested(nl_rate, tb_band[NL80211_BAND_ATTR_RATES], rem_rate) { - nla_parse(tb_rate, NL80211_BITRATE_ATTR_MAX, nla_data(nl_rate), - nla_len(nl_rate), rate_policy); - if (!tb_rate[NL80211_BITRATE_ATTR_RATE]) - continue; - mode->num_rates++; - } - - mode->rates = os_zalloc(mode->num_rates * sizeof(int)); - if (!mode->rates) - return NL_SKIP; - - idx = 0; - - nla_for_each_nested(nl_rate, tb_band[NL80211_BAND_ATTR_RATES], rem_rate) { - nla_parse(tb_rate, NL80211_BITRATE_ATTR_MAX, nla_data(nl_rate), - nla_len(nl_rate), rate_policy); - if (!tb_rate[NL80211_BITRATE_ATTR_RATE]) - continue; - mode->rates[idx] = nla_get_u32(tb_rate[NL80211_BITRATE_ATTR_RATE]); - - /* crude heuristic */ - if (mode->mode == HOSTAPD_MODE_IEEE80211B && - mode->rates[idx] > 200) - mode->mode = HOSTAPD_MODE_IEEE80211G; - - idx++; - } - } - - return NL_SKIP; -} - -static struct hostapd_hw_modes * -wpa_driver_nl80211_add_11b(struct hostapd_hw_modes *modes, u16 *num_modes) -{ - u16 m; - struct hostapd_hw_modes *mode11g = NULL, *nmodes, *mode; - int i, mode11g_idx = -1; - - /* If only 802.11g mode is included, use it to construct matching - * 802.11b mode data. */ - - for (m = 0; m < *num_modes; m++) { - if (modes[m].mode == HOSTAPD_MODE_IEEE80211B) - return modes; /* 802.11b already included */ - if (modes[m].mode == HOSTAPD_MODE_IEEE80211G) - mode11g_idx = m; - } - - if (mode11g_idx < 0) - return modes; /* 2.4 GHz band not supported at all */ - - nmodes = os_realloc(modes, (*num_modes + 1) * sizeof(*nmodes)); - if (nmodes == NULL) - return modes; /* Could not add 802.11b mode */ - - mode = &nmodes[*num_modes]; - os_memset(mode, 0, sizeof(*mode)); - (*num_modes)++; - modes = nmodes; - - mode->mode = HOSTAPD_MODE_IEEE80211B; - - mode11g = &modes[mode11g_idx]; - mode->num_channels = mode11g->num_channels; - mode->channels = os_malloc(mode11g->num_channels * - sizeof(struct hostapd_channel_data)); - if (mode->channels == NULL) { - (*num_modes)--; - return modes; /* Could not add 802.11b mode */ - } - os_memcpy(mode->channels, mode11g->channels, - mode11g->num_channels * sizeof(struct hostapd_channel_data)); - - mode->num_rates = 0; - mode->rates = os_malloc(4 * sizeof(int)); - if (mode->rates == NULL) { - os_free(mode->channels); - (*num_modes)--; - return modes; /* Could not add 802.11b mode */ - } - - for (i = 0; i < mode11g->num_rates; i++) { - if (mode11g->rates[i] != 10 && mode11g->rates[i] != 20 && - mode11g->rates[i] != 55 && mode11g->rates[i] != 110) - continue; - mode->rates[mode->num_rates] = mode11g->rates[i]; - mode->num_rates++; - if (mode->num_rates == 4) - break; - } - - if (mode->num_rates == 0) { - os_free(mode->channels); - os_free(mode->rates); - (*num_modes)--; - return modes; /* No 802.11b rates */ - } - - wpa_printf(MSG_DEBUG, "nl80211: Added 802.11b mode based on 802.11g " - "information"); - - return modes; -} - - -static void nl80211_set_ht40_mode(struct hostapd_hw_modes *mode, int start, - int end) -{ - int c; - - for (c = 0; c < mode->num_channels; c++) { - struct hostapd_channel_data *chan = &mode->channels[c]; - if (chan->freq - 10 >= start && chan->freq + 10 <= end) - chan->flag |= HOSTAPD_CHAN_HT40; - } -} - - -static void nl80211_set_ht40_mode_sec(struct hostapd_hw_modes *mode, int start, - int end) -{ - int c; - - for (c = 0; c < mode->num_channels; c++) { - struct hostapd_channel_data *chan = &mode->channels[c]; - if (!(chan->flag & HOSTAPD_CHAN_HT40)) - continue; - if (chan->freq - 30 >= start && chan->freq - 10 <= end) - chan->flag |= HOSTAPD_CHAN_HT40MINUS; - if (chan->freq + 10 >= start && chan->freq + 30 <= end) - chan->flag |= HOSTAPD_CHAN_HT40PLUS; - } -} - - -static void nl80211_reg_rule_ht40(struct nlattr *tb[], - struct phy_info_arg *results) -{ - u32 start, end, max_bw; - u16 m; - - if (tb[NL80211_ATTR_FREQ_RANGE_START] == NULL || - tb[NL80211_ATTR_FREQ_RANGE_END] == NULL || - tb[NL80211_ATTR_FREQ_RANGE_MAX_BW] == NULL) - return; - - start = nla_get_u32(tb[NL80211_ATTR_FREQ_RANGE_START]) / 1000; - end = nla_get_u32(tb[NL80211_ATTR_FREQ_RANGE_END]) / 1000; - max_bw = nla_get_u32(tb[NL80211_ATTR_FREQ_RANGE_MAX_BW]) / 1000; - - wpa_printf(MSG_DEBUG, "nl80211: %u-%u @ %u MHz", - start, end, max_bw); - if (max_bw < 40) - return; - - for (m = 0; m < *results->num_modes; m++) { - if (!(results->modes[m].ht_capab & - HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET)) - continue; - nl80211_set_ht40_mode(&results->modes[m], start, end); - } -} - - -static void nl80211_reg_rule_sec(struct nlattr *tb[], - struct phy_info_arg *results) -{ - u32 start, end, max_bw; - u16 m; - - if (tb[NL80211_ATTR_FREQ_RANGE_START] == NULL || - tb[NL80211_ATTR_FREQ_RANGE_END] == NULL || - tb[NL80211_ATTR_FREQ_RANGE_MAX_BW] == NULL) - return; - - start = nla_get_u32(tb[NL80211_ATTR_FREQ_RANGE_START]) / 1000; - end = nla_get_u32(tb[NL80211_ATTR_FREQ_RANGE_END]) / 1000; - max_bw = nla_get_u32(tb[NL80211_ATTR_FREQ_RANGE_MAX_BW]) / 1000; - - if (max_bw < 20) - return; - - for (m = 0; m < *results->num_modes; m++) { - if (!(results->modes[m].ht_capab & - HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET)) - continue; - nl80211_set_ht40_mode_sec(&results->modes[m], start, end); - } -} - - -static int nl80211_get_reg(struct nl_msg *msg, void *arg) -{ - struct phy_info_arg *results = arg; - struct nlattr *tb_msg[NL80211_ATTR_MAX + 1]; - struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg)); - struct nlattr *nl_rule; - struct nlattr *tb_rule[NL80211_FREQUENCY_ATTR_MAX + 1]; - int rem_rule; - static struct nla_policy reg_policy[NL80211_FREQUENCY_ATTR_MAX + 1] = { - [NL80211_ATTR_REG_RULE_FLAGS] = { .type = NLA_U32 }, - [NL80211_ATTR_FREQ_RANGE_START] = { .type = NLA_U32 }, - [NL80211_ATTR_FREQ_RANGE_END] = { .type = NLA_U32 }, - [NL80211_ATTR_FREQ_RANGE_MAX_BW] = { .type = NLA_U32 }, - [NL80211_ATTR_POWER_RULE_MAX_ANT_GAIN] = { .type = NLA_U32 }, - [NL80211_ATTR_POWER_RULE_MAX_EIRP] = { .type = NLA_U32 }, - }; - - nla_parse(tb_msg, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0), - genlmsg_attrlen(gnlh, 0), NULL); - if (!tb_msg[NL80211_ATTR_REG_ALPHA2] || - !tb_msg[NL80211_ATTR_REG_RULES]) { - wpa_printf(MSG_DEBUG, "nl80211: No regulatory information " - "available"); - return NL_SKIP; - } - - wpa_printf(MSG_DEBUG, "nl80211: Regulatory information - country=%s", - (char *) nla_data(tb_msg[NL80211_ATTR_REG_ALPHA2])); - - nla_for_each_nested(nl_rule, tb_msg[NL80211_ATTR_REG_RULES], rem_rule) - { - nla_parse(tb_rule, NL80211_FREQUENCY_ATTR_MAX, - nla_data(nl_rule), nla_len(nl_rule), reg_policy); - nl80211_reg_rule_ht40(tb_rule, results); - } - - nla_for_each_nested(nl_rule, tb_msg[NL80211_ATTR_REG_RULES], rem_rule) - { - nla_parse(tb_rule, NL80211_FREQUENCY_ATTR_MAX, - nla_data(nl_rule), nla_len(nl_rule), reg_policy); - nl80211_reg_rule_sec(tb_rule, results); - } - - return NL_SKIP; -} - - -static int nl80211_set_ht40_flags(struct wpa_driver_nl80211_data *drv, - struct phy_info_arg *results) -{ - struct nl_msg *msg; - - msg = nlmsg_alloc(); - if (!msg) - return -ENOMEM; - - genlmsg_put(msg, 0, 0, genl_family_get_id(drv->nl80211), 0, - 0, NL80211_CMD_GET_REG, 0); - return send_and_recv_msgs(drv, msg, nl80211_get_reg, results); -} - - -static struct hostapd_hw_modes * -wpa_driver_nl80211_get_hw_feature_data(void *priv, u16 *num_modes, u16 *flags) -{ - struct i802_bss *bss = priv; - struct wpa_driver_nl80211_data *drv = bss->drv; - struct nl_msg *msg; - struct phy_info_arg result = { - .num_modes = num_modes, - .modes = NULL, - }; - - *num_modes = 0; - *flags = 0; - - msg = nlmsg_alloc(); - if (!msg) - return NULL; - - genlmsg_put(msg, 0, 0, genl_family_get_id(drv->nl80211), 0, - 0, NL80211_CMD_GET_WIPHY, 0); - - NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, drv->ifindex); - - if (send_and_recv_msgs(drv, msg, phy_info_handler, &result) == 0) { - nl80211_set_ht40_flags(drv, &result); - return wpa_driver_nl80211_add_11b(result.modes, num_modes); - } - nla_put_failure: - return NULL; -} - - -static int wpa_driver_nl80211_send_frame(struct wpa_driver_nl80211_data *drv, - const void *data, size_t len, - int encrypt) -{ - __u8 rtap_hdr[] = { - 0x00, 0x00, /* radiotap version */ - 0x0e, 0x00, /* radiotap length */ - 0x02, 0xc0, 0x00, 0x00, /* bmap: flags, tx and rx flags */ - IEEE80211_RADIOTAP_F_FRAG, /* F_FRAG (fragment if required) */ - 0x00, /* padding */ - 0x00, 0x00, /* RX and TX flags to indicate that */ - 0x00, 0x00, /* this is the injected frame directly */ - }; - struct iovec iov[2] = { - { - .iov_base = &rtap_hdr, - .iov_len = sizeof(rtap_hdr), - }, - { - .iov_base = (void *) data, - .iov_len = len, - } - }; - struct msghdr msg = { - .msg_name = NULL, - .msg_namelen = 0, - .msg_iov = iov, - .msg_iovlen = 2, - .msg_control = NULL, - .msg_controllen = 0, - .msg_flags = 0, - }; - int res; - - if (encrypt) - rtap_hdr[8] |= IEEE80211_RADIOTAP_F_WEP; - - res = sendmsg(drv->monitor_sock, &msg, 0); - if (res < 0) { - wpa_printf(MSG_INFO, "nl80211: sendmsg: %s", strerror(errno)); - return -1; - } - return 0; -} - - -static int wpa_driver_nl80211_send_mlme(void *priv, const u8 *data, - size_t data_len) -{ - struct i802_bss *bss = priv; - struct wpa_driver_nl80211_data *drv = bss->drv; - struct ieee80211_mgmt *mgmt; - int encrypt = 1; - u16 fc; - - mgmt = (struct ieee80211_mgmt *) data; - fc = le_to_host16(mgmt->frame_control); - - if (drv->nlmode == NL80211_IFTYPE_STATION && - WLAN_FC_GET_TYPE(fc) == WLAN_FC_TYPE_MGMT && - WLAN_FC_GET_STYPE(fc) == WLAN_FC_STYPE_PROBE_RESP) { - /* - * The use of last_mgmt_freq is a bit of a hack, - * but it works due to the single-threaded nature - * of wpa_supplicant. - */ - return nl80211_send_frame_cmd(drv, drv->last_mgmt_freq, 0, - data, data_len, NULL); - } - - if (WLAN_FC_GET_TYPE(fc) == WLAN_FC_TYPE_MGMT && - WLAN_FC_GET_STYPE(fc) == WLAN_FC_STYPE_AUTH) { - /* - * Only one of the authentication frame types is encrypted. - * In order for static WEP encryption to work properly (i.e., - * to not encrypt the frame), we need to tell mac80211 about - * the frames that must not be encrypted. - */ - u16 auth_alg = le_to_host16(mgmt->u.auth.auth_alg); - u16 auth_trans = le_to_host16(mgmt->u.auth.auth_transaction); - if (auth_alg != WLAN_AUTH_SHARED_KEY || auth_trans != 3) - encrypt = 0; - } - - return wpa_driver_nl80211_send_frame(drv, data, data_len, encrypt); -} - - -static int wpa_driver_nl80211_set_beacon(void *priv, - const u8 *head, size_t head_len, - const u8 *tail, size_t tail_len, - int dtim_period, int beacon_int) -{ - struct i802_bss *bss = priv; - struct wpa_driver_nl80211_data *drv = bss->drv; - struct nl_msg *msg; - u8 cmd = NL80211_CMD_NEW_BEACON; - int ret; - int beacon_set; - int ifindex = if_nametoindex(bss->ifname); - - beacon_set = bss->beacon_set; - - msg = nlmsg_alloc(); - if (!msg) - return -ENOMEM; - - wpa_printf(MSG_DEBUG, "nl80211: Set beacon (beacon_set=%d)", - beacon_set); - if (beacon_set) - cmd = NL80211_CMD_SET_BEACON; - - genlmsg_put(msg, 0, 0, genl_family_get_id(drv->nl80211), 0, - 0, cmd, 0); - NLA_PUT(msg, NL80211_ATTR_BEACON_HEAD, head_len, head); - NLA_PUT(msg, NL80211_ATTR_BEACON_TAIL, tail_len, tail); - NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, ifindex); - NLA_PUT_U32(msg, NL80211_ATTR_BEACON_INTERVAL, beacon_int); - NLA_PUT_U32(msg, NL80211_ATTR_DTIM_PERIOD, dtim_period); - - ret = send_and_recv_msgs(drv, msg, NULL, NULL); - if (ret) { - wpa_printf(MSG_DEBUG, "nl80211: Beacon set failed: %d (%s)", - ret, strerror(-ret)); - } else { - bss->beacon_set = 1; - } - return ret; - nla_put_failure: - return -ENOBUFS; -} - - -static int wpa_driver_nl80211_set_freq(struct wpa_driver_nl80211_data *drv, - int freq, int ht_enabled, - int sec_channel_offset) -{ - struct nl_msg *msg; - int ret; - - msg = nlmsg_alloc(); - if (!msg) - return -1; - - genlmsg_put(msg, 0, 0, genl_family_get_id(drv->nl80211), 0, 0, - NL80211_CMD_SET_WIPHY, 0); - - NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, drv->ifindex); - NLA_PUT_U32(msg, NL80211_ATTR_WIPHY_FREQ, freq); - if (ht_enabled) { - switch (sec_channel_offset) { - case -1: - NLA_PUT_U32(msg, NL80211_ATTR_WIPHY_CHANNEL_TYPE, - NL80211_CHAN_HT40MINUS); - break; - case 1: - NLA_PUT_U32(msg, NL80211_ATTR_WIPHY_CHANNEL_TYPE, - NL80211_CHAN_HT40PLUS); - break; - default: - NLA_PUT_U32(msg, NL80211_ATTR_WIPHY_CHANNEL_TYPE, - NL80211_CHAN_HT20); - break; - } - } - - ret = send_and_recv_msgs(drv, msg, NULL, NULL); - if (ret == 0) - return 0; - wpa_printf(MSG_DEBUG, "nl80211: Failed to set channel (freq=%d): " - "%d (%s)", freq, ret, strerror(-ret)); -nla_put_failure: - return -1; -} - - -static int wpa_driver_nl80211_sta_add(void *priv, - struct hostapd_sta_add_params *params) -{ - struct i802_bss *bss = priv; - struct wpa_driver_nl80211_data *drv = bss->drv; - struct nl_msg *msg; - int ret = -ENOBUFS; - - msg = nlmsg_alloc(); - if (!msg) - return -ENOMEM; - - genlmsg_put(msg, 0, 0, genl_family_get_id(drv->nl80211), 0, - 0, NL80211_CMD_NEW_STATION, 0); - - NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(bss->ifname)); - NLA_PUT(msg, NL80211_ATTR_MAC, ETH_ALEN, params->addr); - NLA_PUT_U16(msg, NL80211_ATTR_STA_AID, params->aid); - NLA_PUT(msg, NL80211_ATTR_STA_SUPPORTED_RATES, params->supp_rates_len, - params->supp_rates); - NLA_PUT_U16(msg, NL80211_ATTR_STA_LISTEN_INTERVAL, - params->listen_interval); - if (params->ht_capabilities) { - NLA_PUT(msg, NL80211_ATTR_HT_CAPABILITY, - sizeof(*params->ht_capabilities), - params->ht_capabilities); - } - - ret = send_and_recv_msgs(drv, msg, NULL, NULL); - if (ret) - wpa_printf(MSG_DEBUG, "nl80211: NL80211_CMD_NEW_STATION " - "result: %d (%s)", ret, strerror(-ret)); - if (ret == -EEXIST) - ret = 0; - nla_put_failure: - return ret; -} - - -static int wpa_driver_nl80211_sta_remove(void *priv, const u8 *addr) -{ - struct i802_bss *bss = priv; - struct wpa_driver_nl80211_data *drv = bss->drv; - struct nl_msg *msg; - int ret; - - msg = nlmsg_alloc(); - if (!msg) - return -ENOMEM; - - genlmsg_put(msg, 0, 0, genl_family_get_id(drv->nl80211), 0, - 0, NL80211_CMD_DEL_STATION, 0); - - NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, - if_nametoindex(bss->ifname)); - NLA_PUT(msg, NL80211_ATTR_MAC, ETH_ALEN, addr); - - ret = send_and_recv_msgs(drv, msg, NULL, NULL); - if (ret == -ENOENT) - return 0; - return ret; - nla_put_failure: - return -ENOBUFS; -} - - -static void nl80211_remove_iface(struct wpa_driver_nl80211_data *drv, - int ifidx) -{ - struct nl_msg *msg; - - wpa_printf(MSG_DEBUG, "nl80211: Remove interface ifindex=%d", ifidx); - -#ifdef HOSTAPD - /* stop listening for EAPOL on this interface */ - del_ifidx(drv, ifidx); -#endif /* HOSTAPD */ - - msg = nlmsg_alloc(); - if (!msg) - goto nla_put_failure; - - genlmsg_put(msg, 0, 0, genl_family_get_id(drv->nl80211), 0, - 0, NL80211_CMD_DEL_INTERFACE, 0); - NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, ifidx); - - if (send_and_recv_msgs(drv, msg, NULL, NULL) == 0) - return; - nla_put_failure: - wpa_printf(MSG_ERROR, "Failed to remove interface (ifidx=%d)", ifidx); -} - - -static int nl80211_create_iface_once(struct wpa_driver_nl80211_data *drv, - const char *ifname, - enum nl80211_iftype iftype, - const u8 *addr, int wds) -{ - struct nl_msg *msg, *flags = NULL; - int ifidx; - int ret = -ENOBUFS; - - msg = nlmsg_alloc(); - if (!msg) - return -1; - - genlmsg_put(msg, 0, 0, genl_family_get_id(drv->nl80211), 0, - 0, NL80211_CMD_NEW_INTERFACE, 0); - NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, drv->ifindex); - NLA_PUT_STRING(msg, NL80211_ATTR_IFNAME, ifname); - NLA_PUT_U32(msg, NL80211_ATTR_IFTYPE, iftype); - - if (iftype == NL80211_IFTYPE_MONITOR) { - int err; - - flags = nlmsg_alloc(); - if (!flags) - goto nla_put_failure; - - NLA_PUT_FLAG(flags, NL80211_MNTR_FLAG_COOK_FRAMES); - - err = nla_put_nested(msg, NL80211_ATTR_MNTR_FLAGS, flags); - - nlmsg_free(flags); - - if (err) - goto nla_put_failure; - } else if (wds) { - NLA_PUT_U8(msg, NL80211_ATTR_4ADDR, wds); - } - - ret = send_and_recv_msgs(drv, msg, NULL, NULL); - if (ret) { - nla_put_failure: - wpa_printf(MSG_ERROR, "Failed to create interface %s: %d (%s)", - ifname, ret, strerror(-ret)); - return ret; - } - - ifidx = if_nametoindex(ifname); - wpa_printf(MSG_DEBUG, "nl80211: New interface %s created: ifindex=%d", - ifname, ifidx); - - if (ifidx <= 0) - return -1; - -#ifdef HOSTAPD - /* start listening for EAPOL on this interface */ - add_ifidx(drv, ifidx); -#endif /* HOSTAPD */ - - if (addr && iftype != NL80211_IFTYPE_MONITOR && - linux_set_ifhwaddr(drv->ioctl_sock, ifname, addr)) { - nl80211_remove_iface(drv, ifidx); - return -1; - } - - return ifidx; -} - - -static int nl80211_create_iface(struct wpa_driver_nl80211_data *drv, - const char *ifname, enum nl80211_iftype iftype, - const u8 *addr, int wds) -{ - int ret; - - ret = nl80211_create_iface_once(drv, ifname, iftype, addr, wds); - - /* if error occured and interface exists already */ - if (ret == -ENFILE && if_nametoindex(ifname)) { - wpa_printf(MSG_INFO, "Try to remove and re-create %s", ifname); - - /* Try to remove the interface that was already there. */ - nl80211_remove_iface(drv, if_nametoindex(ifname)); - - /* Try to create the interface again */ - ret = nl80211_create_iface_once(drv, ifname, iftype, addr, - wds); - } - - if (ret >= 0 && drv->disable_11b_rates) - nl80211_disable_11b_rates(drv, ret, 1); - - return ret; -} - - -static void handle_tx_callback(void *ctx, u8 *buf, size_t len, int ok) -{ - struct ieee80211_hdr *hdr; - u16 fc; - union wpa_event_data event; - - hdr = (struct ieee80211_hdr *) buf; - fc = le_to_host16(hdr->frame_control); - - os_memset(&event, 0, sizeof(event)); - event.tx_status.type = WLAN_FC_GET_TYPE(fc); - event.tx_status.stype = WLAN_FC_GET_STYPE(fc); - event.tx_status.dst = hdr->addr1; - event.tx_status.data = buf; - event.tx_status.data_len = len; - event.tx_status.ack = ok; - wpa_supplicant_event(ctx, EVENT_TX_STATUS, &event); -} - - -static void from_unknown_sta(struct wpa_driver_nl80211_data *drv, - u8 *buf, size_t len) -{ - union wpa_event_data event; - os_memset(&event, 0, sizeof(event)); - event.rx_from_unknown.frame = buf; - event.rx_from_unknown.len = len; - wpa_supplicant_event(drv->ctx, EVENT_RX_FROM_UNKNOWN, &event); -} - - -static void handle_frame(struct wpa_driver_nl80211_data *drv, - u8 *buf, size_t len, int datarate, int ssi_signal) -{ - struct ieee80211_hdr *hdr; - u16 fc; - union wpa_event_data event; - - hdr = (struct ieee80211_hdr *) buf; - fc = le_to_host16(hdr->frame_control); - - switch (WLAN_FC_GET_TYPE(fc)) { - case WLAN_FC_TYPE_MGMT: - os_memset(&event, 0, sizeof(event)); - event.rx_mgmt.frame = buf; - event.rx_mgmt.frame_len = len; - event.rx_mgmt.datarate = datarate; - event.rx_mgmt.ssi_signal = ssi_signal; - wpa_supplicant_event(drv->ctx, EVENT_RX_MGMT, &event); - break; - case WLAN_FC_TYPE_CTRL: - /* can only get here with PS-Poll frames */ - wpa_printf(MSG_DEBUG, "CTRL"); - from_unknown_sta(drv, buf, len); - break; - case WLAN_FC_TYPE_DATA: - from_unknown_sta(drv, buf, len); - break; - } -} - - -static void handle_monitor_read(int sock, void *eloop_ctx, void *sock_ctx) -{ - struct wpa_driver_nl80211_data *drv = eloop_ctx; - int len; - unsigned char buf[3000]; - struct ieee80211_radiotap_iterator iter; - int ret; - int datarate = 0, ssi_signal = 0; - int injected = 0, failed = 0, rxflags = 0; - - len = recv(sock, buf, sizeof(buf), 0); - if (len < 0) { - perror("recv"); - return; - } - - if (ieee80211_radiotap_iterator_init(&iter, (void*)buf, len)) { - printf("received invalid radiotap frame\n"); - return; - } - - while (1) { - ret = ieee80211_radiotap_iterator_next(&iter); - if (ret == -ENOENT) - break; - if (ret) { - printf("received invalid radiotap frame (%d)\n", ret); - return; - } - switch (iter.this_arg_index) { - case IEEE80211_RADIOTAP_FLAGS: - if (*iter.this_arg & IEEE80211_RADIOTAP_F_FCS) - len -= 4; - break; - case IEEE80211_RADIOTAP_RX_FLAGS: - rxflags = 1; - break; - case IEEE80211_RADIOTAP_TX_FLAGS: - injected = 1; - failed = le_to_host16((*(uint16_t *) iter.this_arg)) & - IEEE80211_RADIOTAP_F_TX_FAIL; - break; - case IEEE80211_RADIOTAP_DATA_RETRIES: - break; - case IEEE80211_RADIOTAP_CHANNEL: - /* TODO: convert from freq/flags to channel number */ - break; - case IEEE80211_RADIOTAP_RATE: - datarate = *iter.this_arg * 5; - break; - case IEEE80211_RADIOTAP_DB_ANTSIGNAL: - ssi_signal = *iter.this_arg; - break; - } - } - - if (rxflags && injected) - return; - - if (!injected) - handle_frame(drv, buf + iter.max_length, - len - iter.max_length, datarate, ssi_signal); - else - handle_tx_callback(drv->ctx, buf + iter.max_length, - len - iter.max_length, !failed); -} - - -/* - * we post-process the filter code later and rewrite - * this to the offset to the last instruction - */ -#define PASS 0xFF -#define FAIL 0xFE - -static struct sock_filter msock_filter_insns[] = { - /* - * do a little-endian load of the radiotap length field - */ - /* load lower byte into A */ - BPF_STMT(BPF_LD | BPF_B | BPF_ABS, 2), - /* put it into X (== index register) */ - BPF_STMT(BPF_MISC| BPF_TAX, 0), - /* load upper byte into A */ - BPF_STMT(BPF_LD | BPF_B | BPF_ABS, 3), - /* left-shift it by 8 */ - BPF_STMT(BPF_ALU | BPF_LSH | BPF_K, 8), - /* or with X */ - BPF_STMT(BPF_ALU | BPF_OR | BPF_X, 0), - /* put result into X */ - BPF_STMT(BPF_MISC| BPF_TAX, 0), - - /* - * Allow management frames through, this also gives us those - * management frames that we sent ourselves with status - */ - /* load the lower byte of the IEEE 802.11 frame control field */ - BPF_STMT(BPF_LD | BPF_B | BPF_IND, 0), - /* mask off frame type and version */ - BPF_STMT(BPF_ALU | BPF_AND | BPF_K, 0xF), - /* accept frame if it's both 0, fall through otherwise */ - BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, 0, PASS, 0), - - /* - * TODO: add a bit to radiotap RX flags that indicates - * that the sending station is not associated, then - * add a filter here that filters on our DA and that flag - * to allow us to deauth frames to that bad station. - * - * For now allow all To DS data frames through. - */ - /* load the IEEE 802.11 frame control field */ - BPF_STMT(BPF_LD | BPF_H | BPF_IND, 0), - /* mask off frame type, version and DS status */ - BPF_STMT(BPF_ALU | BPF_AND | BPF_K, 0x0F03), - /* accept frame if version 0, type 2 and To DS, fall through otherwise - */ - BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, 0x0801, PASS, 0), - -#if 0 - /* - * drop non-data frames - */ - /* load the lower byte of the frame control field */ - BPF_STMT(BPF_LD | BPF_B | BPF_IND, 0), - /* mask off QoS bit */ - BPF_STMT(BPF_ALU | BPF_AND | BPF_K, 0x0c), - /* drop non-data frames */ - BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, 8, 0, FAIL), -#endif - /* load the upper byte of the frame control field */ - BPF_STMT(BPF_LD | BPF_B | BPF_IND, 1), - /* mask off toDS/fromDS */ - BPF_STMT(BPF_ALU | BPF_AND | BPF_K, 0x03), - /* accept WDS frames */ - BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, 3, PASS, 0), - - /* - * add header length to index - */ - /* load the lower byte of the frame control field */ - BPF_STMT(BPF_LD | BPF_B | BPF_IND, 0), - /* mask off QoS bit */ - BPF_STMT(BPF_ALU | BPF_AND | BPF_K, 0x80), - /* right shift it by 6 to give 0 or 2 */ - BPF_STMT(BPF_ALU | BPF_RSH | BPF_K, 6), - /* add data frame header length */ - BPF_STMT(BPF_ALU | BPF_ADD | BPF_K, 24), - /* add index, was start of 802.11 header */ - BPF_STMT(BPF_ALU | BPF_ADD | BPF_X, 0), - /* move to index, now start of LL header */ - BPF_STMT(BPF_MISC | BPF_TAX, 0), - - /* - * Accept empty data frames, we use those for - * polling activity. - */ - BPF_STMT(BPF_LD | BPF_W | BPF_LEN, 0), - BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_X, 0, PASS, 0), - - /* - * Accept EAPOL frames - */ - BPF_STMT(BPF_LD | BPF_W | BPF_IND, 0), - BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, 0xAAAA0300, 0, FAIL), - BPF_STMT(BPF_LD | BPF_W | BPF_IND, 4), - BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, 0x0000888E, PASS, FAIL), - - /* keep these last two statements or change the code below */ - /* return 0 == "DROP" */ - BPF_STMT(BPF_RET | BPF_K, 0), - /* return ~0 == "keep all" */ - BPF_STMT(BPF_RET | BPF_K, ~0), -}; - -static struct sock_fprog msock_filter = { - .len = sizeof(msock_filter_insns)/sizeof(msock_filter_insns[0]), - .filter = msock_filter_insns, -}; - - -static int add_monitor_filter(int s) -{ - int idx; - - /* rewrite all PASS/FAIL jump offsets */ - for (idx = 0; idx < msock_filter.len; idx++) { - struct sock_filter *insn = &msock_filter_insns[idx]; - - if (BPF_CLASS(insn->code) == BPF_JMP) { - if (insn->code == (BPF_JMP|BPF_JA)) { - if (insn->k == PASS) - insn->k = msock_filter.len - idx - 2; - else if (insn->k == FAIL) - insn->k = msock_filter.len - idx - 3; - } - - if (insn->jt == PASS) - insn->jt = msock_filter.len - idx - 2; - else if (insn->jt == FAIL) - insn->jt = msock_filter.len - idx - 3; - - if (insn->jf == PASS) - insn->jf = msock_filter.len - idx - 2; - else if (insn->jf == FAIL) - insn->jf = msock_filter.len - idx - 3; - } - } - - if (setsockopt(s, SOL_SOCKET, SO_ATTACH_FILTER, - &msock_filter, sizeof(msock_filter))) { - perror("SO_ATTACH_FILTER"); - return -1; - } - - return 0; -} - - -static void nl80211_remove_monitor_interface( - struct wpa_driver_nl80211_data *drv) -{ - if (drv->monitor_ifidx >= 0) { - nl80211_remove_iface(drv, drv->monitor_ifidx); - drv->monitor_ifidx = -1; - } - if (drv->monitor_sock >= 0) { - eloop_unregister_read_sock(drv->monitor_sock); - close(drv->monitor_sock); - drv->monitor_sock = -1; - } -} - - -static int -nl80211_create_monitor_interface(struct wpa_driver_nl80211_data *drv) -{ - char buf[IFNAMSIZ]; - struct sockaddr_ll ll; - int optval; - socklen_t optlen; - - snprintf(buf, IFNAMSIZ, "mon.%s", drv->first_bss.ifname); - buf[IFNAMSIZ - 1] = '\0'; - - drv->monitor_ifidx = - nl80211_create_iface(drv, buf, NL80211_IFTYPE_MONITOR, NULL, - 0); - - if (drv->monitor_ifidx < 0) - return -1; - - if (linux_set_iface_flags(drv->ioctl_sock, buf, 1)) - goto error; - - memset(&ll, 0, sizeof(ll)); - ll.sll_family = AF_PACKET; - ll.sll_ifindex = drv->monitor_ifidx; - drv->monitor_sock = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL)); - if (drv->monitor_sock < 0) { - perror("socket[PF_PACKET,SOCK_RAW]"); - goto error; - } - - if (add_monitor_filter(drv->monitor_sock)) { - wpa_printf(MSG_INFO, "Failed to set socket filter for monitor " - "interface; do filtering in user space"); - /* This works, but will cost in performance. */ - } - - if (bind(drv->monitor_sock, (struct sockaddr *) &ll, sizeof(ll)) < 0) { - perror("monitor socket bind"); - goto error; - } - - optlen = sizeof(optval); - optval = 20; - if (setsockopt - (drv->monitor_sock, SOL_SOCKET, SO_PRIORITY, &optval, optlen)) { - perror("Failed to set socket priority"); - goto error; - } - - if (eloop_register_read_sock(drv->monitor_sock, handle_monitor_read, - drv, NULL)) { - printf("Could not register monitor read socket\n"); - goto error; - } - - return 0; - error: - nl80211_remove_monitor_interface(drv); - return -1; -} - - -static const u8 rfc1042_header[6] = { 0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00 }; - -static int wpa_driver_nl80211_hapd_send_eapol( - void *priv, const u8 *addr, const u8 *data, - size_t data_len, int encrypt, const u8 *own_addr, u32 flags) -{ - struct i802_bss *bss = priv; - struct wpa_driver_nl80211_data *drv = bss->drv; - struct ieee80211_hdr *hdr; - size_t len; - u8 *pos; - int res; - int qos = flags & WPA_STA_WMM; - - len = sizeof(*hdr) + (qos ? 2 : 0) + sizeof(rfc1042_header) + 2 + - data_len; - hdr = os_zalloc(len); - if (hdr == NULL) { - printf("malloc() failed for i802_send_data(len=%lu)\n", - (unsigned long) len); - return -1; - } - - hdr->frame_control = - IEEE80211_FC(WLAN_FC_TYPE_DATA, WLAN_FC_STYPE_DATA); - hdr->frame_control |= host_to_le16(WLAN_FC_FROMDS); - if (encrypt) - hdr->frame_control |= host_to_le16(WLAN_FC_ISWEP); - if (qos) { - hdr->frame_control |= - host_to_le16(WLAN_FC_STYPE_QOS_DATA << 4); - } - - memcpy(hdr->IEEE80211_DA_FROMDS, addr, ETH_ALEN); - memcpy(hdr->IEEE80211_BSSID_FROMDS, own_addr, ETH_ALEN); - memcpy(hdr->IEEE80211_SA_FROMDS, own_addr, ETH_ALEN); - pos = (u8 *) (hdr + 1); - - if (qos) { - /* add an empty QoS header if needed */ - pos[0] = 0; - pos[1] = 0; - pos += 2; - } - - memcpy(pos, rfc1042_header, sizeof(rfc1042_header)); - pos += sizeof(rfc1042_header); - WPA_PUT_BE16(pos, ETH_P_PAE); - pos += 2; - memcpy(pos, data, data_len); - - res = wpa_driver_nl80211_send_frame(drv, (u8 *) hdr, len, encrypt); - if (res < 0) { - wpa_printf(MSG_ERROR, "i802_send_eapol - packet len: %lu - " - "failed: %d (%s)", - (unsigned long) len, errno, strerror(errno)); - } - os_free(hdr); - - return res; -} - - -static u32 sta_flags_nl80211(int flags) -{ - u32 f = 0; - - if (flags & WPA_STA_AUTHORIZED) - f |= BIT(NL80211_STA_FLAG_AUTHORIZED); - if (flags & WPA_STA_WMM) - f |= BIT(NL80211_STA_FLAG_WME); - if (flags & WPA_STA_SHORT_PREAMBLE) - f |= BIT(NL80211_STA_FLAG_SHORT_PREAMBLE); - if (flags & WPA_STA_MFP) - f |= BIT(NL80211_STA_FLAG_MFP); - - return f; -} - - -static int wpa_driver_nl80211_sta_set_flags(void *priv, const u8 *addr, - int total_flags, - int flags_or, int flags_and) -{ - struct i802_bss *bss = priv; - struct wpa_driver_nl80211_data *drv = bss->drv; - struct nl_msg *msg, *flags = NULL; - struct nl80211_sta_flag_update upd; - - msg = nlmsg_alloc(); - if (!msg) - return -ENOMEM; - - flags = nlmsg_alloc(); - if (!flags) { - nlmsg_free(msg); - return -ENOMEM; - } - - genlmsg_put(msg, 0, 0, genl_family_get_id(drv->nl80211), 0, - 0, NL80211_CMD_SET_STATION, 0); - - NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, - if_nametoindex(bss->ifname)); - NLA_PUT(msg, NL80211_ATTR_MAC, ETH_ALEN, addr); - - /* - * Backwards compatibility version using NL80211_ATTR_STA_FLAGS. This - * can be removed eventually. - */ - if (total_flags & WPA_STA_AUTHORIZED) - NLA_PUT_FLAG(flags, NL80211_STA_FLAG_AUTHORIZED); - - if (total_flags & WPA_STA_WMM) - NLA_PUT_FLAG(flags, NL80211_STA_FLAG_WME); - - if (total_flags & WPA_STA_SHORT_PREAMBLE) - NLA_PUT_FLAG(flags, NL80211_STA_FLAG_SHORT_PREAMBLE); - - if (total_flags & WPA_STA_MFP) - NLA_PUT_FLAG(flags, NL80211_STA_FLAG_MFP); - - if (nla_put_nested(msg, NL80211_ATTR_STA_FLAGS, flags)) - goto nla_put_failure; - - os_memset(&upd, 0, sizeof(upd)); - upd.mask = sta_flags_nl80211(flags_or | ~flags_and); - upd.set = sta_flags_nl80211(flags_or); - NLA_PUT(msg, NL80211_ATTR_STA_FLAGS2, sizeof(upd), &upd); - - nlmsg_free(flags); - - return send_and_recv_msgs(drv, msg, NULL, NULL); - nla_put_failure: - nlmsg_free(flags); - return -ENOBUFS; -} - - -static int wpa_driver_nl80211_ap(struct wpa_driver_nl80211_data *drv, - struct wpa_driver_associate_params *params) -{ - if (params->p2p) - wpa_printf(MSG_DEBUG, "nl80211: Setup AP operations for P2P " - "group (GO)"); - if (wpa_driver_nl80211_set_mode(&drv->first_bss, params->mode) || - wpa_driver_nl80211_set_freq(drv, params->freq, 0, 0)) { - nl80211_remove_monitor_interface(drv); - return -1; - } - - /* TODO: setup monitor interface (and add code somewhere to remove this - * when AP mode is stopped; associate with mode != 2 or drv_deinit) */ - - return 0; -} - - -static int nl80211_leave_ibss(struct wpa_driver_nl80211_data *drv) -{ - struct nl_msg *msg; - int ret = -1; - - msg = nlmsg_alloc(); - if (!msg) - return -1; - - genlmsg_put(msg, 0, 0, genl_family_get_id(drv->nl80211), 0, 0, - NL80211_CMD_LEAVE_IBSS, 0); - NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, drv->ifindex); - ret = send_and_recv_msgs(drv, msg, NULL, NULL); - msg = NULL; - if (ret) { - wpa_printf(MSG_DEBUG, "nl80211: Leave IBSS failed: ret=%d " - "(%s)", ret, strerror(-ret)); - goto nla_put_failure; - } - - ret = 0; - wpa_printf(MSG_DEBUG, "nl80211: Leave IBSS request sent successfully"); - -nla_put_failure: - nlmsg_free(msg); - return ret; -} - - -static int wpa_driver_nl80211_ibss(struct wpa_driver_nl80211_data *drv, - struct wpa_driver_associate_params *params) -{ - struct nl_msg *msg; - int ret = -1; - int count = 0; - - wpa_printf(MSG_DEBUG, "nl80211: Join IBSS (ifindex=%d)", drv->ifindex); - - if (wpa_driver_nl80211_set_mode(&drv->first_bss, params->mode)) { - wpa_printf(MSG_INFO, "nl80211: Failed to set interface into " - "IBSS mode"); - return -1; - } - -retry: - msg = nlmsg_alloc(); - if (!msg) - return -1; - - genlmsg_put(msg, 0, 0, genl_family_get_id(drv->nl80211), 0, 0, - NL80211_CMD_JOIN_IBSS, 0); - NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, drv->ifindex); - - if (params->ssid == NULL || params->ssid_len > sizeof(drv->ssid)) - goto nla_put_failure; - - wpa_hexdump_ascii(MSG_DEBUG, " * SSID", - params->ssid, params->ssid_len); - NLA_PUT(msg, NL80211_ATTR_SSID, params->ssid_len, - params->ssid); - os_memcpy(drv->ssid, params->ssid, params->ssid_len); - drv->ssid_len = params->ssid_len; - - wpa_printf(MSG_DEBUG, " * freq=%d", params->freq); - NLA_PUT_U32(msg, NL80211_ATTR_WIPHY_FREQ, params->freq); - - ret = nl80211_set_conn_keys(params, msg); - if (ret) - goto nla_put_failure; - - if (params->wpa_ie) { - wpa_hexdump(MSG_DEBUG, - " * Extra IEs for Beacon/Probe Response frames", - params->wpa_ie, params->wpa_ie_len); - NLA_PUT(msg, NL80211_ATTR_IE, params->wpa_ie_len, - params->wpa_ie); - } - - ret = send_and_recv_msgs(drv, msg, NULL, NULL); - msg = NULL; - if (ret) { - wpa_printf(MSG_DEBUG, "nl80211: Join IBSS failed: ret=%d (%s)", - ret, strerror(-ret)); - count++; - if (ret == -EALREADY && count == 1) { - wpa_printf(MSG_DEBUG, "nl80211: Retry IBSS join after " - "forced leave"); - nl80211_leave_ibss(drv); - nlmsg_free(msg); - goto retry; - } - - goto nla_put_failure; - } - ret = 0; - wpa_printf(MSG_DEBUG, "nl80211: Join IBSS request sent successfully"); - -nla_put_failure: - nlmsg_free(msg); - return ret; -} - - -static int wpa_driver_nl80211_connect( - struct wpa_driver_nl80211_data *drv, - struct wpa_driver_associate_params *params) -{ - struct nl_msg *msg; - enum nl80211_auth_type type; - int ret = 0; - int algs; - - msg = nlmsg_alloc(); - if (!msg) - return -1; - - wpa_printf(MSG_DEBUG, "nl80211: Connect (ifindex=%d)", drv->ifindex); - genlmsg_put(msg, 0, 0, genl_family_get_id(drv->nl80211), 0, 0, - NL80211_CMD_CONNECT, 0); - - NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, drv->ifindex); - if (params->bssid) { - wpa_printf(MSG_DEBUG, " * bssid=" MACSTR, - MAC2STR(params->bssid)); - NLA_PUT(msg, NL80211_ATTR_MAC, ETH_ALEN, params->bssid); - } - if (params->freq) { - wpa_printf(MSG_DEBUG, " * freq=%d", params->freq); - NLA_PUT_U32(msg, NL80211_ATTR_WIPHY_FREQ, params->freq); - } - if (params->ssid) { - wpa_hexdump_ascii(MSG_DEBUG, " * SSID", - params->ssid, params->ssid_len); - NLA_PUT(msg, NL80211_ATTR_SSID, params->ssid_len, - params->ssid); - if (params->ssid_len > sizeof(drv->ssid)) - goto nla_put_failure; - os_memcpy(drv->ssid, params->ssid, params->ssid_len); - drv->ssid_len = params->ssid_len; - } - wpa_hexdump(MSG_DEBUG, " * IEs", params->wpa_ie, params->wpa_ie_len); - if (params->wpa_ie) - NLA_PUT(msg, NL80211_ATTR_IE, params->wpa_ie_len, - params->wpa_ie); - - algs = 0; - if (params->auth_alg & WPA_AUTH_ALG_OPEN) - algs++; - if (params->auth_alg & WPA_AUTH_ALG_SHARED) - algs++; - if (params->auth_alg & WPA_AUTH_ALG_LEAP) - algs++; - if (algs > 1) { - wpa_printf(MSG_DEBUG, " * Leave out Auth Type for automatic " - "selection"); - goto skip_auth_type; - } - - if (params->auth_alg & WPA_AUTH_ALG_OPEN) - type = NL80211_AUTHTYPE_OPEN_SYSTEM; - else if (params->auth_alg & WPA_AUTH_ALG_SHARED) - type = NL80211_AUTHTYPE_SHARED_KEY; - else if (params->auth_alg & WPA_AUTH_ALG_LEAP) - type = NL80211_AUTHTYPE_NETWORK_EAP; - else if (params->auth_alg & WPA_AUTH_ALG_FT) - type = NL80211_AUTHTYPE_FT; - else - goto nla_put_failure; - - wpa_printf(MSG_DEBUG, " * Auth Type %d", type); - NLA_PUT_U32(msg, NL80211_ATTR_AUTH_TYPE, type); - -skip_auth_type: - if (params->wpa_ie && params->wpa_ie_len) { - enum nl80211_wpa_versions ver; - - if (params->wpa_ie[0] == WLAN_EID_RSN) - ver = NL80211_WPA_VERSION_2; - else - ver = NL80211_WPA_VERSION_1; - - wpa_printf(MSG_DEBUG, " * WPA Version %d", ver); - NLA_PUT_U32(msg, NL80211_ATTR_WPA_VERSIONS, ver); - } - - if (params->pairwise_suite != CIPHER_NONE) { - int cipher; - - switch (params->pairwise_suite) { - case CIPHER_WEP40: - cipher = WLAN_CIPHER_SUITE_WEP40; - break; - case CIPHER_WEP104: - cipher = WLAN_CIPHER_SUITE_WEP104; - break; - case CIPHER_CCMP: - cipher = WLAN_CIPHER_SUITE_CCMP; - break; - case CIPHER_TKIP: - default: - cipher = WLAN_CIPHER_SUITE_TKIP; - break; - } - NLA_PUT_U32(msg, NL80211_ATTR_CIPHER_SUITES_PAIRWISE, cipher); - } - - if (params->group_suite != CIPHER_NONE) { - int cipher; - - switch (params->group_suite) { - case CIPHER_WEP40: - cipher = WLAN_CIPHER_SUITE_WEP40; - break; - case CIPHER_WEP104: - cipher = WLAN_CIPHER_SUITE_WEP104; - break; - case CIPHER_CCMP: - cipher = WLAN_CIPHER_SUITE_CCMP; - break; - case CIPHER_TKIP: - default: - cipher = WLAN_CIPHER_SUITE_TKIP; - break; - } - NLA_PUT_U32(msg, NL80211_ATTR_CIPHER_SUITE_GROUP, cipher); - } - - if (params->key_mgmt_suite == KEY_MGMT_802_1X || - params->key_mgmt_suite == KEY_MGMT_PSK) { - int mgmt = WLAN_AKM_SUITE_PSK; - - switch (params->key_mgmt_suite) { - case KEY_MGMT_802_1X: - mgmt = WLAN_AKM_SUITE_8021X; - break; - case KEY_MGMT_PSK: - default: - mgmt = WLAN_AKM_SUITE_PSK; - break; - } - NLA_PUT_U32(msg, NL80211_ATTR_AKM_SUITES, mgmt); - } - - ret = nl80211_set_conn_keys(params, msg); - if (ret) - goto nla_put_failure; - - ret = send_and_recv_msgs(drv, msg, NULL, NULL); - msg = NULL; - if (ret) { - wpa_printf(MSG_DEBUG, "nl80211: MLME connect failed: ret=%d " - "(%s)", ret, strerror(-ret)); - goto nla_put_failure; - } - ret = 0; - wpa_printf(MSG_DEBUG, "nl80211: Connect request send successfully"); - -nla_put_failure: - nlmsg_free(msg); - return ret; - -} - - -static int wpa_driver_nl80211_associate( - void *priv, struct wpa_driver_associate_params *params) -{ - struct i802_bss *bss = priv; - struct wpa_driver_nl80211_data *drv = bss->drv; - int ret = -1; - struct nl_msg *msg; - - if (params->mode == IEEE80211_MODE_AP) - return wpa_driver_nl80211_ap(drv, params); - - if (params->mode == IEEE80211_MODE_IBSS) - return wpa_driver_nl80211_ibss(drv, params); - - if (!(drv->capa.flags & WPA_DRIVER_FLAGS_SME)) { - if (wpa_driver_nl80211_set_mode(priv, params->mode) < 0) - return -1; - return wpa_driver_nl80211_connect(drv, params); - } - - drv->associated = 0; - - msg = nlmsg_alloc(); - if (!msg) - return -1; - - wpa_printf(MSG_DEBUG, "nl80211: Associate (ifindex=%d)", - drv->ifindex); - genlmsg_put(msg, 0, 0, genl_family_get_id(drv->nl80211), 0, 0, - NL80211_CMD_ASSOCIATE, 0); - - NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, drv->ifindex); - if (params->bssid) { - wpa_printf(MSG_DEBUG, " * bssid=" MACSTR, - MAC2STR(params->bssid)); - NLA_PUT(msg, NL80211_ATTR_MAC, ETH_ALEN, params->bssid); - } - if (params->freq) { - wpa_printf(MSG_DEBUG, " * freq=%d", params->freq); - NLA_PUT_U32(msg, NL80211_ATTR_WIPHY_FREQ, params->freq); - drv->assoc_freq = params->freq; - } else - drv->assoc_freq = 0; - if (params->ssid) { - wpa_hexdump_ascii(MSG_DEBUG, " * SSID", - params->ssid, params->ssid_len); - NLA_PUT(msg, NL80211_ATTR_SSID, params->ssid_len, - params->ssid); - if (params->ssid_len > sizeof(drv->ssid)) - goto nla_put_failure; - os_memcpy(drv->ssid, params->ssid, params->ssid_len); - drv->ssid_len = params->ssid_len; - } - wpa_hexdump(MSG_DEBUG, " * IEs", params->wpa_ie, params->wpa_ie_len); - if (params->wpa_ie) - NLA_PUT(msg, NL80211_ATTR_IE, params->wpa_ie_len, - params->wpa_ie); - - if (params->pairwise_suite != CIPHER_NONE) { - int cipher; - - switch (params->pairwise_suite) { - case CIPHER_WEP40: - cipher = WLAN_CIPHER_SUITE_WEP40; - break; - case CIPHER_WEP104: - cipher = WLAN_CIPHER_SUITE_WEP104; - break; - case CIPHER_CCMP: - cipher = WLAN_CIPHER_SUITE_CCMP; - break; - case CIPHER_TKIP: - default: - cipher = WLAN_CIPHER_SUITE_TKIP; - break; - } - wpa_printf(MSG_DEBUG, " * pairwise=0x%x", cipher); - NLA_PUT_U32(msg, NL80211_ATTR_CIPHER_SUITES_PAIRWISE, cipher); - } - - if (params->group_suite != CIPHER_NONE) { - int cipher; - - switch (params->group_suite) { - case CIPHER_WEP40: - cipher = WLAN_CIPHER_SUITE_WEP40; - break; - case CIPHER_WEP104: - cipher = WLAN_CIPHER_SUITE_WEP104; - break; - case CIPHER_CCMP: - cipher = WLAN_CIPHER_SUITE_CCMP; - break; - case CIPHER_TKIP: - default: - cipher = WLAN_CIPHER_SUITE_TKIP; - break; - } - wpa_printf(MSG_DEBUG, " * group=0x%x", cipher); - NLA_PUT_U32(msg, NL80211_ATTR_CIPHER_SUITE_GROUP, cipher); - } - -#ifdef CONFIG_IEEE80211W - if (params->mgmt_frame_protection == MGMT_FRAME_PROTECTION_REQUIRED) - NLA_PUT_U32(msg, NL80211_ATTR_USE_MFP, NL80211_MFP_REQUIRED); -#endif /* CONFIG_IEEE80211W */ - - NLA_PUT_FLAG(msg, NL80211_ATTR_CONTROL_PORT); - - if (params->prev_bssid) { - wpa_printf(MSG_DEBUG, " * prev_bssid=" MACSTR, - MAC2STR(params->prev_bssid)); - NLA_PUT(msg, NL80211_ATTR_PREV_BSSID, ETH_ALEN, - params->prev_bssid); - } - - if (params->p2p) - wpa_printf(MSG_DEBUG, " * P2P group"); - - ret = send_and_recv_msgs(drv, msg, NULL, NULL); - msg = NULL; - if (ret) { - wpa_printf(MSG_DEBUG, "nl80211: MLME command failed: ret=%d " - "(%s)", ret, strerror(-ret)); - nl80211_dump_scan(drv); - goto nla_put_failure; - } - ret = 0; - wpa_printf(MSG_DEBUG, "nl80211: Association request send " - "successfully"); - -nla_put_failure: - nlmsg_free(msg); - return ret; -} - - -static int nl80211_set_mode(struct wpa_driver_nl80211_data *drv, - int ifindex, int mode) -{ - struct nl_msg *msg; - int ret = -ENOBUFS; - - msg = nlmsg_alloc(); - if (!msg) - return -ENOMEM; - - genlmsg_put(msg, 0, 0, genl_family_get_id(drv->nl80211), 0, - 0, NL80211_CMD_SET_INTERFACE, 0); - NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, ifindex); - NLA_PUT_U32(msg, NL80211_ATTR_IFTYPE, mode); - - ret = send_and_recv_msgs(drv, msg, NULL, NULL); - if (!ret) - return 0; -nla_put_failure: - wpa_printf(MSG_DEBUG, "nl80211: Failed to set interface %d to mode %d:" - " %d (%s)", ifindex, mode, ret, strerror(-ret)); - return ret; -} - - -static int wpa_driver_nl80211_set_mode(void *priv, int mode) -{ - struct i802_bss *bss = priv; - struct wpa_driver_nl80211_data *drv = bss->drv; - int ret = -1; - int nlmode; - int i; - - switch (mode) { - case 0: - nlmode = NL80211_IFTYPE_STATION; - break; - case 1: - nlmode = NL80211_IFTYPE_ADHOC; - break; - case 2: - nlmode = NL80211_IFTYPE_AP; - break; - default: - return -1; - } - - if (nl80211_set_mode(drv, drv->ifindex, nlmode) == 0) { - drv->nlmode = nlmode; - ret = 0; - goto done; - } - - if (nlmode == drv->nlmode) { - wpa_printf(MSG_DEBUG, "nl80211: Interface already in " - "requested mode - ignore error"); - ret = 0; - goto done; /* Already in the requested mode */ - } - - /* mac80211 doesn't allow mode changes while the device is up, so - * take the device down, try to set the mode again, and bring the - * device back up. - */ - wpa_printf(MSG_DEBUG, "nl80211: Try mode change after setting " - "interface down"); - for (i = 0; i < 10; i++) { - if (linux_set_iface_flags(drv->ioctl_sock, bss->ifname, 0) == - 0) { - /* Try to set the mode again while the interface is - * down */ - ret = nl80211_set_mode(drv, drv->ifindex, nlmode); - if (linux_set_iface_flags(drv->ioctl_sock, bss->ifname, - 1)) - ret = -1; - if (!ret) - break; - } else - wpa_printf(MSG_DEBUG, "nl80211: Failed to set " - "interface down"); - os_sleep(0, 100000); - } - - if (!ret) { - wpa_printf(MSG_DEBUG, "nl80211: Mode change succeeded while " - "interface is down"); - drv->nlmode = nlmode; - } - -done: - if (!ret && nlmode == NL80211_IFTYPE_AP) { - /* Setup additional AP mode functionality if needed */ - if (drv->monitor_ifidx < 0 && - nl80211_create_monitor_interface(drv)) - return -1; - } else if (!ret && nlmode != NL80211_IFTYPE_AP) { - /* Remove additional AP mode functionality */ - nl80211_remove_monitor_interface(drv); - bss->beacon_set = 0; - } - - if (ret) - wpa_printf(MSG_DEBUG, "nl80211: Interface mode change to %d " - "from %d failed", nlmode, drv->nlmode); - - return ret; -} - - -static int wpa_driver_nl80211_get_capa(void *priv, - struct wpa_driver_capa *capa) -{ - struct i802_bss *bss = priv; - struct wpa_driver_nl80211_data *drv = bss->drv; - if (!drv->has_capability) - return -1; - os_memcpy(capa, &drv->capa, sizeof(*capa)); - return 0; -} - - -static int wpa_driver_nl80211_set_operstate(void *priv, int state) -{ - struct i802_bss *bss = priv; - struct wpa_driver_nl80211_data *drv = bss->drv; - - wpa_printf(MSG_DEBUG, "%s: operstate %d->%d (%s)", - __func__, drv->operstate, state, state ? "UP" : "DORMANT"); - drv->operstate = state; - return netlink_send_oper_ifla(drv->netlink, drv->ifindex, -1, - state ? IF_OPER_UP : IF_OPER_DORMANT); -} - - -static int wpa_driver_nl80211_set_supp_port(void *priv, int authorized) -{ - struct i802_bss *bss = priv; - struct wpa_driver_nl80211_data *drv = bss->drv; - struct nl_msg *msg; - struct nl80211_sta_flag_update upd; - - msg = nlmsg_alloc(); - if (!msg) - return -ENOMEM; - - genlmsg_put(msg, 0, 0, genl_family_get_id(drv->nl80211), 0, - 0, NL80211_CMD_SET_STATION, 0); - - NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, - if_nametoindex(bss->ifname)); - NLA_PUT(msg, NL80211_ATTR_MAC, ETH_ALEN, drv->bssid); - - os_memset(&upd, 0, sizeof(upd)); - upd.mask = BIT(NL80211_STA_FLAG_AUTHORIZED); - if (authorized) - upd.set = BIT(NL80211_STA_FLAG_AUTHORIZED); - NLA_PUT(msg, NL80211_ATTR_STA_FLAGS2, sizeof(upd), &upd); - - return send_and_recv_msgs(drv, msg, NULL, NULL); - nla_put_failure: - return -ENOBUFS; -} - - -#ifdef HOSTAPD - -static void add_ifidx(struct wpa_driver_nl80211_data *drv, int ifidx) -{ - int i; - int *old; - - wpa_printf(MSG_DEBUG, "nl80211: Add own interface ifindex %d", - ifidx); - for (i = 0; i < drv->num_if_indices; i++) { - if (drv->if_indices[i] == 0) { - drv->if_indices[i] = ifidx; - return; - } - } - - if (drv->if_indices != drv->default_if_indices) - old = drv->if_indices; - else - old = NULL; - - drv->if_indices = os_realloc(old, - sizeof(int) * (drv->num_if_indices + 1)); - if (!drv->if_indices) { - if (!old) - drv->if_indices = drv->default_if_indices; - else - drv->if_indices = old; - wpa_printf(MSG_ERROR, "Failed to reallocate memory for " - "interfaces"); - wpa_printf(MSG_ERROR, "Ignoring EAPOL on interface %d", ifidx); - return; - } else if (!old) - os_memcpy(drv->if_indices, drv->default_if_indices, - sizeof(drv->default_if_indices)); - drv->if_indices[drv->num_if_indices] = ifidx; - drv->num_if_indices++; -} - - -static void del_ifidx(struct wpa_driver_nl80211_data *drv, int ifidx) -{ - int i; - - for (i = 0; i < drv->num_if_indices; i++) { - if (drv->if_indices[i] == ifidx) { - drv->if_indices[i] = 0; - break; - } - } -} - - -static int have_ifidx(struct wpa_driver_nl80211_data *drv, int ifidx) -{ - int i; - - for (i = 0; i < drv->num_if_indices; i++) - if (drv->if_indices[i] == ifidx) - return 1; - - return 0; -} - - -static inline int min_int(int a, int b) -{ - if (a < b) - return a; - return b; -} - - -static int get_key_handler(struct nl_msg *msg, void *arg) -{ - struct nlattr *tb[NL80211_ATTR_MAX + 1]; - struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg)); - - nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0), - genlmsg_attrlen(gnlh, 0), NULL); - - /* - * TODO: validate the key index and mac address! - * Otherwise, there's a race condition as soon as - * the kernel starts sending key notifications. - */ - - if (tb[NL80211_ATTR_KEY_SEQ]) - memcpy(arg, nla_data(tb[NL80211_ATTR_KEY_SEQ]), - min_int(nla_len(tb[NL80211_ATTR_KEY_SEQ]), 6)); - return NL_SKIP; -} - - -static int i802_get_seqnum(const char *iface, void *priv, const u8 *addr, - int idx, u8 *seq) -{ - struct i802_bss *bss = priv; - struct wpa_driver_nl80211_data *drv = bss->drv; - struct nl_msg *msg; - - msg = nlmsg_alloc(); - if (!msg) - return -ENOMEM; - - genlmsg_put(msg, 0, 0, genl_family_get_id(drv->nl80211), 0, - 0, NL80211_CMD_GET_KEY, 0); - - if (addr) - NLA_PUT(msg, NL80211_ATTR_MAC, ETH_ALEN, addr); - NLA_PUT_U8(msg, NL80211_ATTR_KEY_IDX, idx); - NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(iface)); - - memset(seq, 0, 6); - - return send_and_recv_msgs(drv, msg, get_key_handler, seq); - nla_put_failure: - return -ENOBUFS; -} - - -static int i802_set_rate_sets(void *priv, int *supp_rates, int *basic_rates, - int mode) -{ - struct i802_bss *bss = priv; - struct wpa_driver_nl80211_data *drv = bss->drv; - struct nl_msg *msg; - u8 rates[NL80211_MAX_SUPP_RATES]; - u8 rates_len = 0; - int i; - - msg = nlmsg_alloc(); - if (!msg) - return -ENOMEM; - - genlmsg_put(msg, 0, 0, genl_family_get_id(drv->nl80211), 0, 0, - NL80211_CMD_SET_BSS, 0); - - for (i = 0; i < NL80211_MAX_SUPP_RATES && basic_rates[i] >= 0; i++) - rates[rates_len++] = basic_rates[i] / 5; - - NLA_PUT(msg, NL80211_ATTR_BSS_BASIC_RATES, rates_len, rates); - - NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(bss->ifname)); - - return send_and_recv_msgs(drv, msg, NULL, NULL); - nla_put_failure: - return -ENOBUFS; -} - -#endif /* HOSTAPD */ - - -/* Set kernel driver on given frequency (MHz) */ -static int i802_set_freq(void *priv, struct hostapd_freq_params *freq) -{ - struct i802_bss *bss = priv; - struct wpa_driver_nl80211_data *drv = bss->drv; - return wpa_driver_nl80211_set_freq(drv, freq->freq, freq->ht_enabled, - freq->sec_channel_offset); -} - - -#ifdef HOSTAPD - -static int i802_set_rts(void *priv, int rts) -{ - struct i802_bss *bss = priv; - struct wpa_driver_nl80211_data *drv = bss->drv; - struct nl_msg *msg; - int ret = -ENOBUFS; - u32 val; - - msg = nlmsg_alloc(); - if (!msg) - return -ENOMEM; - - if (rts >= 2347) - val = (u32) -1; - else - val = rts; - - genlmsg_put(msg, 0, 0, genl_family_get_id(drv->nl80211), 0, - 0, NL80211_CMD_SET_WIPHY, 0); - NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, drv->ifindex); - NLA_PUT_U32(msg, NL80211_ATTR_WIPHY_RTS_THRESHOLD, val); - - ret = send_and_recv_msgs(drv, msg, NULL, NULL); - if (!ret) - return 0; -nla_put_failure: - wpa_printf(MSG_DEBUG, "nl80211: Failed to set RTS threshold %d: " - "%d (%s)", rts, ret, strerror(-ret)); - return ret; -} - - -static int i802_set_frag(void *priv, int frag) -{ - struct i802_bss *bss = priv; - struct wpa_driver_nl80211_data *drv = bss->drv; - struct nl_msg *msg; - int ret = -ENOBUFS; - u32 val; - - msg = nlmsg_alloc(); - if (!msg) - return -ENOMEM; - - if (frag >= 2346) - val = (u32) -1; - else - val = frag; - - genlmsg_put(msg, 0, 0, genl_family_get_id(drv->nl80211), 0, - 0, NL80211_CMD_SET_WIPHY, 0); - NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, drv->ifindex); - NLA_PUT_U32(msg, NL80211_ATTR_WIPHY_FRAG_THRESHOLD, val); - - ret = send_and_recv_msgs(drv, msg, NULL, NULL); - if (!ret) - return 0; -nla_put_failure: - wpa_printf(MSG_DEBUG, "nl80211: Failed to set fragmentation threshold " - "%d: %d (%s)", frag, ret, strerror(-ret)); - return ret; -} - - -static int i802_flush(void *priv) -{ - struct i802_bss *bss = priv; - struct wpa_driver_nl80211_data *drv = bss->drv; - struct nl_msg *msg; - - msg = nlmsg_alloc(); - if (!msg) - return -1; - - genlmsg_put(msg, 0, 0, genl_family_get_id(drv->nl80211), 0, - 0, NL80211_CMD_DEL_STATION, 0); - - /* - * XXX: FIX! this needs to flush all VLANs too - */ - NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, - if_nametoindex(bss->ifname)); - - return send_and_recv_msgs(drv, msg, NULL, NULL); - nla_put_failure: - return -ENOBUFS; -} - - -static int get_sta_handler(struct nl_msg *msg, void *arg) -{ - struct nlattr *tb[NL80211_ATTR_MAX + 1]; - struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg)); - struct hostap_sta_driver_data *data = arg; - struct nlattr *stats[NL80211_STA_INFO_MAX + 1]; - static struct nla_policy stats_policy[NL80211_STA_INFO_MAX + 1] = { - [NL80211_STA_INFO_INACTIVE_TIME] = { .type = NLA_U32 }, - [NL80211_STA_INFO_RX_BYTES] = { .type = NLA_U32 }, - [NL80211_STA_INFO_TX_BYTES] = { .type = NLA_U32 }, - [NL80211_STA_INFO_RX_PACKETS] = { .type = NLA_U32 }, - [NL80211_STA_INFO_TX_PACKETS] = { .type = NLA_U32 }, - }; - - nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0), - genlmsg_attrlen(gnlh, 0), NULL); - - /* - * TODO: validate the interface and mac address! - * Otherwise, there's a race condition as soon as - * the kernel starts sending station notifications. - */ - - if (!tb[NL80211_ATTR_STA_INFO]) { - wpa_printf(MSG_DEBUG, "sta stats missing!"); - return NL_SKIP; - } - if (nla_parse_nested(stats, NL80211_STA_INFO_MAX, - tb[NL80211_ATTR_STA_INFO], - stats_policy)) { - wpa_printf(MSG_DEBUG, "failed to parse nested attributes!"); - return NL_SKIP; - } - - if (stats[NL80211_STA_INFO_INACTIVE_TIME]) - data->inactive_msec = - nla_get_u32(stats[NL80211_STA_INFO_INACTIVE_TIME]); - if (stats[NL80211_STA_INFO_RX_BYTES]) - data->rx_bytes = nla_get_u32(stats[NL80211_STA_INFO_RX_BYTES]); - if (stats[NL80211_STA_INFO_TX_BYTES]) - data->tx_bytes = nla_get_u32(stats[NL80211_STA_INFO_TX_BYTES]); - if (stats[NL80211_STA_INFO_RX_PACKETS]) - data->rx_packets = - nla_get_u32(stats[NL80211_STA_INFO_RX_PACKETS]); - if (stats[NL80211_STA_INFO_TX_PACKETS]) - data->tx_packets = - nla_get_u32(stats[NL80211_STA_INFO_TX_PACKETS]); - - return NL_SKIP; -} - -static int i802_read_sta_data(void *priv, struct hostap_sta_driver_data *data, - const u8 *addr) -{ - struct i802_bss *bss = priv; - struct wpa_driver_nl80211_data *drv = bss->drv; - struct nl_msg *msg; - - os_memset(data, 0, sizeof(*data)); - msg = nlmsg_alloc(); - if (!msg) - return -ENOMEM; - - genlmsg_put(msg, 0, 0, genl_family_get_id(drv->nl80211), 0, - 0, NL80211_CMD_GET_STATION, 0); - - NLA_PUT(msg, NL80211_ATTR_MAC, ETH_ALEN, addr); - NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(bss->ifname)); - - return send_and_recv_msgs(drv, msg, get_sta_handler, data); - nla_put_failure: - return -ENOBUFS; -} - - -static int i802_set_tx_queue_params(void *priv, int queue, int aifs, - int cw_min, int cw_max, int burst_time) -{ - struct i802_bss *bss = priv; - struct wpa_driver_nl80211_data *drv = bss->drv; - struct nl_msg *msg; - struct nlattr *txq, *params; - - msg = nlmsg_alloc(); - if (!msg) - return -1; - - genlmsg_put(msg, 0, 0, genl_family_get_id(drv->nl80211), 0, - 0, NL80211_CMD_SET_WIPHY, 0); - - NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(bss->ifname)); - - txq = nla_nest_start(msg, NL80211_ATTR_WIPHY_TXQ_PARAMS); - if (!txq) - goto nla_put_failure; - - /* We are only sending parameters for a single TXQ at a time */ - params = nla_nest_start(msg, 1); - if (!params) - goto nla_put_failure; - - switch (queue) { - case 0: - NLA_PUT_U8(msg, NL80211_TXQ_ATTR_QUEUE, NL80211_TXQ_Q_VO); - break; - case 1: - NLA_PUT_U8(msg, NL80211_TXQ_ATTR_QUEUE, NL80211_TXQ_Q_VI); - break; - case 2: - NLA_PUT_U8(msg, NL80211_TXQ_ATTR_QUEUE, NL80211_TXQ_Q_BE); - break; - case 3: - NLA_PUT_U8(msg, NL80211_TXQ_ATTR_QUEUE, NL80211_TXQ_Q_BK); - break; - } - /* Burst time is configured in units of 0.1 msec and TXOP parameter in - * 32 usec, so need to convert the value here. */ - NLA_PUT_U16(msg, NL80211_TXQ_ATTR_TXOP, (burst_time * 100 + 16) / 32); - NLA_PUT_U16(msg, NL80211_TXQ_ATTR_CWMIN, cw_min); - NLA_PUT_U16(msg, NL80211_TXQ_ATTR_CWMAX, cw_max); - NLA_PUT_U8(msg, NL80211_TXQ_ATTR_AIFS, aifs); - - nla_nest_end(msg, params); - - nla_nest_end(msg, txq); - - if (send_and_recv_msgs(drv, msg, NULL, NULL) == 0) - return 0; - nla_put_failure: - return -1; -} - - -static int i802_set_bss(void *priv, int cts, int preamble, int slot, - int ht_opmode) -{ - struct i802_bss *bss = priv; - struct wpa_driver_nl80211_data *drv = bss->drv; - struct nl_msg *msg; - - msg = nlmsg_alloc(); - if (!msg) - return -ENOMEM; - - genlmsg_put(msg, 0, 0, genl_family_get_id(drv->nl80211), 0, 0, - NL80211_CMD_SET_BSS, 0); - - if (cts >= 0) - NLA_PUT_U8(msg, NL80211_ATTR_BSS_CTS_PROT, cts); - if (preamble >= 0) - NLA_PUT_U8(msg, NL80211_ATTR_BSS_SHORT_PREAMBLE, preamble); - if (slot >= 0) - NLA_PUT_U8(msg, NL80211_ATTR_BSS_SHORT_SLOT_TIME, slot); - if (ht_opmode >= 0) - NLA_PUT_U16(msg, NL80211_ATTR_BSS_HT_OPMODE, ht_opmode); - NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(bss->ifname)); - - return send_and_recv_msgs(drv, msg, NULL, NULL); - nla_put_failure: - return -ENOBUFS; -} - - -static int i802_set_cts_protect(void *priv, int value) -{ - return i802_set_bss(priv, value, -1, -1, -1); -} - - -static int i802_set_preamble(void *priv, int value) -{ - return i802_set_bss(priv, -1, value, -1, -1); -} - - -static int i802_set_short_slot_time(void *priv, int value) -{ - return i802_set_bss(priv, -1, -1, value, -1); -} - - -static int i802_set_sta_vlan(void *priv, const u8 *addr, - const char *ifname, int vlan_id) -{ - struct i802_bss *bss = priv; - struct wpa_driver_nl80211_data *drv = bss->drv; - struct nl_msg *msg; - int ret = -ENOBUFS; - - msg = nlmsg_alloc(); - if (!msg) - return -ENOMEM; - - genlmsg_put(msg, 0, 0, genl_family_get_id(drv->nl80211), 0, - 0, NL80211_CMD_SET_STATION, 0); - - NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, - if_nametoindex(bss->ifname)); - NLA_PUT(msg, NL80211_ATTR_MAC, ETH_ALEN, addr); - NLA_PUT_U32(msg, NL80211_ATTR_STA_VLAN, - if_nametoindex(ifname)); - - ret = send_and_recv_msgs(drv, msg, NULL, NULL); - if (ret < 0) { - wpa_printf(MSG_ERROR, "nl80211: NL80211_ATTR_STA_VLAN (addr=" - MACSTR " ifname=%s vlan_id=%d) failed: %d (%s)", - MAC2STR(addr), ifname, vlan_id, ret, - strerror(-ret)); - } - nla_put_failure: - return ret; -} - - -static int i802_set_wds_sta(void *priv, const u8 *addr, int aid, int val, - const char *bridge_ifname) -{ - struct i802_bss *bss = priv; - struct wpa_driver_nl80211_data *drv = bss->drv; - char name[IFNAMSIZ + 1]; - - os_snprintf(name, sizeof(name), "%s.sta%d", bss->ifname, aid); - wpa_printf(MSG_DEBUG, "nl80211: Set WDS STA addr=" MACSTR - " aid=%d val=%d name=%s", MAC2STR(addr), aid, val, name); - if (val) { - if (!if_nametoindex(name)) { - if (nl80211_create_iface(drv, name, - NL80211_IFTYPE_AP_VLAN, - NULL, 1) < 0) - return -1; - if (bridge_ifname && - linux_br_add_if(drv->ioctl_sock, bridge_ifname, - name) < 0) - return -1; - } - linux_set_iface_flags(drv->ioctl_sock, name, 1); - return i802_set_sta_vlan(priv, addr, name, 0); - } else { - i802_set_sta_vlan(priv, addr, bss->ifname, 0); - return wpa_driver_nl80211_if_remove(priv, WPA_IF_AP_VLAN, - name); - } -} - - -static int i802_set_ht_params(void *priv, const u8 *ht_capab, - size_t ht_capab_len, const u8 *ht_oper, - size_t ht_oper_len) -{ - if (ht_oper_len >= 6) { - /* ht opmode uses 16bit in octet 5 & 6 */ - u16 ht_opmode = le_to_host16(((u16 *) ht_oper)[2]); - return i802_set_bss(priv, -1, -1, -1, ht_opmode); - } else - return -1; -} - - -static void handle_eapol(int sock, void *eloop_ctx, void *sock_ctx) -{ - struct wpa_driver_nl80211_data *drv = eloop_ctx; - struct sockaddr_ll lladdr; - unsigned char buf[3000]; - int len; - socklen_t fromlen = sizeof(lladdr); - - len = recvfrom(sock, buf, sizeof(buf), 0, - (struct sockaddr *)&lladdr, &fromlen); - if (len < 0) { - perror("recv"); - return; - } - - if (have_ifidx(drv, lladdr.sll_ifindex)) - drv_event_eapol_rx(drv->ctx, lladdr.sll_addr, buf, len); -} - - -static int i802_get_inact_sec(void *priv, const u8 *addr) -{ - struct hostap_sta_driver_data data; - int ret; - - data.inactive_msec = (unsigned long) -1; - ret = i802_read_sta_data(priv, &data, addr); - if (ret || data.inactive_msec == (unsigned long) -1) - return -1; - return data.inactive_msec / 1000; -} - - -static int i802_sta_clear_stats(void *priv, const u8 *addr) -{ -#if 0 - /* TODO */ -#endif - return 0; -} - -#endif /* HOSTAPD */ - -#if defined(HOSTAPD) || defined(CONFIG_AP) - -static int i802_sta_deauth(void *priv, const u8 *own_addr, const u8 *addr, - int reason) -{ - struct i802_bss *bss = priv; - struct ieee80211_mgmt mgmt; - - memset(&mgmt, 0, sizeof(mgmt)); - mgmt.frame_control = IEEE80211_FC(WLAN_FC_TYPE_MGMT, - WLAN_FC_STYPE_DEAUTH); - memcpy(mgmt.da, addr, ETH_ALEN); - memcpy(mgmt.sa, own_addr, ETH_ALEN); - memcpy(mgmt.bssid, own_addr, ETH_ALEN); - mgmt.u.deauth.reason_code = host_to_le16(reason); - return wpa_driver_nl80211_send_mlme(bss, (u8 *) &mgmt, - IEEE80211_HDRLEN + - sizeof(mgmt.u.deauth)); -} - - -static int i802_sta_disassoc(void *priv, const u8 *own_addr, const u8 *addr, - int reason) -{ - struct i802_bss *bss = priv; - struct ieee80211_mgmt mgmt; - - memset(&mgmt, 0, sizeof(mgmt)); - mgmt.frame_control = IEEE80211_FC(WLAN_FC_TYPE_MGMT, - WLAN_FC_STYPE_DISASSOC); - memcpy(mgmt.da, addr, ETH_ALEN); - memcpy(mgmt.sa, own_addr, ETH_ALEN); - memcpy(mgmt.bssid, own_addr, ETH_ALEN); - mgmt.u.disassoc.reason_code = host_to_le16(reason); - return wpa_driver_nl80211_send_mlme(bss, (u8 *) &mgmt, - IEEE80211_HDRLEN + - sizeof(mgmt.u.disassoc)); -} - -#endif /* HOSTAPD || CONFIG_AP */ - -#ifdef HOSTAPD - -static int i802_check_bridge(struct wpa_driver_nl80211_data *drv, - struct i802_bss *bss, - const char *brname, const char *ifname) -{ - int ifindex; - char in_br[IFNAMSIZ]; - - os_strlcpy(bss->brname, brname, IFNAMSIZ); - ifindex = if_nametoindex(brname); - if (ifindex == 0) { - /* - * Bridge was configured, but the bridge device does - * not exist. Try to add it now. - */ - if (linux_br_add(drv->ioctl_sock, brname) < 0) { - wpa_printf(MSG_ERROR, "nl80211: Failed to add the " - "bridge interface %s: %s", - brname, strerror(errno)); - return -1; - } - bss->added_bridge = 1; - add_ifidx(drv, if_nametoindex(brname)); - } - - if (linux_br_get(in_br, ifname) == 0) { - if (os_strcmp(in_br, brname) == 0) - return 0; /* already in the bridge */ - - wpa_printf(MSG_DEBUG, "nl80211: Removing interface %s from " - "bridge %s", ifname, in_br); - if (linux_br_del_if(drv->ioctl_sock, in_br, ifname) < 0) { - wpa_printf(MSG_ERROR, "nl80211: Failed to " - "remove interface %s from bridge " - "%s: %s", - ifname, brname, strerror(errno)); - return -1; - } - } - - wpa_printf(MSG_DEBUG, "nl80211: Adding interface %s into bridge %s", - ifname, brname); - if (linux_br_add_if(drv->ioctl_sock, brname, ifname) < 0) { - wpa_printf(MSG_ERROR, "nl80211: Failed to add interface %s " - "into bridge %s: %s", - ifname, brname, strerror(errno)); - return -1; - } - bss->added_if_into_bridge = 1; - - return 0; -} - - -static void *i802_init(struct hostapd_data *hapd, - struct wpa_init_params *params) -{ - struct wpa_driver_nl80211_data *drv; - struct i802_bss *bss; - size_t i; - char brname[IFNAMSIZ]; - int ifindex, br_ifindex; - int br_added = 0; - - bss = wpa_driver_nl80211_init(hapd, params->ifname, NULL); - if (bss == NULL) - return NULL; - - drv = bss->drv; - drv->nlmode = NL80211_IFTYPE_AP; - if (linux_br_get(brname, params->ifname) == 0) { - wpa_printf(MSG_DEBUG, "nl80211: Interface %s is in bridge %s", - params->ifname, brname); - br_ifindex = if_nametoindex(brname); - } else { - brname[0] = '\0'; - br_ifindex = 0; - } - - drv->num_if_indices = sizeof(drv->default_if_indices) / sizeof(int); - drv->if_indices = drv->default_if_indices; - for (i = 0; i < params->num_bridge; i++) { - if (params->bridge[i]) { - ifindex = if_nametoindex(params->bridge[i]); - if (ifindex) - add_ifidx(drv, ifindex); - if (ifindex == br_ifindex) - br_added = 1; - } - } - if (!br_added && br_ifindex && - (params->num_bridge == 0 || !params->bridge[0])) - add_ifidx(drv, br_ifindex); - - /* start listening for EAPOL on the default AP interface */ - add_ifidx(drv, drv->ifindex); - - if (linux_set_iface_flags(drv->ioctl_sock, bss->ifname, 0)) - goto failed; - - if (params->bssid) { - if (linux_set_ifhwaddr(drv->ioctl_sock, bss->ifname, - params->bssid)) - goto failed; - } - - if (wpa_driver_nl80211_set_mode(bss, IEEE80211_MODE_AP)) { - wpa_printf(MSG_ERROR, "nl80211: Failed to set interface %s " - "into AP mode", bss->ifname); - goto failed; - } - - if (params->num_bridge && params->bridge[0] && - i802_check_bridge(drv, bss, params->bridge[0], params->ifname) < 0) - goto failed; - - if (linux_set_iface_flags(drv->ioctl_sock, bss->ifname, 1)) - goto failed; - - drv->eapol_sock = socket(PF_PACKET, SOCK_DGRAM, htons(ETH_P_PAE)); - if (drv->eapol_sock < 0) { - perror("socket(PF_PACKET, SOCK_DGRAM, ETH_P_PAE)"); - goto failed; - } - - if (eloop_register_read_sock(drv->eapol_sock, handle_eapol, drv, NULL)) - { - printf("Could not register read socket for eapol\n"); - goto failed; - } - - if (linux_get_ifhwaddr(drv->ioctl_sock, bss->ifname, params->own_addr)) - goto failed; - - return bss; - -failed: - nl80211_remove_monitor_interface(drv); - rfkill_deinit(drv->rfkill); - netlink_deinit(drv->netlink); - if (drv->ioctl_sock >= 0) - close(drv->ioctl_sock); - - genl_family_put(drv->nl80211); - nl_cache_free(drv->nl_cache); - nl80211_handle_destroy(drv->nl_handle); - nl_cb_put(drv->nl_cb); - eloop_unregister_read_sock(nl_socket_get_fd(drv->nl_handle_event)); - - os_free(drv); - return NULL; -} - - -static void i802_deinit(void *priv) -{ - wpa_driver_nl80211_deinit(priv); -} - -#endif /* HOSTAPD */ - - -static enum nl80211_iftype wpa_driver_nl80211_if_type( - enum wpa_driver_if_type type) -{ - switch (type) { - case WPA_IF_STATION: - return NL80211_IFTYPE_STATION; - case WPA_IF_P2P_CLIENT: - case WPA_IF_P2P_GROUP: - return NL80211_IFTYPE_P2P_CLIENT; - case WPA_IF_AP_VLAN: - return NL80211_IFTYPE_AP_VLAN; - case WPA_IF_AP_BSS: - return NL80211_IFTYPE_AP; - case WPA_IF_P2P_GO: - return NL80211_IFTYPE_P2P_GO; - } - return -1; -} - - -#ifdef CONFIG_P2P - -static int nl80211_addr_in_use(struct nl80211_global *global, const u8 *addr) -{ - struct wpa_driver_nl80211_data *drv; - dl_list_for_each(drv, &global->interfaces, - struct wpa_driver_nl80211_data, list) { - if (os_memcmp(addr, drv->addr, ETH_ALEN) == 0) - return 1; - } - return 0; -} - - -static int nl80211_p2p_interface_addr(struct wpa_driver_nl80211_data *drv, - u8 *new_addr) -{ - unsigned int idx; - - if (!drv->global) - return -1; - - os_memcpy(new_addr, drv->addr, ETH_ALEN); - for (idx = 0; idx < 64; idx++) { - new_addr[0] = drv->addr[0] | 0x02; - new_addr[0] ^= idx << 2; - if (!nl80211_addr_in_use(drv->global, new_addr)) - break; - } - if (idx == 64) - return -1; - - wpa_printf(MSG_DEBUG, "nl80211: Assigned new P2P Interface Address " - MACSTR, MAC2STR(new_addr)); - - return 0; -} - -#endif /* CONFIG_P2P */ - - -static int wpa_driver_nl80211_if_add(void *priv, enum wpa_driver_if_type type, - const char *ifname, const u8 *addr, - void *bss_ctx, void **drv_priv, - char *force_ifname, u8 *if_addr, - const char *bridge) -{ - struct i802_bss *bss = priv; - struct wpa_driver_nl80211_data *drv = bss->drv; - int ifidx; -#ifdef HOSTAPD - struct i802_bss *new_bss = NULL; - - if (type == WPA_IF_AP_BSS) { - new_bss = os_zalloc(sizeof(*new_bss)); - if (new_bss == NULL) - return -1; - } -#endif /* HOSTAPD */ - - if (addr) - os_memcpy(if_addr, addr, ETH_ALEN); - ifidx = nl80211_create_iface(drv, ifname, - wpa_driver_nl80211_if_type(type), addr, - 0); - if (ifidx < 0) { -#ifdef HOSTAPD - os_free(new_bss); -#endif /* HOSTAPD */ - return -1; - } - - if (!addr && - linux_get_ifhwaddr(drv->ioctl_sock, bss->ifname, if_addr) < 0) { - nl80211_remove_iface(drv, ifidx); - return -1; - } - -#ifdef CONFIG_P2P - if (!addr && - (type == WPA_IF_P2P_CLIENT || type == WPA_IF_P2P_GROUP || - type == WPA_IF_P2P_GO)) { - /* Enforce unique P2P Interface Address */ - u8 new_addr[ETH_ALEN], own_addr[ETH_ALEN]; - - if (linux_get_ifhwaddr(drv->ioctl_sock, bss->ifname, own_addr) - < 0 || - linux_get_ifhwaddr(drv->ioctl_sock, ifname, new_addr) < 0) - { - nl80211_remove_iface(drv, ifidx); - return -1; - } - if (os_memcmp(own_addr, new_addr, ETH_ALEN) == 0) { - wpa_printf(MSG_DEBUG, "nl80211: Allocate new address " - "for P2P group interface"); - if (nl80211_p2p_interface_addr(drv, new_addr) < 0) { - nl80211_remove_iface(drv, ifidx); - return -1; - } - if (linux_set_ifhwaddr(drv->ioctl_sock, ifname, - new_addr) < 0) { - nl80211_remove_iface(drv, ifidx); - return -1; - } - os_memcpy(if_addr, new_addr, ETH_ALEN); - } - } -#endif /* CONFIG_P2P */ - -#ifdef HOSTAPD - if (bridge && - i802_check_bridge(drv, new_bss, bridge, ifname) < 0) { - wpa_printf(MSG_ERROR, "nl80211: Failed to add the new " - "interface %s to a bridge %s", ifname, bridge); - nl80211_remove_iface(drv, ifidx); - os_free(new_bss); - return -1; - } - - if (type == WPA_IF_AP_BSS) { - if (linux_set_iface_flags(drv->ioctl_sock, ifname, 1)) { - nl80211_remove_iface(drv, ifidx); - os_free(new_bss); - return -1; - } - os_strlcpy(new_bss->ifname, ifname, IFNAMSIZ); - new_bss->ifindex = ifidx; - new_bss->drv = drv; - new_bss->next = drv->first_bss.next; - drv->first_bss.next = new_bss; - if (drv_priv) - *drv_priv = new_bss; - } -#endif /* HOSTAPD */ - - return 0; -} - - -static int wpa_driver_nl80211_if_remove(void *priv, - enum wpa_driver_if_type type, - const char *ifname) -{ - struct i802_bss *bss = priv; - struct wpa_driver_nl80211_data *drv = bss->drv; - int ifindex = if_nametoindex(ifname); - - wpa_printf(MSG_DEBUG, "nl80211: %s(type=%d ifname=%s) ifindex=%d", - __func__, type, ifname, ifindex); - if (ifindex <= 0) - return -1; - -#ifdef HOSTAPD - if (bss->added_if_into_bridge) { - if (linux_br_del_if(drv->ioctl_sock, bss->brname, bss->ifname) - < 0) - wpa_printf(MSG_INFO, "nl80211: Failed to remove " - "interface %s from bridge %s: %s", - bss->ifname, bss->brname, strerror(errno)); - } - if (bss->added_bridge) { - if (linux_br_del(drv->ioctl_sock, bss->brname) < 0) - wpa_printf(MSG_INFO, "nl80211: Failed to remove " - "bridge %s: %s", - bss->brname, strerror(errno)); - } -#endif /* HOSTAPD */ - - nl80211_remove_iface(drv, ifindex); - -#ifdef HOSTAPD - if (type != WPA_IF_AP_BSS) - return 0; - - if (bss != &drv->first_bss) { - struct i802_bss *tbss; - - for (tbss = &drv->first_bss; tbss; tbss = tbss->next) { - if (tbss->next == bss) { - tbss->next = bss->next; - os_free(bss); - bss = NULL; - break; - } - } - if (bss) - wpa_printf(MSG_INFO, "nl80211: %s - could not find " - "BSS %p in the list", __func__, bss); - } -#endif /* HOSTAPD */ - - return 0; -} - - -static int cookie_handler(struct nl_msg *msg, void *arg) -{ - struct nlattr *tb[NL80211_ATTR_MAX + 1]; - struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg)); - u64 *cookie = arg; - nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0), - genlmsg_attrlen(gnlh, 0), NULL); - if (tb[NL80211_ATTR_COOKIE]) - *cookie = nla_get_u64(tb[NL80211_ATTR_COOKIE]); - return NL_SKIP; -} - - -static int nl80211_send_frame_cmd(struct wpa_driver_nl80211_data *drv, - unsigned int freq, unsigned int wait, - const u8 *buf, size_t buf_len, - u64 *cookie_out) -{ - struct nl_msg *msg; - u64 cookie; - int ret = -1; - - msg = nlmsg_alloc(); - if (!msg) - return -1; - - genlmsg_put(msg, 0, 0, genl_family_get_id(drv->nl80211), 0, 0, - NL80211_CMD_FRAME, 0); - - NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, drv->ifindex); - NLA_PUT_U32(msg, NL80211_ATTR_WIPHY_FREQ, freq); - NLA_PUT_U32(msg, NL80211_ATTR_DURATION, wait); - NLA_PUT_FLAG(msg, NL80211_ATTR_OFFCHANNEL_TX_OK); - NLA_PUT(msg, NL80211_ATTR_FRAME, buf_len, buf); - - cookie = 0; - ret = send_and_recv_msgs(drv, msg, cookie_handler, &cookie); - msg = NULL; - if (ret) { - wpa_printf(MSG_DEBUG, "nl80211: Frame command failed: ret=%d " - "(%s)", ret, strerror(-ret)); - goto nla_put_failure; - } - wpa_printf(MSG_DEBUG, "nl80211: Frame TX command accepted; " - "cookie 0x%llx", (long long unsigned int) cookie); - - if (cookie_out) - *cookie_out = cookie; - -nla_put_failure: - nlmsg_free(msg); - return ret; -} - - -static int wpa_driver_nl80211_send_action(void *priv, unsigned int freq, - unsigned int wait_time, - const u8 *dst, const u8 *src, - const u8 *bssid, - const u8 *data, size_t data_len) -{ - struct i802_bss *bss = priv; - struct wpa_driver_nl80211_data *drv = bss->drv; - int ret = -1; - u8 *buf; - struct ieee80211_hdr *hdr; - - wpa_printf(MSG_DEBUG, "nl80211: Send Action frame (ifindex=%d, " - "wait=%d ms)", drv->ifindex, wait_time); - - buf = os_zalloc(24 + data_len); - if (buf == NULL) - return ret; - os_memcpy(buf + 24, data, data_len); - hdr = (struct ieee80211_hdr *) buf; - hdr->frame_control = - IEEE80211_FC(WLAN_FC_TYPE_MGMT, WLAN_FC_STYPE_ACTION); - os_memcpy(hdr->addr1, dst, ETH_ALEN); - os_memcpy(hdr->addr2, src, ETH_ALEN); - os_memcpy(hdr->addr3, bssid, ETH_ALEN); - - if (drv->nlmode == NL80211_IFTYPE_AP) - ret = wpa_driver_nl80211_send_mlme(priv, buf, 24 + data_len); - else - ret = nl80211_send_frame_cmd(drv, freq, wait_time, buf, - 24 + data_len, - &drv->send_action_cookie); - - os_free(buf); - return ret; -} - - -static void wpa_driver_nl80211_send_action_cancel_wait(void *priv) -{ - struct i802_bss *bss = priv; - struct wpa_driver_nl80211_data *drv = bss->drv; - struct nl_msg *msg; - int ret; - - msg = nlmsg_alloc(); - if (!msg) - return; - - genlmsg_put(msg, 0, 0, genl_family_get_id(drv->nl80211), 0, 0, - NL80211_CMD_FRAME_WAIT_CANCEL, 0); - - NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, drv->ifindex); - NLA_PUT_U64(msg, NL80211_ATTR_COOKIE, drv->send_action_cookie); - - ret = send_and_recv_msgs(drv, msg, NULL, NULL); - msg = NULL; - if (ret) - wpa_printf(MSG_DEBUG, "nl80211: wait cancel failed: ret=%d " - "(%s)", ret, strerror(-ret)); - - nla_put_failure: - nlmsg_free(msg); -} - - -static int wpa_driver_nl80211_remain_on_channel(void *priv, unsigned int freq, - unsigned int duration) -{ - struct i802_bss *bss = priv; - struct wpa_driver_nl80211_data *drv = bss->drv; - struct nl_msg *msg; - int ret; - u64 cookie; - - msg = nlmsg_alloc(); - if (!msg) - return -1; - - genlmsg_put(msg, 0, 0, genl_family_get_id(drv->nl80211), 0, 0, - NL80211_CMD_REMAIN_ON_CHANNEL, 0); - - NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, drv->ifindex); - NLA_PUT_U32(msg, NL80211_ATTR_WIPHY_FREQ, freq); - NLA_PUT_U32(msg, NL80211_ATTR_DURATION, duration); - - cookie = 0; - ret = send_and_recv_msgs(drv, msg, cookie_handler, &cookie); - if (ret == 0) { - wpa_printf(MSG_DEBUG, "nl80211: Remain-on-channel cookie " - "0x%llx for freq=%u MHz duration=%u", - (long long unsigned int) cookie, freq, duration); - drv->remain_on_chan_cookie = cookie; - return 0; - } - wpa_printf(MSG_DEBUG, "nl80211: Failed to request remain-on-channel " - "(freq=%d duration=%u): %d (%s)", - freq, duration, ret, strerror(-ret)); -nla_put_failure: - return -1; -} - - -static int wpa_driver_nl80211_cancel_remain_on_channel(void *priv) -{ - struct i802_bss *bss = priv; - struct wpa_driver_nl80211_data *drv = bss->drv; - struct nl_msg *msg; - int ret; - - if (!drv->pending_remain_on_chan) { - wpa_printf(MSG_DEBUG, "nl80211: No pending remain-on-channel " - "to cancel"); - return -1; - } - - wpa_printf(MSG_DEBUG, "nl80211: Cancel remain-on-channel with cookie " - "0x%llx", - (long long unsigned int) drv->remain_on_chan_cookie); - - msg = nlmsg_alloc(); - if (!msg) - return -1; - - genlmsg_put(msg, 0, 0, genl_family_get_id(drv->nl80211), 0, 0, - NL80211_CMD_CANCEL_REMAIN_ON_CHANNEL, 0); - - NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, drv->ifindex); - NLA_PUT_U64(msg, NL80211_ATTR_COOKIE, drv->remain_on_chan_cookie); - - ret = send_and_recv_msgs(drv, msg, NULL, NULL); - if (ret == 0) - return 0; - wpa_printf(MSG_DEBUG, "nl80211: Failed to cancel remain-on-channel: " - "%d (%s)", ret, strerror(-ret)); -nla_put_failure: - return -1; -} - - -static int wpa_driver_nl80211_probe_req_report(void *priv, int report) -{ - struct i802_bss *bss = priv; - struct wpa_driver_nl80211_data *drv = bss->drv; - - if (drv->nlmode != NL80211_IFTYPE_STATION) { - wpa_printf(MSG_DEBUG, "nl80211: probe_req_report control only " - "allowed in station mode (iftype=%d)", - drv->nlmode); - return -1; - } - - if (!report) { - if (drv->nl_handle_preq) { - eloop_unregister_read_sock( - nl_socket_get_fd(drv->nl_handle_preq)); - nl_cache_free(drv->nl_cache_preq); - nl80211_handle_destroy(drv->nl_handle_preq); - drv->nl_handle_preq = NULL; - } - return 0; - } - - if (drv->nl_handle_preq) { - wpa_printf(MSG_DEBUG, "nl80211: Probe Request reporting " - "already on!"); - return 0; - } - - drv->nl_handle_preq = nl80211_handle_alloc(drv->nl_cb); - if (drv->nl_handle_preq == NULL) { - wpa_printf(MSG_ERROR, "nl80211: Failed to allocate " - "netlink callbacks (preq)"); - goto out_err1; - } - - if (genl_connect(drv->nl_handle_preq)) { - wpa_printf(MSG_ERROR, "nl80211: Failed to connect to " - "generic netlink (preq)"); - goto out_err2; - return -1; - } - -#ifdef CONFIG_LIBNL20 - if (genl_ctrl_alloc_cache(drv->nl_handle_preq, - &drv->nl_cache_preq) < 0) { - wpa_printf(MSG_ERROR, "nl80211: Failed to allocate generic " - "netlink cache (preq)"); - goto out_err2; - } -#else /* CONFIG_LIBNL20 */ - drv->nl_cache_preq = genl_ctrl_alloc_cache(drv->nl_handle_preq); - if (drv->nl_cache_preq == NULL) { - wpa_printf(MSG_ERROR, "nl80211: Failed to allocate generic " - "netlink cache (preq)"); - goto out_err2; - } -#endif /* CONFIG_LIBNL20 */ - - if (nl80211_register_frame(drv, drv->nl_handle_preq, - (WLAN_FC_TYPE_MGMT << 2) | - (WLAN_FC_STYPE_PROBE_REQ << 4), - NULL, 0) < 0) { - goto out_err3; - } - - eloop_register_read_sock(nl_socket_get_fd(drv->nl_handle_preq), - wpa_driver_nl80211_event_receive, drv, - drv->nl_handle_preq); - - return 0; - - out_err3: - nl_cache_free(drv->nl_cache_preq); - out_err2: - nl80211_handle_destroy(drv->nl_handle_preq); - drv->nl_handle_preq = NULL; - out_err1: - return -1; -} - - -static int nl80211_disable_11b_rates(struct wpa_driver_nl80211_data *drv, - int ifindex, int disabled) -{ - struct nl_msg *msg; - struct nlattr *bands, *band; - int ret; - - msg = nlmsg_alloc(); - if (!msg) - return -1; - - genlmsg_put(msg, 0, 0, genl_family_get_id(drv->nl80211), 0, 0, - NL80211_CMD_SET_TX_BITRATE_MASK, 0); - NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, ifindex); - - bands = nla_nest_start(msg, NL80211_ATTR_TX_RATES); - if (!bands) - goto nla_put_failure; - - /* - * Disable 2 GHz rates 1, 2, 5.5, 11 Mbps by masking out everything - * else apart from 6, 9, 12, 18, 24, 36, 48, 54 Mbps from non-MCS - * rates. All 5 GHz rates are left enabled. - */ - band = nla_nest_start(msg, NL80211_BAND_2GHZ); - if (!band) - goto nla_put_failure; - NLA_PUT(msg, NL80211_TXRATE_LEGACY, 8, - "\x0c\x12\x18\x24\x30\x48\x60\x6c"); - nla_nest_end(msg, band); - - nla_nest_end(msg, bands); - - ret = send_and_recv_msgs(drv, msg, NULL, NULL); - msg = NULL; - if (ret) { - wpa_printf(MSG_DEBUG, "nl80211: Set TX rates failed: ret=%d " - "(%s)", ret, strerror(-ret)); - } - - return ret; - -nla_put_failure: - nlmsg_free(msg); - return -1; -} - - -static int wpa_driver_nl80211_disable_11b_rates(void *priv, int disabled) -{ - struct i802_bss *bss = priv; - struct wpa_driver_nl80211_data *drv = bss->drv; - drv->disable_11b_rates = disabled; - return nl80211_disable_11b_rates(drv, drv->ifindex, disabled); -} - - -static int wpa_driver_nl80211_deinit_ap(void *priv) -{ - struct i802_bss *bss = priv; - struct wpa_driver_nl80211_data *drv = bss->drv; - if (drv->nlmode != NL80211_IFTYPE_AP) - return -1; - wpa_driver_nl80211_del_beacon(drv); - return wpa_driver_nl80211_set_mode(priv, IEEE80211_MODE_INFRA); -} - - -static void wpa_driver_nl80211_resume(void *priv) -{ - struct i802_bss *bss = priv; - struct wpa_driver_nl80211_data *drv = bss->drv; - if (linux_set_iface_flags(drv->ioctl_sock, bss->ifname, 1)) { - wpa_printf(MSG_DEBUG, "nl80211: Failed to set interface up on " - "resume event"); - } -} - - -static int nl80211_send_ft_action(void *priv, u8 action, const u8 *target_ap, - const u8 *ies, size_t ies_len) -{ - struct i802_bss *bss = priv; - struct wpa_driver_nl80211_data *drv = bss->drv; - int ret; - u8 *data, *pos; - size_t data_len; - u8 own_addr[ETH_ALEN]; - - if (linux_get_ifhwaddr(drv->ioctl_sock, bss->ifname, own_addr) < 0) - return -1; - - if (action != 1) { - wpa_printf(MSG_ERROR, "nl80211: Unsupported send_ft_action " - "action %d", action); - return -1; - } - - /* - * Action frame payload: - * Category[1] = 6 (Fast BSS Transition) - * Action[1] = 1 (Fast BSS Transition Request) - * STA Address - * Target AP Address - * FT IEs - */ - - data_len = 2 + 2 * ETH_ALEN + ies_len; - data = os_malloc(data_len); - if (data == NULL) - return -1; - pos = data; - *pos++ = 0x06; /* FT Action category */ - *pos++ = action; - os_memcpy(pos, own_addr, ETH_ALEN); - pos += ETH_ALEN; - os_memcpy(pos, target_ap, ETH_ALEN); - pos += ETH_ALEN; - os_memcpy(pos, ies, ies_len); - - ret = wpa_driver_nl80211_send_action(bss, drv->assoc_freq, 0, - drv->bssid, own_addr, drv->bssid, - data, data_len); - os_free(data); - - return ret; -} - - -static int nl80211_signal_monitor(void *priv, int threshold, int hysteresis) -{ - struct i802_bss *bss = priv; - struct wpa_driver_nl80211_data *drv = bss->drv; - struct nl_msg *msg, *cqm = NULL; - - wpa_printf(MSG_DEBUG, "nl80211: Signal monitor threshold=%d " - "hysteresis=%d", threshold, hysteresis); - - msg = nlmsg_alloc(); - if (!msg) - return -1; - - genlmsg_put(msg, 0, 0, genl_family_get_id(drv->nl80211), 0, - 0, NL80211_CMD_SET_CQM, 0); - - NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, bss->ifindex); - - cqm = nlmsg_alloc(); - if (cqm == NULL) - return -1; - - NLA_PUT_U32(cqm, NL80211_ATTR_CQM_RSSI_THOLD, threshold); - NLA_PUT_U32(cqm, NL80211_ATTR_CQM_RSSI_HYST, hysteresis); - nla_put_nested(msg, NL80211_ATTR_CQM, cqm); - - if (send_and_recv_msgs(drv, msg, NULL, NULL) == 0) - return 0; - msg = NULL; - -nla_put_failure: - if (cqm) - nlmsg_free(cqm); - nlmsg_free(msg); - return -1; -} - - -static int nl80211_signal_poll(void *priv, struct wpa_signal_info *si) -{ - struct i802_bss *bss = priv; - struct wpa_driver_nl80211_data *drv = bss->drv; - int res; - - os_memset(si, 0, sizeof(*si)); - res = nl80211_get_link_signal(drv, si); - if (res != 0) - return res; - - return nl80211_get_link_noise(drv, si); -} - - -static int nl80211_send_frame(void *priv, const u8 *data, size_t data_len, - int encrypt) -{ - struct i802_bss *bss = priv; - struct wpa_driver_nl80211_data *drv = bss->drv; - return wpa_driver_nl80211_send_frame(drv, data, data_len, encrypt); -} - - -static int nl80211_set_intra_bss(void *priv, int enabled) -{ - struct i802_bss *bss = priv; - struct wpa_driver_nl80211_data *drv = bss->drv; - struct nl_msg *msg; - - msg = nlmsg_alloc(); - if (!msg) - return -ENOMEM; - - genlmsg_put(msg, 0, 0, genl_family_get_id(drv->nl80211), 0, 0, - NL80211_CMD_SET_BSS, 0); - - NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(bss->ifname)); - NLA_PUT_U8(msg, NL80211_ATTR_AP_ISOLATE, !enabled); - - return send_and_recv_msgs(drv, msg, NULL, NULL); - nla_put_failure: - return -ENOBUFS; -} - - -static int nl80211_set_param(void *priv, const char *param) -{ - wpa_printf(MSG_DEBUG, "nl80211: driver param='%s'", param); - if (param == NULL) - return 0; - -#ifdef CONFIG_P2P - if (os_strstr(param, "use_p2p_group_interface=1")) { - struct i802_bss *bss = priv; - struct wpa_driver_nl80211_data *drv = bss->drv; - - wpa_printf(MSG_DEBUG, "nl80211: Use separate P2P group " - "interface"); - drv->capa.flags |= WPA_DRIVER_FLAGS_P2P_CONCURRENT; - drv->capa.flags |= WPA_DRIVER_FLAGS_P2P_MGMT_AND_NON_P2P; - } -#endif /* CONFIG_P2P */ - - return 0; -} - - -static void * nl80211_global_init(void) -{ - struct nl80211_global *global; - global = os_zalloc(sizeof(*global)); - if (global == NULL) - return NULL; - dl_list_init(&global->interfaces); - return global; -} - - -static void nl80211_global_deinit(void *priv) -{ - struct nl80211_global *global = priv; - if (global == NULL) - return; - if (!dl_list_empty(&global->interfaces)) { - wpa_printf(MSG_ERROR, "nl80211: %u interface(s) remain at " - "nl80211_global_deinit", - dl_list_len(&global->interfaces)); - } - os_free(global); -} - - -static const char * nl80211_get_radio_name(void *priv) -{ - struct i802_bss *bss = priv; - struct wpa_driver_nl80211_data *drv = bss->drv; - return drv->phyname; -} - - -const struct wpa_driver_ops wpa_driver_nl80211_ops = { - .name = "nl80211", - .desc = "Linux nl80211/cfg80211", - .get_bssid = wpa_driver_nl80211_get_bssid, - .get_ssid = wpa_driver_nl80211_get_ssid, - .set_key = wpa_driver_nl80211_set_key, - .scan2 = wpa_driver_nl80211_scan, - .get_scan_results2 = wpa_driver_nl80211_get_scan_results, - .deauthenticate = wpa_driver_nl80211_deauthenticate, - .disassociate = wpa_driver_nl80211_disassociate, - .authenticate = wpa_driver_nl80211_authenticate, - .associate = wpa_driver_nl80211_associate, - .global_init = nl80211_global_init, - .global_deinit = nl80211_global_deinit, - .init2 = wpa_driver_nl80211_init, - .deinit = wpa_driver_nl80211_deinit, - .get_capa = wpa_driver_nl80211_get_capa, - .set_operstate = wpa_driver_nl80211_set_operstate, - .set_supp_port = wpa_driver_nl80211_set_supp_port, - .set_country = wpa_driver_nl80211_set_country, - .set_beacon = wpa_driver_nl80211_set_beacon, - .if_add = wpa_driver_nl80211_if_add, - .if_remove = wpa_driver_nl80211_if_remove, - .send_mlme = wpa_driver_nl80211_send_mlme, - .get_hw_feature_data = wpa_driver_nl80211_get_hw_feature_data, - .sta_add = wpa_driver_nl80211_sta_add, - .sta_remove = wpa_driver_nl80211_sta_remove, - .hapd_send_eapol = wpa_driver_nl80211_hapd_send_eapol, - .sta_set_flags = wpa_driver_nl80211_sta_set_flags, -#ifdef HOSTAPD - .hapd_init = i802_init, - .hapd_deinit = i802_deinit, - .get_seqnum = i802_get_seqnum, - .flush = i802_flush, - .read_sta_data = i802_read_sta_data, - .get_inact_sec = i802_get_inact_sec, - .sta_clear_stats = i802_sta_clear_stats, - .set_rts = i802_set_rts, - .set_frag = i802_set_frag, - .set_rate_sets = i802_set_rate_sets, - .set_cts_protect = i802_set_cts_protect, - .set_preamble = i802_set_preamble, - .set_short_slot_time = i802_set_short_slot_time, - .set_tx_queue_params = i802_set_tx_queue_params, - .set_sta_vlan = i802_set_sta_vlan, - .set_wds_sta = i802_set_wds_sta, - .set_ht_params = i802_set_ht_params, -#endif /* HOSTAPD */ -#if defined(HOSTAPD) || defined(CONFIG_AP) - .sta_deauth = i802_sta_deauth, - .sta_disassoc = i802_sta_disassoc, -#endif /* HOSTAPD || CONFIG_AP */ - .set_freq = i802_set_freq, - .send_action = wpa_driver_nl80211_send_action, - .send_action_cancel_wait = wpa_driver_nl80211_send_action_cancel_wait, - .remain_on_channel = wpa_driver_nl80211_remain_on_channel, - .cancel_remain_on_channel = - wpa_driver_nl80211_cancel_remain_on_channel, - .probe_req_report = wpa_driver_nl80211_probe_req_report, - .disable_11b_rates = wpa_driver_nl80211_disable_11b_rates, - .deinit_ap = wpa_driver_nl80211_deinit_ap, - .resume = wpa_driver_nl80211_resume, - .send_ft_action = nl80211_send_ft_action, - .signal_monitor = nl80211_signal_monitor, - .signal_poll = nl80211_signal_poll, - .send_frame = nl80211_send_frame, - .set_intra_bss = nl80211_set_intra_bss, - .set_param = nl80211_set_param, - .get_radio_name = nl80211_get_radio_name, -}; diff --git a/hostapd-0.8/src/drivers/driver_none.c b/hostapd-0.8/src/drivers/driver_none.c deleted file mode 100644 index aaeacd6..0000000 --- a/hostapd-0.8/src/drivers/driver_none.c +++ /dev/null @@ -1,99 +0,0 @@ -/* - * Driver interface for RADIUS server or WPS ER only (no driver) - * Copyright (c) 2008, Atheros Communications - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#include "includes.h" - -#include "common.h" -#include "driver.h" - - -struct none_driver_data { - struct hostapd_data *hapd; - void *ctx; -}; - - -static void * none_driver_hapd_init(struct hostapd_data *hapd, - struct wpa_init_params *params) -{ - struct none_driver_data *drv; - - drv = os_zalloc(sizeof(struct none_driver_data)); - if (drv == NULL) { - wpa_printf(MSG_ERROR, "Could not allocate memory for none " - "driver data"); - return NULL; - } - drv->hapd = hapd; - - return drv; -} - - -static void none_driver_hapd_deinit(void *priv) -{ - struct none_driver_data *drv = priv; - - os_free(drv); -} - - -static int none_driver_send_ether(void *priv, const u8 *dst, const u8 *src, - u16 proto, const u8 *data, size_t data_len) -{ - return 0; -} - - -static void * none_driver_init(void *ctx, const char *ifname) -{ - struct none_driver_data *drv; - - drv = os_zalloc(sizeof(struct none_driver_data)); - if (drv == NULL) { - wpa_printf(MSG_ERROR, "Could not allocate memory for none " - "driver data"); - return NULL; - } - drv->ctx = ctx; - - return drv; -} - - -static void none_driver_deinit(void *priv) -{ - struct none_driver_data *drv = priv; - - os_free(drv); -} - - -static int none_driver_send_eapol(void *priv, const u8 *dest, u16 proto, - const u8 *data, size_t data_len) -{ - return -1; -} - - -const struct wpa_driver_ops wpa_driver_none_ops = { - .name = "none", - .desc = "no driver (RADIUS server/WPS ER)", - .hapd_init = none_driver_hapd_init, - .hapd_deinit = none_driver_hapd_deinit, - .send_ether = none_driver_send_ether, - .init = none_driver_init, - .deinit = none_driver_deinit, - .send_eapol = none_driver_send_eapol, -}; diff --git a/hostapd-0.8/src/drivers/driver_osx.m b/hostapd-0.8/src/drivers/driver_osx.m deleted file mode 100644 index 69ca4b5..0000000 --- a/hostapd-0.8/src/drivers/driver_osx.m +++ /dev/null @@ -1,459 +0,0 @@ -/* - * WPA Supplicant - Mac OS X Apple80211 driver interface - * Copyright (c) 2007, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#include "includes.h" -#define Boolean __DummyBoolean -#include -#undef Boolean - -#include "common.h" -#include "driver.h" -#include "eloop.h" -#include "common/ieee802_11_defs.h" - -#include "Apple80211.h" - -struct wpa_driver_osx_data { - void *ctx; - WirelessRef wireless_ctx; - CFArrayRef scan_results; -}; - - -#ifndef CONFIG_NO_STDOUT_DEBUG -extern int wpa_debug_level; - -static void dump_dict_cb(const void *key, const void *value, void *context) -{ - if (MSG_DEBUG < wpa_debug_level) - return; - - wpa_printf(MSG_DEBUG, "Key:"); - CFShow(key); - wpa_printf(MSG_DEBUG, "Value:"); - CFShow(value); -} -#endif /* CONFIG_NO_STDOUT_DEBUG */ - - -static void wpa_driver_osx_dump_dict(CFDictionaryRef dict, const char *title) -{ -#ifndef CONFIG_NO_STDOUT_DEBUG - wpa_printf(MSG_DEBUG, "OSX: Dump dictionary %s - %u entries", - title, (unsigned int) CFDictionaryGetCount(dict)); - CFDictionaryApplyFunction(dict, dump_dict_cb, NULL); -#endif /* CONFIG_NO_STDOUT_DEBUG */ -} - - -static int wpa_driver_osx_get_ssid(void *priv, u8 *ssid) -{ - struct wpa_driver_osx_data *drv = priv; - WirelessError err; - WirelessInfo info; - int len; - - err = WirelessGetInfo(drv->wireless_ctx, &info); - if (err) { - wpa_printf(MSG_DEBUG, "OSX: WirelessGetInfo failed: %d", - (int) err); - return -1; - } - if (!info.power) { - wpa_printf(MSG_DEBUG, "OSX: Wireless device power off"); - return -1; - } - - for (len = 0; len < 32; len++) - if (info.ssid[len] == 0) - break; - - os_memcpy(ssid, info.ssid, len); - return len; -} - - -static int wpa_driver_osx_get_bssid(void *priv, u8 *bssid) -{ - struct wpa_driver_osx_data *drv = priv; - WirelessError err; - WirelessInfo info; - - err = WirelessGetInfo(drv->wireless_ctx, &info); - if (err) { - wpa_printf(MSG_DEBUG, "OSX: WirelessGetInfo failed: %d", - (int) err); - return -1; - } - if (!info.power) { - wpa_printf(MSG_DEBUG, "OSX: Wireless device power off"); - return -1; - } - - os_memcpy(bssid, info.bssID, ETH_ALEN); - return 0; -} - - -static void wpa_driver_osx_scan_timeout(void *eloop_ctx, void *timeout_ctx) -{ - wpa_supplicant_event(timeout_ctx, EVENT_SCAN_RESULTS, NULL); -} - - -static int wpa_driver_osx_scan(void *priv, struct wpa_driver_scan_params *params) -{ - struct wpa_driver_osx_data *drv = priv; - WirelessError err; - const u8 *ssid = params->ssids[0].ssid; - size_t ssid_len = params->ssids[0].ssid_len; - - if (drv->scan_results) { - CFRelease(drv->scan_results); - drv->scan_results = NULL; - } - - if (ssid) { - CFStringRef data; - data = CFStringCreateWithBytes(kCFAllocatorDefault, - ssid, ssid_len, - kCFStringEncodingISOLatin1, - FALSE); - if (data == NULL) { - wpa_printf(MSG_DEBUG, "CFStringCreateWithBytes " - "failed"); - return -1; - } - - err = WirelessDirectedScan(drv->wireless_ctx, - &drv->scan_results, 0, data); - CFRelease(data); - if (err) { - wpa_printf(MSG_DEBUG, "OSX: WirelessDirectedScan " - "failed: 0x%08x", (unsigned int) err); - return -1; - } - } else { - err = WirelessScan(drv->wireless_ctx, &drv->scan_results, 0); - if (err) { - wpa_printf(MSG_DEBUG, "OSX: WirelessScan failed: " - "0x%08x", (unsigned int) err); - return -1; - } - } - - eloop_register_timeout(0, 0, wpa_driver_osx_scan_timeout, drv, - drv->ctx); - return 0; -} - - -static void wpa_driver_osx_add_scan_entry(struct wpa_scan_results *res, - WirelessNetworkInfo *info) -{ - struct wpa_scan_res *result, **tmp; - size_t extra_len; - u8 *pos; - - extra_len = 2 + info->ssid_len; - - result = os_zalloc(sizeof(*result) + extra_len); - if (result == NULL) - return; - os_memcpy(result->bssid, info->bssid, ETH_ALEN); - result->freq = 2407 + info->channel * 5; - //result->beacon_int =; - result->caps = info->capability; - //result->qual = info->signal; - result->noise = info->noise; - - pos = (u8 *)(result + 1); - - *pos++ = WLAN_EID_SSID; - *pos++ = info->ssid_len; - os_memcpy(pos, info->ssid, info->ssid_len); - pos += info->ssid_len; - - result->ie_len = pos - (u8 *)(result + 1); - - tmp = os_realloc(res->res, - (res->num + 1) * sizeof(struct wpa_scan_res *)); - if (tmp == NULL) { - os_free(result); - return; - } - tmp[res->num++] = result; - res->res = tmp; -} - - -static struct wpa_scan_results * wpa_driver_osx_get_scan_results(void *priv) -{ - struct wpa_driver_osx_data *drv = priv; - struct wpa_scan_results *res; - size_t i, num; - - if (drv->scan_results == NULL) - return 0; - - num = CFArrayGetCount(drv->scan_results); - - res = os_zalloc(sizeof(*res)); - if (res == NULL) - return NULL; - - for (i = 0; i < num; i++) - wpa_driver_osx_add_scan_entry(res, (WirelessNetworkInfo *) - CFDataGetBytePtr(CFArrayGetValueAtIndex( - drv->scan_results, i))); - - return res; -} - - -static void wpa_driver_osx_assoc_timeout(void *eloop_ctx, void *timeout_ctx) -{ - struct wpa_driver_osx_data *drv = eloop_ctx; - u8 bssid[ETH_ALEN]; - CFDictionaryRef ai; - - if (wpa_driver_osx_get_bssid(drv, bssid) != 0) { - eloop_register_timeout(1, 0, wpa_driver_osx_assoc_timeout, - drv, drv->ctx); - return; - } - - ai = WirelessGetAssociationInfo(drv->wireless_ctx); - if (ai) { - wpa_driver_osx_dump_dict(ai, "WirelessGetAssociationInfo"); - CFRelease(ai); - } else { - wpa_printf(MSG_DEBUG, "OSX: Failed to get association info"); - } - - wpa_supplicant_event(timeout_ctx, EVENT_ASSOC, NULL); -} - - -static int wpa_driver_osx_associate(void *priv, - struct wpa_driver_associate_params *params) -{ - struct wpa_driver_osx_data *drv = priv; - WirelessError err; - CFDataRef ssid; - CFStringRef key; - int assoc_type; - - ssid = CFDataCreate(kCFAllocatorDefault, params->ssid, - params->ssid_len); - if (ssid == NULL) - return -1; - - /* TODO: support for WEP */ - if (params->key_mgmt_suite == KEY_MGMT_PSK) { - if (params->passphrase == NULL) - return -1; - key = CFStringCreateWithCString(kCFAllocatorDefault, - params->passphrase, - kCFStringEncodingISOLatin1); - if (key == NULL) { - CFRelease(ssid); - return -1; - } - } else - key = NULL; - - if (params->key_mgmt_suite == KEY_MGMT_NONE) - assoc_type = 0; - else - assoc_type = 4; - - wpa_printf(MSG_DEBUG, "OSX: WirelessAssociate(type=%d key=%p)", - assoc_type, key); - err = WirelessAssociate(drv->wireless_ctx, assoc_type, ssid, key); - CFRelease(ssid); - if (key) - CFRelease(key); - if (err) { - wpa_printf(MSG_DEBUG, "OSX: WirelessAssociate failed: 0x%08x", - (unsigned int) err); - return -1; - } - - /* - * Driver is actually already associated; report association from an - * eloop callback. - */ - eloop_cancel_timeout(wpa_driver_osx_assoc_timeout, drv, drv->ctx); - eloop_register_timeout(0, 0, wpa_driver_osx_assoc_timeout, drv, - drv->ctx); - - return 0; -} - - -static int wpa_driver_osx_set_key(const char *ifname, void *priv, - enum wpa_alg alg, const u8 *addr, - int key_idx, int set_tx, const u8 *seq, - size_t seq_len, const u8 *key, - size_t key_len) -{ - struct wpa_driver_osx_data *drv = priv; - WirelessError err; - - if (alg == WPA_ALG_WEP) { - err = WirelessSetKey(drv->wireless_ctx, 1, key_idx, key_len, - key); - if (err != 0) { - wpa_printf(MSG_DEBUG, "OSX: WirelessSetKey failed: " - "0x%08x", (unsigned int) err); - return -1; - } - - return 0; - } - - if (alg == WPA_ALG_PMK) { - err = WirelessSetWPAKey(drv->wireless_ctx, 1, key_len, key); - if (err != 0) { - wpa_printf(MSG_DEBUG, "OSX: WirelessSetWPAKey failed: " - "0x%08x", (unsigned int) err); - return -1; - } - return 0; - } - - wpa_printf(MSG_DEBUG, "OSX: Unsupported set_key alg %d", alg); - return -1; -} - - -static int wpa_driver_osx_get_capa(void *priv, struct wpa_driver_capa *capa) -{ - os_memset(capa, 0, sizeof(*capa)); - - capa->key_mgmt = WPA_DRIVER_CAPA_KEY_MGMT_WPA | - WPA_DRIVER_CAPA_KEY_MGMT_WPA2 | - WPA_DRIVER_CAPA_KEY_MGMT_WPA_PSK | - WPA_DRIVER_CAPA_KEY_MGMT_WPA2_PSK; - capa->enc = WPA_DRIVER_CAPA_ENC_WEP40 | WPA_DRIVER_CAPA_ENC_WEP104 | - WPA_DRIVER_CAPA_ENC_TKIP | WPA_DRIVER_CAPA_ENC_CCMP; - capa->auth = WPA_DRIVER_AUTH_OPEN | WPA_DRIVER_AUTH_SHARED | - WPA_DRIVER_AUTH_LEAP; - capa->flags = WPA_DRIVER_FLAGS_4WAY_HANDSHAKE; - - return 0; -} - - -static void * wpa_driver_osx_init(void *ctx, const char *ifname) -{ - struct wpa_driver_osx_data *drv; - WirelessError err; - u8 enabled, power; - - if (!WirelessIsAvailable()) { - wpa_printf(MSG_ERROR, "OSX: No wireless interface available"); - return NULL; - } - - drv = os_zalloc(sizeof(*drv)); - if (drv == NULL) - return NULL; - drv->ctx = ctx; - err = WirelessAttach(&drv->wireless_ctx, 0); - if (err) { - wpa_printf(MSG_ERROR, "OSX: WirelessAttach failed: %d", - (int) err); - os_free(drv); - return NULL; - } - - err = WirelessGetEnabled(drv->wireless_ctx, &enabled); - if (err) - wpa_printf(MSG_DEBUG, "OSX: WirelessGetEnabled failed: 0x%08x", - (unsigned int) err); - err = WirelessGetPower(drv->wireless_ctx, &power); - if (err) - wpa_printf(MSG_DEBUG, "OSX: WirelessGetPower failed: 0x%08x", - (unsigned int) err); - - wpa_printf(MSG_DEBUG, "OSX: Enabled=%d Power=%d", enabled, power); - - if (!enabled) { - err = WirelessSetEnabled(drv->wireless_ctx, 1); - if (err) { - wpa_printf(MSG_DEBUG, "OSX: WirelessSetEnabled failed:" - " 0x%08x", (unsigned int) err); - WirelessDetach(drv->wireless_ctx); - os_free(drv); - return NULL; - } - } - - if (!power) { - err = WirelessSetPower(drv->wireless_ctx, 1); - if (err) { - wpa_printf(MSG_DEBUG, "OSX: WirelessSetPower failed: " - "0x%08x", (unsigned int) err); - WirelessDetach(drv->wireless_ctx); - os_free(drv); - return NULL; - } - } - - return drv; -} - - -static void wpa_driver_osx_deinit(void *priv) -{ - struct wpa_driver_osx_data *drv = priv; - WirelessError err; - - eloop_cancel_timeout(wpa_driver_osx_scan_timeout, drv, drv->ctx); - eloop_cancel_timeout(wpa_driver_osx_assoc_timeout, drv, drv->ctx); - - err = WirelessSetPower(drv->wireless_ctx, 0); - if (err) { - wpa_printf(MSG_DEBUG, "OSX: WirelessSetPower(0) failed: " - "0x%08x", (unsigned int) err); - } - - err = WirelessDetach(drv->wireless_ctx); - if (err) { - wpa_printf(MSG_DEBUG, "OSX: WirelessDetach failed: 0x%08x", - (unsigned int) err); - } - - if (drv->scan_results) - CFRelease(drv->scan_results); - - os_free(drv); -} - - -const struct wpa_driver_ops wpa_driver_osx_ops = { - .name = "osx", - .desc = "Mac OS X Apple80211 driver", - .get_ssid = wpa_driver_osx_get_ssid, - .get_bssid = wpa_driver_osx_get_bssid, - .init = wpa_driver_osx_init, - .deinit = wpa_driver_osx_deinit, - .scan2 = wpa_driver_osx_scan, - .get_scan_results2 = wpa_driver_osx_get_scan_results, - .associate = wpa_driver_osx_associate, - .set_key = wpa_driver_osx_set_key, - .get_capa = wpa_driver_osx_get_capa, -}; diff --git a/hostapd-0.8/src/drivers/driver_privsep.c b/hostapd-0.8/src/drivers/driver_privsep.c deleted file mode 100644 index 2848521..0000000 --- a/hostapd-0.8/src/drivers/driver_privsep.c +++ /dev/null @@ -1,758 +0,0 @@ -/* - * WPA Supplicant - privilege separated driver interface - * Copyright (c) 2007-2009, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#include "includes.h" -#include - -#include "common.h" -#include "driver.h" -#include "eloop.h" -#include "common/privsep_commands.h" - - -struct wpa_driver_privsep_data { - void *ctx; - u8 own_addr[ETH_ALEN]; - int priv_socket; - char *own_socket_path; - int cmd_socket; - char *own_cmd_path; - struct sockaddr_un priv_addr; - char ifname[16]; -}; - - -static int wpa_priv_reg_cmd(struct wpa_driver_privsep_data *drv, int cmd) -{ - int res; - - res = sendto(drv->priv_socket, &cmd, sizeof(cmd), 0, - (struct sockaddr *) &drv->priv_addr, - sizeof(drv->priv_addr)); - if (res < 0) - perror("sendto"); - return res < 0 ? -1 : 0; -} - - -static int wpa_priv_cmd(struct wpa_driver_privsep_data *drv, int cmd, - const void *data, size_t data_len, - void *reply, size_t *reply_len) -{ - struct msghdr msg; - struct iovec io[2]; - - io[0].iov_base = &cmd; - io[0].iov_len = sizeof(cmd); - io[1].iov_base = (u8 *) data; - io[1].iov_len = data_len; - - os_memset(&msg, 0, sizeof(msg)); - msg.msg_iov = io; - msg.msg_iovlen = data ? 2 : 1; - msg.msg_name = &drv->priv_addr; - msg.msg_namelen = sizeof(drv->priv_addr); - - if (sendmsg(drv->cmd_socket, &msg, 0) < 0) { - perror("sendmsg(cmd_socket)"); - return -1; - } - - if (reply) { - fd_set rfds; - struct timeval tv; - int res; - - FD_ZERO(&rfds); - FD_SET(drv->cmd_socket, &rfds); - tv.tv_sec = 5; - tv.tv_usec = 0; - res = select(drv->cmd_socket + 1, &rfds, NULL, NULL, &tv); - if (res < 0 && errno != EINTR) { - perror("select"); - return -1; - } - - if (FD_ISSET(drv->cmd_socket, &rfds)) { - res = recv(drv->cmd_socket, reply, *reply_len, 0); - if (res < 0) { - perror("recv"); - return -1; - } - *reply_len = res; - } else { - wpa_printf(MSG_DEBUG, "PRIVSEP: Timeout while waiting " - "for reply (cmd=%d)", cmd); - return -1; - } - } - - return 0; -} - - -static int wpa_driver_privsep_scan(void *priv, - struct wpa_driver_scan_params *params) -{ - struct wpa_driver_privsep_data *drv = priv; - const u8 *ssid = params->ssids[0].ssid; - size_t ssid_len = params->ssids[0].ssid_len; - wpa_printf(MSG_DEBUG, "%s: priv=%p", __func__, priv); - return wpa_priv_cmd(drv, PRIVSEP_CMD_SCAN, ssid, ssid_len, - NULL, NULL); -} - - -static struct wpa_scan_results * -wpa_driver_privsep_get_scan_results2(void *priv) -{ - struct wpa_driver_privsep_data *drv = priv; - int res, num; - u8 *buf, *pos, *end; - size_t reply_len = 60000; - struct wpa_scan_results *results; - struct wpa_scan_res *r; - - buf = os_malloc(reply_len); - if (buf == NULL) - return NULL; - res = wpa_priv_cmd(drv, PRIVSEP_CMD_GET_SCAN_RESULTS, - NULL, 0, buf, &reply_len); - if (res < 0) { - os_free(buf); - return NULL; - } - - wpa_printf(MSG_DEBUG, "privsep: Received %lu bytes of scan results", - (unsigned long) reply_len); - if (reply_len < sizeof(int)) { - wpa_printf(MSG_DEBUG, "privsep: Invalid scan result len %lu", - (unsigned long) reply_len); - os_free(buf); - return NULL; - } - - pos = buf; - end = buf + reply_len; - os_memcpy(&num, pos, sizeof(int)); - if (num < 0 || num > 1000) { - os_free(buf); - return NULL; - } - pos += sizeof(int); - - results = os_zalloc(sizeof(*results)); - if (results == NULL) { - os_free(buf); - return NULL; - } - - results->res = os_zalloc(num * sizeof(struct wpa_scan_res *)); - if (results->res == NULL) { - os_free(results); - os_free(buf); - return NULL; - } - - while (results->num < (size_t) num && pos + sizeof(int) < end) { - int len; - os_memcpy(&len, pos, sizeof(int)); - pos += sizeof(int); - if (len < 0 || len > 10000 || pos + len > end) - break; - - r = os_malloc(len); - if (r == NULL) - break; - os_memcpy(r, pos, len); - pos += len; - if (sizeof(*r) + r->ie_len > (size_t) len) { - os_free(r); - break; - } - - results->res[results->num++] = r; - } - - os_free(buf); - return results; -} - - -static int wpa_driver_privsep_set_key(const char *ifname, void *priv, - enum wpa_alg alg, const u8 *addr, - int key_idx, int set_tx, - const u8 *seq, size_t seq_len, - const u8 *key, size_t key_len) -{ - struct wpa_driver_privsep_data *drv = priv; - struct privsep_cmd_set_key cmd; - - wpa_printf(MSG_DEBUG, "%s: priv=%p alg=%d key_idx=%d set_tx=%d", - __func__, priv, alg, key_idx, set_tx); - - os_memset(&cmd, 0, sizeof(cmd)); - cmd.alg = alg; - if (addr) - os_memcpy(cmd.addr, addr, ETH_ALEN); - else - os_memset(cmd.addr, 0xff, ETH_ALEN); - cmd.key_idx = key_idx; - cmd.set_tx = set_tx; - if (seq && seq_len > 0 && seq_len < sizeof(cmd.seq)) { - os_memcpy(cmd.seq, seq, seq_len); - cmd.seq_len = seq_len; - } - if (key && key_len > 0 && key_len < sizeof(cmd.key)) { - os_memcpy(cmd.key, key, key_len); - cmd.key_len = key_len; - } - - return wpa_priv_cmd(drv, PRIVSEP_CMD_SET_KEY, &cmd, sizeof(cmd), - NULL, NULL); -} - - -static int wpa_driver_privsep_associate( - void *priv, struct wpa_driver_associate_params *params) -{ - struct wpa_driver_privsep_data *drv = priv; - struct privsep_cmd_associate *data; - int res; - size_t buflen; - - wpa_printf(MSG_DEBUG, "%s: priv=%p freq=%d pairwise_suite=%d " - "group_suite=%d key_mgmt_suite=%d auth_alg=%d mode=%d", - __func__, priv, params->freq, params->pairwise_suite, - params->group_suite, params->key_mgmt_suite, - params->auth_alg, params->mode); - - buflen = sizeof(*data) + params->wpa_ie_len; - data = os_zalloc(buflen); - if (data == NULL) - return -1; - - if (params->bssid) - os_memcpy(data->bssid, params->bssid, ETH_ALEN); - os_memcpy(data->ssid, params->ssid, params->ssid_len); - data->ssid_len = params->ssid_len; - data->freq = params->freq; - data->pairwise_suite = params->pairwise_suite; - data->group_suite = params->group_suite; - data->key_mgmt_suite = params->key_mgmt_suite; - data->auth_alg = params->auth_alg; - data->mode = params->mode; - data->wpa_ie_len = params->wpa_ie_len; - if (params->wpa_ie) - os_memcpy(data + 1, params->wpa_ie, params->wpa_ie_len); - /* TODO: add support for other assoc parameters */ - - res = wpa_priv_cmd(drv, PRIVSEP_CMD_ASSOCIATE, data, buflen, - NULL, NULL); - os_free(data); - - return res; -} - - -static int wpa_driver_privsep_get_bssid(void *priv, u8 *bssid) -{ - struct wpa_driver_privsep_data *drv = priv; - int res; - size_t len = ETH_ALEN; - - res = wpa_priv_cmd(drv, PRIVSEP_CMD_GET_BSSID, NULL, 0, bssid, &len); - if (res < 0 || len != ETH_ALEN) - return -1; - return 0; -} - - -static int wpa_driver_privsep_get_ssid(void *priv, u8 *ssid) -{ - struct wpa_driver_privsep_data *drv = priv; - int res, ssid_len; - u8 reply[sizeof(int) + 32]; - size_t len = sizeof(reply); - - res = wpa_priv_cmd(drv, PRIVSEP_CMD_GET_SSID, NULL, 0, reply, &len); - if (res < 0 || len < sizeof(int)) - return -1; - os_memcpy(&ssid_len, reply, sizeof(int)); - if (ssid_len < 0 || ssid_len > 32 || sizeof(int) + ssid_len > len) { - wpa_printf(MSG_DEBUG, "privsep: Invalid get SSID reply"); - return -1; - } - os_memcpy(ssid, &reply[sizeof(int)], ssid_len); - return ssid_len; -} - - -static int wpa_driver_privsep_deauthenticate(void *priv, const u8 *addr, - int reason_code) -{ - //struct wpa_driver_privsep_data *drv = priv; - wpa_printf(MSG_DEBUG, "%s addr=" MACSTR " reason_code=%d", - __func__, MAC2STR(addr), reason_code); - wpa_printf(MSG_DEBUG, "%s - TODO", __func__); - return 0; -} - - -static int wpa_driver_privsep_disassociate(void *priv, const u8 *addr, - int reason_code) -{ - //struct wpa_driver_privsep_data *drv = priv; - wpa_printf(MSG_DEBUG, "%s addr=" MACSTR " reason_code=%d", - __func__, MAC2STR(addr), reason_code); - wpa_printf(MSG_DEBUG, "%s - TODO", __func__); - return 0; -} - - -static void wpa_driver_privsep_event_assoc(void *ctx, - enum wpa_event_type event, - u8 *buf, size_t len) -{ - union wpa_event_data data; - int inc_data = 0; - u8 *pos, *end; - int ie_len; - - os_memset(&data, 0, sizeof(data)); - - pos = buf; - end = buf + len; - - if (end - pos < (int) sizeof(int)) - return; - os_memcpy(&ie_len, pos, sizeof(int)); - pos += sizeof(int); - if (ie_len < 0 || ie_len > end - pos) - return; - if (ie_len) { - data.assoc_info.req_ies = pos; - data.assoc_info.req_ies_len = ie_len; - pos += ie_len; - inc_data = 1; - } - - wpa_supplicant_event(ctx, event, inc_data ? &data : NULL); -} - - -static void wpa_driver_privsep_event_interface_status(void *ctx, u8 *buf, - size_t len) -{ - union wpa_event_data data; - int ievent; - - if (len < sizeof(int) || - len - sizeof(int) > sizeof(data.interface_status.ifname)) - return; - - os_memcpy(&ievent, buf, sizeof(int)); - - os_memset(&data, 0, sizeof(data)); - data.interface_status.ievent = ievent; - os_memcpy(data.interface_status.ifname, buf + sizeof(int), - len - sizeof(int)); - wpa_supplicant_event(ctx, EVENT_INTERFACE_STATUS, &data); -} - - -static void wpa_driver_privsep_event_michael_mic_failure( - void *ctx, u8 *buf, size_t len) -{ - union wpa_event_data data; - - if (len != sizeof(int)) - return; - - os_memset(&data, 0, sizeof(data)); - os_memcpy(&data.michael_mic_failure.unicast, buf, sizeof(int)); - wpa_supplicant_event(ctx, EVENT_MICHAEL_MIC_FAILURE, &data); -} - - -static void wpa_driver_privsep_event_pmkid_candidate(void *ctx, u8 *buf, - size_t len) -{ - union wpa_event_data data; - - if (len != sizeof(struct pmkid_candidate)) - return; - - os_memset(&data, 0, sizeof(data)); - os_memcpy(&data.pmkid_candidate, buf, len); - wpa_supplicant_event(ctx, EVENT_PMKID_CANDIDATE, &data); -} - - -static void wpa_driver_privsep_event_stkstart(void *ctx, u8 *buf, size_t len) -{ - union wpa_event_data data; - - if (len != ETH_ALEN) - return; - - os_memset(&data, 0, sizeof(data)); - os_memcpy(data.stkstart.peer, buf, ETH_ALEN); - wpa_supplicant_event(ctx, EVENT_STKSTART, &data); -} - - -static void wpa_driver_privsep_event_ft_response(void *ctx, u8 *buf, - size_t len) -{ - union wpa_event_data data; - - if (len < sizeof(int) + ETH_ALEN) - return; - - os_memset(&data, 0, sizeof(data)); - os_memcpy(&data.ft_ies.ft_action, buf, sizeof(int)); - os_memcpy(data.ft_ies.target_ap, buf + sizeof(int), ETH_ALEN); - data.ft_ies.ies = buf + sizeof(int) + ETH_ALEN; - data.ft_ies.ies_len = len - sizeof(int) - ETH_ALEN; - wpa_supplicant_event(ctx, EVENT_FT_RESPONSE, &data); -} - - -static void wpa_driver_privsep_event_rx_eapol(void *ctx, u8 *buf, size_t len) -{ - if (len < ETH_ALEN) - return; - drv_event_eapol_rx(ctx, buf, buf + ETH_ALEN, len - ETH_ALEN); -} - - -static void wpa_driver_privsep_receive(int sock, void *eloop_ctx, - void *sock_ctx) -{ - struct wpa_driver_privsep_data *drv = eloop_ctx; - u8 *buf, *event_buf; - size_t event_len; - int res, event; - enum privsep_event e; - struct sockaddr_un from; - socklen_t fromlen = sizeof(from); - const size_t buflen = 2000; - - buf = os_malloc(buflen); - if (buf == NULL) - return; - res = recvfrom(sock, buf, buflen, 0, - (struct sockaddr *) &from, &fromlen); - if (res < 0) { - perror("recvfrom(priv_socket)"); - os_free(buf); - return; - } - - wpa_printf(MSG_DEBUG, "privsep_driver: received %u bytes", res); - - if (res < (int) sizeof(int)) { - wpa_printf(MSG_DEBUG, "Too short event message (len=%d)", res); - return; - } - - os_memcpy(&event, buf, sizeof(int)); - event_buf = &buf[sizeof(int)]; - event_len = res - sizeof(int); - wpa_printf(MSG_DEBUG, "privsep: Event %d received (len=%lu)", - event, (unsigned long) event_len); - - e = event; - switch (e) { - case PRIVSEP_EVENT_SCAN_RESULTS: - wpa_supplicant_event(drv->ctx, EVENT_SCAN_RESULTS, NULL); - break; - case PRIVSEP_EVENT_ASSOC: - wpa_driver_privsep_event_assoc(drv->ctx, EVENT_ASSOC, - event_buf, event_len); - break; - case PRIVSEP_EVENT_DISASSOC: - wpa_supplicant_event(drv->ctx, EVENT_DISASSOC, NULL); - break; - case PRIVSEP_EVENT_ASSOCINFO: - wpa_driver_privsep_event_assoc(drv->ctx, EVENT_ASSOCINFO, - event_buf, event_len); - break; - case PRIVSEP_EVENT_MICHAEL_MIC_FAILURE: - wpa_driver_privsep_event_michael_mic_failure( - drv->ctx, event_buf, event_len); - break; - case PRIVSEP_EVENT_INTERFACE_STATUS: - wpa_driver_privsep_event_interface_status(drv->ctx, event_buf, - event_len); - break; - case PRIVSEP_EVENT_PMKID_CANDIDATE: - wpa_driver_privsep_event_pmkid_candidate(drv->ctx, event_buf, - event_len); - break; - case PRIVSEP_EVENT_STKSTART: - wpa_driver_privsep_event_stkstart(drv->ctx, event_buf, - event_len); - break; - case PRIVSEP_EVENT_FT_RESPONSE: - wpa_driver_privsep_event_ft_response(drv->ctx, event_buf, - event_len); - break; - case PRIVSEP_EVENT_RX_EAPOL: - wpa_driver_privsep_event_rx_eapol(drv->ctx, event_buf, - event_len); - break; - } - - os_free(buf); -} - - -static void * wpa_driver_privsep_init(void *ctx, const char *ifname) -{ - struct wpa_driver_privsep_data *drv; - - drv = os_zalloc(sizeof(*drv)); - if (drv == NULL) - return NULL; - drv->ctx = ctx; - drv->priv_socket = -1; - drv->cmd_socket = -1; - os_strlcpy(drv->ifname, ifname, sizeof(drv->ifname)); - - return drv; -} - - -static void wpa_driver_privsep_deinit(void *priv) -{ - struct wpa_driver_privsep_data *drv = priv; - - if (drv->priv_socket >= 0) { - wpa_priv_reg_cmd(drv, PRIVSEP_CMD_UNREGISTER); - eloop_unregister_read_sock(drv->priv_socket); - close(drv->priv_socket); - } - - if (drv->own_socket_path) { - unlink(drv->own_socket_path); - os_free(drv->own_socket_path); - } - - if (drv->cmd_socket >= 0) { - eloop_unregister_read_sock(drv->cmd_socket); - close(drv->cmd_socket); - } - - if (drv->own_cmd_path) { - unlink(drv->own_cmd_path); - os_free(drv->own_cmd_path); - } - - os_free(drv); -} - - -static int wpa_driver_privsep_set_param(void *priv, const char *param) -{ - struct wpa_driver_privsep_data *drv = priv; - const char *pos; - char *own_dir, *priv_dir; - static unsigned int counter = 0; - size_t len; - struct sockaddr_un addr; - - wpa_printf(MSG_DEBUG, "%s: param='%s'", __func__, param); - if (param == NULL) - pos = NULL; - else - pos = os_strstr(param, "own_dir="); - if (pos) { - char *end; - own_dir = os_strdup(pos + 8); - if (own_dir == NULL) - return -1; - end = os_strchr(own_dir, ' '); - if (end) - *end = '\0'; - } else { - own_dir = os_strdup("/tmp"); - if (own_dir == NULL) - return -1; - } - - if (param == NULL) - pos = NULL; - else - pos = os_strstr(param, "priv_dir="); - if (pos) { - char *end; - priv_dir = os_strdup(pos + 9); - if (priv_dir == NULL) { - os_free(own_dir); - return -1; - } - end = os_strchr(priv_dir, ' '); - if (end) - *end = '\0'; - } else { - priv_dir = os_strdup("/var/run/wpa_priv"); - if (priv_dir == NULL) { - os_free(own_dir); - return -1; - } - } - - len = os_strlen(own_dir) + 50; - drv->own_socket_path = os_malloc(len); - if (drv->own_socket_path == NULL) { - os_free(priv_dir); - os_free(own_dir); - return -1; - } - os_snprintf(drv->own_socket_path, len, "%s/wpa_privsep-%d-%d", - own_dir, getpid(), counter++); - - len = os_strlen(own_dir) + 50; - drv->own_cmd_path = os_malloc(len); - if (drv->own_cmd_path == NULL) { - os_free(drv->own_socket_path); - drv->own_socket_path = NULL; - os_free(priv_dir); - os_free(own_dir); - return -1; - } - os_snprintf(drv->own_cmd_path, len, "%s/wpa_privsep-%d-%d", - own_dir, getpid(), counter++); - - os_free(own_dir); - - drv->priv_addr.sun_family = AF_UNIX; - os_snprintf(drv->priv_addr.sun_path, sizeof(drv->priv_addr.sun_path), - "%s/%s", priv_dir, drv->ifname); - os_free(priv_dir); - - drv->priv_socket = socket(PF_UNIX, SOCK_DGRAM, 0); - if (drv->priv_socket < 0) { - perror("socket(PF_UNIX)"); - os_free(drv->own_socket_path); - drv->own_socket_path = NULL; - return -1; - } - - os_memset(&addr, 0, sizeof(addr)); - addr.sun_family = AF_UNIX; - os_strlcpy(addr.sun_path, drv->own_socket_path, sizeof(addr.sun_path)); - if (bind(drv->priv_socket, (struct sockaddr *) &addr, sizeof(addr)) < - 0) { - perror("bind(PF_UNIX)"); - close(drv->priv_socket); - drv->priv_socket = -1; - unlink(drv->own_socket_path); - os_free(drv->own_socket_path); - drv->own_socket_path = NULL; - return -1; - } - - eloop_register_read_sock(drv->priv_socket, wpa_driver_privsep_receive, - drv, NULL); - - drv->cmd_socket = socket(PF_UNIX, SOCK_DGRAM, 0); - if (drv->cmd_socket < 0) { - perror("socket(PF_UNIX)"); - os_free(drv->own_cmd_path); - drv->own_cmd_path = NULL; - return -1; - } - - os_memset(&addr, 0, sizeof(addr)); - addr.sun_family = AF_UNIX; - os_strlcpy(addr.sun_path, drv->own_cmd_path, sizeof(addr.sun_path)); - if (bind(drv->cmd_socket, (struct sockaddr *) &addr, sizeof(addr)) < 0) - { - perror("bind(PF_UNIX)"); - close(drv->cmd_socket); - drv->cmd_socket = -1; - unlink(drv->own_cmd_path); - os_free(drv->own_cmd_path); - drv->own_cmd_path = NULL; - return -1; - } - - if (wpa_priv_reg_cmd(drv, PRIVSEP_CMD_REGISTER) < 0) { - wpa_printf(MSG_ERROR, "Failed to register with wpa_priv"); - return -1; - } - - return 0; -} - - -static int wpa_driver_privsep_get_capa(void *priv, - struct wpa_driver_capa *capa) -{ - struct wpa_driver_privsep_data *drv = priv; - int res; - size_t len = sizeof(*capa); - - res = wpa_priv_cmd(drv, PRIVSEP_CMD_GET_CAPA, NULL, 0, capa, &len); - if (res < 0 || len != sizeof(*capa)) - return -1; - return 0; -} - - -static const u8 * wpa_driver_privsep_get_mac_addr(void *priv) -{ - struct wpa_driver_privsep_data *drv = priv; - wpa_printf(MSG_DEBUG, "%s", __func__); - return drv->own_addr; -} - - -static int wpa_driver_privsep_set_country(void *priv, const char *alpha2) -{ - struct wpa_driver_privsep_data *drv = priv; - wpa_printf(MSG_DEBUG, "%s country='%s'", __func__, alpha2); - return wpa_priv_cmd(drv, PRIVSEP_CMD_SET_COUNTRY, alpha2, - os_strlen(alpha2), NULL, NULL); -} - - -struct wpa_driver_ops wpa_driver_privsep_ops = { - "privsep", - "wpa_supplicant privilege separated driver", - .get_bssid = wpa_driver_privsep_get_bssid, - .get_ssid = wpa_driver_privsep_get_ssid, - .set_key = wpa_driver_privsep_set_key, - .init = wpa_driver_privsep_init, - .deinit = wpa_driver_privsep_deinit, - .set_param = wpa_driver_privsep_set_param, - .scan2 = wpa_driver_privsep_scan, - .deauthenticate = wpa_driver_privsep_deauthenticate, - .disassociate = wpa_driver_privsep_disassociate, - .associate = wpa_driver_privsep_associate, - .get_capa = wpa_driver_privsep_get_capa, - .get_mac_addr = wpa_driver_privsep_get_mac_addr, - .get_scan_results2 = wpa_driver_privsep_get_scan_results2, - .set_country = wpa_driver_privsep_set_country, -}; - - -struct wpa_driver_ops *wpa_drivers[] = -{ - &wpa_driver_privsep_ops, - NULL -}; diff --git a/hostapd-0.8/src/drivers/driver_ralink.c b/hostapd-0.8/src/drivers/driver_ralink.c deleted file mode 100644 index a1e27be..0000000 --- a/hostapd-0.8/src/drivers/driver_ralink.c +++ /dev/null @@ -1,1498 +0,0 @@ -/* - * WPA Supplicant - driver interaction with Ralink Wireless Client - * Copyright (c) 2003-2006, Jouni Malinen - * Copyright (c) 2007, Snowpin Lee - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - * - */ - -#include "includes.h" -#include - -#include "wireless_copy.h" -#include "common.h" -#include "driver.h" -#include "l2_packet/l2_packet.h" -#include "eloop.h" -#include "common/ieee802_11_defs.h" -#include "priv_netlink.h" -#include "netlink.h" -#include "linux_ioctl.h" -#include "driver_ralink.h" - -static void wpa_driver_ralink_scan_timeout(void *eloop_ctx, void *timeout_ctx); - -#define MAX_SSID_LEN 32 - -struct wpa_driver_ralink_data { - void *ctx; - int ioctl_sock; - struct netlink_data *netlink; - char ifname[IFNAMSIZ + 1]; - u8 *assoc_req_ies; - size_t assoc_req_ies_len; - u8 *assoc_resp_ies; - size_t assoc_resp_ies_len; - int no_of_pmkid; - struct ndis_pmkid_entry *pmkid; - int we_version_compiled; - int ap_scan; - int scanning_done; - u8 g_driver_down; - BOOLEAN bAddWepKey; -}; - -static int ralink_set_oid(struct wpa_driver_ralink_data *drv, - unsigned short oid, char *data, int len) -{ - char *buf; - struct iwreq iwr; - - buf = os_zalloc(len); - if (buf == NULL) - return -1; - os_memset(&iwr, 0, sizeof(iwr)); - os_strlcpy(iwr.ifr_name, drv->ifname, IFNAMSIZ); - iwr.u.data.flags = oid; - iwr.u.data.flags |= OID_GET_SET_TOGGLE; - - if (data) - os_memcpy(buf, data, len); - - iwr.u.data.pointer = (caddr_t) buf; - iwr.u.data.length = len; - - if (ioctl(drv->ioctl_sock, RT_PRIV_IOCTL, &iwr) < 0) { - wpa_printf(MSG_DEBUG, "%s: oid=0x%x len (%d) failed", - __func__, oid, len); - os_free(buf); - return -1; - } - os_free(buf); - return 0; -} - -static int -ralink_get_new_driver_flag(struct wpa_driver_ralink_data *drv) -{ - struct iwreq iwr; - UCHAR enabled = 0; - - os_memset(&iwr, 0, sizeof(iwr)); - os_strlcpy(iwr.ifr_name, drv->ifname, IFNAMSIZ); - iwr.u.data.pointer = (UCHAR*) &enabled; - iwr.u.data.flags = RT_OID_NEW_DRIVER; - - if (ioctl(drv->ioctl_sock, RT_PRIV_IOCTL, &iwr) < 0) { - wpa_printf(MSG_DEBUG, "%s: failed", __func__); - return 0; - } - - return (enabled == 1) ? 1 : 0; -} - -static int wpa_driver_ralink_get_bssid(void *priv, u8 *bssid) -{ - struct wpa_driver_ralink_data *drv = priv; - struct iwreq iwr; - int ret = 0; - - if (drv->g_driver_down == 1) - return -1; - - wpa_printf(MSG_DEBUG, "%s", __FUNCTION__); - - os_memset(&iwr, 0, sizeof(iwr)); - os_strlcpy(iwr.ifr_name, drv->ifname, IFNAMSIZ); - - if (ioctl(drv->ioctl_sock, SIOCGIWAP, &iwr) < 0) { - perror("ioctl[SIOCGIWAP]"); - ret = -1; - } - os_memcpy(bssid, iwr.u.ap_addr.sa_data, ETH_ALEN); - - return ret; -} - -static int wpa_driver_ralink_get_ssid(void *priv, u8 *ssid) -{ - struct wpa_driver_ralink_data *drv = priv; -#if 0 - struct wpa_supplicant *wpa_s = drv->ctx; - struct wpa_ssid *entry; -#endif - int ssid_len; - u8 bssid[ETH_ALEN]; - u8 ssid_str[MAX_SSID_LEN]; - struct iwreq iwr; -#if 0 - int result = 0; -#endif - int ret = 0; -#if 0 - BOOLEAN ieee8021x_mode = FALSE; - BOOLEAN ieee8021x_required_key = FALSE; -#endif - - if (drv->g_driver_down == 1) - return -1; - - wpa_printf(MSG_DEBUG, "%s", __FUNCTION__); - - os_memset(&iwr, 0, sizeof(iwr)); - os_strlcpy(iwr.ifr_name, drv->ifname, IFNAMSIZ); - iwr.u.essid.pointer = (caddr_t) ssid; - iwr.u.essid.length = 32; - - if (ioctl(drv->ioctl_sock, SIOCGIWESSID, &iwr) < 0) { - perror("ioctl[SIOCGIWESSID]"); - ret = -1; - } else - ret = iwr.u.essid.length; - - if (ret <= 0) - return ret; - - ssid_len = ret; - os_memset(ssid_str, 0, MAX_SSID_LEN); - os_memcpy(ssid_str, ssid, ssid_len); - - if (drv->ap_scan == 0) { - /* Read BSSID form driver */ - if (wpa_driver_ralink_get_bssid(priv, bssid) < 0) { - wpa_printf(MSG_WARNING, "Could not read BSSID from " - "driver."); - return ret; - } - -#if 0 - entry = wpa_s->conf->ssid; - while (entry) { - if (!entry->disabled && ssid_len == entry->ssid_len && - os_memcmp(ssid_str, entry->ssid, ssid_len) == 0 && - (!entry->bssid_set || - os_memcmp(bssid, entry->bssid, ETH_ALEN) == 0)) { - /* match the config of driver */ - result = 1; - break; - } - entry = entry->next; - } - - if (result) { - wpa_printf(MSG_DEBUG, "Ready to set 802.1x mode and " - "ieee_required_keys parameters to driver"); - - /* set 802.1x mode and ieee_required_keys parameter */ - if (entry->key_mgmt == WPA_KEY_MGMT_IEEE8021X_NO_WPA) { - if ((entry->eapol_flags & (EAPOL_FLAG_REQUIRE_KEY_UNICAST | EAPOL_FLAG_REQUIRE_KEY_BROADCAST))) - ieee8021x_required_key = TRUE; - ieee8021x_mode = TRUE; - } - - if (ralink_set_oid(drv, OID_802_11_SET_IEEE8021X, (char *) &ieee8021x_mode, sizeof(BOOLEAN)) < 0) - { - wpa_printf(MSG_DEBUG, "RALINK: Failed to set OID_802_11_SET_IEEE8021X(%d)", (int) ieee8021x_mode); - } - else - { - wpa_printf(MSG_DEBUG, "ieee8021x_mode is %s", ieee8021x_mode ? "TRUE" : "FALSE"); - } - - if (ralink_set_oid(drv, OID_802_11_SET_IEEE8021X_REQUIRE_KEY, (char *) &ieee8021x_required_key, sizeof(BOOLEAN)) < 0) - { - wpa_printf(MSG_DEBUG, "ERROR: Failed to set OID_802_11_SET_IEEE8021X_REQUIRE_KEY(%d)", (int) ieee8021x_required_key); - } - else - { - wpa_printf(MSG_DEBUG, "ieee8021x_required_key is %s and eapol_flag(%d)", ieee8021x_required_key ? "TRUE" : "FALSE", - entry->eapol_flags); - } - } -#endif - } - - return ret; -} - -static int wpa_driver_ralink_set_ssid(struct wpa_driver_ralink_data *drv, - const u8 *ssid, size_t ssid_len) -{ - NDIS_802_11_SSID *buf; - int ret = 0; - struct iwreq iwr; - - wpa_printf(MSG_DEBUG, "%s", __FUNCTION__); - - buf = os_zalloc(sizeof(NDIS_802_11_SSID)); - if (buf == NULL) - return -1; - os_memset(buf, 0, sizeof(buf)); - buf->SsidLength = ssid_len; - os_memcpy(buf->Ssid, ssid, ssid_len); - os_memset(&iwr, 0, sizeof(iwr)); - os_strlcpy(iwr.ifr_name, drv->ifname, IFNAMSIZ); - - iwr.u.data.flags = OID_802_11_SSID; - iwr.u.data.flags |= OID_GET_SET_TOGGLE; - iwr.u.data.pointer = (caddr_t) buf; - iwr.u.data.length = sizeof(NDIS_802_11_SSID); - - if (ioctl(drv->ioctl_sock, RT_PRIV_IOCTL, &iwr) < 0) { - perror("ioctl[RT_PRIV_IOCTL] -- OID_802_11_SSID"); - ret = -1; - } - os_free(buf); - return ret; -} - -static void wpa_driver_ralink_event_pmkid(struct wpa_driver_ralink_data *drv, - const u8 *data, size_t data_len) -{ - NDIS_802_11_PMKID_CANDIDATE_LIST *pmkid; - size_t i; - union wpa_event_data event; - - wpa_printf(MSG_DEBUG, "%s", __FUNCTION__); - - if (data_len < 8) { - wpa_printf(MSG_DEBUG, "RALINK: Too short PMKID Candidate List " - "Event (len=%lu)", (unsigned long) data_len); - return; - } - pmkid = (NDIS_802_11_PMKID_CANDIDATE_LIST *) data; - wpa_printf(MSG_DEBUG, "RALINK: PMKID Candidate List Event - Version %d" - " NumCandidates %d", - (int) pmkid->Version, (int) pmkid->NumCandidates); - - if (pmkid->Version != 1) { - wpa_printf(MSG_DEBUG, "RALINK: Unsupported PMKID Candidate " - "List Version %d", (int) pmkid->Version); - return; - } - - if (data_len < 8 + pmkid->NumCandidates * sizeof(PMKID_CANDIDATE)) { - wpa_printf(MSG_DEBUG, "RALINK: PMKID Candidate List " - "underflow"); - - return; - } - - - - os_memset(&event, 0, sizeof(event)); - for (i = 0; i < pmkid->NumCandidates; i++) { - PMKID_CANDIDATE *p = &pmkid->CandidateList[i]; - wpa_printf(MSG_DEBUG, "RALINK: %lu: " MACSTR " Flags 0x%x", - (unsigned long) i, MAC2STR(p->BSSID), - (int) p->Flags); - os_memcpy(event.pmkid_candidate.bssid, p->BSSID, ETH_ALEN); - event.pmkid_candidate.index = i; - event.pmkid_candidate.preauth = - p->Flags & NDIS_802_11_PMKID_CANDIDATE_PREAUTH_ENABLED; - wpa_supplicant_event(drv->ctx, EVENT_PMKID_CANDIDATE, - &event); - } -} - -static int wpa_driver_ralink_set_pmkid(struct wpa_driver_ralink_data *drv) -{ - int len, count, i, ret; - struct ndis_pmkid_entry *entry; - NDIS_802_11_PMKID *p; - - wpa_printf(MSG_DEBUG, "%s", __FUNCTION__); - - count = 0; - entry = drv->pmkid; - while (entry) { - count++; - if (count >= drv->no_of_pmkid) - break; - entry = entry->next; - } - len = 8 + count * sizeof(BSSID_INFO); - p = os_zalloc(len); - if (p == NULL) - return -1; - p->Length = len; - p->BSSIDInfoCount = count; - entry = drv->pmkid; - for (i = 0; i < count; i++) { - os_memcpy(&p->BSSIDInfo[i].BSSID, entry->bssid, ETH_ALEN); - os_memcpy(&p->BSSIDInfo[i].PMKID, entry->pmkid, 16); - entry = entry->next; - } - wpa_hexdump(MSG_MSGDUMP, "NDIS: OID_802_11_PMKID", - (const u8 *) p, len); - ret = ralink_set_oid(drv, OID_802_11_PMKID, (char *) p, len); - os_free(p); - return ret; -} - -static int wpa_driver_ralink_add_pmkid(void *priv, const u8 *bssid, - const u8 *pmkid) -{ - struct wpa_driver_ralink_data *drv = priv; - struct ndis_pmkid_entry *entry, *prev; - - if (drv->g_driver_down == 1) - return -1; - - wpa_printf(MSG_DEBUG, "%s", __FUNCTION__); - - if (drv->no_of_pmkid == 0) - return 0; - - prev = NULL; - entry = drv->pmkid; - while (entry) { - if (os_memcmp(entry->bssid, bssid, ETH_ALEN) == 0) - break; - prev = entry; - entry = entry->next; - } - - if (entry) { - /* Replace existing entry for this BSSID and move it into the - * beginning of the list. */ - os_memcpy(entry->pmkid, pmkid, 16); - if (prev) { - prev->next = entry->next; - entry->next = drv->pmkid; - drv->pmkid = entry; - } - } else { - entry = os_malloc(sizeof(*entry)); - if (entry) { - os_memcpy(entry->bssid, bssid, ETH_ALEN); - os_memcpy(entry->pmkid, pmkid, 16); - entry->next = drv->pmkid; - drv->pmkid = entry; - } - } - - return wpa_driver_ralink_set_pmkid(drv); -} - - -static int wpa_driver_ralink_remove_pmkid(void *priv, const u8 *bssid, - const u8 *pmkid) -{ - struct wpa_driver_ralink_data *drv = priv; - struct ndis_pmkid_entry *entry, *prev; - - if (drv->g_driver_down == 1) - return -1; - - wpa_printf(MSG_DEBUG, "%s", __FUNCTION__); - - if (drv->no_of_pmkid == 0) - return 0; - - entry = drv->pmkid; - prev = NULL; - drv->pmkid = NULL; - while (entry) { - if (os_memcmp(entry->bssid, bssid, ETH_ALEN) == 0 && - os_memcmp(entry->pmkid, pmkid, 16) == 0) { - if (prev) - prev->next = entry->next; - else - drv->pmkid = entry->next; - os_free(entry); - break; - } - prev = entry; - entry = entry->next; - } - return wpa_driver_ralink_set_pmkid(drv); -} - - -static int wpa_driver_ralink_flush_pmkid(void *priv) -{ - struct wpa_driver_ralink_data *drv = priv; - NDIS_802_11_PMKID p; - struct ndis_pmkid_entry *pmkid, *prev; - - if (drv->g_driver_down == 1) - return -1; - - wpa_printf(MSG_DEBUG, "%s", __FUNCTION__); - - if (drv->no_of_pmkid == 0) - return 0; - - pmkid = drv->pmkid; - drv->pmkid = NULL; - while (pmkid) { - prev = pmkid; - pmkid = pmkid->next; - os_free(prev); - } - - os_memset(&p, 0, sizeof(p)); - p.Length = 8; - p.BSSIDInfoCount = 0; - wpa_hexdump(MSG_MSGDUMP, "NDIS: OID_802_11_PMKID (flush)", - (const u8 *) &p, 8); - return ralink_set_oid(drv, OID_802_11_PMKID, (char *) &p, 8); -} - -static void -wpa_driver_ralink_event_wireless_custom(struct wpa_driver_ralink_data *drv, - void *ctx, char *custom) -{ - union wpa_event_data data; - u8 *req_ies = NULL, *resp_ies = NULL; - - wpa_printf(MSG_DEBUG, "%s", __FUNCTION__); - - wpa_printf(MSG_DEBUG, "Custom wireless event: '%s'", custom); - - os_memset(&data, 0, sizeof(data)); - /* Host AP driver */ - if (os_strncmp(custom, "MLME-MICHAELMICFAILURE.indication", 33) == 0) { - /* receive a MICFAILURE report */ - data.michael_mic_failure.unicast = - os_strstr(custom, " unicast") != NULL; - /* TODO: parse parameters(?) */ - wpa_supplicant_event(ctx, EVENT_MICHAEL_MIC_FAILURE, &data); - } else if (os_strncmp(custom, "ASSOCINFO_ReqIEs=", 17) == 0) { - /* receive assoc. req. IEs */ - char *spos; - int bytes; - - spos = custom + 17; - /*get IE's length */ - /* - * bytes = strlen(spos); ==> bug, bytes may less than original - * size by using this way to get size. snowpin 20070312 - * if (!bytes) - * return; - */ - bytes = drv->assoc_req_ies_len; - - req_ies = os_malloc(bytes); - if (req_ies == NULL) - return; - os_memcpy(req_ies, spos, bytes); - data.assoc_info.req_ies = req_ies; - data.assoc_info.req_ies_len = bytes; - - /* skip the '\0' byte */ - spos += bytes + 1; - - data.assoc_info.resp_ies = NULL; - data.assoc_info.resp_ies_len = 0; - - if (os_strncmp(spos, " RespIEs=", 9) == 0) { - /* receive assoc. resp. IEs */ - spos += 9; - /* get IE's length */ - bytes = os_strlen(spos); - if (!bytes) - goto done; - - resp_ies = os_malloc(bytes); - if (resp_ies == NULL) - goto done; - os_memcpy(resp_ies, spos, bytes); - data.assoc_info.resp_ies = resp_ies; - data.assoc_info.resp_ies_len = bytes; - } - - wpa_supplicant_event(ctx, EVENT_ASSOCINFO, &data); - - done: - /* free allocated memory */ - os_free(resp_ies); - os_free(req_ies); - } -} - -static void ralink_interface_up(struct wpa_driver_ralink_data *drv) -{ - union wpa_event_data event; - int enable_wpa_supplicant = 0; - drv->g_driver_down = 0; - os_memset(&event, 0, sizeof(event)); - os_snprintf(event.interface_status.ifname, - sizeof(event.interface_status.ifname), "%s", drv->ifname); - - event.interface_status.ievent = EVENT_INTERFACE_ADDED; - wpa_supplicant_event(drv->ctx, EVENT_INTERFACE_STATUS, &event); - - if (drv->ap_scan == 1) - enable_wpa_supplicant = 1; - else - enable_wpa_supplicant = 2; - /* trigger driver support wpa_supplicant */ - if (ralink_set_oid(drv, RT_OID_WPA_SUPPLICANT_SUPPORT, - (PCHAR) &enable_wpa_supplicant, sizeof(UCHAR)) < 0) - { - wpa_printf(MSG_INFO, "RALINK: Failed to set " - "RT_OID_WPA_SUPPLICANT_SUPPORT(%d)", - (int) enable_wpa_supplicant); - wpa_printf(MSG_ERROR, "ralink. Driver does not support " - "wpa_supplicant"); - } -} - -static void -wpa_driver_ralink_event_wireless(struct wpa_driver_ralink_data *drv, - void *ctx, char *data, int len) -{ - struct iw_event iwe_buf, *iwe = &iwe_buf; - char *pos, *end, *custom, *buf, *assoc_info_buf, *info_pos; -#if 0 - BOOLEAN ieee8021x_required_key = FALSE; -#endif - - wpa_printf(MSG_DEBUG, "%s", __FUNCTION__); - - assoc_info_buf = info_pos = NULL; - pos = data; - end = data + len; - - while (pos + IW_EV_LCP_LEN <= end) { - /* Event data may be unaligned, so make a local, aligned copy - * before processing. */ - os_memcpy(&iwe_buf, pos, IW_EV_LCP_LEN); - wpa_printf(MSG_DEBUG, "Wireless event: cmd=0x%x len=%d", - iwe->cmd, iwe->len); - if (iwe->len <= IW_EV_LCP_LEN) - return; - - custom = pos + IW_EV_POINT_LEN; - - if (drv->we_version_compiled > 18 && iwe->cmd == IWEVCUSTOM) { - /* WE-19 removed the pointer from struct iw_point */ - char *dpos = (char *) &iwe_buf.u.data.length; - int dlen = dpos - (char *) &iwe_buf; - os_memcpy(dpos, pos + IW_EV_LCP_LEN, - sizeof(struct iw_event) - dlen); - } else { - os_memcpy(&iwe_buf, pos, sizeof(struct iw_event)); - custom += IW_EV_POINT_OFF; - } - - switch (iwe->cmd) { - case IWEVCUSTOM: - if (custom + iwe->u.data.length > end) - return; - buf = os_malloc(iwe->u.data.length + 1); - if (buf == NULL) - return; - os_memcpy(buf, custom, iwe->u.data.length); - buf[iwe->u.data.length] = '\0'; - - if (drv->ap_scan == 1) { - if ((iwe->u.data.flags == RT_ASSOC_EVENT_FLAG) - || (iwe->u.data.flags == - RT_REQIE_EVENT_FLAG) || - (iwe->u.data.flags == RT_RESPIE_EVENT_FLAG) - || (iwe->u.data.flags == - RT_ASSOCINFO_EVENT_FLAG)) { - if (drv->scanning_done == 0) { - os_free(buf); - return; - } - } - } - - if (iwe->u.data.flags == RT_ASSOC_EVENT_FLAG) { - wpa_supplicant_event(ctx, EVENT_ASSOC, NULL); - wpa_printf(MSG_DEBUG, "Custom wireless event: " - "receive ASSOCIATED_EVENT !!!"); - } else if (iwe->u.data.flags == RT_REQIE_EVENT_FLAG) { - wpa_printf(MSG_DEBUG, "Custom wireless event: " - "receive ReqIEs !!!"); - drv->assoc_req_ies = - os_malloc(iwe->u.data.length); - if (drv->assoc_req_ies == NULL) { - os_free(buf); - return; - } - - drv->assoc_req_ies_len = iwe->u.data.length; - os_memcpy(drv->assoc_req_ies, custom, - iwe->u.data.length); - } else if (iwe->u.data.flags == RT_RESPIE_EVENT_FLAG) { - wpa_printf(MSG_DEBUG, "Custom wireless event: " - "receive RespIEs !!!"); - drv->assoc_resp_ies = - os_malloc(iwe->u.data.length); - if (drv->assoc_resp_ies == NULL) { - os_free(drv->assoc_req_ies); - drv->assoc_req_ies = NULL; - os_free(buf); - return; - } - - drv->assoc_resp_ies_len = iwe->u.data.length; - os_memcpy(drv->assoc_resp_ies, custom, - iwe->u.data.length); - } else if (iwe->u.data.flags == - RT_ASSOCINFO_EVENT_FLAG) { - wpa_printf(MSG_DEBUG, "Custom wireless event: " - "receive ASSOCINFO_EVENT !!!"); - - assoc_info_buf = - os_zalloc(drv->assoc_req_ies_len + - drv->assoc_resp_ies_len + 1); - - if (assoc_info_buf == NULL) { - os_free(drv->assoc_req_ies); - drv->assoc_req_ies = NULL; - os_free(drv->assoc_resp_ies); - drv->assoc_resp_ies = NULL; - os_free(buf); - return; - } - - if (drv->assoc_req_ies) { - os_memcpy(assoc_info_buf, - drv->assoc_req_ies, - drv->assoc_req_ies_len); - } - info_pos = assoc_info_buf + - drv->assoc_req_ies_len; - if (drv->assoc_resp_ies) { - os_memcpy(info_pos, - drv->assoc_resp_ies, - drv->assoc_resp_ies_len); - } - assoc_info_buf[drv->assoc_req_ies_len + - drv->assoc_resp_ies_len] = '\0'; - wpa_driver_ralink_event_wireless_custom( - drv, ctx, assoc_info_buf); - os_free(drv->assoc_req_ies); - drv->assoc_req_ies = NULL; - os_free(drv->assoc_resp_ies); - drv->assoc_resp_ies = NULL; - os_free(assoc_info_buf); - } else if (iwe->u.data.flags == RT_DISASSOC_EVENT_FLAG) - { - wpa_printf(MSG_DEBUG, "Custom wireless event: " - "receive DISASSOCIATED_EVENT !!!"); - wpa_supplicant_event(ctx, EVENT_DISASSOC, - NULL); - } else if (iwe->u.data.flags == RT_PMKIDCAND_FLAG) { - wpa_printf(MSG_DEBUG, "Custom wireless event: " - "receive PMKIDCAND_EVENT !!!"); - wpa_driver_ralink_event_pmkid( - drv, (const u8 *) custom, - iwe->u.data.length); - } else if (iwe->u.data.flags == RT_INTERFACE_DOWN) { - drv->g_driver_down = 1; - eloop_terminate(); - } else if (iwe->u.data.flags == RT_INTERFACE_UP) { - ralink_interface_up(drv); - } else { - wpa_driver_ralink_event_wireless_custom( - drv, ctx, buf); - } - os_free(buf); - break; - } - - pos += iwe->len; - } -} - -static void -wpa_driver_ralink_event_rtm_newlink(void *ctx, struct ifinfomsg *ifi, - u8 *buf, size_t len) -{ - struct wpa_driver_ralink_data *drv = ctx; - int attrlen, rta_len; - struct rtattr *attr; - - wpa_printf(MSG_DEBUG, "%s", __FUNCTION__); - - wpa_hexdump(MSG_DEBUG, "ifi: ", (u8 *) ifi, sizeof(struct ifinfomsg)); - - attrlen = len; - wpa_printf(MSG_DEBUG, "attrlen=%d", attrlen); - attr = (struct rtattr *) buf; - wpa_hexdump(MSG_DEBUG, "attr1: ", (u8 *) attr, sizeof(struct rtattr)); - rta_len = RTA_ALIGN(sizeof(struct rtattr)); - wpa_hexdump(MSG_DEBUG, "attr2: ", (u8 *)attr,rta_len); - while (RTA_OK(attr, attrlen)) { - wpa_printf(MSG_DEBUG, "rta_type=%02x\n", attr->rta_type); - if (attr->rta_type == IFLA_WIRELESS) { - wpa_driver_ralink_event_wireless( - drv, ctx, - ((char *) attr) + rta_len, - attr->rta_len - rta_len); - } - attr = RTA_NEXT(attr, attrlen); - wpa_hexdump(MSG_DEBUG, "attr3: ", - (u8 *) attr, sizeof(struct rtattr)); - } -} - -static int -ralink_get_we_version_compiled(struct wpa_driver_ralink_data *drv) -{ - struct iwreq iwr; - UINT we_version_compiled = 0; - - os_memset(&iwr, 0, sizeof(iwr)); - os_strlcpy(iwr.ifr_name, drv->ifname, IFNAMSIZ); - iwr.u.data.pointer = (caddr_t) &we_version_compiled; - iwr.u.data.flags = RT_OID_WE_VERSION_COMPILED; - - if (ioctl(drv->ioctl_sock, RT_PRIV_IOCTL, &iwr) < 0) { - wpa_printf(MSG_DEBUG, "%s: failed", __func__); - return -1; - } - - drv->we_version_compiled = we_version_compiled; - - return 0; -} - -static void * wpa_driver_ralink_init(void *ctx, const char *ifname) -{ - int s; - struct wpa_driver_ralink_data *drv; - struct ifreq ifr; - UCHAR enable_wpa_supplicant = 0; - struct netlink_config *cfg; - - wpa_printf(MSG_DEBUG, "%s", __FUNCTION__); - - /* open socket to kernel */ - if ((s = socket(AF_INET, SOCK_DGRAM, 0)) < 0) { - perror("socket"); - return NULL; - } - /* do it */ - os_strlcpy(ifr.ifr_name, ifname, IFNAMSIZ); - - if (ioctl(s, SIOCGIFINDEX, &ifr) < 0) { - perror(ifr.ifr_name); - return NULL; - } - - drv = os_zalloc(sizeof(*drv)); - if (drv == NULL) - return NULL; - - drv->scanning_done = 1; - drv->ap_scan = 1; /* for now - let's assume ap_scan=1 is used */ - drv->ctx = ctx; - os_strlcpy(drv->ifname, ifname, sizeof(drv->ifname)); - drv->ioctl_sock = s; - drv->g_driver_down = 0; - - cfg = os_zalloc(sizeof(*cfg)); - if (cfg == NULL) { - close(drv->ioctl_sock); - os_free(drv); - return NULL; - } - cfg->ctx = drv; - cfg->newlink_cb = wpa_driver_ralink_event_rtm_newlink; - drv->netlink = netlink_init(cfg); - if (drv->netlink == NULL) { - os_free(cfg); - close(drv->ioctl_sock); - os_free(drv); - return NULL; - } - - drv->no_of_pmkid = 4; /* Number of PMKID saved supported */ - - linux_set_iface_flags(drv->ioctl_sock, drv->ifname, 1); - ralink_get_we_version_compiled(drv); - wpa_driver_ralink_flush_pmkid(drv); - - if (drv->ap_scan == 1) - enable_wpa_supplicant = 1; - else - enable_wpa_supplicant = 2; - /* trigger driver support wpa_supplicant */ - if (ralink_set_oid(drv, RT_OID_WPA_SUPPLICANT_SUPPORT, - (PCHAR) &enable_wpa_supplicant, sizeof(UCHAR)) < 0) - { - wpa_printf(MSG_DEBUG, "RALINK: Failed to set " - "RT_OID_WPA_SUPPLICANT_SUPPORT(%d)", - (int) enable_wpa_supplicant); - wpa_printf(MSG_ERROR, "RALINK: Driver does not support " - "wpa_supplicant"); - close(s); - close(drv->ioctl_sock); - os_free(drv); - return NULL; - } - - if (drv->ap_scan == 1) - drv->scanning_done = 0; - - return drv; -} - -static void wpa_driver_ralink_deinit(void *priv) -{ - struct wpa_driver_ralink_data *drv = priv; - UCHAR enable_wpa_supplicant; - - wpa_printf(MSG_DEBUG, "%s", __FUNCTION__); - - enable_wpa_supplicant = 0; - - if (drv->g_driver_down == 0) { - /* trigger driver disable wpa_supplicant support */ - if (ralink_set_oid(drv, RT_OID_WPA_SUPPLICANT_SUPPORT, - (char *) &enable_wpa_supplicant, - sizeof(BOOLEAN)) < 0) { - wpa_printf(MSG_DEBUG, "RALINK: Failed to set " - "RT_OID_WPA_SUPPLICANT_SUPPORT(%d)", - (int) enable_wpa_supplicant); - } - - wpa_driver_ralink_flush_pmkid(drv); - - sleep(1); - /* linux_set_iface_flags(drv->ioctl_sock, drv->ifname, 0); */ - } - - eloop_cancel_timeout(wpa_driver_ralink_scan_timeout, drv, drv->ctx); - netlink_deinit(drv->netlink); - close(drv->ioctl_sock); - os_free(drv); -} - -static void wpa_driver_ralink_scan_timeout(void *eloop_ctx, void *timeout_ctx) -{ - struct wpa_driver_ralink_data *drv = eloop_ctx; - - wpa_printf(MSG_DEBUG, "%s", __FUNCTION__); - - wpa_printf(MSG_DEBUG, "Scan timeout - try to get results"); - wpa_supplicant_event(timeout_ctx, EVENT_SCAN_RESULTS, NULL); - - drv->scanning_done = 1; - -} - -static int wpa_driver_ralink_scan(void *priv, - struct wpa_driver_scan_params *params) -{ - struct wpa_driver_ralink_data *drv = priv; - struct iwreq iwr; - int ret = 0; - - if (drv->g_driver_down == 1) - return -1; - - wpa_printf(MSG_DEBUG, "%s", __FUNCTION__); - -#if 0 - if (ssid_len > IW_ESSID_MAX_SIZE) { - wpa_printf(MSG_DEBUG, "%s: too long SSID (%lu)", - __FUNCTION__, (unsigned long) ssid_len); - return -1; - } - - /* wpa_driver_ralink_set_ssid(drv, ssid, ssid_len); */ -#endif - - if (ralink_set_oid(drv, RT_OID_WPS_PROBE_REQ_IE, - (char *) params->extra_ies, params->extra_ies_len) < - 0) { - wpa_printf(MSG_DEBUG, "RALINK: Failed to set " - "RT_OID_WPS_PROBE_REQ_IE"); - } - - os_memset(&iwr, 0, sizeof(iwr)); - os_strlcpy(iwr.ifr_name, drv->ifname, IFNAMSIZ); - - if (ioctl(drv->ioctl_sock, SIOCSIWSCAN, &iwr) < 0) { - perror("ioctl[SIOCSIWSCAN]"); - ret = -1; - } - - /* Not all drivers generate "scan completed" wireless event, so try to - * read results after a timeout. */ - eloop_cancel_timeout(wpa_driver_ralink_scan_timeout, drv, drv->ctx); - eloop_register_timeout(4, 0, wpa_driver_ralink_scan_timeout, drv, - drv->ctx); - - drv->scanning_done = 0; - - return ret; -} - -static struct wpa_scan_results * -wpa_driver_ralink_get_scan_results(void *priv) -{ - struct wpa_driver_ralink_data *drv = priv; - UCHAR *buf = NULL; - size_t buf_len; - NDIS_802_11_BSSID_LIST_EX *wsr; - NDIS_WLAN_BSSID_EX *wbi; - struct iwreq iwr; - size_t ap_num; - u8 *pos; - struct wpa_scan_results *res; - - if (drv->g_driver_down == 1) - return NULL; - wpa_printf(MSG_DEBUG, "%s", __FUNCTION__); - - if (drv->we_version_compiled >= 17) - buf_len = 8192; - else - buf_len = 4096; - - for (;;) { - buf = os_zalloc(buf_len); - iwr.u.data.length = buf_len; - if (buf == NULL) - return NULL; - - wsr = (NDIS_802_11_BSSID_LIST_EX *) buf; - - wsr->NumberOfItems = 0; - os_strlcpy(iwr.ifr_name, drv->ifname, IFNAMSIZ); - iwr.u.data.pointer = (void *) buf; - iwr.u.data.flags = OID_802_11_BSSID_LIST; - - if (ioctl(drv->ioctl_sock, RT_PRIV_IOCTL, &iwr) == 0) - break; - - if (errno == E2BIG && buf_len < 65535) { - os_free(buf); - buf = NULL; - buf_len *= 2; - if (buf_len > 65535) - buf_len = 65535; /* 16-bit length field */ - wpa_printf(MSG_DEBUG, "Scan results did not fit - " - "trying larger buffer (%lu bytes)", - (unsigned long) buf_len); - } else { - perror("ioctl[RT_PRIV_IOCTL]"); - os_free(buf); - return NULL; - } - } - - res = os_zalloc(sizeof(*res)); - if (res == NULL) { - os_free(buf); - return NULL; - } - - res->res = os_zalloc(wsr->NumberOfItems * - sizeof(struct wpa_scan_res *)); - if (res->res == NULL) { - os_free(res); - os_free(buf); - return NULL; - } - - for (ap_num = 0, wbi = wsr->Bssid; ap_num < wsr->NumberOfItems; - ++ap_num) { - struct wpa_scan_res *r = NULL; - size_t extra_len = 0, var_ie_len = 0; - u8 *pos2; - - /* SSID data element */ - extra_len += 2 + wbi->Ssid.SsidLength; - var_ie_len = wbi->IELength - sizeof(NDIS_802_11_FIXED_IEs); - r = os_zalloc(sizeof(*r) + extra_len + var_ie_len); - if (r == NULL) - break; - res->res[res->num++] = r; - - wpa_printf(MSG_DEBUG, "SSID - %s", wbi->Ssid.Ssid); - /* get ie's */ - wpa_hexdump(MSG_DEBUG, "RALINK: AP IEs", - (u8 *) &wbi->IEs[0], wbi->IELength); - - os_memcpy(r->bssid, wbi->MacAddress, ETH_ALEN); - - extra_len += (2 + wbi->Ssid.SsidLength); - r->ie_len = extra_len + var_ie_len; - pos2 = (u8 *) (r + 1); - - /* - * Generate a fake SSID IE since the driver did not report - * a full IE list. - */ - *pos2++ = WLAN_EID_SSID; - *pos2++ = wbi->Ssid.SsidLength; - os_memcpy(pos2, wbi->Ssid.Ssid, wbi->Ssid.SsidLength); - pos2 += wbi->Ssid.SsidLength; - - r->freq = (wbi->Configuration.DSConfig / 1000); - - pos = (u8 *) wbi + sizeof(*wbi) - 1; - - pos += sizeof(NDIS_802_11_FIXED_IEs) - 2; - os_memcpy(&(r->caps), pos, 2); - pos += 2; - - if (wbi->IELength > sizeof(NDIS_802_11_FIXED_IEs)) - os_memcpy(pos2, pos, var_ie_len); - - wbi = (NDIS_WLAN_BSSID_EX *) ((u8 *) wbi + wbi->Length); - } - - os_free(buf); - return res; -} - -static int ralink_set_auth_mode(struct wpa_driver_ralink_data *drv, - NDIS_802_11_AUTHENTICATION_MODE mode) -{ - NDIS_802_11_AUTHENTICATION_MODE auth_mode = mode; - - wpa_printf(MSG_DEBUG, "%s", __FUNCTION__); - - if (ralink_set_oid(drv, OID_802_11_AUTHENTICATION_MODE, - (char *) &auth_mode, sizeof(auth_mode)) < 0) { - wpa_printf(MSG_DEBUG, "RALINK: Failed to set " - "OID_802_11_AUTHENTICATION_MODE (%d)", - (int) auth_mode); - return -1; - } - return 0; -} - -static int ralink_set_encr_type(struct wpa_driver_ralink_data *drv, - NDIS_802_11_WEP_STATUS encr_type) -{ - NDIS_802_11_WEP_STATUS wep_status = encr_type; - - wpa_printf(MSG_DEBUG, "%s", __FUNCTION__); - - if (ralink_set_oid(drv, OID_802_11_WEP_STATUS, - (char *) &wep_status, sizeof(wep_status)) < 0) { - wpa_printf(MSG_DEBUG, "RALINK: Failed to set " - "OID_802_11_WEP_STATUS (%d)", - (int) wep_status); - return -1; - } - return 0; -} - - -static int wpa_driver_ralink_remove_key(struct wpa_driver_ralink_data *drv, - int key_idx, const u8 *addr, - const u8 *bssid, int pairwise) -{ - NDIS_802_11_REMOVE_KEY rkey; - NDIS_802_11_KEY_INDEX _index; - int res, res2; - - wpa_printf(MSG_DEBUG, "%s", __FUNCTION__); - - os_memset(&rkey, 0, sizeof(rkey)); - - rkey.Length = sizeof(rkey); - rkey.KeyIndex = key_idx; - - if (pairwise) - rkey.KeyIndex |= 1 << 30; - - os_memcpy(rkey.BSSID, bssid, ETH_ALEN); - - res = ralink_set_oid(drv, OID_802_11_REMOVE_KEY, (char *) &rkey, - sizeof(rkey)); - - /* AlbertY@20060210 removed it */ - if (0 /* !pairwise */) { - res2 = ralink_set_oid(drv, OID_802_11_REMOVE_WEP, - (char *) &_index, sizeof(_index)); - } else - res2 = 0; - - if (res < 0 && res2 < 0) - return res; - return 0; -} - -static int wpa_driver_ralink_add_wep(struct wpa_driver_ralink_data *drv, - int pairwise, int key_idx, int set_tx, - const u8 *key, size_t key_len) -{ - NDIS_802_11_WEP *wep; - size_t len; - int res; - - wpa_printf(MSG_DEBUG, "%s", __FUNCTION__); - - len = 12 + key_len; - wep = os_zalloc(len); - if (wep == NULL) - return -1; - - wep->Length = len; - wep->KeyIndex = key_idx; - - if (set_tx) - wep->KeyIndex |= 0x80000000; - - wep->KeyLength = key_len; - os_memcpy(wep->KeyMaterial, key, key_len); - - wpa_hexdump_key(MSG_MSGDUMP, "RALINK: OID_802_11_ADD_WEP", - (const u8 *) wep, len); - res = ralink_set_oid(drv, OID_802_11_ADD_WEP, (char *) wep, len); - - os_free(wep); - - return res; -} - -static int wpa_driver_ralink_set_key(const char *ifname, void *priv, - enum wpa_alg alg, const u8 *addr, - int key_idx, int set_tx, - const u8 *seq, size_t seq_len, - const u8 *key, size_t key_len) -{ - struct wpa_driver_ralink_data *drv = priv; - size_t len, i; - NDIS_802_11_KEY *nkey; - int res, pairwise; - u8 bssid[ETH_ALEN]; - - if (drv->g_driver_down == 1) - return -1; - - wpa_printf(MSG_DEBUG, "%s", __FUNCTION__); - - drv->bAddWepKey = FALSE; - - if (addr == NULL || is_broadcast_ether_addr(addr)) { - /* Group Key */ - pairwise = 0; - wpa_driver_ralink_get_bssid(drv, bssid); - } else { - /* Pairwise Key */ - pairwise = 1; - os_memcpy(bssid, addr, ETH_ALEN); - } - - if (alg == WPA_ALG_NONE || key_len == 0) { - return wpa_driver_ralink_remove_key(drv, key_idx, addr, bssid, - pairwise); - } - - if (alg == WPA_ALG_WEP) { - drv->bAddWepKey = TRUE; - return wpa_driver_ralink_add_wep(drv, pairwise, key_idx, - set_tx, key, key_len); - } - - len = 12 + 6 + 6 + 8 + key_len; - - nkey = os_zalloc(len); - if (nkey == NULL) - return -1; - - nkey->Length = len; - nkey->KeyIndex = key_idx; - - if (set_tx) - nkey->KeyIndex |= 1 << 31; - - if (pairwise) - nkey->KeyIndex |= 1 << 30; - - if (seq && seq_len) - nkey->KeyIndex |= 1 << 29; - - nkey->KeyLength = key_len; - os_memcpy(nkey->BSSID, bssid, ETH_ALEN); - - if (seq && seq_len) { - for (i = 0; i < seq_len; i++) - nkey->KeyRSC |= seq[i] << (i * 8); - } - if (alg == WPA_ALG_TKIP && key_len == 32) { - os_memcpy(nkey->KeyMaterial, key, 16); - os_memcpy(nkey->KeyMaterial + 16, key + 24, 8); - os_memcpy(nkey->KeyMaterial + 24, key + 16, 8); - } else { - os_memcpy(nkey->KeyMaterial, key, key_len); - } - - wpa_printf(MSG_DEBUG, "%s: alg=%d key_idx=%d set_tx=%d seq_len=%lu " - "key_len=%lu", __FUNCTION__, alg, key_idx, set_tx, - (unsigned long) seq_len, (unsigned long) key_len); - - wpa_hexdump_key(MSG_MSGDUMP, "RALINK: OID_802_11_ADD_KEY", - (const u8 *) nkey, len); - res = ralink_set_oid(drv, OID_802_11_ADD_KEY, (char *) nkey, len); - os_free(nkey); - - return res; -} - -static int wpa_driver_ralink_disassociate(void *priv, const u8 *addr, - int reason_code) -{ - struct wpa_driver_ralink_data *drv = priv; - - if (drv->g_driver_down == 1) - return -1; - wpa_printf(MSG_DEBUG, "%s", __FUNCTION__); - if (ralink_set_oid(drv, OID_802_11_DISASSOCIATE, " ", 4) < 0) { - wpa_printf(MSG_DEBUG, "RALINK: Failed to set " - "OID_802_11_DISASSOCIATE"); - } - - return 0; -} - -static int wpa_driver_ralink_deauthenticate(void *priv, const u8 *addr, - int reason_code) -{ - struct wpa_driver_ralink_data *drv = priv; - - wpa_printf(MSG_DEBUG, "g_driver_down = %d", drv->g_driver_down); - - if (drv->g_driver_down == 1) - return -1; - - wpa_printf(MSG_DEBUG, "%s", __FUNCTION__); - if (ralink_get_new_driver_flag(drv) == 0) { - return wpa_driver_ralink_disassociate(priv, addr, reason_code); - } else { - MLME_DEAUTH_REQ_STRUCT mlme; - os_memset(&mlme, 0, sizeof(MLME_DEAUTH_REQ_STRUCT)); - mlme.Reason = reason_code; - os_memcpy(mlme.Addr, addr, MAC_ADDR_LEN); - return ralink_set_oid(drv, OID_802_11_DEAUTHENTICATION, - (char *) &mlme, - sizeof(MLME_DEAUTH_REQ_STRUCT)); - } -} - -static int wpa_driver_ralink_set_gen_ie(void *priv, const u8 *ie, - size_t ie_len) -{ - struct wpa_driver_ralink_data *drv = priv; - struct iwreq iwr; - int ret = 0; - - os_memset(&iwr, 0, sizeof(iwr)); - os_strlcpy(iwr.ifr_name, drv->ifname, IFNAMSIZ); - iwr.u.data.pointer = (caddr_t) ie; - iwr.u.data.length = ie_len; - - wpa_hexdump(MSG_DEBUG, "wpa_driver_ralink_set_gen_ie: ", - (u8 *) ie, ie_len); - - if (ioctl(drv->ioctl_sock, SIOCSIWGENIE, &iwr) < 0) { - perror("ioctl[SIOCSIWGENIE]"); - ret = -1; - } - - return ret; -} - -static int -wpa_driver_ralink_associate(void *priv, - struct wpa_driver_associate_params *params) -{ - struct wpa_driver_ralink_data *drv = priv; - - NDIS_802_11_NETWORK_INFRASTRUCTURE mode; - NDIS_802_11_AUTHENTICATION_MODE auth_mode; - NDIS_802_11_WEP_STATUS encr; - BOOLEAN ieee8021xMode; - BOOLEAN ieee8021x_required_key = TRUE; - - if (drv->g_driver_down == 1) - return -1; - wpa_printf(MSG_DEBUG, "%s", __FUNCTION__); - - if (params->mode == IEEE80211_MODE_IBSS) - mode = Ndis802_11IBSS; - else - mode = Ndis802_11Infrastructure; - - if (ralink_set_oid(drv, OID_802_11_INFRASTRUCTURE_MODE, - (char *) &mode, sizeof(mode)) < 0) { - wpa_printf(MSG_DEBUG, "RALINK: Failed to set " - "OID_802_11_INFRASTRUCTURE_MODE (%d)", - (int) mode); - /* Try to continue anyway */ - } - - if (params->key_mgmt_suite == KEY_MGMT_WPS) { - UCHAR enable_wps = 0x80; - /* trigger driver support wpa_supplicant */ - if (ralink_set_oid(drv, RT_OID_WPA_SUPPLICANT_SUPPORT, - (PCHAR) &enable_wps, sizeof(UCHAR)) < 0) { - wpa_printf(MSG_INFO, "RALINK: Failed to set " - "RT_OID_WPA_SUPPLICANT_SUPPORT (%d)", - (int) enable_wps); - } - - wpa_driver_ralink_set_gen_ie(priv, params->wpa_ie, - params->wpa_ie_len); - - ralink_set_auth_mode(drv, Ndis802_11AuthModeOpen); - - ralink_set_encr_type(drv, Ndis802_11EncryptionDisabled); - } else { -#ifdef CONFIG_WPS - UCHAR enable_wpa_supplicant; - - if (drv->ap_scan == 1) - enable_wpa_supplicant = 0x01; - else - enable_wpa_supplicant = 0x02; - - /* trigger driver support wpa_supplicant */ - if (ralink_set_oid(drv, RT_OID_WPA_SUPPLICANT_SUPPORT, - (PCHAR) &enable_wpa_supplicant, - sizeof(UCHAR)) < 0) { - wpa_printf(MSG_DEBUG, "RALINK: Failed to set " - "RT_OID_WPA_SUPPLICANT_SUPPORT (%d)", - (int) enable_wpa_supplicant); - } - - wpa_driver_ralink_set_gen_ie(priv, (u8 *) "", 0); -#endif /* CONFIG_WPS */ - - if (params->wpa_ie == NULL || params->wpa_ie_len == 0) { - if (params->auth_alg & WPA_AUTH_ALG_SHARED) { - if (params->auth_alg & WPA_AUTH_ALG_OPEN) - auth_mode = Ndis802_11AuthModeAutoSwitch; - else - auth_mode = Ndis802_11AuthModeShared; - } else - auth_mode = Ndis802_11AuthModeOpen; - } else if (params->wpa_ie[0] == WLAN_EID_RSN) { - if (params->key_mgmt_suite == KEY_MGMT_PSK) - auth_mode = Ndis802_11AuthModeWPA2PSK; - else - auth_mode = Ndis802_11AuthModeWPA2; - } else { - if (params->key_mgmt_suite == KEY_MGMT_WPA_NONE) - auth_mode = Ndis802_11AuthModeWPANone; - else if (params->key_mgmt_suite == KEY_MGMT_PSK) - auth_mode = Ndis802_11AuthModeWPAPSK; - else - auth_mode = Ndis802_11AuthModeWPA; - } - - switch (params->pairwise_suite) { - case CIPHER_CCMP: - encr = Ndis802_11Encryption3Enabled; - break; - case CIPHER_TKIP: - encr = Ndis802_11Encryption2Enabled; - break; - case CIPHER_WEP40: - case CIPHER_WEP104: - encr = Ndis802_11Encryption1Enabled; - break; - case CIPHER_NONE: - if (params->group_suite == CIPHER_CCMP) - encr = Ndis802_11Encryption3Enabled; - else if (params->group_suite == CIPHER_TKIP) - encr = Ndis802_11Encryption2Enabled; - else - encr = Ndis802_11EncryptionDisabled; - break; - default: - encr = Ndis802_11EncryptionDisabled; - break; - } - - ralink_set_auth_mode(drv, auth_mode); - - /* notify driver that IEEE8021x mode is enabled */ - if (params->key_mgmt_suite == KEY_MGMT_802_1X_NO_WPA) { - ieee8021xMode = TRUE; - if (drv->bAddWepKey) - ieee8021x_required_key = FALSE; - } else - ieee8021xMode = FALSE; - - if (ralink_set_oid(drv, OID_802_11_SET_IEEE8021X_REQUIRE_KEY, - (char *) &ieee8021x_required_key, - sizeof(BOOLEAN)) < 0) { - wpa_printf(MSG_DEBUG, "ERROR: Failed to set " - "OID_802_11_SET_IEEE8021X_REQUIRE_KEY(%d)", - (int) ieee8021x_required_key); - } else { - wpa_printf(MSG_DEBUG, "ieee8021x_required_key is %s", - ieee8021x_required_key ? "TRUE" : "FALSE"); - } - - if (ralink_set_oid(drv, OID_802_11_SET_IEEE8021X, - (char *) &ieee8021xMode, sizeof(BOOLEAN)) < - 0) { - wpa_printf(MSG_DEBUG, "RALINK: Failed to set " - "OID_802_11_SET_IEEE8021X(%d)", - (int) ieee8021xMode); - } - - ralink_set_encr_type(drv, encr); - - if ((ieee8021xMode == FALSE) && - (encr == Ndis802_11Encryption1Enabled)) { - /* static WEP */ - int enabled = 0; - if (ralink_set_oid(drv, OID_802_11_DROP_UNENCRYPTED, - (char *) &enabled, sizeof(enabled)) - < 0) { - wpa_printf(MSG_DEBUG, "RALINK: Failed to set " - "OID_802_11_DROP_UNENCRYPTED(%d)", - (int) encr); - } - } - } - - return wpa_driver_ralink_set_ssid(drv, params->ssid, params->ssid_len); -} - -static int -wpa_driver_ralink_set_countermeasures(void *priv, int enabled) -{ - struct wpa_driver_ralink_data *drv = priv; - if (drv->g_driver_down == 1) - return -1; - wpa_printf(MSG_DEBUG, "%s: enabled=%d", __FUNCTION__, enabled); - return ralink_set_oid(drv, OID_SET_COUNTERMEASURES, (char *) &enabled, - sizeof(int)); -} - -const struct wpa_driver_ops wpa_driver_ralink_ops = { - .name = "ralink", - .desc = "Ralink Wireless Client driver", - .get_bssid = wpa_driver_ralink_get_bssid, - .get_ssid = wpa_driver_ralink_get_ssid, - .set_key = wpa_driver_ralink_set_key, - .init = wpa_driver_ralink_init, - .deinit = wpa_driver_ralink_deinit, - .set_countermeasures = wpa_driver_ralink_set_countermeasures, - .scan2 = wpa_driver_ralink_scan, - .get_scan_results2 = wpa_driver_ralink_get_scan_results, - .deauthenticate = wpa_driver_ralink_deauthenticate, - .disassociate = wpa_driver_ralink_disassociate, - .associate = wpa_driver_ralink_associate, - .add_pmkid = wpa_driver_ralink_add_pmkid, - .remove_pmkid = wpa_driver_ralink_remove_pmkid, - .flush_pmkid = wpa_driver_ralink_flush_pmkid, -}; diff --git a/hostapd-0.8/src/drivers/driver_ralink.h b/hostapd-0.8/src/drivers/driver_ralink.h deleted file mode 100644 index d13df28..0000000 --- a/hostapd-0.8/src/drivers/driver_ralink.h +++ /dev/null @@ -1,383 +0,0 @@ -/* - * WPA Supplicant - driver_ralink exported functions - * Copyright (c) 2003-2005, Jouni Malinen - * Copyright (c) 2007, Snowpin Lee - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -// Ralink defined OIDs -#if WIRELESS_EXT <= 11 -#ifndef SIOCDEVPRIVATE -#define SIOCDEVPRIVATE 0x8BE0 -#endif -#define SIOCIWFIRSTPRIV SIOCDEVPRIVATE -#endif - -#define RT_PRIV_IOCTL (SIOCIWFIRSTPRIV + 0x0E) -#define RTPRIV_IOCTL_SET (SIOCIWFIRSTPRIV + 0x02) - -// IEEE 802.11 OIDs & Ralink defined OIDs ****** - -// (RaConfig Set/QueryInform) ==> -#define OID_GET_SET_TOGGLE 0x8000 - -#define OID_802_11_ADD_WEP 0x0112 -#define OID_802_11_REMOVE_WEP 0x0113 -#define OID_802_11_DISASSOCIATE 0x0114 -#define OID_802_11_PRIVACY_FILTER 0x0118 -#define OID_802_11_ASSOCIATION_INFORMATION 0x011E -#define OID_802_11_BSSID_LIST_SCAN 0x0508 -#define OID_802_11_SSID 0x0509 -#define OID_802_11_BSSID 0x050A -#define OID_802_11_WEP_STATUS 0x0510 -#define OID_802_11_AUTHENTICATION_MODE 0x0511 -#define OID_802_11_INFRASTRUCTURE_MODE 0x0512 -#define OID_802_11_TX_POWER_LEVEL 0x0517 -#define OID_802_11_REMOVE_KEY 0x0519 -#define OID_802_11_ADD_KEY 0x0520 -#define OID_802_11_DEAUTHENTICATION 0x0526 -#define OID_802_11_DROP_UNENCRYPTED 0x0527 -#define OID_802_11_BSSID_LIST 0x0609 -#define OID_802_3_CURRENT_ADDRESS 0x060A -#define OID_SET_COUNTERMEASURES 0x0616 -#define OID_802_11_SET_IEEE8021X 0x0617 // For IEEE8021x mode -#define OID_802_11_SET_IEEE8021X_REQUIRE_KEY 0x0618 // For DynamicWEP in IEEE802.1x mode -#define OID_802_11_PMKID 0x0620 -#define RT_OID_WPA_SUPPLICANT_SUPPORT 0x0621 // for trigger driver enable/disable wpa_supplicant support -#define RT_OID_WE_VERSION_COMPILED 0x0622 -#define RT_OID_NEW_DRIVER 0x0623 -#define RT_OID_WPS_PROBE_REQ_IE 0x0625 - -#define PACKED __attribute__ ((packed)) - -//wpa_supplicant event flags -#define RT_ASSOC_EVENT_FLAG 0x0101 -#define RT_DISASSOC_EVENT_FLAG 0x0102 -#define RT_REQIE_EVENT_FLAG 0x0103 -#define RT_RESPIE_EVENT_FLAG 0x0104 -#define RT_ASSOCINFO_EVENT_FLAG 0x0105 -#define RT_PMKIDCAND_FLAG 0x0106 -#define RT_INTERFACE_DOWN 0x0107 -#define RT_INTERFACE_UP 0x0108 - -// -// IEEE 802.11 Structures and definitions -// -// new types for Media Specific Indications - -#ifndef ULONG -#define CHAR char -#define INT int -#define SHORT int -#define UINT u32 -#undef ULONG -//#define ULONG u32 -#define ULONG unsigned long /* 32-bit in 32-bit CPU or 64-bit in 64-bit CPU */ -#define USHORT unsigned short -#define UCHAR unsigned char - -#define uint32 u32 -#define uint8 u8 - - -#define BOOLEAN u8 -//#define LARGE_INTEGER s64 -#define VOID void -#define LONG long -#define LONGLONG s64 -#define ULONGLONG u64 -typedef VOID *PVOID; -typedef CHAR *PCHAR; -typedef UCHAR *PUCHAR; -typedef USHORT *PUSHORT; -typedef LONG *PLONG; -typedef ULONG *PULONG; - -typedef union _LARGE_INTEGER { - struct { - ULONG LowPart; - LONG HighPart; - }vv; - struct { - ULONG LowPart; - LONG HighPart; - } u; - s64 QuadPart; -} LARGE_INTEGER; - -#endif - -#define NDIS_802_11_LENGTH_SSID 32 -#define NDIS_802_11_LENGTH_RATES 8 -#define NDIS_802_11_LENGTH_RATES_EX 16 -#define MAX_LEN_OF_SSID 32 -#define MAC_ADDR_LEN 6 - -typedef UCHAR NDIS_802_11_MAC_ADDRESS[6]; - -// mask for authentication/integrity fields -#define NDIS_802_11_AUTH_REQUEST_AUTH_FIELDS 0x0f - -#define NDIS_802_11_AUTH_REQUEST_REAUTH 0x01 -#define NDIS_802_11_AUTH_REQUEST_KEYUPDATE 0x02 -#define NDIS_802_11_AUTH_REQUEST_PAIRWISE_ERROR 0x06 -#define NDIS_802_11_AUTH_REQUEST_GROUP_ERROR 0x0E - -// Added new types for OFDM 5G and 2.4G -typedef enum _NDIS_802_11_NETWORK_TYPE -{ - Ndis802_11FH, - Ndis802_11DS, - Ndis802_11OFDM5, - Ndis802_11OFDM24, - Ndis802_11Automode, - Ndis802_11NetworkTypeMax // not a real type, defined as an upper bound -} NDIS_802_11_NETWORK_TYPE, *PNDIS_802_11_NETWORK_TYPE; - -// -// Received Signal Strength Indication -// -typedef LONG NDIS_802_11_RSSI; // in dBm - -typedef struct _NDIS_802_11_CONFIGURATION_FH -{ - ULONG Length; // Length of structure - ULONG HopPattern; // As defined by 802.11, MSB set - ULONG HopSet; // to one if non-802.11 - ULONG DwellTime; // units are Kusec -} NDIS_802_11_CONFIGURATION_FH, *PNDIS_802_11_CONFIGURATION_FH; - -typedef struct _NDIS_802_11_CONFIGURATION -{ - ULONG Length; // Length of structure - ULONG BeaconPeriod; // units are Kusec - ULONG ATIMWindow; // units are Kusec - ULONG DSConfig; // Frequency, units are kHz - NDIS_802_11_CONFIGURATION_FH FHConfig; -} NDIS_802_11_CONFIGURATION, *PNDIS_802_11_CONFIGURATION; - -typedef ULONG NDIS_802_11_KEY_INDEX; -typedef ULONGLONG NDIS_802_11_KEY_RSC; - -// Key mapping keys require a BSSID -typedef struct _NDIS_802_11_KEY -{ - UINT Length; // Length of this structure - UINT KeyIndex; - UINT KeyLength; // length of key in bytes - NDIS_802_11_MAC_ADDRESS BSSID; - NDIS_802_11_KEY_RSC KeyRSC; - UCHAR KeyMaterial[1]; // variable length depending on above field -} NDIS_802_11_KEY, *PNDIS_802_11_KEY; - -typedef struct _NDIS_802_11_REMOVE_KEY -{ - UINT Length; // Length of this structure - UINT KeyIndex; - NDIS_802_11_MAC_ADDRESS BSSID; -} NDIS_802_11_REMOVE_KEY, *PNDIS_802_11_REMOVE_KEY; - -typedef struct PACKED _NDIS_802_11_WEP -{ - UINT Length; // Length of this structure - UINT KeyIndex; // 0 is the per-client key, 1-N are the - // global keys - UINT KeyLength; // length of key in bytes - UCHAR KeyMaterial[1];// variable length depending on above field -} NDIS_802_11_WEP, *PNDIS_802_11_WEP; - - -typedef enum _NDIS_802_11_NETWORK_INFRASTRUCTURE -{ - Ndis802_11IBSS, - Ndis802_11Infrastructure, - Ndis802_11AutoUnknown, - Ndis802_11InfrastructureMax // Not a real value, defined as upper bound -} NDIS_802_11_NETWORK_INFRASTRUCTURE, *PNDIS_802_11_NETWORK_INFRASTRUCTURE; - -// PMKID Structures -typedef UCHAR NDIS_802_11_PMKID_VALUE[16]; - -typedef struct _BSSID_INFO -{ - NDIS_802_11_MAC_ADDRESS BSSID; - NDIS_802_11_PMKID_VALUE PMKID; -} BSSID_INFO, *PBSSID_INFO; - -typedef struct _NDIS_802_11_PMKID -{ - ULONG Length; - ULONG BSSIDInfoCount; - BSSID_INFO BSSIDInfo[1]; -} NDIS_802_11_PMKID, *PNDIS_802_11_PMKID; - -//Added new types for PMKID Candidate lists. -typedef struct _PMKID_CANDIDATE { - NDIS_802_11_MAC_ADDRESS BSSID; - ULONG Flags; -} PMKID_CANDIDATE, *PPMKID_CANDIDATE; - -typedef struct _NDIS_802_11_PMKID_CANDIDATE_LIST -{ - ULONG Version; // Version of the structure - ULONG NumCandidates; // No. of pmkid candidates - PMKID_CANDIDATE CandidateList[1]; -} NDIS_802_11_PMKID_CANDIDATE_LIST, *PNDIS_802_11_PMKID_CANDIDATE_LIST; - -//Flags for PMKID Candidate list structure -#define NDIS_802_11_PMKID_CANDIDATE_PREAUTH_ENABLED 0x01 - -// Add new authentication modes -typedef enum _NDIS_802_11_AUTHENTICATION_MODE -{ - Ndis802_11AuthModeOpen, - Ndis802_11AuthModeShared, - Ndis802_11AuthModeAutoSwitch, - Ndis802_11AuthModeWPA, - Ndis802_11AuthModeWPAPSK, - Ndis802_11AuthModeWPANone, - Ndis802_11AuthModeWPA2, - Ndis802_11AuthModeWPA2PSK, - Ndis802_11AuthModeMax // Not a real mode, defined as upper bound -} NDIS_802_11_AUTHENTICATION_MODE, *PNDIS_802_11_AUTHENTICATION_MODE; - -typedef UCHAR NDIS_802_11_RATES[NDIS_802_11_LENGTH_RATES]; // Set of 8 data rates -typedef UCHAR NDIS_802_11_RATES_EX[NDIS_802_11_LENGTH_RATES_EX]; // Set of 16 data rates - -typedef struct PACKED _NDIS_802_11_SSID -{ - INT SsidLength; // length of SSID field below, in bytes; - // this can be zero. - UCHAR Ssid[NDIS_802_11_LENGTH_SSID]; // SSID information field -} NDIS_802_11_SSID, *PNDIS_802_11_SSID; - - -typedef struct PACKED _NDIS_WLAN_BSSID -{ - ULONG Length; // Length of this structure - NDIS_802_11_MAC_ADDRESS MacAddress; // BSSID - UCHAR Reserved[2]; - NDIS_802_11_SSID Ssid; // SSID - ULONG Privacy; // WEP encryption requirement - NDIS_802_11_RSSI Rssi; // receive signal - // strength in dBm - NDIS_802_11_NETWORK_TYPE NetworkTypeInUse; - NDIS_802_11_CONFIGURATION Configuration; - NDIS_802_11_NETWORK_INFRASTRUCTURE InfrastructureMode; - NDIS_802_11_RATES SupportedRates; -} NDIS_WLAN_BSSID, *PNDIS_WLAN_BSSID; - -typedef struct PACKED _NDIS_802_11_BSSID_LIST -{ - UINT NumberOfItems; // in list below, at least 1 - NDIS_WLAN_BSSID Bssid[1]; -} NDIS_802_11_BSSID_LIST, *PNDIS_802_11_BSSID_LIST; - -// Added Capabilities, IELength and IEs for each BSSID -typedef struct PACKED _NDIS_WLAN_BSSID_EX -{ - ULONG Length; // Length of this structure - NDIS_802_11_MAC_ADDRESS MacAddress; // BSSID - UCHAR Reserved[2]; - NDIS_802_11_SSID Ssid; // SSID - UINT Privacy; // WEP encryption requirement - NDIS_802_11_RSSI Rssi; // receive signal - // strength in dBm - NDIS_802_11_NETWORK_TYPE NetworkTypeInUse; - NDIS_802_11_CONFIGURATION Configuration; - NDIS_802_11_NETWORK_INFRASTRUCTURE InfrastructureMode; - NDIS_802_11_RATES_EX SupportedRates; - ULONG IELength; - UCHAR IEs[1]; -} NDIS_WLAN_BSSID_EX, *PNDIS_WLAN_BSSID_EX; - -typedef struct PACKED _NDIS_802_11_BSSID_LIST_EX -{ - UINT NumberOfItems; // in list below, at least 1 - NDIS_WLAN_BSSID_EX Bssid[1]; -} NDIS_802_11_BSSID_LIST_EX, *PNDIS_802_11_BSSID_LIST_EX; - -typedef struct PACKED _NDIS_802_11_FIXED_IEs -{ - UCHAR Timestamp[8]; - USHORT BeaconInterval; - USHORT Capabilities; -} NDIS_802_11_FIXED_IEs, *PNDIS_802_11_FIXED_IEs; - -// Added new encryption types -// Also aliased typedef to new name -typedef enum _NDIS_802_11_WEP_STATUS -{ - Ndis802_11WEPEnabled, - Ndis802_11Encryption1Enabled = Ndis802_11WEPEnabled, - Ndis802_11WEPDisabled, - Ndis802_11EncryptionDisabled = Ndis802_11WEPDisabled, - Ndis802_11WEPKeyAbsent, - Ndis802_11Encryption1KeyAbsent = Ndis802_11WEPKeyAbsent, - Ndis802_11WEPNotSupported, - Ndis802_11EncryptionNotSupported = Ndis802_11WEPNotSupported, - Ndis802_11Encryption2Enabled, - Ndis802_11Encryption2KeyAbsent, - Ndis802_11Encryption3Enabled, - Ndis802_11Encryption3KeyAbsent -} NDIS_802_11_WEP_STATUS, *PNDIS_802_11_WEP_STATUS, - NDIS_802_11_ENCRYPTION_STATUS, *PNDIS_802_11_ENCRYPTION_STATUS; - -typedef enum _NDIS_802_11_RELOAD_DEFAULTS -{ - Ndis802_11ReloadWEPKeys -} NDIS_802_11_RELOAD_DEFAULTS, *PNDIS_802_11_RELOAD_DEFAULTS; - -#define NDIS_802_11_AI_REQFI_CAPABILITIES 1 -#define NDIS_802_11_AI_REQFI_LISTENINTERVAL 2 -#define NDIS_802_11_AI_REQFI_CURRENTAPADDRESS 4 - -#define NDIS_802_11_AI_RESFI_CAPABILITIES 1 -#define NDIS_802_11_AI_RESFI_STATUSCODE 2 -#define NDIS_802_11_AI_RESFI_ASSOCIATIONID 4 - -typedef struct _NDIS_802_11_AI_REQFI -{ - USHORT Capabilities; - USHORT ListenInterval; - NDIS_802_11_MAC_ADDRESS CurrentAPAddress; -} NDIS_802_11_AI_REQFI, *PNDIS_802_11_AI_REQFI; - -typedef struct _NDIS_802_11_AI_RESFI -{ - USHORT Capabilities; - USHORT StatusCode; - USHORT AssociationId; -} NDIS_802_11_AI_RESFI, *PNDIS_802_11_AI_RESFI; - -typedef struct _NDIS_802_11_ASSOCIATION_INFORMATION -{ - ULONG Length; - USHORT AvailableRequestFixedIEs; - NDIS_802_11_AI_REQFI RequestFixedIEs; - ULONG RequestIELength; - ULONG OffsetRequestIEs; - USHORT AvailableResponseFixedIEs; - NDIS_802_11_AI_RESFI ResponseFixedIEs; - ULONG ResponseIELength; - ULONG OffsetResponseIEs; -} NDIS_802_11_ASSOCIATION_INFORMATION, *PNDIS_802_11_ASSOCIATION_INFORMATION; - -struct ndis_pmkid_entry { - struct ndis_pmkid_entry *next; - u8 bssid[ETH_ALEN]; - u8 pmkid[16]; -}; - -typedef struct _MLME_DEAUTH_REQ_STRUCT { - UCHAR Addr[MAC_ADDR_LEN]; - USHORT Reason; -} MLME_DEAUTH_REQ_STRUCT, *PMLME_DEAUTH_REQ_STRUCT; diff --git a/hostapd-0.8/src/drivers/driver_roboswitch.c b/hostapd-0.8/src/drivers/driver_roboswitch.c deleted file mode 100644 index c014b96..0000000 --- a/hostapd-0.8/src/drivers/driver_roboswitch.c +++ /dev/null @@ -1,480 +0,0 @@ -/* - * WPA Supplicant - roboswitch driver interface - * Copyright (c) 2008-2009 Jouke Witteveen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#include "includes.h" -#include -#include -#include -#include -#include - -#include "common.h" -#include "driver.h" -#include "l2_packet/l2_packet.h" - -#define ROBO_PHY_ADDR 0x1e /* RoboSwitch PHY address */ - -/* MII access registers */ -#define ROBO_MII_PAGE 0x10 /* MII page register */ -#define ROBO_MII_ADDR 0x11 /* MII address register */ -#define ROBO_MII_DATA_OFFSET 0x18 /* Start of MII data registers */ - -#define ROBO_MII_PAGE_ENABLE 0x01 /* MII page op code */ -#define ROBO_MII_ADDR_WRITE 0x01 /* MII address write op code */ -#define ROBO_MII_ADDR_READ 0x02 /* MII address read op code */ -#define ROBO_MII_DATA_MAX 4 /* Consecutive MII data registers */ -#define ROBO_MII_RETRY_MAX 10 /* Read attempts before giving up */ - -/* Page numbers */ -#define ROBO_ARLCTRL_PAGE 0x04 /* ARL control page */ -#define ROBO_VLAN_PAGE 0x34 /* VLAN page */ - -/* ARL control page registers */ -#define ROBO_ARLCTRL_CONF 0x00 /* ARL configuration register */ -#define ROBO_ARLCTRL_ADDR_1 0x10 /* Multiport address 1 */ -#define ROBO_ARLCTRL_VEC_1 0x16 /* Multiport vector 1 */ -#define ROBO_ARLCTRL_ADDR_2 0x20 /* Multiport address 2 */ -#define ROBO_ARLCTRL_VEC_2 0x26 /* Multiport vector 2 */ - -/* VLAN page registers */ -#define ROBO_VLAN_ACCESS 0x08 /* VLAN table access register */ -#define ROBO_VLAN_ACCESS_5350 0x06 /* VLAN table access register (5350) */ -#define ROBO_VLAN_READ 0x0c /* VLAN read register */ -#define ROBO_VLAN_MAX 0xff /* Maximum number of VLANs */ - - -static const u8 pae_group_addr[ETH_ALEN] = -{ 0x01, 0x80, 0xc2, 0x00, 0x00, 0x03 }; - - -struct wpa_driver_roboswitch_data { - void *ctx; - struct l2_packet_data *l2; - char ifname[IFNAMSIZ + 1]; - u8 own_addr[ETH_ALEN]; - struct ifreq ifr; - int fd, is_5350; - u16 ports; -}; - - -/* Copied from the kernel-only part of mii.h. */ -static inline struct mii_ioctl_data *if_mii(struct ifreq *rq) -{ - return (struct mii_ioctl_data *) &rq->ifr_ifru; -} - - -/* - * RoboSwitch uses 16-bit Big Endian addresses. - * The ordering of the words is reversed in the MII registers. - */ -static void wpa_driver_roboswitch_addr_be16(const u8 addr[ETH_ALEN], u16 *be) -{ - int i; - for (i = 0; i < ETH_ALEN; i += 2) - be[(ETH_ALEN - i) / 2 - 1] = WPA_GET_BE16(addr + i); -} - - -static u16 wpa_driver_roboswitch_mdio_read( - struct wpa_driver_roboswitch_data *drv, u8 reg) -{ - struct mii_ioctl_data *mii = if_mii(&drv->ifr); - - mii->phy_id = ROBO_PHY_ADDR; - mii->reg_num = reg; - - if (ioctl(drv->fd, SIOCGMIIREG, &drv->ifr) < 0) { - perror("ioctl[SIOCGMIIREG]"); - return 0x00; - } - return mii->val_out; -} - - -static void wpa_driver_roboswitch_mdio_write( - struct wpa_driver_roboswitch_data *drv, u8 reg, u16 val) -{ - struct mii_ioctl_data *mii = if_mii(&drv->ifr); - - mii->phy_id = ROBO_PHY_ADDR; - mii->reg_num = reg; - mii->val_in = val; - - if (ioctl(drv->fd, SIOCSMIIREG, &drv->ifr) < 0) { - perror("ioctl[SIOCSMIIREG"); - } -} - - -static int wpa_driver_roboswitch_reg(struct wpa_driver_roboswitch_data *drv, - u8 page, u8 reg, u8 op) -{ - int i; - - /* set page number */ - wpa_driver_roboswitch_mdio_write(drv, ROBO_MII_PAGE, - (page << 8) | ROBO_MII_PAGE_ENABLE); - /* set register address */ - wpa_driver_roboswitch_mdio_write(drv, ROBO_MII_ADDR, (reg << 8) | op); - - /* check if operation completed */ - for (i = 0; i < ROBO_MII_RETRY_MAX; ++i) { - if ((wpa_driver_roboswitch_mdio_read(drv, ROBO_MII_ADDR) & 3) - == 0) - return 0; - } - /* timeout */ - return -1; -} - - -static int wpa_driver_roboswitch_read(struct wpa_driver_roboswitch_data *drv, - u8 page, u8 reg, u16 *val, int len) -{ - int i; - - if (len > ROBO_MII_DATA_MAX || - wpa_driver_roboswitch_reg(drv, page, reg, ROBO_MII_ADDR_READ) < 0) - return -1; - - for (i = 0; i < len; ++i) { - val[i] = wpa_driver_roboswitch_mdio_read( - drv, ROBO_MII_DATA_OFFSET + i); - } - - return 0; -} - - -static int wpa_driver_roboswitch_write(struct wpa_driver_roboswitch_data *drv, - u8 page, u8 reg, u16 *val, int len) -{ - int i; - - if (len > ROBO_MII_DATA_MAX) return -1; - for (i = 0; i < len; ++i) { - wpa_driver_roboswitch_mdio_write(drv, ROBO_MII_DATA_OFFSET + i, - val[i]); - } - return wpa_driver_roboswitch_reg(drv, page, reg, ROBO_MII_ADDR_WRITE); -} - - -static void wpa_driver_roboswitch_receive(void *priv, const u8 *src_addr, - const u8 *buf, size_t len) -{ - struct wpa_driver_roboswitch_data *drv = priv; - - if (len > 14 && WPA_GET_BE16(buf + 12) == ETH_P_EAPOL && - os_memcmp(buf, drv->own_addr, ETH_ALEN) == 0) - drv_event_eapol_rx(drv->ctx, src_addr, buf + 14, len - 14); -} - - -static int wpa_driver_roboswitch_get_ssid(void *priv, u8 *ssid) -{ - ssid[0] = 0; - return 0; -} - - -static int wpa_driver_roboswitch_get_bssid(void *priv, u8 *bssid) -{ - /* Report PAE group address as the "BSSID" for wired connection. */ - os_memcpy(bssid, pae_group_addr, ETH_ALEN); - return 0; -} - - -static int wpa_driver_roboswitch_get_capa(void *priv, - struct wpa_driver_capa *capa) -{ - os_memset(capa, 0, sizeof(*capa)); - capa->flags = WPA_DRIVER_FLAGS_WIRED; - return 0; -} - - -static int wpa_driver_roboswitch_set_param(void *priv, const char *param) -{ - struct wpa_driver_roboswitch_data *drv = priv; - char *sep; - - if (param == NULL || os_strstr(param, "multicast_only=1") == NULL) { - sep = drv->ifname + os_strlen(drv->ifname); - *sep = '.'; - drv->l2 = l2_packet_init(drv->ifname, NULL, ETH_P_ALL, - wpa_driver_roboswitch_receive, drv, - 1); - if (drv->l2 == NULL) { - wpa_printf(MSG_INFO, "%s: Unable to listen on %s", - __func__, drv->ifname); - return -1; - } - *sep = '\0'; - l2_packet_get_own_addr(drv->l2, drv->own_addr); - } else { - wpa_printf(MSG_DEBUG, "%s: Ignoring unicast frames", __func__); - drv->l2 = NULL; - } - return 0; -} - - -static const char * wpa_driver_roboswitch_get_ifname(void *priv) -{ - struct wpa_driver_roboswitch_data *drv = priv; - return drv->ifname; -} - - -static int wpa_driver_roboswitch_join(struct wpa_driver_roboswitch_data *drv, - u16 ports, const u8 *addr) -{ - u16 read1[3], read2[3], addr_be16[3]; - - wpa_driver_roboswitch_addr_be16(addr, addr_be16); - - if (wpa_driver_roboswitch_read(drv, ROBO_ARLCTRL_PAGE, - ROBO_ARLCTRL_CONF, read1, 1) < 0) - return -1; - if (!(read1[0] & (1 << 4))) { - /* multiport addresses are not yet enabled */ - read1[0] |= 1 << 4; - wpa_driver_roboswitch_write(drv, ROBO_ARLCTRL_PAGE, - ROBO_ARLCTRL_ADDR_1, addr_be16, 3); - wpa_driver_roboswitch_write(drv, ROBO_ARLCTRL_PAGE, - ROBO_ARLCTRL_VEC_1, &ports, 1); - wpa_driver_roboswitch_write(drv, ROBO_ARLCTRL_PAGE, - ROBO_ARLCTRL_ADDR_2, addr_be16, 3); - wpa_driver_roboswitch_write(drv, ROBO_ARLCTRL_PAGE, - ROBO_ARLCTRL_VEC_2, &ports, 1); - wpa_driver_roboswitch_write(drv, ROBO_ARLCTRL_PAGE, - ROBO_ARLCTRL_CONF, read1, 1); - } else { - /* if both multiport addresses are the same we can add */ - wpa_driver_roboswitch_read(drv, ROBO_ARLCTRL_PAGE, - ROBO_ARLCTRL_ADDR_1, read1, 3); - wpa_driver_roboswitch_read(drv, ROBO_ARLCTRL_PAGE, - ROBO_ARLCTRL_ADDR_2, read2, 3); - if (os_memcmp(read1, read2, 6) != 0) - return -1; - wpa_driver_roboswitch_read(drv, ROBO_ARLCTRL_PAGE, - ROBO_ARLCTRL_VEC_1, read1, 1); - wpa_driver_roboswitch_read(drv, ROBO_ARLCTRL_PAGE, - ROBO_ARLCTRL_VEC_2, read2, 1); - if (read1[0] != read2[0]) - return -1; - wpa_driver_roboswitch_write(drv, ROBO_ARLCTRL_PAGE, - ROBO_ARLCTRL_ADDR_1, addr_be16, 3); - wpa_driver_roboswitch_write(drv, ROBO_ARLCTRL_PAGE, - ROBO_ARLCTRL_VEC_1, &ports, 1); - } - return 0; -} - - -static int wpa_driver_roboswitch_leave(struct wpa_driver_roboswitch_data *drv, - u16 ports, const u8 *addr) -{ - u16 _read, addr_be16[3], addr_read[3], ports_read; - - wpa_driver_roboswitch_addr_be16(addr, addr_be16); - - wpa_driver_roboswitch_read(drv, ROBO_ARLCTRL_PAGE, ROBO_ARLCTRL_CONF, - &_read, 1); - /* If ARL control is disabled, there is nothing to leave. */ - if (!(_read & (1 << 4))) return -1; - - wpa_driver_roboswitch_read(drv, ROBO_ARLCTRL_PAGE, - ROBO_ARLCTRL_ADDR_1, addr_read, 3); - wpa_driver_roboswitch_read(drv, ROBO_ARLCTRL_PAGE, ROBO_ARLCTRL_VEC_1, - &ports_read, 1); - /* check if we occupy multiport address 1 */ - if (os_memcmp(addr_read, addr_be16, 6) == 0 && ports_read == ports) { - wpa_driver_roboswitch_read(drv, ROBO_ARLCTRL_PAGE, - ROBO_ARLCTRL_ADDR_2, addr_read, 3); - wpa_driver_roboswitch_read(drv, ROBO_ARLCTRL_PAGE, - ROBO_ARLCTRL_VEC_2, &ports_read, 1); - /* and multiport address 2 */ - if (os_memcmp(addr_read, addr_be16, 6) == 0 && - ports_read == ports) { - _read &= ~(1 << 4); - wpa_driver_roboswitch_write(drv, ROBO_ARLCTRL_PAGE, - ROBO_ARLCTRL_CONF, &_read, - 1); - } else { - wpa_driver_roboswitch_read(drv, ROBO_ARLCTRL_PAGE, - ROBO_ARLCTRL_ADDR_1, - addr_read, 3); - wpa_driver_roboswitch_read(drv, ROBO_ARLCTRL_PAGE, - ROBO_ARLCTRL_VEC_1, - &ports_read, 1); - wpa_driver_roboswitch_write(drv, ROBO_ARLCTRL_PAGE, - ROBO_ARLCTRL_ADDR_2, - addr_read, 3); - wpa_driver_roboswitch_write(drv, ROBO_ARLCTRL_PAGE, - ROBO_ARLCTRL_VEC_2, - &ports_read, 1); - } - } else { - wpa_driver_roboswitch_read(drv, ROBO_ARLCTRL_PAGE, - ROBO_ARLCTRL_ADDR_2, addr_read, 3); - wpa_driver_roboswitch_read(drv, ROBO_ARLCTRL_PAGE, - ROBO_ARLCTRL_VEC_2, &ports_read, 1); - /* or multiport address 2 */ - if (os_memcmp(addr_read, addr_be16, 6) == 0 && - ports_read == ports) { - wpa_driver_roboswitch_write(drv, ROBO_ARLCTRL_PAGE, - ROBO_ARLCTRL_ADDR_1, - addr_read, 3); - wpa_driver_roboswitch_write(drv, ROBO_ARLCTRL_PAGE, - ROBO_ARLCTRL_VEC_1, - &ports_read, 1); - } else return -1; - } - return 0; -} - - -static void * wpa_driver_roboswitch_init(void *ctx, const char *ifname) -{ - struct wpa_driver_roboswitch_data *drv; - char *sep; - u16 vlan = 0, _read[2]; - - drv = os_zalloc(sizeof(*drv)); - if (drv == NULL) return NULL; - drv->ctx = ctx; - drv->own_addr[0] = '\0'; - - /* copy ifname and take a pointer to the second to last character */ - sep = drv->ifname + - os_strlcpy(drv->ifname, ifname, sizeof(drv->ifname)) - 2; - /* find the '.' seperating and */ - while (sep > drv->ifname && *sep != '.') sep--; - if (sep <= drv->ifname) { - wpa_printf(MSG_INFO, "%s: No . pair in " - "interface name %s", __func__, drv->ifname); - os_free(drv); - return NULL; - } - *sep = '\0'; - while (*++sep) { - if (*sep < '0' || *sep > '9') { - wpa_printf(MSG_INFO, "%s: Invalid vlan specification " - "in interface name %s", __func__, ifname); - os_free(drv); - return NULL; - } - vlan *= 10; - vlan += *sep - '0'; - if (vlan > ROBO_VLAN_MAX) { - wpa_printf(MSG_INFO, "%s: VLAN out of range in " - "interface name %s", __func__, ifname); - os_free(drv); - return NULL; - } - } - - drv->fd = socket(PF_INET, SOCK_DGRAM, 0); - if (drv->fd < 0) { - wpa_printf(MSG_INFO, "%s: Unable to create socket", __func__); - os_free(drv); - return NULL; - } - - os_memset(&drv->ifr, 0, sizeof(drv->ifr)); - os_strlcpy(drv->ifr.ifr_name, drv->ifname, IFNAMSIZ); - if (ioctl(drv->fd, SIOCGMIIPHY, &drv->ifr) < 0) { - perror("ioctl[SIOCGMIIPHY]"); - os_free(drv); - return NULL; - } - if (if_mii(&drv->ifr)->phy_id != ROBO_PHY_ADDR) { - wpa_printf(MSG_INFO, "%s: Invalid phy address (not a " - "RoboSwitch?)", __func__); - os_free(drv); - return NULL; - } - - /* set and read back to see if the register can be used */ - _read[0] = ROBO_VLAN_MAX; - wpa_driver_roboswitch_write(drv, ROBO_VLAN_PAGE, ROBO_VLAN_ACCESS_5350, - _read, 1); - wpa_driver_roboswitch_read(drv, ROBO_VLAN_PAGE, ROBO_VLAN_ACCESS_5350, - _read + 1, 1); - drv->is_5350 = _read[0] == _read[1]; - - /* set the read bit */ - vlan |= 1 << 13; - wpa_driver_roboswitch_write(drv, ROBO_VLAN_PAGE, - drv->is_5350 ? ROBO_VLAN_ACCESS_5350 - : ROBO_VLAN_ACCESS, - &vlan, 1); - wpa_driver_roboswitch_read(drv, ROBO_VLAN_PAGE, ROBO_VLAN_READ, _read, - drv->is_5350 ? 2 : 1); - if (!(drv->is_5350 ? _read[1] & (1 << 4) : _read[0] & (1 << 14))) { - wpa_printf(MSG_INFO, "%s: Could not get port information for " - "VLAN %d", __func__, vlan & ~(1 << 13)); - os_free(drv); - return NULL; - } - drv->ports = _read[0] & 0x001F; - /* add the MII port */ - drv->ports |= 1 << 8; - if (wpa_driver_roboswitch_join(drv, drv->ports, pae_group_addr) < 0) { - wpa_printf(MSG_INFO, "%s: Unable to join PAE group", __func__); - os_free(drv); - return NULL; - } else { - wpa_printf(MSG_DEBUG, "%s: Added PAE group address to " - "RoboSwitch ARL", __func__); - } - - return drv; -} - - -static void wpa_driver_roboswitch_deinit(void *priv) -{ - struct wpa_driver_roboswitch_data *drv = priv; - - if (drv->l2) { - l2_packet_deinit(drv->l2); - drv->l2 = NULL; - } - if (wpa_driver_roboswitch_leave(drv, drv->ports, pae_group_addr) < 0) { - wpa_printf(MSG_DEBUG, "%s: Unable to leave PAE group", - __func__); - } - - close(drv->fd); - os_free(drv); -} - - -const struct wpa_driver_ops wpa_driver_roboswitch_ops = { - .name = "roboswitch", - .desc = "wpa_supplicant roboswitch driver", - .get_ssid = wpa_driver_roboswitch_get_ssid, - .get_bssid = wpa_driver_roboswitch_get_bssid, - .get_capa = wpa_driver_roboswitch_get_capa, - .init = wpa_driver_roboswitch_init, - .deinit = wpa_driver_roboswitch_deinit, - .set_param = wpa_driver_roboswitch_set_param, - .get_ifname = wpa_driver_roboswitch_get_ifname, -}; diff --git a/hostapd-0.8/src/drivers/driver_rtl.h b/hostapd-0.8/src/drivers/driver_rtl.h deleted file mode 100644 index efcd38f..0000000 --- a/hostapd-0.8/src/drivers/driver_rtl.h +++ /dev/null @@ -1,113 +0,0 @@ - -#ifndef _DRIVER_RTL_H_ -#define _DRIVER_RTL_H_ - - -#define RTL_IOCTL_HOSTAPD (SIOCIWFIRSTPRIV + 28) - -#define IEEE_CRYPT_ALG_NAME_LEN (16) - -/* RTL871X_IOCTL_HOSTAPD ioctl() cmd: */ -enum { - RTL871X_HOSTAPD_FLUSH = 1, - RTL871X_HOSTAPD_ADD_STA = 2, - RTL871X_HOSTAPD_REMOVE_STA = 3, - RTL871X_HOSTAPD_GET_INFO_STA = 4, - /* REMOVED: PRISM2_HOSTAPD_RESET_TXEXC_STA = 5, */ - RTL871X_HOSTAPD_GET_WPAIE_STA = 5, - RTL871X_SET_ENCRYPTION = 6, - RTL871X_GET_ENCRYPTION = 7, - RTL871X_HOSTAPD_SET_FLAGS_STA = 8, - RTL871X_HOSTAPD_GET_RID = 9, - RTL871X_HOSTAPD_SET_RID = 10, - RTL871X_HOSTAPD_SET_ASSOC_AP_ADDR = 11, - RTL871X_HOSTAPD_SET_GENERIC_ELEMENT = 12, - RTL871X_HOSTAPD_MLME = 13, - RTL871X_HOSTAPD_SCAN_REQ = 14, - RTL871X_HOSTAPD_STA_CLEAR_STATS = 15, - RTL871X_HOSTAPD_SET_BEACON = 16, - RTL871X_HOSTAPD_SET_WPS_BEACON = 17, - RTL871X_HOSTAPD_SET_WPS_PROBE_RESP = 18, - RTL871X_HOSTAPD_SET_WPS_ASSOC_RESP = 19, -}; - -typedef struct ieee_param { - u32 cmd; - u8 sta_addr[ETH_ALEN]; - union { - struct { - u8 name; - u32 value; - } wpa_param; - struct { - u32 len; - u8 reserved[32]; - u8 data[0]; - } wpa_ie; - struct{ - int command; - int reason_code; - } mlme; - struct { - u8 alg[IEEE_CRYPT_ALG_NAME_LEN]; - u8 set_tx; - u32 err; - u8 idx; - u8 seq[8]; /* sequence counter (set: RX, get: TX) */ - u16 key_len; - u8 key[0]; - } crypt; - struct { - u16 aid; - u16 capability; - int flags; - u8 tx_supp_rates[16]; - //struct ieee80211_ht_capability ht_cap; - struct ieee80211_ht_capabilities ht_cap; - } add_sta; - struct { - u8 reserved[2];//for set max_num_sta - u8 buf[0]; - } bcn_ie; - - } u; - -} ieee_param; - - - -#define IEEE80211_CCK_RATE_LEN 4 -#define IEEE80211_OFDM_RATE_LEN 8 - -#define IEEE80211_CCK_RATE_1MB 0x02 -#define IEEE80211_CCK_RATE_2MB 0x04 -#define IEEE80211_CCK_RATE_5MB 0x0B -#define IEEE80211_CCK_RATE_11MB 0x16 -#define IEEE80211_OFDM_RATE_6MB 0x0C -#define IEEE80211_OFDM_RATE_9MB 0x12 -#define IEEE80211_OFDM_RATE_12MB 0x18 -#define IEEE80211_OFDM_RATE_18MB 0x24 -#define IEEE80211_OFDM_RATE_24MB 0x30 -#define IEEE80211_OFDM_RATE_36MB 0x48 -#define IEEE80211_OFDM_RATE_48MB 0x60 -#define IEEE80211_OFDM_RATE_54MB 0x6C -#define IEEE80211_BASIC_RATE_MASK 0x80 - -#define IEEE80211_CCK_RATE_1MB_MASK (1<<0) -#define IEEE80211_CCK_RATE_2MB_MASK (1<<1) -#define IEEE80211_CCK_RATE_5MB_MASK (1<<2) -#define IEEE80211_CCK_RATE_11MB_MASK (1<<3) -#define IEEE80211_OFDM_RATE_6MB_MASK (1<<4) -#define IEEE80211_OFDM_RATE_9MB_MASK (1<<5) -#define IEEE80211_OFDM_RATE_12MB_MASK (1<<6) -#define IEEE80211_OFDM_RATE_18MB_MASK (1<<7) -#define IEEE80211_OFDM_RATE_24MB_MASK (1<<8) -#define IEEE80211_OFDM_RATE_36MB_MASK (1<<9) -#define IEEE80211_OFDM_RATE_48MB_MASK (1<<10) -#define IEEE80211_OFDM_RATE_54MB_MASK (1<<11) - -#define IEEE80211_CCK_RATES_MASK 0x0000000F -#define IEEE80211_OFDM_RATES_MASK 0x00000FF0 - -#endif - diff --git a/hostapd-0.8/src/drivers/driver_rtw.c b/hostapd-0.8/src/drivers/driver_rtw.c deleted file mode 100644 index e683e6d..0000000 --- a/hostapd-0.8/src/drivers/driver_rtw.c +++ /dev/null @@ -1,1902 +0,0 @@ -/* - * hostapd / Driver interface for rtl871x driver - * Copyright (c) 2010, - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -//#define CONFIG_MGNT_L2SOCK 1 -#define CONFIG_MLME_OFFLOAD 1 - - -#include "includes.h" -#include -#include - -#include "common.h" - -#include "wireless_copy.h" - -#include "driver.h" -#include "eloop.h" -#include "priv_netlink.h" -#include "l2_packet/l2_packet.h" -#include "common/ieee802_11_defs.h" -#include "netlink.h" -#include "linux_ioctl.h" - -//#include "../src/ap/hostapd.h" -//#include "../src/ap/ap_config.h" -#include "ap/hostapd.h" -#include "ap/ap_config.h" - -#ifdef USE_KERNEL_HEADERS -/* compat-wireless does not include linux/compiler.h to define __user, so - * define it here */ -#ifndef __user -#define __user -#endif /* __user */ -#include -#include -#include /* The L2 protocols */ -#include -#include -#else /* USE_KERNEL_HEADERS */ -#include -#include -//#include "wireless_copy.h" -#endif /* USE_KERNEL_HEADERS */ - -//#include - - -#ifndef ETH_P_80211_RAW -#define ETH_P_80211_RAW 0x0019 -#endif - -#if 0 -#include "hostapd.h" -#include "driver.h" -#include "ieee802_1x.h" -#include "eloop.h" -#include "priv_netlink.h" -#include "sta_info.h" -#include "l2_packet/l2_packet.h" - -#include "wpa.h" -#include "accounting.h" -#include "ieee802_11.h" -#include "hw_features.h" -#include "radius/radius.h" -#endif - -#include "driver_rtl.h" - - -//static int rtl871x_sta_remove_ops(void *priv, const u8 *addr); - -struct rtl871x_driver_data { - struct hostapd_data *hapd; - - char iface[IFNAMSIZ + 1]; - int ifindex; - struct l2_packet_data *l2_sock;/* socket for sending eapol frames*/ - struct l2_packet_data *l2_sock_recv;/* raw packet recv socket from bridge interface*/ -#ifdef CONFIG_MGNT_L2SOCK - struct l2_packet_data *mgnt_l2_sock; /* socket for tx/rx management frames*/ -#else - int mgnt_sock;/* socket for tx/rx management frames*/ -#endif - int ioctl_sock; /* socket for ioctl() use */ - int wext_sock; /* socket for wireless events */ - - struct netlink_data *netlink; - - int we_version; - - u8 hw_mac[ETH_ALEN]; - - u8 acct_mac[ETH_ALEN]; - - struct hostap_sta_driver_data acct_data; - -}; - -/* -static const char *ether_sprintf(const u8 *addr) -{ - static char buf[sizeof(MACSTR)]; - - if (addr != NULL) - snprintf(buf, sizeof(buf), MACSTR, MAC2STR(addr)); - else - snprintf(buf, sizeof(buf), MACSTR, 0,0,0,0,0,0); - - return buf; -} -*/ - -#ifndef CONFIG_MLME_OFFLOAD -static int rtl871x_set_iface_flags(void *priv, int dev_up) -{ - struct rtl871x_driver_data *drv = priv; - struct ifreq ifr; - - wpa_printf(MSG_DEBUG, "%s: dev_up=%d", __func__, dev_up); - - if (drv->mgnt_sock < 0) - return -1; - - memset(&ifr, 0, sizeof(ifr)); - //os_strlcpy(ifr.ifr_name, drv->iface, IFNAMSIZ); - //os_strlcpy(ifr.ifr_name, "mgnt.wlan", IFNAMSIZ); - snprintf(ifr.ifr_name, IFNAMSIZ, "mgnt.%s", "wlan0"); - - if (ioctl(drv->mgnt_sock, SIOCGIFFLAGS, &ifr) != 0) { - perror("ioctl[SIOCGIFFLAGS]"); - return -1; - } - - if (dev_up) - ifr.ifr_flags |= IFF_UP; - else - ifr.ifr_flags &= ~IFF_UP; - - if (ioctl(drv->mgnt_sock, SIOCSIFFLAGS, &ifr) != 0) { - perror("ioctl[SIOCSIFFLAGS]"); - return -1; - } - -#if 0 - if (dev_up) { - memset(&ifr, 0, sizeof(ifr)); - os_strlcpy(ifr.ifr_name, drv->iface, IFNAMSIZ); - ifr.ifr_mtu = HOSTAPD_MTU; - if (ioctl(drv->ioctl_sock, SIOCSIFMTU, &ifr) != 0) { - perror("ioctl[SIOCSIFMTU]"); - printf("Setting MTU failed - trying to survive with " - "current value\n"); - } - } -#endif - - return 0; -} -#endif - -static int rtl871x_hostapd_ioctl(struct rtl871x_driver_data *drv, ieee_param *param, int len) -{ - struct iwreq iwr; - - memset(&iwr, 0, sizeof(iwr)); - os_strlcpy(iwr.ifr_name, drv->iface, IFNAMSIZ); - iwr.u.data.pointer = (caddr_t) param; - iwr.u.data.length = len; - - if (ioctl(drv->ioctl_sock, RTL_IOCTL_HOSTAPD, &iwr) < 0) { - perror("ioctl[RTL_IOCTL_HOSTAPD]"); - return -1; - } - - return 0; -} - -static int rtl871x_set_mode(struct rtl871x_driver_data *drv, u32 mode) -{ - struct iwreq iwr; - - if (drv->ioctl_sock < 0) - return -1; - - memset(&iwr, 0, sizeof(iwr)); - - os_strlcpy(iwr.ifr_name, drv->iface, IFNAMSIZ); - - //iwr.u.mode = IW_MODE_MASTER; - iwr.u.mode = mode; - - if (ioctl(drv->ioctl_sock, SIOCSIWMODE, &iwr) < 0) { - perror("ioctl[SIOCSIWMODE]"); - printf("Could not set interface to mode(%d)!\n", mode); - return -1; - } - - return 0; - -} - -/* -static int rtl871x_notif_assoc(struct hostapd_data *hapd, const u8 *addr, - const u8 *ie, size_t ielen) -{ - struct sta_info *sta; - int new_assoc, res; - - //hostapd_logger(hapd, addr, HOSTAPD_MODULE_IEEE80211, - // HOSTAPD_LEVEL_INFO, "associated"); - - sta = ap_get_sta(hapd, addr); - if (sta) { - accounting_sta_stop(hapd, sta); - } else { - sta = ap_sta_add(hapd, addr); - if (sta == NULL) - { - rtl871x_sta_remove_ops(hapd->drv_priv, addr); - return -1; - } - } - sta->flags &= ~(WLAN_STA_WPS | WLAN_STA_MAYBE_WPS); - - if (hapd->conf->wpa) { - if (ie == NULL || ielen == 0) { - if (hapd->conf->wps_state) { - wpa_printf(MSG_DEBUG, "STA did not include " - "WPA/RSN IE in (Re)Association " - "Request - possible WPS use"); - sta->flags |= WLAN_STA_MAYBE_WPS; - goto skip_wpa_check; - } - - wpa_printf(MSG_DEBUG, "No WPA/RSN IE from STA"); - return -1; - } - if (hapd->conf->wps_state && ie[0] == 0xdd && ie[1] >= 4 && - os_memcmp(ie + 2, "\x00\x50\xf2\x04", 4) == 0) { - sta->flags |= WLAN_STA_WPS; - goto skip_wpa_check; - } - - if (sta->wpa_sm == NULL) - sta->wpa_sm = wpa_auth_sta_init(hapd->wpa_auth, - sta->addr); - if (sta->wpa_sm == NULL) { - wpa_printf(MSG_ERROR, "Failed to initialize WPA state " - "machine"); - return -1; - } - res = wpa_validate_wpa_ie(hapd->wpa_auth, sta->wpa_sm, - ie, ielen, NULL, 0); - if (res != WPA_IE_OK) { - wpa_printf(MSG_DEBUG, "WPA/RSN information element " - "rejected? (res %u)", res); - wpa_hexdump(MSG_DEBUG, "IE", ie, ielen); - return -1; - } - } else if (hapd->conf->wps_state) { - if (ie && ielen > 4 && ie[0] == 0xdd && ie[1] >= 4 && - os_memcmp(ie + 2, "\x00\x50\xf2\x04", 4) == 0) { - sta->flags |= WLAN_STA_WPS; - } else - sta->flags |= WLAN_STA_MAYBE_WPS; - } -skip_wpa_check: - - new_assoc = (sta->flags & WLAN_STA_ASSOC) == 0; - sta->flags |= WLAN_STA_AUTH | WLAN_STA_ASSOC; - wpa_auth_sm_event(sta->wpa_sm, WPA_ASSOC); - - hostapd_new_assoc_sta(hapd, sta, !new_assoc); - - ieee802_1x_notify_port_enabled(sta->eapol_sm, 1); - - return 0; -} -*/ - -static int rtl871x_get_sta_wpaie(struct rtl871x_driver_data *drv, u8 *iebuf, u8 *addr) -{ - struct ieee_param param; - - printf("+%s, " MACSTR " is sta's address\n", __func__, MAC2STR(addr)); - - memset(¶m, 0, sizeof(param)); - - param.cmd = RTL871X_HOSTAPD_GET_WPAIE_STA; - - memcpy(param.sta_addr, addr, ETH_ALEN); - - if (rtl871x_hostapd_ioctl(drv, ¶m, sizeof(param))) { - printf("Could not get sta wpaie from kernel driver.\n"); - return -1; - } - - - if(param.u.wpa_ie.len > 32) - return -1; - - memcpy(iebuf, param.u.wpa_ie.reserved, param.u.wpa_ie.len); - - return 0; - -} - -static int rtl871x_del_sta(struct rtl871x_driver_data *drv, u8 *addr) -{ - struct hostapd_data *hapd = drv->hapd; - -#if 1 - - //union wpa_event_data event; - //os_memset(&event, 0, sizeof(event)); - //event.disassoc_info.addr = addr; - //wpa_supplicant_event(hapd, EVENT_DISASSOC, &event); - - drv_event_disassoc(hapd, addr); - -#else - - struct sta_info *sta; - - //hostapd_logger(hapd, addr, HOSTAPD_MODULE_IEEE80211, - // HOSTAPD_LEVEL_INFO, "disassociated"); - - sta = ap_get_sta(hapd, addr); - if (sta != NULL) - { - sta->flags &= ~(WLAN_STA_AUTH | WLAN_STA_ASSOC); - wpa_auth_sm_event(sta->wpa_sm, WPA_DISASSOC); - sta->acct_terminate_cause = RADIUS_ACCT_TERMINATE_CAUSE_USER_REQUEST; - ieee802_1x_notify_port_enabled(sta->eapol_sm, 0); - ap_free_sta(hapd, sta); - } - else - { - wpa_printf(MSG_DEBUG, "Disassociation notification for " - "unknown STA " MACSTR, MAC2STR(addr)); - } -#endif - - return 0; - -} - -static int rtl871x_new_sta(struct rtl871x_driver_data *drv, u8 *addr) -{ - struct hostapd_data *hapd = drv->hapd; - //struct ieee80211req_wpaie ie; - int ielen = 0, res=0; - //u8 *iebuf = NULL; - u8 iebuf[32], *piebuf=NULL; - - /* - * Fetch negotiated WPA/RSN parameters from the driver. - */ - //memset(&ie, 0, sizeof(ie)); - //memcpy(ie.wpa_macaddr, addr, IEEE80211_ADDR_LEN); - memset(iebuf, 0 , sizeof(iebuf)); - if (rtl871x_get_sta_wpaie(drv, iebuf, addr)) { - //if (set80211priv(drv, IEEE80211_IOCTL_GETWPAIE, &ie, sizeof(ie))) { - - wpa_printf(MSG_DEBUG, "%s: Failed to get WPA/RSN IE: %s", - __func__, strerror(errno)); - goto no_ie; - } - - //wpa_hexdump(MSG_MSGDUMP, "req WPA IE", - // ie.wpa_ie, IEEE80211_MAX_OPT_IE); - - //wpa_hexdump(MSG_MSGDUMP, "req RSN IE", - // ie.rsn_ie, IEEE80211_MAX_OPT_IE); - - //iebuf = ie.wpa_ie; - -/* - if (iebuf[0] != WLAN_EID_VENDOR_SPECIFIC) - iebuf[1] = 0; - if (iebuf[1] == 0 && ie.rsn_ie[1] > 0) { - iebuf = ie.rsn_ie; - if (iebuf[0] != WLAN_EID_RSN) - iebuf[1] = 0; - } -*/ - - if ((iebuf[0] == WLAN_EID_VENDOR_SPECIFIC) || (iebuf[0] == WLAN_EID_RSN) ) - { - piebuf = iebuf; - ielen = iebuf[1]; - - if (ielen == 0) - piebuf = NULL; - else - ielen += 2; - } - -no_ie: - - //res = rtl871x_notif_assoc(hapd, addr, piebuf, ielen); - //drv_event_assoc(hapd, addr, piebuf, ielen); - drv_event_assoc(hapd, addr, piebuf, ielen, 0); - - if (memcmp(addr, drv->acct_mac, ETH_ALEN) == 0) { - /* Cached accounting data is not valid anymore. */ - memset(drv->acct_mac, 0, ETH_ALEN); - memset(&drv->acct_data, 0, sizeof(drv->acct_data)); - } - - return res; - -} - -static void rtl871x_wireless_event_wireless(struct rtl871x_driver_data *drv, - char *data, int len) -{ - struct iw_event iwe_buf, *iwe = &iwe_buf; - char *pos, *end, *custom, *buf; - - pos = data; - end = data + len; - - while (pos + IW_EV_LCP_LEN <= end) { - /* Event data may be unaligned, so make a local, aligned copy - * before processing. */ - memcpy(&iwe_buf, pos, IW_EV_LCP_LEN); - wpa_printf(MSG_MSGDUMP, "Wireless event: cmd=0x%x len=%d", - iwe->cmd, iwe->len); - if (iwe->len <= IW_EV_LCP_LEN) - return; - - custom = pos + IW_EV_POINT_LEN; - if (drv->we_version > 18 && - (iwe->cmd == IWEVMICHAELMICFAILURE || - iwe->cmd == IWEVCUSTOM)) { - /* WE-19 removed the pointer from struct iw_point */ - char *dpos = (char *) &iwe_buf.u.data.length; - int dlen = dpos - (char *) &iwe_buf; - memcpy(dpos, pos + IW_EV_LCP_LEN, - sizeof(struct iw_event) - dlen); - } else { - memcpy(&iwe_buf, pos, sizeof(struct iw_event)); - custom += IW_EV_POINT_OFF; - } - - //printf("got wireless event, iwe->cmd=%d\n", iwe->cmd); - - switch (iwe->cmd) { - case IWEVEXPIRED: - rtl871x_del_sta(drv, (u8 *)iwe->u.addr.sa_data); - break; - case IWEVREGISTERED: - if(rtl871x_new_sta(drv, (u8 *)iwe->u.addr.sa_data)) - { - printf("Failed to add new sta: "MACSTR" \n", MAC2STR((u8 *)iwe->u.addr.sa_data)); - } - break; - case IWEVCUSTOM: - if (custom + iwe->u.data.length > end) - return; - buf = malloc(iwe->u.data.length + 1); - if (buf == NULL) - return; /* XXX */ - memcpy(buf, custom, iwe->u.data.length); - buf[iwe->u.data.length] = '\0'; - //madwifi_wireless_event_wireless_custom(drv, buf); - free(buf); - break; - } - - pos += iwe->len; - } - -} - -#if 1 -static void rtl871x_wireless_event_rtm_newlink(void *ctx, - struct ifinfomsg *ifi, u8 *buf, size_t len) -{ - struct rtl871x_driver_data *drv = ctx; - int attrlen, rta_len; - struct rtattr *attr; - - if (ifi->ifi_index != drv->ifindex) - return; - - attrlen = len; - attr = (struct rtattr *) buf; - - rta_len = RTA_ALIGN(sizeof(struct rtattr)); - while (RTA_OK(attr, attrlen)) { - if (attr->rta_type == IFLA_WIRELESS) { - rtl871x_wireless_event_wireless( - drv, ((char *) attr) + rta_len, - attr->rta_len - rta_len); - } - attr = RTA_NEXT(attr, attrlen); - } -} - -#else -static void rtl871x_wireless_event_rtm_newlink(struct rtl871x_driver_data *drv, - struct nlmsghdr *h, int len) -{ - struct ifinfomsg *ifi; - int attrlen, nlmsg_len, rta_len; - struct rtattr * attr; - - if (len < (int) sizeof(*ifi)) - return; - - ifi = NLMSG_DATA(h); - - if (ifi->ifi_index != drv->ifindex) - return; - - nlmsg_len = NLMSG_ALIGN(sizeof(struct ifinfomsg)); - - attrlen = h->nlmsg_len - nlmsg_len; - if (attrlen < 0) - return; - - attr = (struct rtattr *) (((char *) ifi) + nlmsg_len); - - rta_len = RTA_ALIGN(sizeof(struct rtattr)); - while (RTA_OK(attr, attrlen)) { - if (attr->rta_type == IFLA_WIRELESS) { - rtl871x_wireless_event_wireless( - drv, ((char *) attr) + rta_len, - attr->rta_len - rta_len); - } - attr = RTA_NEXT(attr, attrlen); - } -} -#endif - -/* -static void rtl871x_wireless_event_receive(int sock, void *eloop_ctx, void *sock_ctx) -{ - char buf[256];//!!! - int left; - struct sockaddr_nl from; - socklen_t fromlen; - struct nlmsghdr *h; - struct rtl871x_driver_data *drv = eloop_ctx; - - //printf("+rtl871x_wireless_event_receive\n"); - - fromlen = sizeof(from); - left = recvfrom(sock, buf, sizeof(buf), MSG_DONTWAIT, - (struct sockaddr *) &from, &fromlen); - if (left < 0) { - if (errno != EINTR && errno != EAGAIN) - perror("recvfrom(netlink)"); - return; - } - - h = (struct nlmsghdr *)buf; - while (left >= (int) sizeof(*h)) { - int len, plen; - - len = h->nlmsg_len; - plen = len - sizeof(*h);//payload len - if (len > left || plen < 0) { - printf("Malformed netlink message: " - "len=%d left=%d plen=%d\n", - len, left, plen); - break; - } - - switch (h->nlmsg_type) { - case RTM_NEWLINK: - rtl871x_wireless_event_rtm_newlink(drv, h, plen); - break; - } - - len = NLMSG_ALIGN(len); - left -= len; - h = (struct nlmsghdr *) ((char *) h + len); - } - - if (left > 0) { - printf("%d extra bytes in the end of netlink message\n", left); - } - -} -*/ - -static int rtl871x_wireless_event_init(struct rtl871x_driver_data *drv) -{ - struct netlink_config *cfg; - - //madwifi_get_we_version(drv); - - cfg = os_zalloc(sizeof(*cfg)); - if (cfg == NULL) - return -1; - cfg->ctx = drv; - cfg->newlink_cb = rtl871x_wireless_event_rtm_newlink; - drv->netlink = netlink_init(cfg); - if (drv->netlink == NULL) { - os_free(cfg); - return -1; - } - - return 0; -} - -/* -static int rtl871x_wireless_event_init_ops(void *priv) -{ - int s; - struct sockaddr_nl local; - struct rtl871x_driver_data *drv = priv; - - //madwifi_get_we_version(drv); - - drv->wext_sock = -1; - - s = socket(PF_NETLINK, SOCK_RAW, NETLINK_ROUTE); - if (s < 0) { - perror("socket(PF_NETLINK,SOCK_RAW,NETLINK_ROUTE)"); - return -1; - } - - memset(&local, 0, sizeof(local)); - local.nl_family = AF_NETLINK; - local.nl_groups = RTMGRP_LINK; - if (bind(s, (struct sockaddr *) &local, sizeof(local)) < 0) { - perror("bind(netlink)"); - close(s); - return -1; - } - - eloop_register_read_sock(s, rtl871x_wireless_event_receive, drv, NULL); - drv->wext_sock = s; - - return 0; - -} - -static void rtl871x_wireless_event_deinit_ops(void *priv) -{ - struct rtl871x_driver_data *drv = priv; - - if (drv != NULL) { - if (drv->wext_sock < 0) - return; - eloop_unregister_read_sock(drv->wext_sock); - close(drv->wext_sock); - } -} -*/ - -#if 1 -static void rtl871x_handle_read(void *ctx, const u8 *src_addr, const u8 *buf, size_t len) -{ - struct rtl871x_driver_data *drv = ctx; - drv_event_eapol_rx(drv->hapd, src_addr, buf + sizeof(struct l2_ethhdr), - len - sizeof(struct l2_ethhdr)); -} -#else -static void rtl871x_handle_read(void *ctx, const u8 *src_addr, const u8 *buf, size_t len) -{ - struct rtl871x_driver_data *drv = ctx; - struct hostapd_data *hapd = drv->hapd; - struct sta_info *sta; - - sta = ap_get_sta(hapd, src_addr); - if (!sta || !(sta->flags & WLAN_STA_ASSOC)) { - printf("Data frame from not associated STA %s\n", - ether_sprintf(src_addr)); - /* XXX cannot happen */ - return; - } - ieee802_1x_receive(hapd, src_addr, buf + sizeof(struct l2_ethhdr), - len - sizeof(struct l2_ethhdr)); -} -#endif - -static int rtl871x_send_eapol_ops(void *priv, const u8 *addr, const u8 *data, size_t data_len, - int encrypt, const u8 *own_addr, u32 flags) -{ - struct rtl871x_driver_data *drv = priv; - unsigned char buf[3000]; - unsigned char *bp = buf; - struct l2_ethhdr *eth; - size_t len; - int status; - - printf("+rtl871x_send_eapol\n"); - - /* - * Prepend the Ethernet header. If the caller left us - * space at the front we could just insert it but since - * we don't know we copy to a local buffer. Given the frequency - * and size of frames this probably doesn't matter. - */ - len = data_len + sizeof(struct l2_ethhdr); - if (len > sizeof(buf)) { - bp = malloc(len); - if (bp == NULL) { - printf("EAPOL frame discarded, cannot malloc temp " - "buffer of size %lu!\n", (unsigned long) len); - return -1; - } - } - - eth = (struct l2_ethhdr *) bp; - memcpy(eth->h_dest, addr, ETH_ALEN); - memcpy(eth->h_source, own_addr, ETH_ALEN); - eth->h_proto = htons(ETH_P_EAPOL); - memcpy(eth+1, data, data_len); - - wpa_hexdump(MSG_MSGDUMP, "TX EAPOL", bp, len); - - status = l2_packet_send(drv->l2_sock, addr, ETH_P_EAPOL, bp, len); - - if (bp != buf) - free(bp); - - return status; - -} - -#ifndef CONFIG_MLME_OFFLOAD -static void rtl871x_receive_mgnt(struct rtl871x_driver_data *drv , const u8 *buf, size_t len) -{ - const struct ieee80211_mgmt *mgmt; - //const u8 *end, *ie; - u16 fc, type, stype; - //size_t ie_len; - struct hostapd_data *hapd = drv->hapd; - - //printf("+rtl871x_receive_mgnt, " MACSTR " is our address\n", MAC2STR(hapd->own_addr)); - - -#if 0 - { - int i; - for(i=0; iu.probe_req)) - return; - - mgmt = (const struct ieee80211_mgmt *)buf; - - fc = le_to_host16(mgmt->frame_control); - type = WLAN_FC_GET_TYPE(fc); - stype = WLAN_FC_GET_STYPE(fc); - -#if 1 - if (WLAN_FC_GET_TYPE(fc) == WLAN_FC_TYPE_MGMT && - WLAN_FC_GET_STYPE(fc) == WLAN_FC_STYPE_PROBE_RESP) - { - //printf("MGNT Frame - PROBE_RESP Frame\n"); - } -#endif - - //end = buf + len; - //ie = mgmt->u.probe_req.variable; - //ie_len = len - (IEEE80211_HDRLEN + sizeof(mgmt->u.probe_req)); - //hostapd_wps_probe_req_rx(drv->hapd, mgmt->sa, ie, ie_len); - - switch (type) { - case WLAN_FC_TYPE_MGMT: - if (stype != WLAN_FC_STYPE_BEACON) - wpa_printf(MSG_MSGDUMP, "MGMT"); - - - - if (stype == WLAN_FC_STYPE_PROBE_REQ) - { - - } - else - { - //printf("rtl871x_receive_mgnt, type=0x%x, stype=0x%x\n", type, stype); - } - - - //ieee802_11_mgmt(hapd, (u8 *)buf, len, stype, NULL); - - break; - case WLAN_FC_TYPE_CTRL: - printf("rtl871x_receive_mgnt, CTRL\n"); - break; - case WLAN_FC_TYPE_DATA: - printf("rtl871x_receive_mgnt, DATA\n"); - //handle_data(hapd, buf, data_len, stype); - break; - default: - printf("unknown frame type %d\n", type); - break; - } - - -} - -#ifdef CONFIG_MGNT_L2SOCK -static void rtl871x_recvive_mgmt_frame(void *ctx, const u8 *src_addr, const u8 *buf, - size_t len) -{ - struct rtl871x_driver_data *drv = ctx; - - rtl871x_receive_mgnt(drv, buf, len); -} -#else -static void rtl871x_recvive_mgmt_frame(int sock, void *eloop_ctx, void *sock_ctx) -{ -#if 0 - int len; - unsigned char buf[1024]; - struct hostapd_data *hapd = (struct hostapd_data *)eloop_ctx; - struct rtl871x_driver_data *drv = (struct rtl871x_driver_data *)hapd->drv_priv; - - len = recv(sock, buf, sizeof(buf), 0); - if (len < 0) { - perror("recv"); - return; - } - - rtl871x_receive_mgnt(drv, buf, len); -#endif -} - -static int rtl871x_mgnt_sock_init(struct rtl871x_driver_data *drv, const char *name) -{ - int sock; - struct ifreq ifr; - struct sockaddr_ll addr; - - sock = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL)); - if (sock < 0) { - perror("socket[PF_PACKET,SOCK_RAW]"); - return -1; - } - - if (eloop_register_read_sock(sock, rtl871x_recvive_mgmt_frame, drv->hapd, NULL)) - { - printf("Could not register read socket\n"); - return -1; - } - - memset(&ifr, 0, sizeof(ifr)); - //snprintf(ifr.ifr_name, sizeof(ifr.ifr_name), "%sap", drv->iface); - os_strlcpy(ifr.ifr_name, name, sizeof(ifr.ifr_name)); - if (ioctl(sock, SIOCGIFINDEX, &ifr) != 0) { - perror("ioctl(SIOCGIFINDEX)"); - return -1; - } - - //if (rtl871x_set_iface_flags(drv, 1)) { - // return -1; - //} - - memset(&addr, 0, sizeof(addr)); - addr.sll_family = AF_PACKET; - addr.sll_ifindex = ifr.ifr_ifindex; - wpa_printf(MSG_DEBUG, "Opening raw packet socket for ifindex %d", - addr.sll_ifindex); - - if (bind(sock, (struct sockaddr *) &addr, sizeof(addr)) < 0) { - perror("bind"); - return -1; - } - - memset(&ifr, 0, sizeof(ifr)); - os_strlcpy(ifr.ifr_name, name, sizeof(ifr.ifr_name)); - if (ioctl(sock, SIOCGIFHWADDR, &ifr) != 0) { - perror("ioctl(SIOCGIFHWADDR)"); - return -1; - } - - - if (ifr.ifr_hwaddr.sa_family != ARPHRD_ETHER) { - printf("Invalid HW-addr family 0x%04x\n", - ifr.ifr_hwaddr.sa_family); - return -1; - } - - //memcpy(drv->hapd->own_addr, ifr.ifr_hwaddr.sa_data, ETH_ALEN); - - return sock; - -} -#endif -#endif - -static void rtl871x_handle_tx_callback(struct hostapd_data *hapd, u8 *buf, size_t len, - int ok) -{ -#if 0 - struct ieee80211_hdr *hdr; - u16 fc, type, stype; - struct sta_info *sta; - - //printf("%s\n", __func__); - - hdr = (struct ieee80211_hdr *) buf; - fc = le_to_host16(hdr->frame_control); - - type = WLAN_FC_GET_TYPE(fc); - stype = WLAN_FC_GET_STYPE(fc); - - switch (type) { - case WLAN_FC_TYPE_MGMT: - //printf("MGMT (TX callback) %s\n", - // ok ? "ACK" : "fail"); - ieee802_11_mgmt_cb(hapd, buf, len, stype, ok); - break; - case WLAN_FC_TYPE_CTRL: - printf("CTRL (TX callback) %s\n", - ok ? "ACK" : "fail"); - break; - case WLAN_FC_TYPE_DATA: - printf("DATA (TX callback) %s\n", - ok ? "ACK" : "fail"); - sta = ap_get_sta(hapd, hdr->addr1); - if (sta && sta->flags & WLAN_STA_PENDING_POLL) { - wpa_printf(MSG_DEBUG, "STA " MACSTR - " %s pending activity poll", - MAC2STR(sta->addr), - ok ? "ACKed" : "did not ACK"); - if (ok) - sta->flags &= ~WLAN_STA_PENDING_POLL; - } - if (sta) - ieee802_1x_tx_status(hapd, sta, buf, len, ok); - break; - default: - printf("unknown TX callback frame type %d\n", type); - break; - } -#endif -} - -static int rtl871x_send_mgnt(struct rtl871x_driver_data *drv, const void *msg, size_t len) -{ - int res=0; - - return res; -} - -static int rtl871x_send_mgmt_frame_ops(void *priv, const void *msg, size_t len, - int flags) -{ - struct rtl871x_driver_data *drv = priv; - //struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)msg; - int res=0; - - //printf("%s\n", __func__); - - - //hdr->frame_control |= host_to_le16(BIT(1));/* Request TX callback */ -#ifdef CONFIG_MGNT_L2SOCK - //res = send(drv->mgnt_l2_sock, msg, len, flags); - //res = l2_packet_send(drv->mgnt_l2_sock, addr, ETH_P_EAPOL, msg, len); - if(drv->mgnt_l2_sock == NULL) - return res; - - res = l2_packet_send(drv->mgnt_l2_sock, NULL, ETH_P_80211_RAW, msg, len); -#else - - if(drv->mgnt_sock < 0) - return res; - - res = send(drv->mgnt_sock, msg, len, flags); -#endif - //hdr->frame_control &= ~host_to_le16(BIT(1)); - - - rtl871x_send_mgnt(drv, msg, len); - - rtl871x_handle_tx_callback(drv->hapd, (u8*)msg, len, 1); - - return res; - -} - -/* -static int rtl871x_driver_send_ether_ops(void *priv, const u8 *dst, const u8 *src, - u16 proto, const u8 *data, size_t data_len) -{ - return 0; -} -*/ - -static struct hostapd_hw_modes *rtl871x_get_hw_feature_data_ops(void *priv, - u16 *num_modes, - u16 *flags) -{ - -#define MAX_NUM_CHANNEL (14) -#define MAX_NUM_CHANNEL_5G (24) - - struct hostapd_hw_modes *modes; - size_t i; - int k; - - *num_modes = 3; - *flags = 0; - - modes = os_zalloc(*num_modes * sizeof(struct hostapd_hw_modes)); - if (modes == NULL) - return NULL; - - //.1 - modes[0].mode = HOSTAPD_MODE_IEEE80211G; - modes[0].num_channels = MAX_NUM_CHANNEL; - modes[0].num_rates = 12; - modes[0].channels = - os_zalloc(MAX_NUM_CHANNEL * sizeof(struct hostapd_channel_data)); - modes[0].rates = os_zalloc(modes[0].num_rates * sizeof(int)); - if (modes[0].channels == NULL || modes[0].rates == NULL) - goto fail; - for (i = 0; i < MAX_NUM_CHANNEL; i++) { - modes[0].channels[i].chan = i + 1; - modes[0].channels[i].freq = 2412 + 5 * i; - modes[0].channels[i].flag = 0; - if (i >= 13) - modes[0].channels[i].flag = HOSTAPD_CHAN_DISABLED; - } - modes[0].rates[0] = 10; - modes[0].rates[1] = 20; - modes[0].rates[2] = 55; - modes[0].rates[3] = 110; - modes[0].rates[4] = 60; - modes[0].rates[5] = 90; - modes[0].rates[6] = 120; - modes[0].rates[7] = 180; - modes[0].rates[8] = 240; - modes[0].rates[9] = 360; - modes[0].rates[10] = 480; - modes[0].rates[11] = 540; - - - //.2 - modes[1].mode = HOSTAPD_MODE_IEEE80211B; - modes[1].num_channels = MAX_NUM_CHANNEL; - modes[1].num_rates = 4; - modes[1].channels = - os_zalloc(MAX_NUM_CHANNEL * sizeof(struct hostapd_channel_data)); - modes[1].rates = os_zalloc(modes[1].num_rates * sizeof(int)); - if (modes[1].channels == NULL || modes[1].rates == NULL) - goto fail; - for (i = 0; i < MAX_NUM_CHANNEL; i++) { - modes[1].channels[i].chan = i + 1; - modes[1].channels[i].freq = 2412 + 5 * i; - modes[1].channels[i].flag = 0; - if (i >= 11) - modes[1].channels[i].flag = HOSTAPD_CHAN_DISABLED; - } - modes[1].rates[0] = 10; - modes[1].rates[1] = 20; - modes[1].rates[2] = 55; - modes[1].rates[3] = 110; - - - //.3 - modes[2].mode = HOSTAPD_MODE_IEEE80211A; -#ifdef CONFIG_DRIVER_RTL_DFS - modes[2].num_channels = MAX_NUM_CHANNEL_5G; -#else /* CONFIG_DRIVER_RTL_DFS */ - modes[2].num_channels = 9; -#endif /* CONFIG_DRIVER_RTL_DFS */ - - modes[2].num_rates = 8; - modes[2].channels = os_zalloc(modes[2].num_channels * sizeof(struct hostapd_channel_data)); - modes[2].rates = os_zalloc(modes[2].num_rates * sizeof(int)); - if (modes[2].channels == NULL || modes[2].rates == NULL) - goto fail; - - - k = 0; - // 5G band1 Channel: 36, 40, 44, 48 - for (i=0; i < 4; i++) { - modes[2].channels[k].chan = 36+(i*4); - modes[2].channels[k].freq = 5180+(i*20); - modes[2].channels[k].flag = 0; - k++; - } - -#ifdef CONFIG_DRIVER_RTL_DFS - // 5G band2 Channel: 52, 56, 60, 64 - for (i=0; i < 4; i++) { - modes[2].channels[k].chan = 52+(i*4); - modes[2].channels[k].freq = 5260+(i*20); - modes[2].channels[k].flag = 0; - k++; - } - - // 5G band3 Channel: 100, 104, 108. 112, 116, 120, 124, 128, 132, 136, 140 - for (i=0; i < 11; i++) { - modes[2].channels[k].chan = 100+(i*4); - modes[2].channels[k].freq = 5500+(i*20); - modes[2].channels[k].flag = 0; - k++; - } -#endif /* CONFIG_DRIVER_RTL_DFS */ - - // 5G band4 Channel: 149, 153, 157, 161, 165 - for (i=0; i < 5; i++) { - modes[2].channels[k].chan = 149+(i*4); - modes[2].channels[k].freq = 5745+(i*20); - modes[2].channels[k].flag = 0; - k++; - } - - modes[2].rates[0] = 60; - modes[2].rates[1] = 90; - modes[2].rates[2] = 120; - modes[2].rates[3] = 180; - modes[2].rates[4] = 240; - modes[2].rates[5] = 360; - modes[2].rates[6] = 480; - modes[2].rates[7] = 540; - - - // -#if 0 -#define HT_CAP_INFO_LDPC_CODING_CAP ((u16) BIT(0)) -#define HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET ((u16) BIT(1)) -#define HT_CAP_INFO_SMPS_MASK ((u16) (BIT(2) | BIT(3))) -#define HT_CAP_INFO_SMPS_STATIC ((u16) 0) -#define HT_CAP_INFO_SMPS_DYNAMIC ((u16) BIT(2)) -#define HT_CAP_INFO_SMPS_DISABLED ((u16) (BIT(2) | BIT(3))) -#define HT_CAP_INFO_GREEN_FIELD ((u16) BIT(4)) -#define HT_CAP_INFO_SHORT_GI20MHZ ((u16) BIT(5)) -#define HT_CAP_INFO_SHORT_GI40MHZ ((u16) BIT(6)) -#define HT_CAP_INFO_TX_STBC ((u16) BIT(7)) -#define HT_CAP_INFO_RX_STBC_MASK ((u16) (BIT(8) | BIT(9))) -#define HT_CAP_INFO_RX_STBC_1 ((u16) BIT(8)) -#define HT_CAP_INFO_RX_STBC_12 ((u16) BIT(9)) -#define HT_CAP_INFO_RX_STBC_123 ((u16) (BIT(8) | BIT(9))) -#define HT_CAP_INFO_DELAYED_BA ((u16) BIT(10)) -#define HT_CAP_INFO_MAX_AMSDU_SIZE ((u16) BIT(11)) -#define HT_CAP_INFO_DSSS_CCK40MHZ ((u16) BIT(12)) -#define HT_CAP_INFO_PSMP_SUPP ((u16) BIT(13)) -#define HT_CAP_INFO_40MHZ_INTOLERANT ((u16) BIT(14)) -#define HT_CAP_INFO_LSIG_TXOP_PROTECT_SUPPORT ((u16) BIT(15)) -#endif - - //HOSTAPD_MODE_IEEE80211G - modes[0].ht_capab = HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET|HT_CAP_INFO_SHORT_GI20MHZ| - HT_CAP_INFO_SHORT_GI40MHZ|HT_CAP_INFO_MAX_AMSDU_SIZE|HT_CAP_INFO_DSSS_CCK40MHZ; - - modes[0].mcs_set[0]= 0xff; - modes[0].mcs_set[1]= 0xff; - - //HOSTAPD_MODE_IEEE80211B - modes[1].ht_capab = 0; - - //HOSTAPD_MODE_IEEE80211A - modes[2].ht_capab = modes[0].ht_capab; - - modes[2].mcs_set[0]= 0xff; - modes[2].mcs_set[1]= 0xff; - - return modes; - -fail: - if (modes) { - for (i = 0; i < *num_modes; i++) { - os_free(modes[i].channels); - os_free(modes[i].rates); - } - os_free(modes); - } - - return NULL; - -} - -#if 0 -static int rtl871x_sta_add_ops(const char *ifname, void *priv, const u8 *addr, - u16 aid, u16 capability, u8 *supp_rates, - size_t supp_rates_len, int flags, - u16 listen_interval) -{ - -#if 1 - printf("+%s, " MACSTR " is new sta address added\n", __func__, MAC2STR(addr)); - return 0; -#else - struct hostap_driver_data *drv = priv; - struct prism2_hostapd_param param; - int tx_supp_rates = 0; - size_t i; - -#define WLAN_RATE_1M BIT(0) -#define WLAN_RATE_2M BIT(1) -#define WLAN_RATE_5M5 BIT(2) -#define WLAN_RATE_11M BIT(3) - - for (i = 0; i < supp_rates_len; i++) { - if ((supp_rates[i] & 0x7f) == 2) - tx_supp_rates |= WLAN_RATE_1M; - if ((supp_rates[i] & 0x7f) == 4) - tx_supp_rates |= WLAN_RATE_2M; - if ((supp_rates[i] & 0x7f) == 11) - tx_supp_rates |= WLAN_RATE_5M5; - if ((supp_rates[i] & 0x7f) == 22) - tx_supp_rates |= WLAN_RATE_11M; - } - - memset(¶m, 0, sizeof(param)); - param.cmd = PRISM2_HOSTAPD_ADD_STA; - memcpy(param.sta_addr, addr, ETH_ALEN); - param.u.add_sta.aid = aid; - param.u.add_sta.capability = capability; - param.u.add_sta.tx_supp_rates = tx_supp_rates; - return hostapd_ioctl(drv, ¶m, sizeof(param)); -#endif -} - -static int rtl871x_sta_add2_ops(const char *ifname, void *priv, - struct hostapd_sta_add_params *params) -{ -#if 0 - ieee_param param; - //int i, tx_supp_rates = 0; - struct rtl871x_driver_data *drv = priv; - - printf("%s\n", __func__); - - memset(¶m, 0, sizeof(param)); - param.cmd = RTL871X_HOSTAPD_ADD_STA; - memcpy(param.sta_addr, params->addr, ETH_ALEN); - param.u.add_sta.aid = params->aid; - param.u.add_sta.capability = params->capability; - param.u.add_sta.flags = params->flags; - - memcpy(param.u.add_sta.tx_supp_rates, params->supp_rates, params->supp_rates_len); - -/* - for (i = 0; i < params->supp_rates_len; i++) - { - if ((params->supp_rates[i] & 0x7f) == IEEE80211_CCK_RATE_1MB) - tx_supp_rates |= IEEE80211_CCK_RATE_1MB_MASK; - if ((params->supp_rates[i] & 0x7f) == IEEE80211_CCK_RATE_2MB) - tx_supp_rates |= IEEE80211_CCK_RATE_2MB_MASK; - if ((params->supp_rates[i] & 0x7f) == IEEE80211_CCK_RATE_5MB) - tx_supp_rates |= IEEE80211_CCK_RATE_5MB_MASK; - if ((params->supp_rates[i] & 0x7f) == IEEE80211_CCK_RATE_11MB) - tx_supp_rates |= IEEE80211_CCK_RATE_11MB_MASK; - - if ((params->supp_rates[i] & 0x7f) == IEEE80211_OFDM_RATE_6MB) - tx_supp_rates |= IEEE80211_OFDM_RATE_6MB_MASK; - if ((params->supp_rates[i] & 0x7f) == IEEE80211_OFDM_RATE_9MB) - tx_supp_rates |= IEEE80211_OFDM_RATE_9MB_MASK; - if ((params->supp_rates[i] & 0x7f) == IEEE80211_OFDM_RATE_12MB) - tx_supp_rates |= IEEE80211_OFDM_RATE_12MB_MASK; - if ((params->supp_rates[i] & 0x7f) == IEEE80211_OFDM_RATE_18MB) - tx_supp_rates |= IEEE80211_OFDM_RATE_18MB_MASK; - - if ((params->supp_rates[i] & 0x7f) == IEEE80211_OFDM_RATE_24MB) - tx_supp_rates |= IEEE80211_OFDM_RATE_24MB_MASK; - if ((params->supp_rates[i] & 0x7f) == IEEE80211_OFDM_RATE_36MB) - tx_supp_rates |= IEEE80211_OFDM_RATE_36MB_MASK; - if ((params->supp_rates[i] & 0x7f) == IEEE80211_OFDM_RATE_48MB) - tx_supp_rates |= IEEE80211_OFDM_RATE_48MB_MASK; - if ((params->supp_rates[i] & 0x7f) == IEEE80211_OFDM_RATE_54MB) - tx_supp_rates |= IEEE80211_OFDM_RATE_54MB_MASK; - - } - - param.u.add_sta.tx_supp_rates = tx_supp_rates; -*/ - -#ifdef CONFIG_IEEE80211N - if (params->ht_capabilities && params->ht_capabilities->length>0) - { - struct ieee80211_ht_capability *pht_cap = (struct ieee80211_ht_capability *)¶ms->ht_capabilities->data; - memcpy((u8*)¶m.u.add_sta.ht_cap, (u8*)pht_cap, sizeof(struct ieee80211_ht_capability)); - - } -#endif /* CONFIG_IEEE80211N */ - - return rtl871x_hostapd_ioctl(drv, ¶m, sizeof(param)); -#else - return 0; -#endif -} -#endif - -static int rtl871x_sta_remove_ops(void *priv, const u8 *addr) -{ - struct rtl871x_driver_data *drv = priv; - struct ieee_param param; - - printf("+%s, " MACSTR " is sta address removed\n", __func__, MAC2STR(addr)); - - //hostap_sta_set_flags(drv, addr, 0, 0, ~WLAN_STA_AUTHORIZED); - - memset(¶m, 0, sizeof(param)); - param.cmd = RTL871X_HOSTAPD_REMOVE_STA; - memcpy(param.sta_addr, addr, ETH_ALEN); - if (rtl871x_hostapd_ioctl(drv, ¶m, sizeof(param))) { - printf("Could not remove station from kernel driver.\n"); - return -1; - } - - return 0; - -} - - -//static int rtl871x_set_beacon_ops(const char *iface, void *priv, -// u8 *head, size_t head_len, -// u8 *tail, size_t tail_len) -int rtl871x_set_beacon_ops(void *priv, const u8 *head, size_t head_len, - const u8 *tail, size_t tail_len, int dtim_period, - int beacon_int) -{ - int ret; - size_t sz; - ieee_param *pparam; - struct rtl871x_driver_data *drv = priv; - struct hostapd_data *hapd = drv->hapd; - - if((head_len<24) ||(!head)) - return -1; - - printf("%s\n", __func__); - - sz = head_len+tail_len+12-24 + 2;// 12+2 = cmd+sta_addr+reserved, sizeof(ieee_param)=64, no packed - pparam = os_zalloc(sz); - if (pparam == NULL) { - return -ENOMEM; - } - - pparam->cmd = RTL871X_HOSTAPD_SET_BEACON; - - memcpy(pparam->u.bcn_ie.reserved, &hapd->conf->max_num_sta, 2);//for set max_num_sta - - memcpy(pparam->u.bcn_ie.buf, (head+24), (head_len-24));// 24=beacon header len. - - memcpy(&pparam->u.bcn_ie.buf[head_len-24], tail, tail_len); - - ret = rtl871x_hostapd_ioctl(drv, pparam, sz); - - os_free(pparam); - - //rtl871x_set_max_num_sta(drv); - - return ret; - -} - -/* -enum wpa_alg { - WPA_ALG_NONE, - WPA_ALG_WEP, - WPA_ALG_TKIP, - WPA_ALG_CCMP, - WPA_ALG_IGTK, - WPA_ALG_PMK -}; -*/ -static int rtl871x_set_key_ops(const char *ifname, void *priv, enum wpa_alg alg, - const u8 *addr, int idx, int txkey, const u8 *seq, - size_t seq_len, const u8 *key, size_t key_len) -{ - ieee_param *param; - u8 *buf; - char *alg_str; - size_t blen; - int ret = 0; - struct rtl871x_driver_data *drv = priv; - - printf("%s\n", __func__); - - blen = sizeof(*param) + key_len; - buf = os_zalloc(blen); - if (buf == NULL) - return -1; - - param = (ieee_param *)buf; - param->cmd = RTL871X_SET_ENCRYPTION; - if (addr == NULL) - memset(param->sta_addr, 0xff, ETH_ALEN); - else - memcpy(param->sta_addr, addr, ETH_ALEN); - - - switch (alg) { - case WPA_ALG_NONE: - alg_str = "none"; - break; - case WPA_ALG_WEP: - //cipher = IEEE80211_CIPHER_WEP; - alg_str = "WEP"; - break; - case WPA_ALG_TKIP: - //cipher = IEEE80211_CIPHER_TKIP; - alg_str = "TKIP"; - break; - case WPA_ALG_CCMP: - //cipher = IEEE80211_CIPHER_AES_CCM; - alg_str = "CCMP"; - break; - default: - printf("%s: unknown/unsupported algorithm %d\n", - __func__, alg); - return -1; - } - - os_strlcpy((char *) param->u.crypt.alg, alg_str, - IEEE_CRYPT_ALG_NAME_LEN); - - //param->u.crypt.flags = txkey ? HOSTAP_CRYPT_FLAG_SET_TX_KEY : 0; - param->u.crypt.set_tx = txkey ? 1 : 0; - param->u.crypt.idx = idx; - param->u.crypt.key_len = key_len; - - //memcpy((u8 *) (param + 1), key, key_len); - memcpy(param->u.crypt.key, key, key_len); - - if (rtl871x_hostapd_ioctl(drv, param, blen)) { - printf("Failed to set encryption.\n"); - ret = -1; - } - - os_free(buf); - - return ret; - -} - -/* -static int rtl871x_set_encryption_ops(const char *ifname, void *priv, - const char *alg, const u8 *addr, - int idx, const u8 *key, size_t key_len, - int txkey) -{ - ieee_param *param; - u8 *buf; - size_t blen; - int ret = 0; - struct rtl871x_driver_data *drv = priv; - - printf("%s\n", __func__); -#if 0 - blen = sizeof(*param) + key_len; - buf = os_zalloc(blen); - if (buf == NULL) - return -1; - - param = (ieee_param *)buf; - param->cmd = RTL871X_SET_ENCRYPTION; - if (addr == NULL) - memset(param->sta_addr, 0xff, ETH_ALEN); - else - memcpy(param->sta_addr, addr, ETH_ALEN); - - os_strlcpy((char *) param->u.crypt.alg, alg, - IEEE_CRYPT_ALG_NAME_LEN); - - //param->u.crypt.flags = txkey ? HOSTAP_CRYPT_FLAG_SET_TX_KEY : 0; - param->u.crypt.set_tx = txkey ? 1 : 0; - param->u.crypt.idx = idx; - param->u.crypt.key_len = key_len; - - //memcpy((u8 *) (param + 1), key, key_len); - memcpy(param->u.crypt.key, key, key_len); - - if (rtl871x_hostapd_ioctl(drv, param, blen)) { - printf("Failed to set encryption.\n"); - ret = -1; - } - - os_free(buf); -#endif - return ret; - -} -*/ - -//static int rtl871x_sta_deauth_ops(void *priv, const u8 *addr, int reason) -static int rtl871x_sta_deauth_ops(void *priv, const u8 *own_addr, const u8 *addr, - int reason) -{ - printf("+%s, " MACSTR " is deauth, reason=%d\n", __func__, MAC2STR(addr), reason); - - //struct hostap_driver_data *drv = priv; - struct rtl871x_driver_data *drv = priv; - struct ieee80211_mgmt mgmt; - - memset(&mgmt, 0, sizeof(mgmt)); - mgmt.frame_control = IEEE80211_FC(WLAN_FC_TYPE_MGMT, - WLAN_FC_STYPE_DEAUTH); - - memcpy(mgmt.da, addr, ETH_ALEN); - //memcpy(mgmt.sa, drv->hapd->own_addr, ETH_ALEN); - //memcpy(mgmt.bssid, drv->hapd->own_addr, ETH_ALEN); - memcpy(mgmt.sa, own_addr, ETH_ALEN); - memcpy(mgmt.bssid, own_addr, ETH_ALEN); - mgmt.u.deauth.reason_code = host_to_le16(reason); - - return rtl871x_send_mgmt_frame_ops(drv, &mgmt, IEEE80211_HDRLEN + - sizeof(mgmt.u.deauth), 0); - -} - - -//static int rtl871x_sta_disassoc_ops(void *priv, const u8 *addr, int reason) -static int rtl871x_sta_disassoc_ops(void *priv, const u8 *own_addr, const u8 *addr, - int reason) -{ - printf("+%s, " MACSTR " is disassoc, reason=%d\n", __func__, MAC2STR(addr), reason); - - struct rtl871x_driver_data *drv = priv; - struct ieee80211_mgmt mgmt; - - memset(&mgmt, 0, sizeof(mgmt)); - mgmt.frame_control = IEEE80211_FC(WLAN_FC_TYPE_MGMT, - WLAN_FC_STYPE_DISASSOC); - - memcpy(mgmt.da, addr, ETH_ALEN); - //memcpy(mgmt.sa, drv->hapd->own_addr, ETH_ALEN); - //memcpy(mgmt.bssid, drv->hapd->own_addr, ETH_ALEN); - memcpy(mgmt.sa, own_addr, ETH_ALEN); - memcpy(mgmt.bssid, own_addr, ETH_ALEN); - - mgmt.u.disassoc.reason_code = host_to_le16(reason); - - return rtl871x_send_mgmt_frame_ops(drv, &mgmt, IEEE80211_HDRLEN + - sizeof(mgmt.u.disassoc), 0); - -} - -static int rtl871x_set_wps_assoc_resp_ie(struct rtl871x_driver_data *drv, const void *ie, size_t len) -{ - int ret; - size_t sz; - ieee_param *pparam; - - - printf("%s\n", __func__); - - sz = len + 12 + 2;// 12+2 = cmd+sta_addr+reserved, sizeof(ieee_param)=64, no packed - pparam = os_zalloc(sz); - if (pparam == NULL) { - return -ENOMEM; - } - - pparam->cmd = RTL871X_HOSTAPD_SET_WPS_ASSOC_RESP; - - if(ie && len>0) - { - memcpy(pparam->u.bcn_ie.buf, ie, len); - } - - ret = rtl871x_hostapd_ioctl(drv, pparam, sz); - - os_free(pparam); - - return ret; - -} - -static int rtl871x_set_wps_beacon_ie(struct rtl871x_driver_data *drv, const void *ie, size_t len) -{ - int ret; - size_t sz; - ieee_param *pparam; - - - printf("%s\n", __func__); - - sz = len + 12 + 2;// 12+2 = cmd+sta_addr+reserved, sizeof(ieee_param)=64, no packed - pparam = os_zalloc(sz); - if (pparam == NULL) { - return -ENOMEM; - } - - pparam->cmd = RTL871X_HOSTAPD_SET_WPS_BEACON; - - if(ie && len>0) - { - memcpy(pparam->u.bcn_ie.buf, ie, len); - } - - ret = rtl871x_hostapd_ioctl(drv, pparam, sz); - - os_free(pparam); - - return ret; - -} - -static int rtl871x_set_wps_probe_resp_ie(struct rtl871x_driver_data *drv, const void *ie, size_t len) -{ - int ret; - size_t sz; - ieee_param *pparam; - - - printf("%s\n", __func__); - - sz = len + 12 + 2;// 12+2 = cmd+sta_addr+reserved, sizeof(ieee_param)=64, no packed - pparam = os_zalloc(sz); - if (pparam == NULL) { - return -ENOMEM; - } - - pparam->cmd = RTL871X_HOSTAPD_SET_WPS_PROBE_RESP; - - if(ie && len>0) - { - memcpy(pparam->u.bcn_ie.buf, ie, len); - } - - ret = rtl871x_hostapd_ioctl(drv, pparam, sz); - - os_free(pparam); - - return ret; - -} - -static int rtl871x_set_ap_wps_ie(void *priv, const struct wpabuf *beacon, - const struct wpabuf *proberesp, const struct wpabuf *assocresp) -{ - struct rtl871x_driver_data *drv = priv; - - if (rtl871x_set_wps_assoc_resp_ie(drv, assocresp ? wpabuf_head(assocresp) : NULL, - assocresp ? wpabuf_len(assocresp) : 0)) - return -1; - - if (rtl871x_set_wps_beacon_ie(drv, beacon ? wpabuf_head(beacon) : NULL, - beacon ? wpabuf_len(beacon) : 0)) - return -1; - - return rtl871x_set_wps_probe_resp_ie(drv, - proberesp ? wpabuf_head(proberesp) : NULL, - proberesp ? wpabuf_len(proberesp): 0); - -} - -static int rtl871x_sta_flush_ops(void *priv) -{ - ieee_param param; - struct rtl871x_driver_data *drv = priv; - - memset(¶m, 0, sizeof(param)); - - param.cmd = RTL871X_HOSTAPD_FLUSH; - - return rtl871x_hostapd_ioctl(drv, ¶m, sizeof(param)); -} - -static void *rtl871x_driver_init_ops(struct hostapd_data *hapd, struct wpa_init_params *params) -{ - struct rtl871x_driver_data *drv; - struct ifreq ifr; - //struct iwreq iwr; - char ifrn_name[IFNAMSIZ + 1];//for mgnt_l2_sock/mgnt_sock - char brname[IFNAMSIZ]; - - drv = os_zalloc(sizeof(struct rtl871x_driver_data)); - if (drv == NULL) { - printf("Could not allocate memory for rtl871x driver data\n"); - return NULL; - } - - drv->hapd = hapd; - drv->ioctl_sock = socket(PF_INET, SOCK_DGRAM, 0); - if (drv->ioctl_sock < 0) { - perror("socket[PF_INET,SOCK_DGRAM]"); - goto bad; - } - os_memcpy(drv->iface, params->ifname, sizeof(drv->iface)); - - linux_set_iface_flags(drv->ioctl_sock, drv->iface, 1);/*set interface up*/ - - os_memset(&ifr, 0, sizeof(ifr)); - os_strlcpy(ifr.ifr_name, drv->iface, sizeof(ifr.ifr_name)); - if (ioctl(drv->ioctl_sock, SIOCGIFINDEX, &ifr) != 0) { - perror("ioctl(SIOCGIFINDEX)"); - goto bad; - } - drv->ifindex = ifr.ifr_ifindex; - printf("drv->ifindex=%d\n", drv->ifindex); - - drv->l2_sock = l2_packet_init(drv->iface, NULL, ETH_P_EAPOL, - rtl871x_handle_read, drv, 1); - - if (drv->l2_sock == NULL) - goto bad; - - if (l2_packet_get_own_addr(drv->l2_sock, params->own_addr)) - goto bad; - - - if (params->bridge[0]) { - wpa_printf(MSG_DEBUG, "Configure bridge %s for EAPOL traffic.", - params->bridge[0]); - drv->l2_sock_recv = l2_packet_init(params->bridge[0], NULL, - ETH_P_EAPOL, rtl871x_handle_read, drv, - 1); - if (drv->l2_sock_recv == NULL) - { - //goto bad; - drv->l2_sock_recv = drv->l2_sock; - printf("no br0 interface , let l2_sock_recv==l2_sock_xmit=0x%p\n", drv->l2_sock); - } - - } else if (linux_br_get(brname, drv->iface) == 0) { - wpa_printf(MSG_DEBUG, "Interface in bridge %s; configure for " - "EAPOL receive", brname); - drv->l2_sock_recv = l2_packet_init(brname, NULL, ETH_P_EAPOL, - rtl871x_handle_read, drv, 1); - if (drv->l2_sock_recv == NULL) - goto bad; - } - else - { - drv->l2_sock_recv = drv->l2_sock; - printf("l2_sock_recv==l2_sock_xmit=0x%p\n", drv->l2_sock); - } - - - os_memset(ifrn_name, 0, sizeof(ifrn_name)); - //snprintf(ifrn_name, sizeof(ifrn_name), "mgnt.%s_rena", drv->iface); - snprintf(ifrn_name, sizeof(ifrn_name), "mgnt.%s", "wlan0"/*drv->iface*/); -#ifdef CONFIG_MGNT_L2SOCK - drv->mgnt_l2_sock = NULL; - drv->mgnt_l2_sock = l2_packet_init(ifrn_name, NULL, ETH_P_80211_RAW, - rtl871x_recvive_mgmt_frame, drv, 1); - if (drv->mgnt_l2_sock == NULL) - goto bad; - -#else - -#ifdef CONFIG_MLME_OFFLOAD - drv->mgnt_sock = -1; -#else - drv->mgnt_sock = rtl871x_mgnt_sock_init(drv, ifrn_name); - if (drv->mgnt_sock < 0) { - goto bad; - } -#endif - -#endif - - - //madwifi_set_iface_flags(drv, 0); /* mark down during setup */ - //madwifi_set_privacy(drv->iface, drv, 0); /* default to no privacy */ - - - //linux_set_iface_flags(drv->ioctl_sock, drv->iface, 1);/*set interface up*/ - - - //enter MASTER MODE when init. - if(rtl871x_set_mode(drv, IW_MODE_MASTER)<0) - { - printf("Could not set interface to master mode!\n"); - goto bad; - } - -/* - memset(&iwr, 0, sizeof(iwr)); - os_strlcpy(iwr.ifr_name, drv->iface, IFNAMSIZ); - iwr.u.mode = IW_MODE_MASTER; - if (ioctl(drv->ioctl_sock, SIOCSIWMODE, &iwr) < 0) { - perror("ioctl[SIOCSIWMODE]"); - printf("Could not set interface to master mode!\n"); - goto bad; - } -*/ - -#ifndef CONFIG_MLME_OFFLOAD - rtl871x_set_iface_flags(drv, 1); /*set mgnt interface up*/ -#endif - - - if (rtl871x_wireless_event_init(drv)) - goto bad; - - - os_memcpy(drv->hw_mac, params->own_addr, ETH_ALEN); - - return drv; - -bad: - - if (drv->l2_sock_recv != NULL && drv->l2_sock_recv != drv->l2_sock) - l2_packet_deinit(drv->l2_sock_recv); - - if (drv->l2_sock != NULL) - l2_packet_deinit(drv->l2_sock); - - if (drv->ioctl_sock >= 0) - close(drv->ioctl_sock); - -#ifdef CONFIG_MGNT_L2SOCK - if ( drv->mgnt_l2_sock != NULL) - l2_packet_deinit(drv->mgnt_l2_sock); -#else - if (drv->mgnt_sock >= 0) - close(drv->mgnt_sock); -#endif - - if (drv != NULL) - free(drv); - - return NULL; - -} - -static void rtl871x_driver_deinit_ops(void *priv) -{ - //struct iwreq iwr; - struct rtl871x_driver_data *drv = priv; - - //back to INFRA MODE when exit. -/* - memset(&iwr, 0, sizeof(iwr)); - os_strlcpy(iwr.ifr_name, drv->iface, IFNAMSIZ); - iwr.u.mode = IW_MODE_INFRA; - if (ioctl(drv->ioctl_sock, SIOCSIWMODE, &iwr) < 0) { - perror("ioctl[SIOCSIWMODE]"); - } -*/ - rtl871x_set_mode(drv, IW_MODE_INFRA); - - - if (drv->ioctl_sock >= 0) - close(drv->ioctl_sock); - - - if (drv->l2_sock_recv != NULL && drv->l2_sock_recv != drv->l2_sock) - l2_packet_deinit(drv->l2_sock_recv); - - if(drv->l2_sock) - l2_packet_deinit(drv->l2_sock); - - //if (drv->sock_xmit != NULL) - // l2_packet_deinit(drv->sock_xmit); - -#ifdef CONFIG_MGNT_L2SOCK - if (drv->mgnt_l2_sock) - l2_packet_deinit(drv->mgnt_l2_sock); -#else - if (drv->mgnt_sock >= 0) - close(drv->mgnt_sock); -#endif - - os_free(drv); - -} - - -const struct wpa_driver_ops wpa_driver_rtw_ops = { - .name = "rtl871xdrv", - //.init = rtl871x_driver_init_ops, - //.deinit = rtl871x_driver_deinit_ops, - .hapd_init = rtl871x_driver_init_ops, - .hapd_deinit = rtl871x_driver_deinit_ops, - //.wireless_event_init = rtl871x_wireless_event_init_ops, - //.wireless_event_deinit = rtl871x_wireless_event_deinit_ops, - //.send_eapol = rtl871x_send_eapol_ops, - .hapd_send_eapol = rtl871x_send_eapol_ops, - //.send_ether = rtl871x_driver_send_ether_ops, - //.send_mgmt_frame = rtl871x_send_mgmt_frame_ops, - .get_hw_feature_data = rtl871x_get_hw_feature_data_ops, - //.sta_add = rtl871x_sta_add_ops, - //.sta_add2 = rtl871x_sta_add2_ops, - .sta_remove = rtl871x_sta_remove_ops, - .set_beacon = rtl871x_set_beacon_ops, - //.set_encryption = rtl871x_set_encryption_ops, - .set_key = rtl871x_set_key_ops, - .sta_deauth = rtl871x_sta_deauth_ops, - .sta_disassoc = rtl871x_sta_disassoc_ops, - //.set_wps_beacon_ie = rtl871x_set_wps_beacon_ie_ops, - //.set_wps_probe_resp_ie = rtl871x_set_wps_probe_resp_ie_ops, - .set_ap_wps_ie = rtl871x_set_ap_wps_ie, - .flush = rtl871x_sta_flush_ops, -}; - diff --git a/hostapd-0.8/src/drivers/driver_test.c b/hostapd-0.8/src/drivers/driver_test.c deleted file mode 100644 index 6bfa46d..0000000 --- a/hostapd-0.8/src/drivers/driver_test.c +++ /dev/null @@ -1,3391 +0,0 @@ -/* - * Testing driver interface for a simulated network driver - * Copyright (c) 2004-2010, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -/* Make sure we get winsock2.h for Windows build to get sockaddr_storage */ -#include "build_config.h" -#ifdef CONFIG_NATIVE_WINDOWS -#include -#endif /* CONFIG_NATIVE_WINDOWS */ - -#include "utils/includes.h" - -#ifndef CONFIG_NATIVE_WINDOWS -#include -#include -#include -#define DRIVER_TEST_UNIX -#endif /* CONFIG_NATIVE_WINDOWS */ - -#include "utils/common.h" -#include "utils/eloop.h" -#include "utils/list.h" -#include "utils/trace.h" -#include "common/ieee802_11_defs.h" -#include "crypto/sha1.h" -#include "l2_packet/l2_packet.h" -#include "p2p/p2p.h" -#include "wps/wps.h" -#include "driver.h" - - -struct test_client_socket { - struct test_client_socket *next; - u8 addr[ETH_ALEN]; - struct sockaddr_un un; - socklen_t unlen; - struct test_driver_bss *bss; -}; - -struct test_driver_bss { - struct wpa_driver_test_data *drv; - struct dl_list list; - void *bss_ctx; - char ifname[IFNAMSIZ]; - u8 bssid[ETH_ALEN]; - u8 *ie; - size_t ielen; - u8 *wps_beacon_ie; - size_t wps_beacon_ie_len; - u8 *wps_probe_resp_ie; - size_t wps_probe_resp_ie_len; - u8 ssid[32]; - size_t ssid_len; - int privacy; -}; - -struct wpa_driver_test_global { - int bss_add_used; - u8 req_addr[ETH_ALEN]; -}; - -struct wpa_driver_test_data { - struct wpa_driver_test_global *global; - void *ctx; - WPA_TRACE_REF(ctx); - u8 own_addr[ETH_ALEN]; - int test_socket; -#ifdef DRIVER_TEST_UNIX - struct sockaddr_un hostapd_addr; -#endif /* DRIVER_TEST_UNIX */ - int hostapd_addr_set; - struct sockaddr_in hostapd_addr_udp; - int hostapd_addr_udp_set; - char *own_socket_path; - char *test_dir; -#define MAX_SCAN_RESULTS 30 - struct wpa_scan_res *scanres[MAX_SCAN_RESULTS]; - size_t num_scanres; - int use_associnfo; - u8 assoc_wpa_ie[80]; - size_t assoc_wpa_ie_len; - int use_mlme; - int associated; - u8 *probe_req_ie; - size_t probe_req_ie_len; - u8 probe_req_ssid[32]; - size_t probe_req_ssid_len; - int ibss; - int ap; - - struct test_client_socket *cli; - struct dl_list bss; - int udp_port; - - int alloc_iface_idx; - - int probe_req_report; - unsigned int remain_on_channel_freq; - unsigned int remain_on_channel_duration; - - int current_freq; - - struct p2p_data *p2p; - unsigned int off_channel_freq; - struct wpabuf *pending_action_tx; - u8 pending_action_src[ETH_ALEN]; - u8 pending_action_dst[ETH_ALEN]; - u8 pending_action_bssid[ETH_ALEN]; - unsigned int pending_action_freq; - unsigned int pending_listen_freq; - unsigned int pending_listen_duration; - int pending_p2p_scan; - struct sockaddr *probe_from; - socklen_t probe_from_len; -}; - - -static void wpa_driver_test_deinit(void *priv); -static int wpa_driver_test_attach(struct wpa_driver_test_data *drv, - const char *dir, int ap); -static void wpa_driver_test_close_test_socket( - struct wpa_driver_test_data *drv); -static void test_remain_on_channel_timeout(void *eloop_ctx, void *timeout_ctx); -static int wpa_driver_test_init_p2p(struct wpa_driver_test_data *drv); - - -static void test_driver_free_bss(struct test_driver_bss *bss) -{ - os_free(bss->ie); - os_free(bss->wps_beacon_ie); - os_free(bss->wps_probe_resp_ie); - os_free(bss); -} - - -static void test_driver_free_bsses(struct wpa_driver_test_data *drv) -{ - struct test_driver_bss *bss, *tmp; - - dl_list_for_each_safe(bss, tmp, &drv->bss, struct test_driver_bss, - list) { - dl_list_del(&bss->list); - test_driver_free_bss(bss); - } -} - - -static struct test_client_socket * -test_driver_get_cli(struct wpa_driver_test_data *drv, struct sockaddr_un *from, - socklen_t fromlen) -{ - struct test_client_socket *cli = drv->cli; - - while (cli) { - if (cli->unlen == fromlen && - strncmp(cli->un.sun_path, from->sun_path, - fromlen - sizeof(cli->un.sun_family)) == 0) - return cli; - cli = cli->next; - } - - return NULL; -} - - -static int test_driver_send_eapol(void *priv, const u8 *addr, const u8 *data, - size_t data_len, int encrypt, - const u8 *own_addr, u32 flags) -{ - struct test_driver_bss *dbss = priv; - struct wpa_driver_test_data *drv = dbss->drv; - struct test_client_socket *cli; - struct msghdr msg; - struct iovec io[3]; - struct l2_ethhdr eth; - - if (drv->test_socket < 0) - return -1; - - cli = drv->cli; - while (cli) { - if (memcmp(cli->addr, addr, ETH_ALEN) == 0) - break; - cli = cli->next; - } - - if (!cli) { - wpa_printf(MSG_DEBUG, "%s: no destination client entry", - __func__); - return -1; - } - - memcpy(eth.h_dest, addr, ETH_ALEN); - memcpy(eth.h_source, own_addr, ETH_ALEN); - eth.h_proto = host_to_be16(ETH_P_EAPOL); - - io[0].iov_base = "EAPOL "; - io[0].iov_len = 6; - io[1].iov_base = ð - io[1].iov_len = sizeof(eth); - io[2].iov_base = (u8 *) data; - io[2].iov_len = data_len; - - memset(&msg, 0, sizeof(msg)); - msg.msg_iov = io; - msg.msg_iovlen = 3; - msg.msg_name = &cli->un; - msg.msg_namelen = cli->unlen; - return sendmsg(drv->test_socket, &msg, 0); -} - - -static int test_driver_send_ether(void *priv, const u8 *dst, const u8 *src, - u16 proto, const u8 *data, size_t data_len) -{ - struct test_driver_bss *dbss = priv; - struct wpa_driver_test_data *drv = dbss->drv; - struct msghdr msg; - struct iovec io[3]; - struct l2_ethhdr eth; - char desttxt[30]; - struct sockaddr_un addr; - struct dirent *dent; - DIR *dir; - int ret = 0, broadcast = 0, count = 0; - - if (drv->test_socket < 0 || drv->test_dir == NULL) { - wpa_printf(MSG_DEBUG, "%s: invalid parameters (sock=%d " - "test_dir=%p)", - __func__, drv->test_socket, drv->test_dir); - return -1; - } - - broadcast = memcmp(dst, "\xff\xff\xff\xff\xff\xff", ETH_ALEN) == 0; - snprintf(desttxt, sizeof(desttxt), MACSTR, MAC2STR(dst)); - - memcpy(eth.h_dest, dst, ETH_ALEN); - memcpy(eth.h_source, src, ETH_ALEN); - eth.h_proto = host_to_be16(proto); - - io[0].iov_base = "ETHER "; - io[0].iov_len = 6; - io[1].iov_base = ð - io[1].iov_len = sizeof(eth); - io[2].iov_base = (u8 *) data; - io[2].iov_len = data_len; - - memset(&msg, 0, sizeof(msg)); - msg.msg_iov = io; - msg.msg_iovlen = 3; - - dir = opendir(drv->test_dir); - if (dir == NULL) { - perror("test_driver: opendir"); - return -1; - } - while ((dent = readdir(dir))) { -#ifdef _DIRENT_HAVE_D_TYPE - /* Skip the file if it is not a socket. Also accept - * DT_UNKNOWN (0) in case the C library or underlying file - * system does not support d_type. */ - if (dent->d_type != DT_SOCK && dent->d_type != DT_UNKNOWN) - continue; -#endif /* _DIRENT_HAVE_D_TYPE */ - if (strcmp(dent->d_name, ".") == 0 || - strcmp(dent->d_name, "..") == 0) - continue; - - memset(&addr, 0, sizeof(addr)); - addr.sun_family = AF_UNIX; - snprintf(addr.sun_path, sizeof(addr.sun_path), "%s/%s", - drv->test_dir, dent->d_name); - - if (strcmp(addr.sun_path, drv->own_socket_path) == 0) - continue; - if (!broadcast && strstr(dent->d_name, desttxt) == NULL) - continue; - - wpa_printf(MSG_DEBUG, "%s: Send ether frame to %s", - __func__, dent->d_name); - - msg.msg_name = &addr; - msg.msg_namelen = sizeof(addr); - ret = sendmsg(drv->test_socket, &msg, 0); - if (ret < 0) - perror("driver_test: sendmsg"); - count++; - } - closedir(dir); - - if (!broadcast && count == 0) { - wpa_printf(MSG_DEBUG, "%s: Destination " MACSTR " not found", - __func__, MAC2STR(dst)); - return -1; - } - - return ret; -} - - -static int wpa_driver_test_send_mlme(void *priv, const u8 *data, - size_t data_len) -{ - struct test_driver_bss *dbss = priv; - struct wpa_driver_test_data *drv = dbss->drv; - struct msghdr msg; - struct iovec io[2]; - const u8 *dest; - struct sockaddr_un addr; - struct dirent *dent; - DIR *dir; - int broadcast; - int ret = 0; - struct ieee80211_hdr *hdr; - u16 fc; - char cmd[50]; - int freq; -#ifdef HOSTAPD - char desttxt[30]; -#endif /* HOSTAPD */ - union wpa_event_data event; - - wpa_hexdump(MSG_MSGDUMP, "test_send_mlme", data, data_len); - if (drv->test_socket < 0 || data_len < 10) { - wpa_printf(MSG_DEBUG, "%s: invalid parameters (sock=%d len=%lu" - " test_dir=%p)", - __func__, drv->test_socket, - (unsigned long) data_len, - drv->test_dir); - return -1; - } - - dest = data + 4; - broadcast = os_memcmp(dest, "\xff\xff\xff\xff\xff\xff", ETH_ALEN) == 0; - -#ifdef HOSTAPD - snprintf(desttxt, sizeof(desttxt), MACSTR, MAC2STR(dest)); -#endif /* HOSTAPD */ - - if (drv->remain_on_channel_freq) - freq = drv->remain_on_channel_freq; - else - freq = drv->current_freq; - wpa_printf(MSG_DEBUG, "test_driver(%s): MLME TX on freq %d MHz", - dbss->ifname, freq); - os_snprintf(cmd, sizeof(cmd), "MLME freq=%d ", freq); - io[0].iov_base = cmd; - io[0].iov_len = os_strlen(cmd); - io[1].iov_base = (void *) data; - io[1].iov_len = data_len; - - os_memset(&msg, 0, sizeof(msg)); - msg.msg_iov = io; - msg.msg_iovlen = 2; - -#ifdef HOSTAPD - if (drv->test_dir == NULL) { - wpa_printf(MSG_DEBUG, "%s: test_dir == NULL", __func__); - return -1; - } - - dir = opendir(drv->test_dir); - if (dir == NULL) { - perror("test_driver: opendir"); - return -1; - } - while ((dent = readdir(dir))) { -#ifdef _DIRENT_HAVE_D_TYPE - /* Skip the file if it is not a socket. Also accept - * DT_UNKNOWN (0) in case the C library or underlying file - * system does not support d_type. */ - if (dent->d_type != DT_SOCK && dent->d_type != DT_UNKNOWN) - continue; -#endif /* _DIRENT_HAVE_D_TYPE */ - if (os_strcmp(dent->d_name, ".") == 0 || - os_strcmp(dent->d_name, "..") == 0) - continue; - - os_memset(&addr, 0, sizeof(addr)); - addr.sun_family = AF_UNIX; - os_snprintf(addr.sun_path, sizeof(addr.sun_path), "%s/%s", - drv->test_dir, dent->d_name); - - if (os_strcmp(addr.sun_path, drv->own_socket_path) == 0) - continue; - if (!broadcast && os_strstr(dent->d_name, desttxt) == NULL) - continue; - - wpa_printf(MSG_DEBUG, "%s: Send management frame to %s", - __func__, dent->d_name); - - msg.msg_name = &addr; - msg.msg_namelen = sizeof(addr); - ret = sendmsg(drv->test_socket, &msg, 0); - if (ret < 0) - perror("driver_test: sendmsg(test_socket)"); - } - closedir(dir); -#else /* HOSTAPD */ - - if (os_memcmp(dest, dbss->bssid, ETH_ALEN) == 0 || - drv->test_dir == NULL) { - if (drv->hostapd_addr_udp_set) { - msg.msg_name = &drv->hostapd_addr_udp; - msg.msg_namelen = sizeof(drv->hostapd_addr_udp); - } else { -#ifdef DRIVER_TEST_UNIX - msg.msg_name = &drv->hostapd_addr; - msg.msg_namelen = sizeof(drv->hostapd_addr); -#endif /* DRIVER_TEST_UNIX */ - } - } else if (broadcast) { - dir = opendir(drv->test_dir); - if (dir == NULL) - return -1; - while ((dent = readdir(dir))) { -#ifdef _DIRENT_HAVE_D_TYPE - /* Skip the file if it is not a socket. - * Also accept DT_UNKNOWN (0) in case - * the C library or underlying file - * system does not support d_type. */ - if (dent->d_type != DT_SOCK && - dent->d_type != DT_UNKNOWN) - continue; -#endif /* _DIRENT_HAVE_D_TYPE */ - if (os_strcmp(dent->d_name, ".") == 0 || - os_strcmp(dent->d_name, "..") == 0) - continue; - wpa_printf(MSG_DEBUG, "%s: Send broadcast MLME to %s", - __func__, dent->d_name); - os_memset(&addr, 0, sizeof(addr)); - addr.sun_family = AF_UNIX; - os_snprintf(addr.sun_path, sizeof(addr.sun_path), - "%s/%s", drv->test_dir, dent->d_name); - - msg.msg_name = &addr; - msg.msg_namelen = sizeof(addr); - - ret = sendmsg(drv->test_socket, &msg, 0); - if (ret < 0) - perror("driver_test: sendmsg(test_socket)"); - } - closedir(dir); - return ret; - } else { - struct stat st; - os_memset(&addr, 0, sizeof(addr)); - addr.sun_family = AF_UNIX; - os_snprintf(addr.sun_path, sizeof(addr.sun_path), - "%s/AP-" MACSTR, drv->test_dir, MAC2STR(dest)); - if (stat(addr.sun_path, &st) < 0) { - os_snprintf(addr.sun_path, sizeof(addr.sun_path), - "%s/STA-" MACSTR, - drv->test_dir, MAC2STR(dest)); - } - msg.msg_name = &addr; - msg.msg_namelen = sizeof(addr); - } - - if (sendmsg(drv->test_socket, &msg, 0) < 0) { - perror("sendmsg(test_socket)"); - return -1; - } -#endif /* HOSTAPD */ - - hdr = (struct ieee80211_hdr *) data; - fc = le_to_host16(hdr->frame_control); - - os_memset(&event, 0, sizeof(event)); - event.tx_status.type = WLAN_FC_GET_TYPE(fc); - event.tx_status.stype = WLAN_FC_GET_STYPE(fc); - event.tx_status.dst = hdr->addr1; - event.tx_status.data = data; - event.tx_status.data_len = data_len; - event.tx_status.ack = ret >= 0; - wpa_supplicant_event(drv->ctx, EVENT_TX_STATUS, &event); - -#ifdef CONFIG_P2P - if (drv->p2p && - WLAN_FC_GET_TYPE(fc) == WLAN_FC_TYPE_MGMT && - WLAN_FC_GET_STYPE(fc) == WLAN_FC_STYPE_ACTION) { - if (drv->pending_action_tx == NULL) { - wpa_printf(MSG_DEBUG, "P2P: Ignore Action TX status - " - "no pending operation"); - return ret; - } - - if (os_memcmp(hdr->addr1, drv->pending_action_dst, ETH_ALEN) != - 0) { - wpa_printf(MSG_DEBUG, "P2P: Ignore Action TX status - " - "unknown destination address"); - return ret; - } - - wpabuf_free(drv->pending_action_tx); - drv->pending_action_tx = NULL; - - p2p_send_action_cb(drv->p2p, drv->pending_action_freq, - drv->pending_action_dst, - drv->pending_action_src, - drv->pending_action_bssid, - ret >= 0); - } -#endif /* CONFIG_P2P */ - - return ret; -} - - -static void test_driver_scan(struct wpa_driver_test_data *drv, - struct sockaddr_un *from, socklen_t fromlen, - char *data) -{ - char buf[512], *pos, *end; - int ret; - struct test_driver_bss *bss; - u8 sa[ETH_ALEN]; - u8 ie[512]; - size_t ielen; - union wpa_event_data event; - - /* data: optional [ ' ' | STA-addr | ' ' | IEs(hex) ] */ - - wpa_printf(MSG_DEBUG, "test_driver: SCAN"); - - if (*data) { - if (*data != ' ' || - hwaddr_aton(data + 1, sa)) { - wpa_printf(MSG_DEBUG, "test_driver: Unexpected SCAN " - "command format"); - return; - } - - data += 18; - while (*data == ' ') - data++; - ielen = os_strlen(data) / 2; - if (ielen > sizeof(ie)) - ielen = sizeof(ie); - if (hexstr2bin(data, ie, ielen) < 0) - ielen = 0; - - wpa_printf(MSG_DEBUG, "test_driver: Scan from " MACSTR, - MAC2STR(sa)); - wpa_hexdump(MSG_MSGDUMP, "test_driver: scan IEs", ie, ielen); - - os_memset(&event, 0, sizeof(event)); - event.rx_probe_req.sa = sa; - event.rx_probe_req.ie = ie; - event.rx_probe_req.ie_len = ielen; - wpa_supplicant_event(drv->ctx, EVENT_RX_PROBE_REQ, &event); -#ifdef CONFIG_P2P - if (drv->p2p) - p2p_probe_req_rx(drv->p2p, sa, ie, ielen); -#endif /* CONFIG_P2P */ - } - - dl_list_for_each(bss, &drv->bss, struct test_driver_bss, list) { - pos = buf; - end = buf + sizeof(buf); - - /* reply: SCANRESP BSSID SSID IEs */ - ret = snprintf(pos, end - pos, "SCANRESP " MACSTR " ", - MAC2STR(bss->bssid)); - if (ret < 0 || ret >= end - pos) - return; - pos += ret; - pos += wpa_snprintf_hex(pos, end - pos, - bss->ssid, bss->ssid_len); - ret = snprintf(pos, end - pos, " "); - if (ret < 0 || ret >= end - pos) - return; - pos += ret; - pos += wpa_snprintf_hex(pos, end - pos, bss->ie, bss->ielen); - pos += wpa_snprintf_hex(pos, end - pos, bss->wps_probe_resp_ie, - bss->wps_probe_resp_ie_len); - - if (bss->privacy) { - ret = snprintf(pos, end - pos, " PRIVACY"); - if (ret < 0 || ret >= end - pos) - return; - pos += ret; - } - - sendto(drv->test_socket, buf, pos - buf, 0, - (struct sockaddr *) from, fromlen); - } -} - - -static void test_driver_assoc(struct wpa_driver_test_data *drv, - struct sockaddr_un *from, socklen_t fromlen, - char *data) -{ - struct test_client_socket *cli; - u8 ie[256], ssid[32]; - size_t ielen, ssid_len = 0; - char *pos, *pos2, cmd[50]; - struct test_driver_bss *bss, *tmp; - - /* data: STA-addr SSID(hex) IEs(hex) */ - - cli = os_zalloc(sizeof(*cli)); - if (cli == NULL) - return; - - if (hwaddr_aton(data, cli->addr)) { - printf("test_socket: Invalid MAC address '%s' in ASSOC\n", - data); - os_free(cli); - return; - } - pos = data + 17; - while (*pos == ' ') - pos++; - pos2 = strchr(pos, ' '); - ielen = 0; - if (pos2) { - ssid_len = (pos2 - pos) / 2; - if (hexstr2bin(pos, ssid, ssid_len) < 0) { - wpa_printf(MSG_DEBUG, "%s: Invalid SSID", __func__); - os_free(cli); - return; - } - wpa_hexdump_ascii(MSG_DEBUG, "test_driver_assoc: SSID", - ssid, ssid_len); - - pos = pos2 + 1; - ielen = strlen(pos) / 2; - if (ielen > sizeof(ie)) - ielen = sizeof(ie); - if (hexstr2bin(pos, ie, ielen) < 0) - ielen = 0; - } - - bss = NULL; - dl_list_for_each(tmp, &drv->bss, struct test_driver_bss, list) { - if (tmp->ssid_len == ssid_len && - os_memcmp(tmp->ssid, ssid, ssid_len) == 0) { - bss = tmp; - break; - } - } - if (bss == NULL) { - wpa_printf(MSG_DEBUG, "%s: No matching SSID found from " - "configured BSSes", __func__); - os_free(cli); - return; - } - - cli->bss = bss; - memcpy(&cli->un, from, sizeof(cli->un)); - cli->unlen = fromlen; - cli->next = drv->cli; - drv->cli = cli; - wpa_hexdump_ascii(MSG_DEBUG, "test_socket: ASSOC sun_path", - (const u8 *) cli->un.sun_path, - cli->unlen - sizeof(cli->un.sun_family)); - - snprintf(cmd, sizeof(cmd), "ASSOCRESP " MACSTR " 0", - MAC2STR(bss->bssid)); - sendto(drv->test_socket, cmd, strlen(cmd), 0, - (struct sockaddr *) from, fromlen); - - drv_event_assoc(bss->bss_ctx, cli->addr, ie, ielen, 0); -} - - -static void test_driver_disassoc(struct wpa_driver_test_data *drv, - struct sockaddr_un *from, socklen_t fromlen) -{ - struct test_client_socket *cli; - - cli = test_driver_get_cli(drv, from, fromlen); - if (!cli) - return; - - drv_event_disassoc(drv->ctx, cli->addr); -} - - -static void test_driver_eapol(struct wpa_driver_test_data *drv, - struct sockaddr_un *from, socklen_t fromlen, - u8 *data, size_t datalen) -{ -#ifdef HOSTAPD - struct test_client_socket *cli; -#endif /* HOSTAPD */ - const u8 *src = NULL; - - if (datalen > 14) { - /* Skip Ethernet header */ - src = data + ETH_ALEN; - wpa_printf(MSG_DEBUG, "test_driver: dst=" MACSTR " src=" - MACSTR " proto=%04x", - MAC2STR(data), MAC2STR(src), - WPA_GET_BE16(data + 2 * ETH_ALEN)); - data += 14; - datalen -= 14; - } - -#ifdef HOSTAPD - cli = test_driver_get_cli(drv, from, fromlen); - if (cli) { - drv_event_eapol_rx(cli->bss->bss_ctx, cli->addr, data, - datalen); - } else { - wpa_printf(MSG_DEBUG, "test_socket: EAPOL from unknown " - "client"); - } -#else /* HOSTAPD */ - if (src) - drv_event_eapol_rx(drv->ctx, src, data, datalen); -#endif /* HOSTAPD */ -} - - -static void test_driver_ether(struct wpa_driver_test_data *drv, - struct sockaddr_un *from, socklen_t fromlen, - u8 *data, size_t datalen) -{ - struct l2_ethhdr *eth; - - if (datalen < sizeof(*eth)) - return; - - eth = (struct l2_ethhdr *) data; - wpa_printf(MSG_DEBUG, "test_driver: RX ETHER dst=" MACSTR " src=" - MACSTR " proto=%04x", - MAC2STR(eth->h_dest), MAC2STR(eth->h_source), - be_to_host16(eth->h_proto)); - -#ifdef CONFIG_IEEE80211R - if (be_to_host16(eth->h_proto) == ETH_P_RRB) { - union wpa_event_data ev; - os_memset(&ev, 0, sizeof(ev)); - ev.ft_rrb_rx.src = eth->h_source; - ev.ft_rrb_rx.data = data + sizeof(*eth); - ev.ft_rrb_rx.data_len = datalen - sizeof(*eth); - } -#endif /* CONFIG_IEEE80211R */ -} - - -static void test_driver_mlme(struct wpa_driver_test_data *drv, - struct sockaddr_un *from, socklen_t fromlen, - u8 *data, size_t datalen) -{ - struct ieee80211_hdr *hdr; - u16 fc; - union wpa_event_data event; - int freq = 0, own_freq; - struct test_driver_bss *bss; - - bss = dl_list_first(&drv->bss, struct test_driver_bss, list); - - if (datalen > 6 && os_memcmp(data, "freq=", 5) == 0) { - size_t pos; - for (pos = 5; pos < datalen; pos++) { - if (data[pos] == ' ') - break; - } - if (pos < datalen) { - freq = atoi((const char *) &data[5]); - wpa_printf(MSG_DEBUG, "test_driver(%s): MLME RX on " - "freq %d MHz", bss->ifname, freq); - pos++; - data += pos; - datalen -= pos; - } - } - - if (drv->remain_on_channel_freq) - own_freq = drv->remain_on_channel_freq; - else - own_freq = drv->current_freq; - - if (freq && own_freq && freq != own_freq) { - wpa_printf(MSG_DEBUG, "test_driver(%s): Ignore MLME RX on " - "another frequency %d MHz (own %d MHz)", - bss->ifname, freq, own_freq); - return; - } - - hdr = (struct ieee80211_hdr *) data; - - if (test_driver_get_cli(drv, from, fromlen) == NULL && datalen >= 16) { - struct test_client_socket *cli; - cli = os_zalloc(sizeof(*cli)); - if (cli == NULL) - return; - wpa_printf(MSG_DEBUG, "Adding client entry for " MACSTR, - MAC2STR(hdr->addr2)); - memcpy(cli->addr, hdr->addr2, ETH_ALEN); - memcpy(&cli->un, from, sizeof(cli->un)); - cli->unlen = fromlen; - cli->next = drv->cli; - drv->cli = cli; - } - - wpa_hexdump(MSG_MSGDUMP, "test_driver_mlme: received frame", - data, datalen); - fc = le_to_host16(hdr->frame_control); - if (WLAN_FC_GET_TYPE(fc) != WLAN_FC_TYPE_MGMT) { - wpa_printf(MSG_ERROR, "%s: received non-mgmt frame", - __func__); - return; - } - - os_memset(&event, 0, sizeof(event)); - event.rx_mgmt.frame = data; - event.rx_mgmt.frame_len = datalen; - wpa_supplicant_event(drv->ctx, EVENT_RX_MGMT, &event); -} - - -static void test_driver_receive_unix(int sock, void *eloop_ctx, void *sock_ctx) -{ - struct wpa_driver_test_data *drv = eloop_ctx; - char buf[2000]; - int res; - struct sockaddr_un from; - socklen_t fromlen = sizeof(from); - - res = recvfrom(sock, buf, sizeof(buf) - 1, 0, - (struct sockaddr *) &from, &fromlen); - if (res < 0) { - perror("recvfrom(test_socket)"); - return; - } - buf[res] = '\0'; - - wpa_printf(MSG_DEBUG, "test_driver: received %u bytes", res); - - if (strncmp(buf, "SCAN", 4) == 0) { - test_driver_scan(drv, &from, fromlen, buf + 4); - } else if (strncmp(buf, "ASSOC ", 6) == 0) { - test_driver_assoc(drv, &from, fromlen, buf + 6); - } else if (strcmp(buf, "DISASSOC") == 0) { - test_driver_disassoc(drv, &from, fromlen); - } else if (strncmp(buf, "EAPOL ", 6) == 0) { - test_driver_eapol(drv, &from, fromlen, (u8 *) buf + 6, - res - 6); - } else if (strncmp(buf, "ETHER ", 6) == 0) { - test_driver_ether(drv, &from, fromlen, (u8 *) buf + 6, - res - 6); - } else if (strncmp(buf, "MLME ", 5) == 0) { - test_driver_mlme(drv, &from, fromlen, (u8 *) buf + 5, res - 5); - } else { - wpa_hexdump_ascii(MSG_DEBUG, "Unknown test_socket command", - (u8 *) buf, res); - } -} - - -static int test_driver_set_generic_elem(void *priv, - const u8 *elem, size_t elem_len) -{ - struct test_driver_bss *bss = priv; - - os_free(bss->ie); - - if (elem == NULL) { - bss->ie = NULL; - bss->ielen = 0; - return 0; - } - - bss->ie = os_malloc(elem_len); - if (bss->ie == NULL) { - bss->ielen = 0; - return -1; - } - - memcpy(bss->ie, elem, elem_len); - bss->ielen = elem_len; - return 0; -} - - -static int test_driver_set_ap_wps_ie(void *priv, const struct wpabuf *beacon, - const struct wpabuf *proberesp, - const struct wpabuf *assocresp) -{ - struct test_driver_bss *bss = priv; - - if (beacon == NULL) - wpa_printf(MSG_DEBUG, "test_driver: Clear Beacon WPS IE"); - else - wpa_hexdump_buf(MSG_DEBUG, "test_driver: Beacon WPS IE", - beacon); - - os_free(bss->wps_beacon_ie); - - if (beacon == NULL) { - bss->wps_beacon_ie = NULL; - bss->wps_beacon_ie_len = 0; - } else { - bss->wps_beacon_ie = os_malloc(wpabuf_len(beacon)); - if (bss->wps_beacon_ie == NULL) { - bss->wps_beacon_ie_len = 0; - return -1; - } - - os_memcpy(bss->wps_beacon_ie, wpabuf_head(beacon), - wpabuf_len(beacon)); - bss->wps_beacon_ie_len = wpabuf_len(beacon); - } - - if (proberesp == NULL) - wpa_printf(MSG_DEBUG, "test_driver: Clear Probe Response WPS " - "IE"); - else - wpa_hexdump_buf(MSG_DEBUG, "test_driver: Probe Response WPS " - "IE", proberesp); - - os_free(bss->wps_probe_resp_ie); - - if (proberesp == NULL) { - bss->wps_probe_resp_ie = NULL; - bss->wps_probe_resp_ie_len = 0; - } else { - bss->wps_probe_resp_ie = os_malloc(wpabuf_len(proberesp)); - if (bss->wps_probe_resp_ie == NULL) { - bss->wps_probe_resp_ie_len = 0; - return -1; - } - - os_memcpy(bss->wps_probe_resp_ie, wpabuf_head(proberesp), - wpabuf_len(proberesp)); - bss->wps_probe_resp_ie_len = wpabuf_len(proberesp); - } - - return 0; -} - - -static int test_driver_sta_deauth(void *priv, const u8 *own_addr, - const u8 *addr, int reason) -{ - struct test_driver_bss *dbss = priv; - struct wpa_driver_test_data *drv = dbss->drv; - struct test_client_socket *cli; - - if (drv->test_socket < 0) - return -1; - - cli = drv->cli; - while (cli) { - if (memcmp(cli->addr, addr, ETH_ALEN) == 0) - break; - cli = cli->next; - } - - if (!cli) - return -1; - - return sendto(drv->test_socket, "DEAUTH", 6, 0, - (struct sockaddr *) &cli->un, cli->unlen); -} - - -static int test_driver_sta_disassoc(void *priv, const u8 *own_addr, - const u8 *addr, int reason) -{ - struct test_driver_bss *dbss = priv; - struct wpa_driver_test_data *drv = dbss->drv; - struct test_client_socket *cli; - - if (drv->test_socket < 0) - return -1; - - cli = drv->cli; - while (cli) { - if (memcmp(cli->addr, addr, ETH_ALEN) == 0) - break; - cli = cli->next; - } - - if (!cli) - return -1; - - return sendto(drv->test_socket, "DISASSOC", 8, 0, - (struct sockaddr *) &cli->un, cli->unlen); -} - - -static int test_driver_bss_add(void *priv, const char *ifname, const u8 *bssid, - void *bss_ctx, void **drv_priv) -{ - struct test_driver_bss *dbss = priv; - struct wpa_driver_test_data *drv = dbss->drv; - struct test_driver_bss *bss; - - wpa_printf(MSG_DEBUG, "%s(ifname=%s bssid=" MACSTR ")", - __func__, ifname, MAC2STR(bssid)); - - bss = os_zalloc(sizeof(*bss)); - if (bss == NULL) - return -1; - - bss->bss_ctx = bss_ctx; - bss->drv = drv; - os_strlcpy(bss->ifname, ifname, IFNAMSIZ); - os_memcpy(bss->bssid, bssid, ETH_ALEN); - - dl_list_add(&drv->bss, &bss->list); - if (drv->global) { - drv->global->bss_add_used = 1; - os_memcpy(drv->global->req_addr, bssid, ETH_ALEN); - } - - if (drv_priv) - *drv_priv = bss; - - return 0; -} - - -static int test_driver_bss_remove(void *priv, const char *ifname) -{ - struct test_driver_bss *dbss = priv; - struct wpa_driver_test_data *drv = dbss->drv; - struct test_driver_bss *bss; - struct test_client_socket *cli, *prev_c; - - wpa_printf(MSG_DEBUG, "%s(ifname=%s)", __func__, ifname); - - dl_list_for_each(bss, &drv->bss, struct test_driver_bss, list) { - if (strcmp(bss->ifname, ifname) != 0) - continue; - - for (prev_c = NULL, cli = drv->cli; cli; - prev_c = cli, cli = cli->next) { - if (cli->bss != bss) - continue; - if (prev_c) - prev_c->next = cli->next; - else - drv->cli = cli->next; - os_free(cli); - break; - } - - dl_list_del(&bss->list); - test_driver_free_bss(bss); - return 0; - } - - return -1; -} - - -static int test_driver_if_add(void *priv, enum wpa_driver_if_type type, - const char *ifname, const u8 *addr, - void *bss_ctx, void **drv_priv, - char *force_ifname, u8 *if_addr, - const char *bridge) -{ - struct test_driver_bss *dbss = priv; - struct wpa_driver_test_data *drv = dbss->drv; - - wpa_printf(MSG_DEBUG, "%s(type=%d ifname=%s bss_ctx=%p)", - __func__, type, ifname, bss_ctx); - if (addr) - os_memcpy(if_addr, addr, ETH_ALEN); - else { - drv->alloc_iface_idx++; - if_addr[0] = 0x02; /* locally administered */ - sha1_prf(drv->own_addr, ETH_ALEN, - "hostapd test addr generation", - (const u8 *) &drv->alloc_iface_idx, - sizeof(drv->alloc_iface_idx), - if_addr + 1, ETH_ALEN - 1); - } - if (type == WPA_IF_AP_BSS || type == WPA_IF_P2P_GO || - type == WPA_IF_P2P_CLIENT || type == WPA_IF_P2P_GROUP) - return test_driver_bss_add(priv, ifname, if_addr, bss_ctx, - drv_priv); - return 0; -} - - -static int test_driver_if_remove(void *priv, enum wpa_driver_if_type type, - const char *ifname) -{ - wpa_printf(MSG_DEBUG, "%s(type=%d ifname=%s)", __func__, type, ifname); - if (type == WPA_IF_AP_BSS || type == WPA_IF_P2P_GO || - type == WPA_IF_P2P_CLIENT || type == WPA_IF_P2P_GROUP) - return test_driver_bss_remove(priv, ifname); - return 0; -} - - -static int test_driver_valid_bss_mask(void *priv, const u8 *addr, - const u8 *mask) -{ - return 0; -} - - -static int test_driver_set_ssid(void *priv, const u8 *buf, int len) -{ - struct test_driver_bss *bss = priv; - - wpa_printf(MSG_DEBUG, "%s(ifname=%s)", __func__, bss->ifname); - if (len < 0) - return -1; - wpa_hexdump_ascii(MSG_DEBUG, "test_driver_set_ssid: SSID", buf, len); - - if ((size_t) len > sizeof(bss->ssid)) - return -1; - - os_memcpy(bss->ssid, buf, len); - bss->ssid_len = len; - - return 0; -} - - -static int test_driver_set_privacy(void *priv, int enabled) -{ - struct test_driver_bss *dbss = priv; - - wpa_printf(MSG_DEBUG, "%s(enabled=%d)", __func__, enabled); - dbss->privacy = enabled; - - return 0; -} - - -static int test_driver_set_sta_vlan(void *priv, const u8 *addr, - const char *ifname, int vlan_id) -{ - wpa_printf(MSG_DEBUG, "%s(addr=" MACSTR " ifname=%s vlan_id=%d)", - __func__, MAC2STR(addr), ifname, vlan_id); - return 0; -} - - -static int test_driver_sta_add(void *priv, - struct hostapd_sta_add_params *params) -{ - struct test_driver_bss *bss = priv; - struct wpa_driver_test_data *drv = bss->drv; - struct test_client_socket *cli; - - wpa_printf(MSG_DEBUG, "%s(ifname=%s addr=" MACSTR " aid=%d " - "capability=0x%x listen_interval=%d)", - __func__, bss->ifname, MAC2STR(params->addr), params->aid, - params->capability, params->listen_interval); - wpa_hexdump(MSG_DEBUG, "test_driver_sta_add - supp_rates", - params->supp_rates, params->supp_rates_len); - - cli = drv->cli; - while (cli) { - if (os_memcmp(cli->addr, params->addr, ETH_ALEN) == 0) - break; - cli = cli->next; - } - if (!cli) { - wpa_printf(MSG_DEBUG, "%s: no matching client entry", - __func__); - return -1; - } - - cli->bss = bss; - - return 0; -} - - -static struct wpa_driver_test_data * test_alloc_data(void *ctx, - const char *ifname) -{ - struct wpa_driver_test_data *drv; - struct test_driver_bss *bss; - - drv = os_zalloc(sizeof(struct wpa_driver_test_data)); - if (drv == NULL) { - wpa_printf(MSG_ERROR, "Could not allocate memory for test " - "driver data"); - return NULL; - } - - bss = os_zalloc(sizeof(struct test_driver_bss)); - if (bss == NULL) { - os_free(drv); - return NULL; - } - - drv->ctx = ctx; - wpa_trace_add_ref(drv, ctx, ctx); - dl_list_init(&drv->bss); - dl_list_add(&drv->bss, &bss->list); - os_strlcpy(bss->ifname, ifname, IFNAMSIZ); - bss->bss_ctx = ctx; - bss->drv = drv; - - /* Generate a MAC address to help testing with multiple STAs */ - drv->own_addr[0] = 0x02; /* locally administered */ - sha1_prf((const u8 *) ifname, os_strlen(ifname), - "test mac addr generation", - NULL, 0, drv->own_addr + 1, ETH_ALEN - 1); - - return drv; -} - - -static void * test_driver_init(struct hostapd_data *hapd, - struct wpa_init_params *params) -{ - struct wpa_driver_test_data *drv; - struct sockaddr_un addr_un; - struct sockaddr_in addr_in; - struct sockaddr *addr; - socklen_t alen; - struct test_driver_bss *bss; - - drv = test_alloc_data(hapd, params->ifname); - if (drv == NULL) - return NULL; - drv->ap = 1; - bss = dl_list_first(&drv->bss, struct test_driver_bss, list); - - bss->bss_ctx = hapd; - os_memcpy(bss->bssid, drv->own_addr, ETH_ALEN); - os_memcpy(params->own_addr, drv->own_addr, ETH_ALEN); - - if (params->test_socket) { - if (os_strlen(params->test_socket) >= - sizeof(addr_un.sun_path)) { - printf("Too long test_socket path\n"); - wpa_driver_test_deinit(bss); - return NULL; - } - if (strncmp(params->test_socket, "DIR:", 4) == 0) { - size_t len = strlen(params->test_socket) + 30; - drv->test_dir = os_strdup(params->test_socket + 4); - drv->own_socket_path = os_malloc(len); - if (drv->own_socket_path) { - snprintf(drv->own_socket_path, len, - "%s/AP-" MACSTR, - params->test_socket + 4, - MAC2STR(params->own_addr)); - } - } else if (strncmp(params->test_socket, "UDP:", 4) == 0) { - drv->udp_port = atoi(params->test_socket + 4); - } else { - drv->own_socket_path = os_strdup(params->test_socket); - } - if (drv->own_socket_path == NULL && drv->udp_port == 0) { - wpa_driver_test_deinit(bss); - return NULL; - } - - drv->test_socket = socket(drv->udp_port ? PF_INET : PF_UNIX, - SOCK_DGRAM, 0); - if (drv->test_socket < 0) { - perror("socket"); - wpa_driver_test_deinit(bss); - return NULL; - } - - if (drv->udp_port) { - os_memset(&addr_in, 0, sizeof(addr_in)); - addr_in.sin_family = AF_INET; - addr_in.sin_port = htons(drv->udp_port); - addr = (struct sockaddr *) &addr_in; - alen = sizeof(addr_in); - } else { - os_memset(&addr_un, 0, sizeof(addr_un)); - addr_un.sun_family = AF_UNIX; - os_strlcpy(addr_un.sun_path, drv->own_socket_path, - sizeof(addr_un.sun_path)); - addr = (struct sockaddr *) &addr_un; - alen = sizeof(addr_un); - } - if (bind(drv->test_socket, addr, alen) < 0) { - perror("bind(PF_UNIX)"); - close(drv->test_socket); - if (drv->own_socket_path) - unlink(drv->own_socket_path); - wpa_driver_test_deinit(bss); - return NULL; - } - eloop_register_read_sock(drv->test_socket, - test_driver_receive_unix, drv, NULL); - } else - drv->test_socket = -1; - - return bss; -} - - -static void wpa_driver_test_poll(void *eloop_ctx, void *timeout_ctx) -{ - struct wpa_driver_test_data *drv = eloop_ctx; - -#ifdef DRIVER_TEST_UNIX - if (drv->associated && drv->hostapd_addr_set) { - struct stat st; - if (stat(drv->hostapd_addr.sun_path, &st) < 0) { - wpa_printf(MSG_DEBUG, "%s: lost connection to AP: %s", - __func__, strerror(errno)); - drv->associated = 0; - wpa_supplicant_event(drv->ctx, EVENT_DISASSOC, NULL); - } - } -#endif /* DRIVER_TEST_UNIX */ - - eloop_register_timeout(1, 0, wpa_driver_test_poll, drv, NULL); -} - - -static void wpa_driver_test_scan_timeout(void *eloop_ctx, void *timeout_ctx) -{ - struct wpa_driver_test_data *drv = eloop_ctx; - wpa_printf(MSG_DEBUG, "Scan timeout - try to get results"); - if (drv->pending_p2p_scan && drv->p2p) { -#ifdef CONFIG_P2P - size_t i; - for (i = 0; i < drv->num_scanres; i++) { - struct wpa_scan_res *bss = drv->scanres[i]; - if (p2p_scan_res_handler(drv->p2p, bss->bssid, - bss->freq, bss->level, - (const u8 *) (bss + 1), - bss->ie_len) > 0) - return; - } - p2p_scan_res_handled(drv->p2p); -#endif /* CONFIG_P2P */ - return; - } - wpa_supplicant_event(timeout_ctx, EVENT_SCAN_RESULTS, NULL); -} - - -#ifdef DRIVER_TEST_UNIX -static void wpa_driver_scan_dir(struct wpa_driver_test_data *drv, - const char *path) -{ - struct dirent *dent; - DIR *dir; - struct sockaddr_un addr; - char cmd[512], *pos, *end; - int ret; - - dir = opendir(path); - if (dir == NULL) - return; - - end = cmd + sizeof(cmd); - pos = cmd; - ret = os_snprintf(pos, end - pos, "SCAN " MACSTR, - MAC2STR(drv->own_addr)); - if (ret >= 0 && ret < end - pos) - pos += ret; - if (drv->probe_req_ie) { - ret = os_snprintf(pos, end - pos, " "); - if (ret >= 0 && ret < end - pos) - pos += ret; - pos += wpa_snprintf_hex(pos, end - pos, drv->probe_req_ie, - drv->probe_req_ie_len); - } - if (drv->probe_req_ssid_len) { - /* Add SSID IE */ - ret = os_snprintf(pos, end - pos, "%02x%02x", - WLAN_EID_SSID, - (unsigned int) drv->probe_req_ssid_len); - if (ret >= 0 && ret < end - pos) - pos += ret; - pos += wpa_snprintf_hex(pos, end - pos, drv->probe_req_ssid, - drv->probe_req_ssid_len); - } - end[-1] = '\0'; - - while ((dent = readdir(dir))) { - if (os_strncmp(dent->d_name, "AP-", 3) != 0 && - os_strncmp(dent->d_name, "STA-", 4) != 0) - continue; - if (drv->own_socket_path) { - size_t olen, dlen; - olen = os_strlen(drv->own_socket_path); - dlen = os_strlen(dent->d_name); - if (olen >= dlen && - os_strcmp(dent->d_name, - drv->own_socket_path + olen - dlen) == 0) - continue; - } - wpa_printf(MSG_DEBUG, "%s: SCAN %s", __func__, dent->d_name); - - os_memset(&addr, 0, sizeof(addr)); - addr.sun_family = AF_UNIX; - os_snprintf(addr.sun_path, sizeof(addr.sun_path), "%s/%s", - path, dent->d_name); - - if (sendto(drv->test_socket, cmd, os_strlen(cmd), 0, - (struct sockaddr *) &addr, sizeof(addr)) < 0) { - perror("sendto(test_socket)"); - } - } - closedir(dir); -} -#endif /* DRIVER_TEST_UNIX */ - - -static int wpa_driver_test_scan(void *priv, - struct wpa_driver_scan_params *params) -{ - struct test_driver_bss *dbss = priv; - struct wpa_driver_test_data *drv = dbss->drv; - size_t i; - - wpa_printf(MSG_DEBUG, "%s: priv=%p", __func__, priv); - - os_free(drv->probe_req_ie); - if (params->extra_ies) { - drv->probe_req_ie = os_malloc(params->extra_ies_len); - if (drv->probe_req_ie == NULL) { - drv->probe_req_ie_len = 0; - return -1; - } - os_memcpy(drv->probe_req_ie, params->extra_ies, - params->extra_ies_len); - drv->probe_req_ie_len = params->extra_ies_len; - } else { - drv->probe_req_ie = NULL; - drv->probe_req_ie_len = 0; - } - - for (i = 0; i < params->num_ssids; i++) - wpa_hexdump(MSG_DEBUG, "Scan SSID", - params->ssids[i].ssid, params->ssids[i].ssid_len); - drv->probe_req_ssid_len = 0; - if (params->num_ssids) { - os_memcpy(drv->probe_req_ssid, params->ssids[0].ssid, - params->ssids[0].ssid_len); - drv->probe_req_ssid_len = params->ssids[0].ssid_len; - } - wpa_hexdump(MSG_DEBUG, "Scan extra IE(s)", - params->extra_ies, params->extra_ies_len); - - drv->num_scanres = 0; - -#ifdef DRIVER_TEST_UNIX - if (drv->test_socket >= 0 && drv->test_dir) - wpa_driver_scan_dir(drv, drv->test_dir); - - if (drv->test_socket >= 0 && drv->hostapd_addr_set && - sendto(drv->test_socket, "SCAN", 4, 0, - (struct sockaddr *) &drv->hostapd_addr, - sizeof(drv->hostapd_addr)) < 0) { - perror("sendto(test_socket)"); - } -#endif /* DRIVER_TEST_UNIX */ - - if (drv->test_socket >= 0 && drv->hostapd_addr_udp_set && - sendto(drv->test_socket, "SCAN", 4, 0, - (struct sockaddr *) &drv->hostapd_addr_udp, - sizeof(drv->hostapd_addr_udp)) < 0) { - perror("sendto(test_socket)"); - } - - eloop_cancel_timeout(wpa_driver_test_scan_timeout, drv, drv->ctx); - eloop_register_timeout(1, 0, wpa_driver_test_scan_timeout, drv, - drv->ctx); - return 0; -} - - -static struct wpa_scan_results * wpa_driver_test_get_scan_results2(void *priv) -{ - struct test_driver_bss *dbss = priv; - struct wpa_driver_test_data *drv = dbss->drv; - struct wpa_scan_results *res; - size_t i; - - res = os_zalloc(sizeof(*res)); - if (res == NULL) - return NULL; - - res->res = os_zalloc(drv->num_scanres * sizeof(struct wpa_scan_res *)); - if (res->res == NULL) { - os_free(res); - return NULL; - } - - for (i = 0; i < drv->num_scanres; i++) { - struct wpa_scan_res *r; - if (drv->scanres[i] == NULL) - continue; - r = os_malloc(sizeof(*r) + drv->scanres[i]->ie_len); - if (r == NULL) - break; - os_memcpy(r, drv->scanres[i], - sizeof(*r) + drv->scanres[i]->ie_len); - res->res[res->num++] = r; - } - - return res; -} - - -static int wpa_driver_test_set_key(const char *ifname, void *priv, - enum wpa_alg alg, const u8 *addr, - int key_idx, int set_tx, - const u8 *seq, size_t seq_len, - const u8 *key, size_t key_len) -{ - wpa_printf(MSG_DEBUG, "%s: ifname=%s priv=%p alg=%d key_idx=%d " - "set_tx=%d", - __func__, ifname, priv, alg, key_idx, set_tx); - if (addr) - wpa_printf(MSG_DEBUG, " addr=" MACSTR, MAC2STR(addr)); - if (seq) - wpa_hexdump(MSG_DEBUG, " seq", seq, seq_len); - if (key) - wpa_hexdump_key(MSG_DEBUG, " key", key, key_len); - return 0; -} - - -static int wpa_driver_update_mode(struct wpa_driver_test_data *drv, int ap) -{ - if (ap && !drv->ap) { - wpa_driver_test_close_test_socket(drv); - wpa_driver_test_attach(drv, drv->test_dir, 1); - drv->ap = 1; - } else if (!ap && drv->ap) { - wpa_driver_test_close_test_socket(drv); - wpa_driver_test_attach(drv, drv->test_dir, 0); - drv->ap = 0; - } - - return 0; -} - - -static int wpa_driver_test_associate( - void *priv, struct wpa_driver_associate_params *params) -{ - struct test_driver_bss *dbss = priv; - struct wpa_driver_test_data *drv = dbss->drv; - wpa_printf(MSG_DEBUG, "%s: priv=%p freq=%d pairwise_suite=%d " - "group_suite=%d key_mgmt_suite=%d auth_alg=%d mode=%d", - __func__, priv, params->freq, params->pairwise_suite, - params->group_suite, params->key_mgmt_suite, - params->auth_alg, params->mode); - wpa_driver_update_mode(drv, params->mode == IEEE80211_MODE_AP); - if (params->bssid) { - wpa_printf(MSG_DEBUG, " bssid=" MACSTR, - MAC2STR(params->bssid)); - } - if (params->ssid) { - wpa_hexdump_ascii(MSG_DEBUG, " ssid", - params->ssid, params->ssid_len); - } - if (params->wpa_ie) { - wpa_hexdump(MSG_DEBUG, " wpa_ie", - params->wpa_ie, params->wpa_ie_len); - drv->assoc_wpa_ie_len = params->wpa_ie_len; - if (drv->assoc_wpa_ie_len > sizeof(drv->assoc_wpa_ie)) - drv->assoc_wpa_ie_len = sizeof(drv->assoc_wpa_ie); - os_memcpy(drv->assoc_wpa_ie, params->wpa_ie, - drv->assoc_wpa_ie_len); - } else - drv->assoc_wpa_ie_len = 0; - - wpa_driver_update_mode(drv, params->mode == IEEE80211_MODE_AP); - - drv->ibss = params->mode == IEEE80211_MODE_IBSS; - dbss->privacy = params->key_mgmt_suite & - (WPA_KEY_MGMT_IEEE8021X | - WPA_KEY_MGMT_PSK | - WPA_KEY_MGMT_WPA_NONE | - WPA_KEY_MGMT_FT_IEEE8021X | - WPA_KEY_MGMT_FT_PSK | - WPA_KEY_MGMT_IEEE8021X_SHA256 | - WPA_KEY_MGMT_PSK_SHA256); - if (params->wep_key_len[params->wep_tx_keyidx]) - dbss->privacy = 1; - -#ifdef DRIVER_TEST_UNIX - if (drv->test_dir && params->bssid && - params->mode != IEEE80211_MODE_IBSS) { - os_memset(&drv->hostapd_addr, 0, sizeof(drv->hostapd_addr)); - drv->hostapd_addr.sun_family = AF_UNIX; - os_snprintf(drv->hostapd_addr.sun_path, - sizeof(drv->hostapd_addr.sun_path), - "%s/AP-" MACSTR, - drv->test_dir, MAC2STR(params->bssid)); - drv->hostapd_addr_set = 1; - } -#endif /* DRIVER_TEST_UNIX */ - - if (params->mode == IEEE80211_MODE_AP) { - os_memcpy(dbss->ssid, params->ssid, params->ssid_len); - dbss->ssid_len = params->ssid_len; - os_memcpy(dbss->bssid, drv->own_addr, ETH_ALEN); - if (params->wpa_ie && params->wpa_ie_len) { - dbss->ie = os_malloc(params->wpa_ie_len); - if (dbss->ie) { - os_memcpy(dbss->ie, params->wpa_ie, - params->wpa_ie_len); - dbss->ielen = params->wpa_ie_len; - } - } - } else if (drv->test_socket >= 0 && - (drv->hostapd_addr_set || drv->hostapd_addr_udp_set)) { - char cmd[200], *pos, *end; - int ret; - end = cmd + sizeof(cmd); - pos = cmd; - ret = os_snprintf(pos, end - pos, "ASSOC " MACSTR " ", - MAC2STR(drv->own_addr)); - if (ret >= 0 && ret < end - pos) - pos += ret; - pos += wpa_snprintf_hex(pos, end - pos, params->ssid, - params->ssid_len); - ret = os_snprintf(pos, end - pos, " "); - if (ret >= 0 && ret < end - pos) - pos += ret; - pos += wpa_snprintf_hex(pos, end - pos, params->wpa_ie, - params->wpa_ie_len); - end[-1] = '\0'; -#ifdef DRIVER_TEST_UNIX - if (drv->hostapd_addr_set && - sendto(drv->test_socket, cmd, os_strlen(cmd), 0, - (struct sockaddr *) &drv->hostapd_addr, - sizeof(drv->hostapd_addr)) < 0) { - perror("sendto(test_socket)"); - return -1; - } -#endif /* DRIVER_TEST_UNIX */ - if (drv->hostapd_addr_udp_set && - sendto(drv->test_socket, cmd, os_strlen(cmd), 0, - (struct sockaddr *) &drv->hostapd_addr_udp, - sizeof(drv->hostapd_addr_udp)) < 0) { - perror("sendto(test_socket)"); - return -1; - } - - os_memcpy(dbss->ssid, params->ssid, params->ssid_len); - dbss->ssid_len = params->ssid_len; - } else { - drv->associated = 1; - if (params->mode == IEEE80211_MODE_IBSS) { - os_memcpy(dbss->ssid, params->ssid, params->ssid_len); - dbss->ssid_len = params->ssid_len; - if (params->bssid) - os_memcpy(dbss->bssid, params->bssid, - ETH_ALEN); - else { - os_get_random(dbss->bssid, ETH_ALEN); - dbss->bssid[0] &= ~0x01; - dbss->bssid[0] |= 0x02; - } - } - wpa_supplicant_event(drv->ctx, EVENT_ASSOC, NULL); - } - - return 0; -} - - -static int wpa_driver_test_get_bssid(void *priv, u8 *bssid) -{ - struct test_driver_bss *dbss = priv; - os_memcpy(bssid, dbss->bssid, ETH_ALEN); - return 0; -} - - -static int wpa_driver_test_get_ssid(void *priv, u8 *ssid) -{ - struct test_driver_bss *dbss = priv; - os_memcpy(ssid, dbss->ssid, 32); - return dbss->ssid_len; -} - - -static int wpa_driver_test_send_disassoc(struct wpa_driver_test_data *drv) -{ -#ifdef DRIVER_TEST_UNIX - if (drv->test_socket >= 0 && - sendto(drv->test_socket, "DISASSOC", 8, 0, - (struct sockaddr *) &drv->hostapd_addr, - sizeof(drv->hostapd_addr)) < 0) { - perror("sendto(test_socket)"); - return -1; - } -#endif /* DRIVER_TEST_UNIX */ - if (drv->test_socket >= 0 && drv->hostapd_addr_udp_set && - sendto(drv->test_socket, "DISASSOC", 8, 0, - (struct sockaddr *) &drv->hostapd_addr_udp, - sizeof(drv->hostapd_addr_udp)) < 0) { - perror("sendto(test_socket)"); - return -1; - } - return 0; -} - - -static int wpa_driver_test_deauthenticate(void *priv, const u8 *addr, - int reason_code) -{ - struct test_driver_bss *dbss = priv; - struct wpa_driver_test_data *drv = dbss->drv; - wpa_printf(MSG_DEBUG, "%s addr=" MACSTR " reason_code=%d", - __func__, MAC2STR(addr), reason_code); - os_memset(dbss->bssid, 0, ETH_ALEN); - drv->associated = 0; - wpa_supplicant_event(drv->ctx, EVENT_DISASSOC, NULL); - return wpa_driver_test_send_disassoc(drv); -} - - -static int wpa_driver_test_disassociate(void *priv, const u8 *addr, - int reason_code) -{ - struct test_driver_bss *dbss = priv; - struct wpa_driver_test_data *drv = dbss->drv; - wpa_printf(MSG_DEBUG, "%s addr=" MACSTR " reason_code=%d", - __func__, MAC2STR(addr), reason_code); - os_memset(dbss->bssid, 0, ETH_ALEN); - drv->associated = 0; - wpa_supplicant_event(drv->ctx, EVENT_DISASSOC, NULL); - return wpa_driver_test_send_disassoc(drv); -} - - -static const u8 * wpa_scan_get_ie(const struct wpa_scan_res *res, u8 ie) -{ - const u8 *end, *pos; - - pos = (const u8 *) (res + 1); - end = pos + res->ie_len; - - while (pos + 1 < end) { - if (pos + 2 + pos[1] > end) - break; - if (pos[0] == ie) - return pos; - pos += 2 + pos[1]; - } - - return NULL; -} - - -static void wpa_driver_test_scanresp(struct wpa_driver_test_data *drv, - struct sockaddr *from, - socklen_t fromlen, - const char *data) -{ - struct wpa_scan_res *res; - const char *pos, *pos2; - size_t len; - u8 *ie_pos, *ie_start, *ie_end; -#define MAX_IE_LEN 1000 - const u8 *ds_params; - - wpa_printf(MSG_DEBUG, "test_driver: SCANRESP %s", data); - if (drv->num_scanres >= MAX_SCAN_RESULTS) { - wpa_printf(MSG_DEBUG, "test_driver: No room for the new scan " - "result"); - return; - } - - /* SCANRESP BSSID SSID IEs */ - - res = os_zalloc(sizeof(*res) + MAX_IE_LEN); - if (res == NULL) - return; - ie_start = ie_pos = (u8 *) (res + 1); - ie_end = ie_pos + MAX_IE_LEN; - - if (hwaddr_aton(data, res->bssid)) { - wpa_printf(MSG_DEBUG, "test_driver: invalid BSSID in scanres"); - os_free(res); - return; - } - - pos = data + 17; - while (*pos == ' ') - pos++; - pos2 = os_strchr(pos, ' '); - if (pos2 == NULL) { - wpa_printf(MSG_DEBUG, "test_driver: invalid SSID termination " - "in scanres"); - os_free(res); - return; - } - len = (pos2 - pos) / 2; - if (len > 32) - len = 32; - /* - * Generate SSID IE from the SSID field since this IE is not included - * in the main IE field. - */ - *ie_pos++ = WLAN_EID_SSID; - *ie_pos++ = len; - if (hexstr2bin(pos, ie_pos, len) < 0) { - wpa_printf(MSG_DEBUG, "test_driver: invalid SSID in scanres"); - os_free(res); - return; - } - ie_pos += len; - - pos = pos2 + 1; - pos2 = os_strchr(pos, ' '); - if (pos2 == NULL) - len = os_strlen(pos) / 2; - else - len = (pos2 - pos) / 2; - if ((int) len > ie_end - ie_pos) - len = ie_end - ie_pos; - if (hexstr2bin(pos, ie_pos, len) < 0) { - wpa_printf(MSG_DEBUG, "test_driver: invalid IEs in scanres"); - os_free(res); - return; - } - ie_pos += len; - res->ie_len = ie_pos - ie_start; - - if (pos2) { - pos = pos2 + 1; - while (*pos == ' ') - pos++; - if (os_strstr(pos, "PRIVACY")) - res->caps |= IEEE80211_CAP_PRIVACY; - if (os_strstr(pos, "IBSS")) - res->caps |= IEEE80211_CAP_IBSS; - } - - ds_params = wpa_scan_get_ie(res, WLAN_EID_DS_PARAMS); - if (ds_params && ds_params[1] > 0) { - if (ds_params[2] >= 1 && ds_params[2] <= 13) - res->freq = 2407 + ds_params[2] * 5; - } - - os_free(drv->scanres[drv->num_scanres]); - drv->scanres[drv->num_scanres++] = res; -} - - -static void wpa_driver_test_assocresp(struct wpa_driver_test_data *drv, - struct sockaddr *from, - socklen_t fromlen, - const char *data) -{ - struct test_driver_bss *bss; - - bss = dl_list_first(&drv->bss, struct test_driver_bss, list); - - /* ASSOCRESP BSSID */ - if (hwaddr_aton(data, bss->bssid)) { - wpa_printf(MSG_DEBUG, "test_driver: invalid BSSID in " - "assocresp"); - } - if (drv->use_associnfo) { - union wpa_event_data event; - os_memset(&event, 0, sizeof(event)); - event.assoc_info.req_ies = drv->assoc_wpa_ie; - event.assoc_info.req_ies_len = drv->assoc_wpa_ie_len; - wpa_supplicant_event(drv->ctx, EVENT_ASSOCINFO, &event); - } - drv->associated = 1; - wpa_supplicant_event(drv->ctx, EVENT_ASSOC, NULL); -} - - -static void wpa_driver_test_disassoc(struct wpa_driver_test_data *drv, - struct sockaddr *from, - socklen_t fromlen) -{ - drv->associated = 0; - wpa_supplicant_event(drv->ctx, EVENT_DISASSOC, NULL); -} - - -static void wpa_driver_test_eapol(struct wpa_driver_test_data *drv, - struct sockaddr *from, - socklen_t fromlen, - const u8 *data, size_t data_len) -{ - const u8 *src; - struct test_driver_bss *bss; - - bss = dl_list_first(&drv->bss, struct test_driver_bss, list); - - if (data_len > 14) { - /* Skip Ethernet header */ - src = data + ETH_ALEN; - data += 14; - data_len -= 14; - } else - src = bss->bssid; - - drv_event_eapol_rx(drv->ctx, src, data, data_len); -} - - -static void wpa_driver_test_mlme(struct wpa_driver_test_data *drv, - struct sockaddr *from, - socklen_t fromlen, - const u8 *data, size_t data_len) -{ - int freq = 0, own_freq; - union wpa_event_data event; - const struct ieee80211_mgmt *mgmt; - u16 fc; - struct test_driver_bss *bss; - - bss = dl_list_first(&drv->bss, struct test_driver_bss, list); - if (data_len > 6 && os_memcmp(data, "freq=", 5) == 0) { - size_t pos; - for (pos = 5; pos < data_len; pos++) { - if (data[pos] == ' ') - break; - } - if (pos < data_len) { - freq = atoi((const char *) &data[5]); - wpa_printf(MSG_DEBUG, "test_driver(%s): MLME RX on " - "freq %d MHz", bss->ifname, freq); - pos++; - data += pos; - data_len -= pos; - } - } - - if (drv->remain_on_channel_freq) - own_freq = drv->remain_on_channel_freq; - else - own_freq = drv->current_freq; - - if (freq && own_freq && freq != own_freq) { - wpa_printf(MSG_DEBUG, "test_driver(%s): Ignore MLME RX on " - "another frequency %d MHz (own %d MHz)", - bss->ifname, freq, own_freq); - return; - } - - os_memset(&event, 0, sizeof(event)); - event.mlme_rx.buf = data; - event.mlme_rx.len = data_len; - event.mlme_rx.freq = freq; - wpa_supplicant_event(drv->ctx, EVENT_MLME_RX, &event); - - mgmt = (const struct ieee80211_mgmt *) data; - fc = le_to_host16(mgmt->frame_control); - - if (drv->probe_req_report && data_len >= 24) { - if (WLAN_FC_GET_TYPE(fc) == WLAN_FC_TYPE_MGMT && - WLAN_FC_GET_STYPE(fc) == WLAN_FC_STYPE_PROBE_REQ) { - os_memset(&event, 0, sizeof(event)); - event.rx_probe_req.sa = mgmt->sa; - event.rx_probe_req.ie = mgmt->u.probe_req.variable; - event.rx_probe_req.ie_len = - data_len - (mgmt->u.probe_req.variable - data); - wpa_supplicant_event(drv->ctx, EVENT_RX_PROBE_REQ, - &event); -#ifdef CONFIG_P2P - if (drv->p2p) - p2p_probe_req_rx(drv->p2p, mgmt->sa, - event.rx_probe_req.ie, - event.rx_probe_req.ie_len); -#endif /* CONFIG_P2P */ - } - } - -#ifdef CONFIG_P2P - if (drv->p2p && - WLAN_FC_GET_TYPE(fc) == WLAN_FC_TYPE_MGMT && - WLAN_FC_GET_STYPE(fc) == WLAN_FC_STYPE_ACTION) { - size_t hdr_len; - hdr_len = (const u8 *) - &mgmt->u.action.u.vs_public_action.action - data; - p2p_rx_action(drv->p2p, mgmt->da, mgmt->sa, mgmt->bssid, - mgmt->u.action.category, - &mgmt->u.action.u.vs_public_action.action, - data_len - hdr_len, freq); - } -#endif /* CONFIG_P2P */ - -} - - -static void wpa_driver_test_scan_cmd(struct wpa_driver_test_data *drv, - struct sockaddr *from, - socklen_t fromlen, - const u8 *data, size_t data_len) -{ - char buf[512], *pos, *end; - int ret; - struct test_driver_bss *bss; - - bss = dl_list_first(&drv->bss, struct test_driver_bss, list); - - /* data: optional [ STA-addr | ' ' | IEs(hex) ] */ -#ifdef CONFIG_P2P - if (drv->probe_req_report && drv->p2p && data_len) { - const char *d = (const char *) data; - u8 sa[ETH_ALEN]; - u8 ie[512]; - size_t ielen; - - if (hwaddr_aton(d, sa)) - return; - d += 18; - while (*d == ' ') - d++; - ielen = os_strlen(d) / 2; - if (ielen > sizeof(ie)) - ielen = sizeof(ie); - if (hexstr2bin(d, ie, ielen) < 0) - ielen = 0; - drv->probe_from = from; - drv->probe_from_len = fromlen; - p2p_probe_req_rx(drv->p2p, sa, ie, ielen); - drv->probe_from = NULL; - } -#endif /* CONFIG_P2P */ - - if (!drv->ibss) - return; - - pos = buf; - end = buf + sizeof(buf); - - /* reply: SCANRESP BSSID SSID IEs */ - ret = snprintf(pos, end - pos, "SCANRESP " MACSTR " ", - MAC2STR(bss->bssid)); - if (ret < 0 || ret >= end - pos) - return; - pos += ret; - pos += wpa_snprintf_hex(pos, end - pos, - bss->ssid, bss->ssid_len); - ret = snprintf(pos, end - pos, " "); - if (ret < 0 || ret >= end - pos) - return; - pos += ret; - pos += wpa_snprintf_hex(pos, end - pos, drv->assoc_wpa_ie, - drv->assoc_wpa_ie_len); - - if (bss->privacy) { - ret = snprintf(pos, end - pos, " PRIVACY"); - if (ret < 0 || ret >= end - pos) - return; - pos += ret; - } - - ret = snprintf(pos, end - pos, " IBSS"); - if (ret < 0 || ret >= end - pos) - return; - pos += ret; - - sendto(drv->test_socket, buf, pos - buf, 0, - (struct sockaddr *) from, fromlen); -} - - -static void wpa_driver_test_receive_unix(int sock, void *eloop_ctx, - void *sock_ctx) -{ - struct wpa_driver_test_data *drv = eloop_ctx; - char *buf; - int res; - struct sockaddr_storage from; - socklen_t fromlen = sizeof(from); - const size_t buflen = 2000; - - if (drv->ap) { - test_driver_receive_unix(sock, eloop_ctx, sock_ctx); - return; - } - - buf = os_malloc(buflen); - if (buf == NULL) - return; - res = recvfrom(sock, buf, buflen - 1, 0, - (struct sockaddr *) &from, &fromlen); - if (res < 0) { - perror("recvfrom(test_socket)"); - os_free(buf); - return; - } - buf[res] = '\0'; - - wpa_printf(MSG_DEBUG, "test_driver: received %u bytes", res); - - if (os_strncmp(buf, "SCANRESP ", 9) == 0) { - wpa_driver_test_scanresp(drv, (struct sockaddr *) &from, - fromlen, buf + 9); - } else if (os_strncmp(buf, "ASSOCRESP ", 10) == 0) { - wpa_driver_test_assocresp(drv, (struct sockaddr *) &from, - fromlen, buf + 10); - } else if (os_strcmp(buf, "DISASSOC") == 0) { - wpa_driver_test_disassoc(drv, (struct sockaddr *) &from, - fromlen); - } else if (os_strcmp(buf, "DEAUTH") == 0) { - wpa_driver_test_disassoc(drv, (struct sockaddr *) &from, - fromlen); - } else if (os_strncmp(buf, "EAPOL ", 6) == 0) { - wpa_driver_test_eapol(drv, (struct sockaddr *) &from, fromlen, - (const u8 *) buf + 6, res - 6); - } else if (os_strncmp(buf, "MLME ", 5) == 0) { - wpa_driver_test_mlme(drv, (struct sockaddr *) &from, fromlen, - (const u8 *) buf + 5, res - 5); - } else if (os_strncmp(buf, "SCAN ", 5) == 0) { - wpa_driver_test_scan_cmd(drv, (struct sockaddr *) &from, - fromlen, - (const u8 *) buf + 5, res - 5); - } else { - wpa_hexdump_ascii(MSG_DEBUG, "Unknown test_socket command", - (u8 *) buf, res); - } - os_free(buf); -} - - -static void * wpa_driver_test_init2(void *ctx, const char *ifname, - void *global_priv) -{ - struct wpa_driver_test_data *drv; - struct wpa_driver_test_global *global = global_priv; - struct test_driver_bss *bss; - - drv = test_alloc_data(ctx, ifname); - if (drv == NULL) - return NULL; - bss = dl_list_first(&drv->bss, struct test_driver_bss, list); - drv->global = global_priv; - drv->test_socket = -1; - - /* Set dummy BSSID and SSID for testing. */ - bss->bssid[0] = 0x02; - bss->bssid[1] = 0x00; - bss->bssid[2] = 0x00; - bss->bssid[3] = 0x00; - bss->bssid[4] = 0x00; - bss->bssid[5] = 0x01; - os_memcpy(bss->ssid, "test", 5); - bss->ssid_len = 4; - - if (global->bss_add_used) { - os_memcpy(drv->own_addr, global->req_addr, ETH_ALEN); - global->bss_add_used = 0; - } - - eloop_register_timeout(1, 0, wpa_driver_test_poll, drv, NULL); - - return bss; -} - - -static void wpa_driver_test_close_test_socket(struct wpa_driver_test_data *drv) -{ - if (drv->test_socket >= 0) { - eloop_unregister_read_sock(drv->test_socket); - close(drv->test_socket); - drv->test_socket = -1; - } - - if (drv->own_socket_path) { - unlink(drv->own_socket_path); - os_free(drv->own_socket_path); - drv->own_socket_path = NULL; - } -} - - -static void wpa_driver_test_deinit(void *priv) -{ - struct test_driver_bss *dbss = priv; - struct wpa_driver_test_data *drv = dbss->drv; - struct test_client_socket *cli, *prev; - int i; - -#ifdef CONFIG_P2P - if (drv->p2p) - p2p_deinit(drv->p2p); - wpabuf_free(drv->pending_action_tx); -#endif /* CONFIG_P2P */ - - cli = drv->cli; - while (cli) { - prev = cli; - cli = cli->next; - os_free(prev); - } - -#ifdef HOSTAPD - /* There should be only one BSS remaining at this point. */ - if (dl_list_len(&drv->bss) != 1) - wpa_printf(MSG_ERROR, "%s: %u remaining BSS entries", - __func__, dl_list_len(&drv->bss)); -#endif /* HOSTAPD */ - - test_driver_free_bsses(drv); - - wpa_driver_test_close_test_socket(drv); - eloop_cancel_timeout(wpa_driver_test_scan_timeout, drv, drv->ctx); - eloop_cancel_timeout(wpa_driver_test_poll, drv, NULL); - eloop_cancel_timeout(test_remain_on_channel_timeout, drv, NULL); - os_free(drv->test_dir); - for (i = 0; i < MAX_SCAN_RESULTS; i++) - os_free(drv->scanres[i]); - os_free(drv->probe_req_ie); - wpa_trace_remove_ref(drv, ctx, drv->ctx); - os_free(drv); -} - - -static int wpa_driver_test_attach(struct wpa_driver_test_data *drv, - const char *dir, int ap) -{ -#ifdef DRIVER_TEST_UNIX - static unsigned int counter = 0; - struct sockaddr_un addr; - size_t len; - - os_free(drv->own_socket_path); - if (dir) { - len = os_strlen(dir) + 30; - drv->own_socket_path = os_malloc(len); - if (drv->own_socket_path == NULL) - return -1; - os_snprintf(drv->own_socket_path, len, "%s/%s-" MACSTR, - dir, ap ? "AP" : "STA", MAC2STR(drv->own_addr)); - } else { - drv->own_socket_path = os_malloc(100); - if (drv->own_socket_path == NULL) - return -1; - os_snprintf(drv->own_socket_path, 100, - "/tmp/wpa_supplicant_test-%d-%d", - getpid(), counter++); - } - - drv->test_socket = socket(PF_UNIX, SOCK_DGRAM, 0); - if (drv->test_socket < 0) { - perror("socket(PF_UNIX)"); - os_free(drv->own_socket_path); - drv->own_socket_path = NULL; - return -1; - } - - os_memset(&addr, 0, sizeof(addr)); - addr.sun_family = AF_UNIX; - os_strlcpy(addr.sun_path, drv->own_socket_path, sizeof(addr.sun_path)); - if (bind(drv->test_socket, (struct sockaddr *) &addr, - sizeof(addr)) < 0) { - perror("bind(PF_UNIX)"); - close(drv->test_socket); - unlink(drv->own_socket_path); - os_free(drv->own_socket_path); - drv->own_socket_path = NULL; - return -1; - } - - eloop_register_read_sock(drv->test_socket, - wpa_driver_test_receive_unix, drv, NULL); - - return 0; -#else /* DRIVER_TEST_UNIX */ - return -1; -#endif /* DRIVER_TEST_UNIX */ -} - - -static int wpa_driver_test_attach_udp(struct wpa_driver_test_data *drv, - char *dst) -{ - char *pos; - - pos = os_strchr(dst, ':'); - if (pos == NULL) - return -1; - *pos++ = '\0'; - wpa_printf(MSG_DEBUG, "%s: addr=%s port=%s", __func__, dst, pos); - - drv->test_socket = socket(PF_INET, SOCK_DGRAM, 0); - if (drv->test_socket < 0) { - perror("socket(PF_INET)"); - return -1; - } - - os_memset(&drv->hostapd_addr_udp, 0, sizeof(drv->hostapd_addr_udp)); - drv->hostapd_addr_udp.sin_family = AF_INET; -#if defined(CONFIG_NATIVE_WINDOWS) || defined(CONFIG_ANSI_C_EXTRA) - { - int a[4]; - u8 *pos; - sscanf(dst, "%d.%d.%d.%d", &a[0], &a[1], &a[2], &a[3]); - pos = (u8 *) &drv->hostapd_addr_udp.sin_addr; - *pos++ = a[0]; - *pos++ = a[1]; - *pos++ = a[2]; - *pos++ = a[3]; - } -#else /* CONFIG_NATIVE_WINDOWS or CONFIG_ANSI_C_EXTRA */ - inet_aton(dst, &drv->hostapd_addr_udp.sin_addr); -#endif /* CONFIG_NATIVE_WINDOWS or CONFIG_ANSI_C_EXTRA */ - drv->hostapd_addr_udp.sin_port = htons(atoi(pos)); - - drv->hostapd_addr_udp_set = 1; - - eloop_register_read_sock(drv->test_socket, - wpa_driver_test_receive_unix, drv, NULL); - - return 0; -} - - -static int wpa_driver_test_set_param(void *priv, const char *param) -{ - struct test_driver_bss *dbss = priv; - struct wpa_driver_test_data *drv = dbss->drv; - const char *pos; - - wpa_printf(MSG_DEBUG, "%s: param='%s'", __func__, param); - if (param == NULL) - return 0; - - wpa_driver_test_close_test_socket(drv); - -#ifdef DRIVER_TEST_UNIX - pos = os_strstr(param, "test_socket="); - if (pos) { - const char *pos2; - size_t len; - - pos += 12; - pos2 = os_strchr(pos, ' '); - if (pos2) - len = pos2 - pos; - else - len = os_strlen(pos); - if (len > sizeof(drv->hostapd_addr.sun_path)) - return -1; - os_memset(&drv->hostapd_addr, 0, sizeof(drv->hostapd_addr)); - drv->hostapd_addr.sun_family = AF_UNIX; - os_memcpy(drv->hostapd_addr.sun_path, pos, len); - drv->hostapd_addr_set = 1; - } -#endif /* DRIVER_TEST_UNIX */ - - pos = os_strstr(param, "test_dir="); - if (pos) { - char *end; - os_free(drv->test_dir); - drv->test_dir = os_strdup(pos + 9); - if (drv->test_dir == NULL) - return -1; - end = os_strchr(drv->test_dir, ' '); - if (end) - *end = '\0'; - if (wpa_driver_test_attach(drv, drv->test_dir, 0)) - return -1; - } else { - pos = os_strstr(param, "test_udp="); - if (pos) { - char *dst, *epos; - dst = os_strdup(pos + 9); - if (dst == NULL) - return -1; - epos = os_strchr(dst, ' '); - if (epos) - *epos = '\0'; - if (wpa_driver_test_attach_udp(drv, dst)) - return -1; - os_free(dst); - } else if (wpa_driver_test_attach(drv, NULL, 0)) - return -1; - } - - if (os_strstr(param, "use_associnfo=1")) { - wpa_printf(MSG_DEBUG, "test_driver: Use AssocInfo events"); - drv->use_associnfo = 1; - } - -#ifdef CONFIG_CLIENT_MLME - if (os_strstr(param, "use_mlme=1")) { - wpa_printf(MSG_DEBUG, "test_driver: Use internal MLME"); - drv->use_mlme = 1; - } -#endif /* CONFIG_CLIENT_MLME */ - - if (os_strstr(param, "p2p_mgmt=1")) { - wpa_printf(MSG_DEBUG, "test_driver: Use internal P2P " - "management"); - if (wpa_driver_test_init_p2p(drv) < 0) - return -1; - } - - return 0; -} - - -static const u8 * wpa_driver_test_get_mac_addr(void *priv) -{ - struct test_driver_bss *dbss = priv; - struct wpa_driver_test_data *drv = dbss->drv; - wpa_printf(MSG_DEBUG, "%s", __func__); - return drv->own_addr; -} - - -static int wpa_driver_test_send_eapol(void *priv, const u8 *dest, u16 proto, - const u8 *data, size_t data_len) -{ - struct test_driver_bss *dbss = priv; - struct wpa_driver_test_data *drv = dbss->drv; - char *msg; - size_t msg_len; - struct l2_ethhdr eth; - struct sockaddr *addr; - socklen_t alen; -#ifdef DRIVER_TEST_UNIX - struct sockaddr_un addr_un; -#endif /* DRIVER_TEST_UNIX */ - - wpa_hexdump(MSG_MSGDUMP, "test_send_eapol TX frame", data, data_len); - - os_memset(ð, 0, sizeof(eth)); - os_memcpy(eth.h_dest, dest, ETH_ALEN); - os_memcpy(eth.h_source, drv->own_addr, ETH_ALEN); - eth.h_proto = host_to_be16(proto); - - msg_len = 6 + sizeof(eth) + data_len; - msg = os_malloc(msg_len); - if (msg == NULL) - return -1; - os_memcpy(msg, "EAPOL ", 6); - os_memcpy(msg + 6, ð, sizeof(eth)); - os_memcpy(msg + 6 + sizeof(eth), data, data_len); - - if (os_memcmp(dest, dbss->bssid, ETH_ALEN) == 0 || - drv->test_dir == NULL) { - if (drv->hostapd_addr_udp_set) { - addr = (struct sockaddr *) &drv->hostapd_addr_udp; - alen = sizeof(drv->hostapd_addr_udp); - } else { -#ifdef DRIVER_TEST_UNIX - addr = (struct sockaddr *) &drv->hostapd_addr; - alen = sizeof(drv->hostapd_addr); -#else /* DRIVER_TEST_UNIX */ - os_free(msg); - return -1; -#endif /* DRIVER_TEST_UNIX */ - } - } else { -#ifdef DRIVER_TEST_UNIX - struct stat st; - os_memset(&addr_un, 0, sizeof(addr_un)); - addr_un.sun_family = AF_UNIX; - os_snprintf(addr_un.sun_path, sizeof(addr_un.sun_path), - "%s/STA-" MACSTR, drv->test_dir, MAC2STR(dest)); - if (stat(addr_un.sun_path, &st) < 0) { - os_snprintf(addr_un.sun_path, sizeof(addr_un.sun_path), - "%s/AP-" MACSTR, - drv->test_dir, MAC2STR(dest)); - } - addr = (struct sockaddr *) &addr_un; - alen = sizeof(addr_un); -#else /* DRIVER_TEST_UNIX */ - os_free(msg); - return -1; -#endif /* DRIVER_TEST_UNIX */ - } - - if (sendto(drv->test_socket, msg, msg_len, 0, addr, alen) < 0) { - perror("sendmsg(test_socket)"); - os_free(msg); - return -1; - } - - os_free(msg); - return 0; -} - - -static int wpa_driver_test_get_capa(void *priv, struct wpa_driver_capa *capa) -{ - struct test_driver_bss *dbss = priv; - struct wpa_driver_test_data *drv = dbss->drv; - os_memset(capa, 0, sizeof(*capa)); - capa->key_mgmt = WPA_DRIVER_CAPA_KEY_MGMT_WPA | - WPA_DRIVER_CAPA_KEY_MGMT_WPA2 | - WPA_DRIVER_CAPA_KEY_MGMT_WPA_PSK | - WPA_DRIVER_CAPA_KEY_MGMT_WPA2_PSK | - WPA_DRIVER_CAPA_KEY_MGMT_WPA_NONE | - WPA_DRIVER_CAPA_KEY_MGMT_FT | - WPA_DRIVER_CAPA_KEY_MGMT_FT_PSK; - capa->enc = WPA_DRIVER_CAPA_ENC_WEP40 | - WPA_DRIVER_CAPA_ENC_WEP104 | - WPA_DRIVER_CAPA_ENC_TKIP | - WPA_DRIVER_CAPA_ENC_CCMP; - capa->auth = WPA_DRIVER_AUTH_OPEN | - WPA_DRIVER_AUTH_SHARED | - WPA_DRIVER_AUTH_LEAP; - if (drv->use_mlme) - capa->flags |= WPA_DRIVER_FLAGS_USER_SPACE_MLME; - if (drv->p2p) - capa->flags |= WPA_DRIVER_FLAGS_P2P_MGMT; - capa->flags |= WPA_DRIVER_FLAGS_AP; - capa->flags |= WPA_DRIVER_FLAGS_P2P_CONCURRENT; - capa->flags |= WPA_DRIVER_FLAGS_P2P_DEDICATED_INTERFACE; - capa->flags |= WPA_DRIVER_FLAGS_P2P_CAPABLE; - capa->max_scan_ssids = 2; - capa->max_remain_on_chan = 60000; - - return 0; -} - - -static int wpa_driver_test_mlme_setprotection(void *priv, const u8 *addr, - int protect_type, - int key_type) -{ - wpa_printf(MSG_DEBUG, "%s: protect_type=%d key_type=%d", - __func__, protect_type, key_type); - - if (addr) { - wpa_printf(MSG_DEBUG, "%s: addr=" MACSTR, - __func__, MAC2STR(addr)); - } - - return 0; -} - - -static int wpa_driver_test_set_channel(void *priv, - enum hostapd_hw_mode phymode, - int chan, int freq) -{ - struct test_driver_bss *dbss = priv; - struct wpa_driver_test_data *drv = dbss->drv; - wpa_printf(MSG_DEBUG, "%s: phymode=%d chan=%d freq=%d", - __func__, phymode, chan, freq); - drv->current_freq = freq; - return 0; -} - - -static int wpa_driver_test_mlme_add_sta(void *priv, const u8 *addr, - const u8 *supp_rates, - size_t supp_rates_len) -{ - wpa_printf(MSG_DEBUG, "%s: addr=" MACSTR, __func__, MAC2STR(addr)); - return 0; -} - - -static int wpa_driver_test_mlme_remove_sta(void *priv, const u8 *addr) -{ - wpa_printf(MSG_DEBUG, "%s: addr=" MACSTR, __func__, MAC2STR(addr)); - return 0; -} - - -static int wpa_driver_test_set_ssid(void *priv, const u8 *ssid, - size_t ssid_len) -{ - wpa_printf(MSG_DEBUG, "%s", __func__); - return 0; -} - - -static int wpa_driver_test_set_bssid(void *priv, const u8 *bssid) -{ - wpa_printf(MSG_DEBUG, "%s: bssid=" MACSTR, __func__, MAC2STR(bssid)); - return 0; -} - - -static void * wpa_driver_test_global_init(void) -{ - struct wpa_driver_test_global *global; - - global = os_zalloc(sizeof(*global)); - return global; -} - - -static void wpa_driver_test_global_deinit(void *priv) -{ - struct wpa_driver_test_global *global = priv; - os_free(global); -} - - -static struct wpa_interface_info * -wpa_driver_test_get_interfaces(void *global_priv) -{ - /* struct wpa_driver_test_global *global = priv; */ - struct wpa_interface_info *iface; - - iface = os_zalloc(sizeof(*iface)); - if (iface == NULL) - return iface; - iface->ifname = os_strdup("sta0"); - iface->desc = os_strdup("test interface 0"); - iface->drv_name = "test"; - iface->next = os_zalloc(sizeof(*iface)); - if (iface->next) { - iface->next->ifname = os_strdup("sta1"); - iface->next->desc = os_strdup("test interface 1"); - iface->next->drv_name = "test"; - } - - return iface; -} - - -static struct hostapd_hw_modes * -wpa_driver_test_get_hw_feature_data(void *priv, u16 *num_modes, u16 *flags) -{ - struct hostapd_hw_modes *modes; - size_t i; - - *num_modes = 3; - *flags = 0; - modes = os_zalloc(*num_modes * sizeof(struct hostapd_hw_modes)); - if (modes == NULL) - return NULL; - modes[0].mode = HOSTAPD_MODE_IEEE80211G; - modes[0].num_channels = 11; - modes[0].num_rates = 12; - modes[0].channels = - os_zalloc(11 * sizeof(struct hostapd_channel_data)); - modes[0].rates = os_zalloc(modes[0].num_rates * sizeof(int)); - if (modes[0].channels == NULL || modes[0].rates == NULL) - goto fail; - for (i = 0; i < 11; i++) { - modes[0].channels[i].chan = i + 1; - modes[0].channels[i].freq = 2412 + 5 * i; - modes[0].channels[i].flag = 0; - } - modes[0].rates[0] = 10; - modes[0].rates[1] = 20; - modes[0].rates[2] = 55; - modes[0].rates[3] = 110; - modes[0].rates[4] = 60; - modes[0].rates[5] = 90; - modes[0].rates[6] = 120; - modes[0].rates[7] = 180; - modes[0].rates[8] = 240; - modes[0].rates[9] = 360; - modes[0].rates[10] = 480; - modes[0].rates[11] = 540; - - modes[1].mode = HOSTAPD_MODE_IEEE80211B; - modes[1].num_channels = 11; - modes[1].num_rates = 4; - modes[1].channels = - os_zalloc(11 * sizeof(struct hostapd_channel_data)); - modes[1].rates = os_zalloc(modes[1].num_rates * sizeof(int)); - if (modes[1].channels == NULL || modes[1].rates == NULL) - goto fail; - for (i = 0; i < 11; i++) { - modes[1].channels[i].chan = i + 1; - modes[1].channels[i].freq = 2412 + 5 * i; - modes[1].channels[i].flag = 0; - } - modes[1].rates[0] = 10; - modes[1].rates[1] = 20; - modes[1].rates[2] = 55; - modes[1].rates[3] = 110; - - modes[2].mode = HOSTAPD_MODE_IEEE80211A; - modes[2].num_channels = 1; - modes[2].num_rates = 8; - modes[2].channels = os_zalloc(sizeof(struct hostapd_channel_data)); - modes[2].rates = os_zalloc(modes[2].num_rates * sizeof(int)); - if (modes[2].channels == NULL || modes[2].rates == NULL) - goto fail; - modes[2].channels[0].chan = 60; - modes[2].channels[0].freq = 5300; - modes[2].channels[0].flag = 0; - modes[2].rates[0] = 60; - modes[2].rates[1] = 90; - modes[2].rates[2] = 120; - modes[2].rates[3] = 180; - modes[2].rates[4] = 240; - modes[2].rates[5] = 360; - modes[2].rates[6] = 480; - modes[2].rates[7] = 540; - - return modes; - -fail: - if (modes) { - for (i = 0; i < *num_modes; i++) { - os_free(modes[i].channels); - os_free(modes[i].rates); - } - os_free(modes); - } - return NULL; -} - - -static int wpa_driver_test_set_freq(void *priv, - struct hostapd_freq_params *freq) -{ - struct test_driver_bss *dbss = priv; - struct wpa_driver_test_data *drv = dbss->drv; - wpa_printf(MSG_DEBUG, "test: set_freq %u MHz", freq->freq); - drv->current_freq = freq->freq; - return 0; -} - - -static int wpa_driver_test_send_action(void *priv, unsigned int freq, - unsigned int wait, - const u8 *dst, const u8 *src, - const u8 *bssid, - const u8 *data, size_t data_len) -{ - struct test_driver_bss *dbss = priv; - struct wpa_driver_test_data *drv = dbss->drv; - int ret = -1; - u8 *buf; - struct ieee80211_hdr *hdr; - - wpa_printf(MSG_DEBUG, "test: Send Action frame"); - - if ((drv->remain_on_channel_freq && - freq != drv->remain_on_channel_freq) || - (drv->remain_on_channel_freq == 0 && - freq != (unsigned int) drv->current_freq)) { - wpa_printf(MSG_DEBUG, "test: Reject Action frame TX on " - "unexpected channel: freq=%u MHz (current_freq=%u " - "MHz, remain-on-channel freq=%u MHz)", - freq, drv->current_freq, - drv->remain_on_channel_freq); - return -1; - } - - buf = os_zalloc(24 + data_len); - if (buf == NULL) - return ret; - os_memcpy(buf + 24, data, data_len); - hdr = (struct ieee80211_hdr *) buf; - hdr->frame_control = - IEEE80211_FC(WLAN_FC_TYPE_MGMT, WLAN_FC_STYPE_ACTION); - os_memcpy(hdr->addr1, dst, ETH_ALEN); - os_memcpy(hdr->addr2, src, ETH_ALEN); - os_memcpy(hdr->addr3, bssid, ETH_ALEN); - - ret = wpa_driver_test_send_mlme(priv, buf, 24 + data_len); - os_free(buf); - return ret; -} - - -#ifdef CONFIG_P2P -static void test_send_action_cb(void *eloop_ctx, void *timeout_ctx) -{ - struct wpa_driver_test_data *drv = eloop_ctx; - int res; - - if (drv->pending_action_tx == NULL) - return; - - if (drv->off_channel_freq != drv->pending_action_freq) { - wpa_printf(MSG_DEBUG, "P2P: Pending Action frame TX " - "waiting for another freq=%u", - drv->pending_action_freq); - return; - } - wpa_printf(MSG_DEBUG, "P2P: Sending pending Action frame to " - MACSTR, MAC2STR(drv->pending_action_dst)); - res = wpa_driver_test_send_action(drv, drv->pending_action_freq, 0, - drv->pending_action_dst, - drv->pending_action_src, - drv->pending_action_bssid, - wpabuf_head(drv->pending_action_tx), - wpabuf_len(drv->pending_action_tx)); -} -#endif /* CONFIG_P2P */ - - -static void test_remain_on_channel_timeout(void *eloop_ctx, void *timeout_ctx) -{ - struct wpa_driver_test_data *drv = eloop_ctx; - union wpa_event_data data; - - wpa_printf(MSG_DEBUG, "test: Remain-on-channel timeout"); - - os_memset(&data, 0, sizeof(data)); - data.remain_on_channel.freq = drv->remain_on_channel_freq; - data.remain_on_channel.duration = drv->remain_on_channel_duration; - - if (drv->p2p) - drv->off_channel_freq = 0; - - drv->remain_on_channel_freq = 0; - - wpa_supplicant_event(drv->ctx, EVENT_CANCEL_REMAIN_ON_CHANNEL, &data); -} - - -static int wpa_driver_test_remain_on_channel(void *priv, unsigned int freq, - unsigned int duration) -{ - struct test_driver_bss *dbss = priv; - struct wpa_driver_test_data *drv = dbss->drv; - union wpa_event_data data; - - wpa_printf(MSG_DEBUG, "%s(freq=%u, duration=%u)", - __func__, freq, duration); - if (drv->remain_on_channel_freq && - drv->remain_on_channel_freq != freq) { - wpa_printf(MSG_DEBUG, "test: Refuse concurrent " - "remain_on_channel request"); - return -1; - } - - drv->remain_on_channel_freq = freq; - drv->remain_on_channel_duration = duration; - eloop_cancel_timeout(test_remain_on_channel_timeout, drv, NULL); - eloop_register_timeout(duration / 1000, (duration % 1000) * 1000, - test_remain_on_channel_timeout, drv, NULL); - - os_memset(&data, 0, sizeof(data)); - data.remain_on_channel.freq = freq; - data.remain_on_channel.duration = duration; - wpa_supplicant_event(drv->ctx, EVENT_REMAIN_ON_CHANNEL, &data); - -#ifdef CONFIG_P2P - if (drv->p2p) { - drv->off_channel_freq = drv->remain_on_channel_freq; - test_send_action_cb(drv, NULL); - if (drv->off_channel_freq == drv->pending_listen_freq) { - p2p_listen_cb(drv->p2p, drv->pending_listen_freq, - drv->pending_listen_duration); - drv->pending_listen_freq = 0; - } - } -#endif /* CONFIG_P2P */ - - return 0; -} - - -static int wpa_driver_test_cancel_remain_on_channel(void *priv) -{ - struct test_driver_bss *dbss = priv; - struct wpa_driver_test_data *drv = dbss->drv; - wpa_printf(MSG_DEBUG, "%s", __func__); - if (!drv->remain_on_channel_freq) - return -1; - drv->remain_on_channel_freq = 0; - eloop_cancel_timeout(test_remain_on_channel_timeout, drv, NULL); - return 0; -} - - -static int wpa_driver_test_probe_req_report(void *priv, int report) -{ - struct test_driver_bss *dbss = priv; - struct wpa_driver_test_data *drv = dbss->drv; - wpa_printf(MSG_DEBUG, "%s(report=%d)", __func__, report); - drv->probe_req_report = report; - return 0; -} - - -#ifdef CONFIG_P2P - -static int wpa_driver_test_p2p_find(void *priv, unsigned int timeout, int type) -{ - struct wpa_driver_test_data *drv = priv; - wpa_printf(MSG_DEBUG, "%s(timeout=%u)", __func__, timeout); - if (!drv->p2p) - return -1; - return p2p_find(drv->p2p, timeout, type, 0, NULL); -} - - -static int wpa_driver_test_p2p_stop_find(void *priv) -{ - struct wpa_driver_test_data *drv = priv; - wpa_printf(MSG_DEBUG, "%s", __func__); - if (!drv->p2p) - return -1; - p2p_stop_find(drv->p2p); - return 0; -} - - -static int wpa_driver_test_p2p_listen(void *priv, unsigned int timeout) -{ - struct wpa_driver_test_data *drv = priv; - wpa_printf(MSG_DEBUG, "%s(timeout=%u)", __func__, timeout); - if (!drv->p2p) - return -1; - return p2p_listen(drv->p2p, timeout); -} - - -static int wpa_driver_test_p2p_connect(void *priv, const u8 *peer_addr, - int wps_method, int go_intent, - const u8 *own_interface_addr, - unsigned int force_freq, - int persistent_group) -{ - struct wpa_driver_test_data *drv = priv; - wpa_printf(MSG_DEBUG, "%s(peer_addr=" MACSTR " wps_method=%d " - "go_intent=%d " - "own_interface_addr=" MACSTR " force_freq=%u " - "persistent_group=%d)", - __func__, MAC2STR(peer_addr), wps_method, go_intent, - MAC2STR(own_interface_addr), force_freq, persistent_group); - if (!drv->p2p) - return -1; - return p2p_connect(drv->p2p, peer_addr, wps_method, go_intent, - own_interface_addr, force_freq, persistent_group); -} - - -static int wpa_driver_test_wps_success_cb(void *priv, const u8 *peer_addr) -{ - struct wpa_driver_test_data *drv = priv; - wpa_printf(MSG_DEBUG, "%s(peer_addr=" MACSTR ")", - __func__, MAC2STR(peer_addr)); - if (!drv->p2p) - return -1; - p2p_wps_success_cb(drv->p2p, peer_addr); - return 0; -} - - -static int wpa_driver_test_p2p_group_formation_failed(void *priv) -{ - struct wpa_driver_test_data *drv = priv; - wpa_printf(MSG_DEBUG, "%s", __func__); - if (!drv->p2p) - return -1; - p2p_group_formation_failed(drv->p2p); - return 0; -} - - -static int wpa_driver_test_p2p_set_params(void *priv, - const struct p2p_params *params) -{ - struct wpa_driver_test_data *drv = priv; - wpa_printf(MSG_DEBUG, "%s", __func__); - if (!drv->p2p) - return -1; - if (p2p_set_dev_name(drv->p2p, params->dev_name) < 0 || - p2p_set_pri_dev_type(drv->p2p, params->pri_dev_type) < 0 || - p2p_set_sec_dev_types(drv->p2p, params->sec_dev_type, - params->num_sec_dev_types) < 0) - return -1; - return 0; -} - - -static int test_p2p_scan(void *ctx, enum p2p_scan_type type, int freq, - unsigned int num_req_dev_types, - const u8 *req_dev_types) -{ - struct wpa_driver_test_data *drv = ctx; - struct wpa_driver_scan_params params; - int ret; - struct wpabuf *wps_ie, *ies; - int social_channels[] = { 2412, 2437, 2462, 0, 0 }; - - wpa_printf(MSG_DEBUG, "%s(type=%d freq=%d)", - __func__, type, freq); - - os_memset(¶ms, 0, sizeof(params)); - - /* P2P Wildcard SSID */ - params.num_ssids = 1; - params.ssids[0].ssid = (u8 *) P2P_WILDCARD_SSID; - params.ssids[0].ssid_len = P2P_WILDCARD_SSID_LEN; - -#if 0 /* TODO: WPS IE */ - wpa_s->wps->dev.p2p = 1; - wps_ie = wps_build_probe_req_ie(0, &wpa_s->wps->dev, wpa_s->wps->uuid, - WPS_REQ_ENROLLEE); -#else - wps_ie = wpabuf_alloc(1); -#endif - if (wps_ie == NULL) - return -1; - - ies = wpabuf_alloc(wpabuf_len(wps_ie) + 100); - if (ies == NULL) { - wpabuf_free(wps_ie); - return -1; - } - wpabuf_put_buf(ies, wps_ie); - wpabuf_free(wps_ie); - - p2p_scan_ie(drv->p2p, ies); - - params.extra_ies = wpabuf_head(ies); - params.extra_ies_len = wpabuf_len(ies); - - switch (type) { - case P2P_SCAN_SOCIAL: - params.freqs = social_channels; - break; - case P2P_SCAN_FULL: - break; - case P2P_SCAN_SPECIFIC: - social_channels[0] = freq; - social_channels[1] = 0; - params.freqs = social_channels; - break; - case P2P_SCAN_SOCIAL_PLUS_ONE: - social_channels[3] = freq; - params.freqs = social_channels; - break; - } - - drv->pending_p2p_scan = 1; - ret = wpa_driver_test_scan(drv, ¶ms); - - wpabuf_free(ies); - - return ret; -} - - -static int test_send_action(void *ctx, unsigned int freq, const u8 *dst, - const u8 *src, const u8 *bssid, const u8 *buf, - size_t len, unsigned int wait_time) -{ - struct wpa_driver_test_data *drv = ctx; - - wpa_printf(MSG_DEBUG, "%s(freq=%u dst=" MACSTR " src=" MACSTR - " bssid=" MACSTR " len=%d", - __func__, freq, MAC2STR(dst), MAC2STR(src), MAC2STR(bssid), - (int) len); - if (freq <= 0) { - wpa_printf(MSG_WARNING, "P2P: No frequency specified for " - "action frame TX"); - return -1; - } - - if (drv->pending_action_tx) { - wpa_printf(MSG_DEBUG, "P2P: Dropped pending Action frame TX " - "to " MACSTR, MAC2STR(drv->pending_action_dst)); - wpabuf_free(drv->pending_action_tx); - } - drv->pending_action_tx = wpabuf_alloc(len); - if (drv->pending_action_tx == NULL) - return -1; - wpabuf_put_data(drv->pending_action_tx, buf, len); - os_memcpy(drv->pending_action_src, src, ETH_ALEN); - os_memcpy(drv->pending_action_dst, dst, ETH_ALEN); - os_memcpy(drv->pending_action_bssid, bssid, ETH_ALEN); - drv->pending_action_freq = freq; - - if (drv->off_channel_freq == freq) { - /* Already on requested channel; send immediately */ - /* TODO: Would there ever be need to extend the current - * duration on the channel? */ - eloop_cancel_timeout(test_send_action_cb, drv, NULL); - eloop_register_timeout(0, 0, test_send_action_cb, drv, NULL); - return 0; - } - - wpa_printf(MSG_DEBUG, "P2P: Schedule Action frame to be transmitted " - "once the driver gets to the requested channel"); - if (wpa_driver_test_remain_on_channel(drv, freq, wait_time) < 0) { - wpa_printf(MSG_DEBUG, "P2P: Failed to request driver " - "to remain on channel (%u MHz) for Action " - "Frame TX", freq); - return -1; - } - - return 0; -} - - -static void test_send_action_done(void *ctx) -{ - wpa_printf(MSG_DEBUG, "%s", __func__); - /* TODO */ -} - - -static void test_go_neg_completed(void *ctx, struct p2p_go_neg_results *res) -{ - struct wpa_driver_test_data *drv = ctx; - union wpa_event_data event; - wpa_printf(MSG_DEBUG, "%s", __func__); - os_memset(&event, 0, sizeof(event)); - event.p2p_go_neg_completed.res = res; - wpa_supplicant_event(drv->ctx, EVENT_P2P_GO_NEG_COMPLETED, &event); -} - - -static void test_go_neg_req_rx(void *ctx, const u8 *src, u16 dev_passwd_id) -{ - struct wpa_driver_test_data *drv = ctx; - union wpa_event_data event; - wpa_printf(MSG_DEBUG, "%s(src=" MACSTR ")", __func__, MAC2STR(src)); - os_memset(&event, 0, sizeof(event)); - event.p2p_go_neg_req_rx.src = src; - event.p2p_go_neg_req_rx.dev_passwd_id = dev_passwd_id; - wpa_supplicant_event(drv->ctx, EVENT_P2P_GO_NEG_REQ_RX, &event); -} - - -static void test_dev_found(void *ctx, const u8 *addr, - const struct p2p_peer_info *info, int new_device) -{ - struct wpa_driver_test_data *drv = ctx; - union wpa_event_data event; - char devtype[WPS_DEV_TYPE_BUFSIZE]; - wpa_printf(MSG_DEBUG, "%s(" MACSTR " p2p_dev_addr=" MACSTR - " pri_dev_type=%s name='%s' config_methods=0x%x " - "dev_capab=0x%x group_capab=0x%x)", - __func__, MAC2STR(addr), MAC2STR(info->p2p_device_addr), - wps_dev_type_bin2str(info->pri_dev_type, devtype, - sizeof(devtype)), - info->device_name, info->config_methods, info->dev_capab, - info->group_capab); - - os_memset(&event, 0, sizeof(event)); - event.p2p_dev_found.addr = addr; - event.p2p_dev_found.dev_addr = info->p2p_device_addr; - event.p2p_dev_found.pri_dev_type = info->pri_dev_type; - event.p2p_dev_found.dev_name = info->device_name; - event.p2p_dev_found.config_methods = info->config_methods; - event.p2p_dev_found.dev_capab = info->dev_capab; - event.p2p_dev_found.group_capab = info->group_capab; - wpa_supplicant_event(drv->ctx, EVENT_P2P_DEV_FOUND, &event); -} - - -static int test_start_listen(void *ctx, unsigned int freq, - unsigned int duration, - const struct wpabuf *probe_resp_ie) -{ - struct wpa_driver_test_data *drv = ctx; - - wpa_printf(MSG_DEBUG, "%s(freq=%u duration=%u)", - __func__, freq, duration); - - if (wpa_driver_test_probe_req_report(drv, 1) < 0) - return -1; - - drv->pending_listen_freq = freq; - drv->pending_listen_duration = duration; - - if (wpa_driver_test_remain_on_channel(drv, freq, duration) < 0) { - drv->pending_listen_freq = 0; - return -1; - } - - return 0; -} - - -static void test_stop_listen(void *ctx) -{ - wpa_printf(MSG_DEBUG, "%s", __func__); - /* TODO */ -} - - -static int test_send_probe_resp(void *ctx, const struct wpabuf *buf) -{ - struct wpa_driver_test_data *drv = ctx; - char resp[512], *pos, *end; - int ret; - const struct ieee80211_mgmt *mgmt; - const u8 *ie, *ie_end; - - wpa_printf(MSG_DEBUG, "%s", __func__); - wpa_hexdump_buf(MSG_MSGDUMP, "Probe Response", buf); - if (wpabuf_len(buf) < 24) - return -1; - if (!drv->probe_from) { - wpa_printf(MSG_DEBUG, "%s: probe_from not set", __func__); - return -1; - } - - pos = resp; - end = resp + sizeof(resp); - - mgmt = wpabuf_head(buf); - - /* reply: SCANRESP BSSID SSID IEs */ - ret = os_snprintf(pos, end - pos, "SCANRESP " MACSTR " ", - MAC2STR(mgmt->bssid)); - if (ret < 0 || ret >= end - pos) - return -1; - pos += ret; - - ie = mgmt->u.probe_resp.variable; - ie_end = wpabuf_head_u8(buf) + wpabuf_len(buf); - if (ie_end - ie < 2 || ie[0] != WLAN_EID_SSID || - ie + 2 + ie[1] > ie_end) - return -1; - pos += wpa_snprintf_hex(pos, end - pos, ie + 2, ie[1]); - - ret = os_snprintf(pos, end - pos, " "); - if (ret < 0 || ret >= end - pos) - return -1; - pos += ret; - pos += wpa_snprintf_hex(pos, end - pos, ie, ie_end - ie); - - sendto(drv->test_socket, resp, pos - resp, 0, - drv->probe_from, drv->probe_from_len); - - return 0; -} - - -static void test_sd_request(void *ctx, int freq, const u8 *sa, u8 dialog_token, - u16 update_indic, const u8 *tlvs, size_t tlvs_len) -{ - wpa_printf(MSG_DEBUG, "%s", __func__); - /* TODO */ -} - - -static void test_sd_response(void *ctx, const u8 *sa, u16 update_indic, - const u8 *tlvs, size_t tlvs_len) -{ - wpa_printf(MSG_DEBUG, "%s", __func__); - /* TODO */ -} - - -static void test_prov_disc_req(void *ctx, const u8 *peer, u16 config_methods, - const u8 *dev_addr, const u8 *pri_dev_type, - const char *dev_name, u16 supp_config_methods, - u8 dev_capab, u8 group_capab) -{ - wpa_printf(MSG_DEBUG, "%s(peer=" MACSTR " config_methods=0x%x)", - __func__, MAC2STR(peer), config_methods); - /* TODO */ -} - - -static void test_prov_disc_resp(void *ctx, const u8 *peer, u16 config_methods) -{ - wpa_printf(MSG_DEBUG, "%s(peer=" MACSTR " config_methods=0x%x)", - __func__, MAC2STR(peer), config_methods); - /* TODO */ -} - -#endif /* CONFIG_P2P */ - - -static int wpa_driver_test_init_p2p(struct wpa_driver_test_data *drv) -{ -#ifdef CONFIG_P2P - struct p2p_config p2p; - unsigned int r; - int i; - - os_memset(&p2p, 0, sizeof(p2p)); - p2p.msg_ctx = drv->ctx; - p2p.cb_ctx = drv; - p2p.p2p_scan = test_p2p_scan; - p2p.send_action = test_send_action; - p2p.send_action_done = test_send_action_done; - p2p.go_neg_completed = test_go_neg_completed; - p2p.go_neg_req_rx = test_go_neg_req_rx; - p2p.dev_found = test_dev_found; - p2p.start_listen = test_start_listen; - p2p.stop_listen = test_stop_listen; - p2p.send_probe_resp = test_send_probe_resp; - p2p.sd_request = test_sd_request; - p2p.sd_response = test_sd_response; - p2p.prov_disc_req = test_prov_disc_req; - p2p.prov_disc_resp = test_prov_disc_resp; - - os_memcpy(p2p.dev_addr, drv->own_addr, ETH_ALEN); - - p2p.reg_class = 12; /* TODO: change depending on location */ - /* - * Pick one of the social channels randomly as the listen - * channel. - */ - os_get_random((u8 *) &r, sizeof(r)); - p2p.channel = 1 + (r % 3) * 5; - - /* TODO: change depending on location */ - p2p.op_reg_class = 12; - /* - * For initial tests, pick the operation channel randomly. - * TODO: Use scan results (etc.) to select the best channel. - */ - p2p.op_channel = 1 + r % 11; - - os_memcpy(p2p.country, "US ", 3); - - /* FIX: fetch available channels from the driver */ - p2p.channels.reg_classes = 1; - p2p.channels.reg_class[0].reg_class = 12; /* US/12 = 2.4 GHz band */ - p2p.channels.reg_class[0].channels = 11; - for (i = 0; i < 11; i++) - p2p.channels.reg_class[0].channel[i] = i + 1; - - p2p.max_peers = 100; - - drv->p2p = p2p_init(&p2p); - if (drv->p2p == NULL) - return -1; - return 0; -#else /* CONFIG_P2P */ - wpa_printf(MSG_INFO, "driver_test: P2P support not included"); - return -1; -#endif /* CONFIG_P2P */ -} - - -const struct wpa_driver_ops wpa_driver_test_ops = { - "test", - "wpa_supplicant test driver", - .hapd_init = test_driver_init, - .hapd_deinit = wpa_driver_test_deinit, - .hapd_send_eapol = test_driver_send_eapol, - .send_mlme = wpa_driver_test_send_mlme, - .set_generic_elem = test_driver_set_generic_elem, - .sta_deauth = test_driver_sta_deauth, - .sta_disassoc = test_driver_sta_disassoc, - .get_hw_feature_data = wpa_driver_test_get_hw_feature_data, - .if_add = test_driver_if_add, - .if_remove = test_driver_if_remove, - .valid_bss_mask = test_driver_valid_bss_mask, - .hapd_set_ssid = test_driver_set_ssid, - .set_privacy = test_driver_set_privacy, - .set_sta_vlan = test_driver_set_sta_vlan, - .sta_add = test_driver_sta_add, - .send_ether = test_driver_send_ether, - .set_ap_wps_ie = test_driver_set_ap_wps_ie, - .get_bssid = wpa_driver_test_get_bssid, - .get_ssid = wpa_driver_test_get_ssid, - .set_key = wpa_driver_test_set_key, - .deinit = wpa_driver_test_deinit, - .set_param = wpa_driver_test_set_param, - .deauthenticate = wpa_driver_test_deauthenticate, - .disassociate = wpa_driver_test_disassociate, - .associate = wpa_driver_test_associate, - .get_capa = wpa_driver_test_get_capa, - .get_mac_addr = wpa_driver_test_get_mac_addr, - .send_eapol = wpa_driver_test_send_eapol, - .mlme_setprotection = wpa_driver_test_mlme_setprotection, - .set_channel = wpa_driver_test_set_channel, - .set_ssid = wpa_driver_test_set_ssid, - .set_bssid = wpa_driver_test_set_bssid, - .mlme_add_sta = wpa_driver_test_mlme_add_sta, - .mlme_remove_sta = wpa_driver_test_mlme_remove_sta, - .get_scan_results2 = wpa_driver_test_get_scan_results2, - .global_init = wpa_driver_test_global_init, - .global_deinit = wpa_driver_test_global_deinit, - .init2 = wpa_driver_test_init2, - .get_interfaces = wpa_driver_test_get_interfaces, - .scan2 = wpa_driver_test_scan, - .set_freq = wpa_driver_test_set_freq, - .send_action = wpa_driver_test_send_action, - .remain_on_channel = wpa_driver_test_remain_on_channel, - .cancel_remain_on_channel = wpa_driver_test_cancel_remain_on_channel, - .probe_req_report = wpa_driver_test_probe_req_report, -#ifdef CONFIG_P2P - .p2p_find = wpa_driver_test_p2p_find, - .p2p_stop_find = wpa_driver_test_p2p_stop_find, - .p2p_listen = wpa_driver_test_p2p_listen, - .p2p_connect = wpa_driver_test_p2p_connect, - .wps_success_cb = wpa_driver_test_wps_success_cb, - .p2p_group_formation_failed = - wpa_driver_test_p2p_group_formation_failed, - .p2p_set_params = wpa_driver_test_p2p_set_params, -#endif /* CONFIG_P2P */ -}; diff --git a/hostapd-0.8/src/drivers/driver_wext.c b/hostapd-0.8/src/drivers/driver_wext.c deleted file mode 100644 index d9f12bc..0000000 --- a/hostapd-0.8/src/drivers/driver_wext.c +++ /dev/null @@ -1,2356 +0,0 @@ -/* - * Driver interaction with generic Linux Wireless Extensions - * Copyright (c) 2003-2010, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - * - * This file implements a driver interface for the Linux Wireless Extensions. - * When used with WE-18 or newer, this interface can be used as-is with number - * of drivers. In addition to this, some of the common functions in this file - * can be used by other driver interface implementations that use generic WE - * ioctls, but require private ioctls for some of the functionality. - */ - -#include "includes.h" -#include -#include -#include -#include -#include - -#include "wireless_copy.h" -#include "common.h" -#include "eloop.h" -#include "common/ieee802_11_defs.h" -#include "common/wpa_common.h" -#include "priv_netlink.h" -#include "netlink.h" -#include "linux_ioctl.h" -#include "rfkill.h" -#include "driver.h" -#include "driver_wext.h" - - -static int wpa_driver_wext_flush_pmkid(void *priv); -static int wpa_driver_wext_get_range(void *priv); -static int wpa_driver_wext_finish_drv_init(struct wpa_driver_wext_data *drv); -static void wpa_driver_wext_disconnect(struct wpa_driver_wext_data *drv); -static int wpa_driver_wext_set_auth_alg(void *priv, int auth_alg); - - -int wpa_driver_wext_set_auth_param(struct wpa_driver_wext_data *drv, - int idx, u32 value) -{ - struct iwreq iwr; - int ret = 0; - - os_memset(&iwr, 0, sizeof(iwr)); - os_strlcpy(iwr.ifr_name, drv->ifname, IFNAMSIZ); - iwr.u.param.flags = idx & IW_AUTH_INDEX; - iwr.u.param.value = value; - - if (ioctl(drv->ioctl_sock, SIOCSIWAUTH, &iwr) < 0) { - if (errno != EOPNOTSUPP) { - wpa_printf(MSG_DEBUG, "WEXT: SIOCSIWAUTH(param %d " - "value 0x%x) failed: %s)", - idx, value, strerror(errno)); - } - ret = errno == EOPNOTSUPP ? -2 : -1; - } - - return ret; -} - - -/** - * wpa_driver_wext_get_bssid - Get BSSID, SIOCGIWAP - * @priv: Pointer to private wext data from wpa_driver_wext_init() - * @bssid: Buffer for BSSID - * Returns: 0 on success, -1 on failure - */ -int wpa_driver_wext_get_bssid(void *priv, u8 *bssid) -{ - struct wpa_driver_wext_data *drv = priv; - struct iwreq iwr; - int ret = 0; - - os_memset(&iwr, 0, sizeof(iwr)); - os_strlcpy(iwr.ifr_name, drv->ifname, IFNAMSIZ); - - if (ioctl(drv->ioctl_sock, SIOCGIWAP, &iwr) < 0) { - perror("ioctl[SIOCGIWAP]"); - ret = -1; - } - os_memcpy(bssid, iwr.u.ap_addr.sa_data, ETH_ALEN); - - return ret; -} - - -/** - * wpa_driver_wext_set_bssid - Set BSSID, SIOCSIWAP - * @priv: Pointer to private wext data from wpa_driver_wext_init() - * @bssid: BSSID - * Returns: 0 on success, -1 on failure - */ -int wpa_driver_wext_set_bssid(void *priv, const u8 *bssid) -{ - struct wpa_driver_wext_data *drv = priv; - struct iwreq iwr; - int ret = 0; - - os_memset(&iwr, 0, sizeof(iwr)); - os_strlcpy(iwr.ifr_name, drv->ifname, IFNAMSIZ); - iwr.u.ap_addr.sa_family = ARPHRD_ETHER; - if (bssid) - os_memcpy(iwr.u.ap_addr.sa_data, bssid, ETH_ALEN); - else - os_memset(iwr.u.ap_addr.sa_data, 0, ETH_ALEN); - - if (ioctl(drv->ioctl_sock, SIOCSIWAP, &iwr) < 0) { - perror("ioctl[SIOCSIWAP]"); - ret = -1; - } - - return ret; -} - - -/** - * wpa_driver_wext_get_ssid - Get SSID, SIOCGIWESSID - * @priv: Pointer to private wext data from wpa_driver_wext_init() - * @ssid: Buffer for the SSID; must be at least 32 bytes long - * Returns: SSID length on success, -1 on failure - */ -int wpa_driver_wext_get_ssid(void *priv, u8 *ssid) -{ - struct wpa_driver_wext_data *drv = priv; - struct iwreq iwr; - int ret = 0; - - os_memset(&iwr, 0, sizeof(iwr)); - os_strlcpy(iwr.ifr_name, drv->ifname, IFNAMSIZ); - iwr.u.essid.pointer = (caddr_t) ssid; - iwr.u.essid.length = 32; - - if (ioctl(drv->ioctl_sock, SIOCGIWESSID, &iwr) < 0) { - perror("ioctl[SIOCGIWESSID]"); - ret = -1; - } else { - ret = iwr.u.essid.length; - if (ret > 32) - ret = 32; - /* Some drivers include nul termination in the SSID, so let's - * remove it here before further processing. WE-21 changes this - * to explicitly require the length _not_ to include nul - * termination. */ - if (ret > 0 && ssid[ret - 1] == '\0' && - drv->we_version_compiled < 21) - ret--; - } - - return ret; -} - - -/** - * wpa_driver_wext_set_ssid - Set SSID, SIOCSIWESSID - * @priv: Pointer to private wext data from wpa_driver_wext_init() - * @ssid: SSID - * @ssid_len: Length of SSID (0..32) - * Returns: 0 on success, -1 on failure - */ -int wpa_driver_wext_set_ssid(void *priv, const u8 *ssid, size_t ssid_len) -{ - struct wpa_driver_wext_data *drv = priv; - struct iwreq iwr; - int ret = 0; - char buf[33]; - - if (ssid_len > 32) - return -1; - - os_memset(&iwr, 0, sizeof(iwr)); - os_strlcpy(iwr.ifr_name, drv->ifname, IFNAMSIZ); - /* flags: 1 = ESSID is active, 0 = not (promiscuous) */ - iwr.u.essid.flags = (ssid_len != 0); - os_memset(buf, 0, sizeof(buf)); - os_memcpy(buf, ssid, ssid_len); - iwr.u.essid.pointer = (caddr_t) buf; - if (drv->we_version_compiled < 21) { - /* For historic reasons, set SSID length to include one extra - * character, C string nul termination, even though SSID is - * really an octet string that should not be presented as a C - * string. Some Linux drivers decrement the length by one and - * can thus end up missing the last octet of the SSID if the - * length is not incremented here. WE-21 changes this to - * explicitly require the length _not_ to include nul - * termination. */ - if (ssid_len) - ssid_len++; - } - iwr.u.essid.length = ssid_len; - - if (ioctl(drv->ioctl_sock, SIOCSIWESSID, &iwr) < 0) { - perror("ioctl[SIOCSIWESSID]"); - ret = -1; - } - - return ret; -} - - -/** - * wpa_driver_wext_set_freq - Set frequency/channel, SIOCSIWFREQ - * @priv: Pointer to private wext data from wpa_driver_wext_init() - * @freq: Frequency in MHz - * Returns: 0 on success, -1 on failure - */ -int wpa_driver_wext_set_freq(void *priv, int freq) -{ - struct wpa_driver_wext_data *drv = priv; - struct iwreq iwr; - int ret = 0; - - os_memset(&iwr, 0, sizeof(iwr)); - os_strlcpy(iwr.ifr_name, drv->ifname, IFNAMSIZ); - iwr.u.freq.m = freq * 100000; - iwr.u.freq.e = 1; - - if (ioctl(drv->ioctl_sock, SIOCSIWFREQ, &iwr) < 0) { - perror("ioctl[SIOCSIWFREQ]"); - ret = -1; - } - - return ret; -} - - -static void -wpa_driver_wext_event_wireless_custom(void *ctx, char *custom) -{ - union wpa_event_data data; - - wpa_printf(MSG_MSGDUMP, "WEXT: Custom wireless event: '%s'", - custom); - - os_memset(&data, 0, sizeof(data)); - /* Host AP driver */ - if (os_strncmp(custom, "MLME-MICHAELMICFAILURE.indication", 33) == 0) { - data.michael_mic_failure.unicast = - os_strstr(custom, " unicast ") != NULL; - /* TODO: parse parameters(?) */ - wpa_supplicant_event(ctx, EVENT_MICHAEL_MIC_FAILURE, &data); - } else if (os_strncmp(custom, "ASSOCINFO(ReqIEs=", 17) == 0) { - char *spos; - int bytes; - u8 *req_ies = NULL, *resp_ies = NULL; - - spos = custom + 17; - - bytes = strspn(spos, "0123456789abcdefABCDEF"); - if (!bytes || (bytes & 1)) - return; - bytes /= 2; - - req_ies = os_malloc(bytes); - if (req_ies == NULL || - hexstr2bin(spos, req_ies, bytes) < 0) - goto done; - data.assoc_info.req_ies = req_ies; - data.assoc_info.req_ies_len = bytes; - - spos += bytes * 2; - - data.assoc_info.resp_ies = NULL; - data.assoc_info.resp_ies_len = 0; - - if (os_strncmp(spos, " RespIEs=", 9) == 0) { - spos += 9; - - bytes = strspn(spos, "0123456789abcdefABCDEF"); - if (!bytes || (bytes & 1)) - goto done; - bytes /= 2; - - resp_ies = os_malloc(bytes); - if (resp_ies == NULL || - hexstr2bin(spos, resp_ies, bytes) < 0) - goto done; - data.assoc_info.resp_ies = resp_ies; - data.assoc_info.resp_ies_len = bytes; - } - - wpa_supplicant_event(ctx, EVENT_ASSOCINFO, &data); - - done: - os_free(resp_ies); - os_free(req_ies); -#ifdef CONFIG_PEERKEY - } else if (os_strncmp(custom, "STKSTART.request=", 17) == 0) { - if (hwaddr_aton(custom + 17, data.stkstart.peer)) { - wpa_printf(MSG_DEBUG, "WEXT: unrecognized " - "STKSTART.request '%s'", custom + 17); - return; - } - wpa_supplicant_event(ctx, EVENT_STKSTART, &data); -#endif /* CONFIG_PEERKEY */ - } -} - - -static int wpa_driver_wext_event_wireless_michaelmicfailure( - void *ctx, const char *ev, size_t len) -{ - const struct iw_michaelmicfailure *mic; - union wpa_event_data data; - - if (len < sizeof(*mic)) - return -1; - - mic = (const struct iw_michaelmicfailure *) ev; - - wpa_printf(MSG_DEBUG, "Michael MIC failure wireless event: " - "flags=0x%x src_addr=" MACSTR, mic->flags, - MAC2STR(mic->src_addr.sa_data)); - - os_memset(&data, 0, sizeof(data)); - data.michael_mic_failure.unicast = !(mic->flags & IW_MICFAILURE_GROUP); - wpa_supplicant_event(ctx, EVENT_MICHAEL_MIC_FAILURE, &data); - - return 0; -} - - -static int wpa_driver_wext_event_wireless_pmkidcand( - struct wpa_driver_wext_data *drv, const char *ev, size_t len) -{ - const struct iw_pmkid_cand *cand; - union wpa_event_data data; - const u8 *addr; - - if (len < sizeof(*cand)) - return -1; - - cand = (const struct iw_pmkid_cand *) ev; - addr = (const u8 *) cand->bssid.sa_data; - - wpa_printf(MSG_DEBUG, "PMKID candidate wireless event: " - "flags=0x%x index=%d bssid=" MACSTR, cand->flags, - cand->index, MAC2STR(addr)); - - os_memset(&data, 0, sizeof(data)); - os_memcpy(data.pmkid_candidate.bssid, addr, ETH_ALEN); - data.pmkid_candidate.index = cand->index; - data.pmkid_candidate.preauth = cand->flags & IW_PMKID_CAND_PREAUTH; - wpa_supplicant_event(drv->ctx, EVENT_PMKID_CANDIDATE, &data); - - return 0; -} - - -static int wpa_driver_wext_event_wireless_assocreqie( - struct wpa_driver_wext_data *drv, const char *ev, int len) -{ - if (len < 0) - return -1; - - wpa_hexdump(MSG_DEBUG, "AssocReq IE wireless event", (const u8 *) ev, - len); - os_free(drv->assoc_req_ies); - drv->assoc_req_ies = os_malloc(len); - if (drv->assoc_req_ies == NULL) { - drv->assoc_req_ies_len = 0; - return -1; - } - os_memcpy(drv->assoc_req_ies, ev, len); - drv->assoc_req_ies_len = len; - - return 0; -} - - -static int wpa_driver_wext_event_wireless_assocrespie( - struct wpa_driver_wext_data *drv, const char *ev, int len) -{ - if (len < 0) - return -1; - - wpa_hexdump(MSG_DEBUG, "AssocResp IE wireless event", (const u8 *) ev, - len); - os_free(drv->assoc_resp_ies); - drv->assoc_resp_ies = os_malloc(len); - if (drv->assoc_resp_ies == NULL) { - drv->assoc_resp_ies_len = 0; - return -1; - } - os_memcpy(drv->assoc_resp_ies, ev, len); - drv->assoc_resp_ies_len = len; - - return 0; -} - - -static void wpa_driver_wext_event_assoc_ies(struct wpa_driver_wext_data *drv) -{ - union wpa_event_data data; - - if (drv->assoc_req_ies == NULL && drv->assoc_resp_ies == NULL) - return; - - os_memset(&data, 0, sizeof(data)); - if (drv->assoc_req_ies) { - data.assoc_info.req_ies = drv->assoc_req_ies; - data.assoc_info.req_ies_len = drv->assoc_req_ies_len; - } - if (drv->assoc_resp_ies) { - data.assoc_info.resp_ies = drv->assoc_resp_ies; - data.assoc_info.resp_ies_len = drv->assoc_resp_ies_len; - } - - wpa_supplicant_event(drv->ctx, EVENT_ASSOCINFO, &data); - - os_free(drv->assoc_req_ies); - drv->assoc_req_ies = NULL; - os_free(drv->assoc_resp_ies); - drv->assoc_resp_ies = NULL; -} - - -static void wpa_driver_wext_event_wireless(struct wpa_driver_wext_data *drv, - char *data, int len) -{ - struct iw_event iwe_buf, *iwe = &iwe_buf; - char *pos, *end, *custom, *buf; - - pos = data; - end = data + len; - - while (pos + IW_EV_LCP_LEN <= end) { - /* Event data may be unaligned, so make a local, aligned copy - * before processing. */ - os_memcpy(&iwe_buf, pos, IW_EV_LCP_LEN); - wpa_printf(MSG_DEBUG, "Wireless event: cmd=0x%x len=%d", - iwe->cmd, iwe->len); - if (iwe->len <= IW_EV_LCP_LEN) - return; - - custom = pos + IW_EV_POINT_LEN; - if (drv->we_version_compiled > 18 && - (iwe->cmd == IWEVMICHAELMICFAILURE || - iwe->cmd == IWEVCUSTOM || - iwe->cmd == IWEVASSOCREQIE || - iwe->cmd == IWEVASSOCRESPIE || - iwe->cmd == IWEVPMKIDCAND)) { - /* WE-19 removed the pointer from struct iw_point */ - char *dpos = (char *) &iwe_buf.u.data.length; - int dlen = dpos - (char *) &iwe_buf; - os_memcpy(dpos, pos + IW_EV_LCP_LEN, - sizeof(struct iw_event) - dlen); - } else { - os_memcpy(&iwe_buf, pos, sizeof(struct iw_event)); - custom += IW_EV_POINT_OFF; - } - - switch (iwe->cmd) { - case SIOCGIWAP: - wpa_printf(MSG_DEBUG, "Wireless event: new AP: " - MACSTR, - MAC2STR((u8 *) iwe->u.ap_addr.sa_data)); - if (is_zero_ether_addr( - (const u8 *) iwe->u.ap_addr.sa_data) || - os_memcmp(iwe->u.ap_addr.sa_data, - "\x44\x44\x44\x44\x44\x44", ETH_ALEN) == - 0) { - os_free(drv->assoc_req_ies); - drv->assoc_req_ies = NULL; - os_free(drv->assoc_resp_ies); - drv->assoc_resp_ies = NULL; - wpa_supplicant_event(drv->ctx, EVENT_DISASSOC, - NULL); - - } else { - wpa_driver_wext_event_assoc_ies(drv); - wpa_supplicant_event(drv->ctx, EVENT_ASSOC, - NULL); - } - break; - case IWEVMICHAELMICFAILURE: - if (custom + iwe->u.data.length > end) { - wpa_printf(MSG_DEBUG, "WEXT: Invalid " - "IWEVMICHAELMICFAILURE length"); - return; - } - wpa_driver_wext_event_wireless_michaelmicfailure( - drv->ctx, custom, iwe->u.data.length); - break; - case IWEVCUSTOM: - if (custom + iwe->u.data.length > end) { - wpa_printf(MSG_DEBUG, "WEXT: Invalid " - "IWEVCUSTOM length"); - return; - } - buf = os_malloc(iwe->u.data.length + 1); - if (buf == NULL) - return; - os_memcpy(buf, custom, iwe->u.data.length); - buf[iwe->u.data.length] = '\0'; - wpa_driver_wext_event_wireless_custom(drv->ctx, buf); - os_free(buf); - break; - case SIOCGIWSCAN: - drv->scan_complete_events = 1; - eloop_cancel_timeout(wpa_driver_wext_scan_timeout, - drv, drv->ctx); - wpa_supplicant_event(drv->ctx, EVENT_SCAN_RESULTS, - NULL); - break; - case IWEVASSOCREQIE: - if (custom + iwe->u.data.length > end) { - wpa_printf(MSG_DEBUG, "WEXT: Invalid " - "IWEVASSOCREQIE length"); - return; - } - wpa_driver_wext_event_wireless_assocreqie( - drv, custom, iwe->u.data.length); - break; - case IWEVASSOCRESPIE: - if (custom + iwe->u.data.length > end) { - wpa_printf(MSG_DEBUG, "WEXT: Invalid " - "IWEVASSOCRESPIE length"); - return; - } - wpa_driver_wext_event_wireless_assocrespie( - drv, custom, iwe->u.data.length); - break; - case IWEVPMKIDCAND: - if (custom + iwe->u.data.length > end) { - wpa_printf(MSG_DEBUG, "WEXT: Invalid " - "IWEVPMKIDCAND length"); - return; - } - wpa_driver_wext_event_wireless_pmkidcand( - drv, custom, iwe->u.data.length); - break; - } - - pos += iwe->len; - } -} - - -static void wpa_driver_wext_event_link(struct wpa_driver_wext_data *drv, - char *buf, size_t len, int del) -{ - union wpa_event_data event; - - os_memset(&event, 0, sizeof(event)); - if (len > sizeof(event.interface_status.ifname)) - len = sizeof(event.interface_status.ifname) - 1; - os_memcpy(event.interface_status.ifname, buf, len); - event.interface_status.ievent = del ? EVENT_INTERFACE_REMOVED : - EVENT_INTERFACE_ADDED; - - wpa_printf(MSG_DEBUG, "RTM_%sLINK, IFLA_IFNAME: Interface '%s' %s", - del ? "DEL" : "NEW", - event.interface_status.ifname, - del ? "removed" : "added"); - - if (os_strcmp(drv->ifname, event.interface_status.ifname) == 0) { - if (del) - drv->if_removed = 1; - else - drv->if_removed = 0; - } - - wpa_supplicant_event(drv->ctx, EVENT_INTERFACE_STATUS, &event); -} - - -static int wpa_driver_wext_own_ifname(struct wpa_driver_wext_data *drv, - u8 *buf, size_t len) -{ - int attrlen, rta_len; - struct rtattr *attr; - - attrlen = len; - attr = (struct rtattr *) buf; - - rta_len = RTA_ALIGN(sizeof(struct rtattr)); - while (RTA_OK(attr, attrlen)) { - if (attr->rta_type == IFLA_IFNAME) { - if (os_strcmp(((char *) attr) + rta_len, drv->ifname) - == 0) - return 1; - else - break; - } - attr = RTA_NEXT(attr, attrlen); - } - - return 0; -} - - -static int wpa_driver_wext_own_ifindex(struct wpa_driver_wext_data *drv, - int ifindex, u8 *buf, size_t len) -{ - if (drv->ifindex == ifindex || drv->ifindex2 == ifindex) - return 1; - - if (drv->if_removed && wpa_driver_wext_own_ifname(drv, buf, len)) { - drv->ifindex = if_nametoindex(drv->ifname); - wpa_printf(MSG_DEBUG, "WEXT: Update ifindex for a removed " - "interface"); - wpa_driver_wext_finish_drv_init(drv); - return 1; - } - - return 0; -} - - -static void wpa_driver_wext_event_rtm_newlink(void *ctx, struct ifinfomsg *ifi, - u8 *buf, size_t len) -{ - struct wpa_driver_wext_data *drv = ctx; - int attrlen, rta_len; - struct rtattr *attr; - - if (!wpa_driver_wext_own_ifindex(drv, ifi->ifi_index, buf, len)) { - wpa_printf(MSG_DEBUG, "Ignore event for foreign ifindex %d", - ifi->ifi_index); - return; - } - - wpa_printf(MSG_DEBUG, "RTM_NEWLINK: operstate=%d ifi_flags=0x%x " - "(%s%s%s%s)", - drv->operstate, ifi->ifi_flags, - (ifi->ifi_flags & IFF_UP) ? "[UP]" : "", - (ifi->ifi_flags & IFF_RUNNING) ? "[RUNNING]" : "", - (ifi->ifi_flags & IFF_LOWER_UP) ? "[LOWER_UP]" : "", - (ifi->ifi_flags & IFF_DORMANT) ? "[DORMANT]" : ""); - - if (!drv->if_disabled && !(ifi->ifi_flags & IFF_UP)) { - wpa_printf(MSG_DEBUG, "WEXT: Interface down"); - drv->if_disabled = 1; - wpa_supplicant_event(drv->ctx, EVENT_INTERFACE_DISABLED, NULL); - } - - if (drv->if_disabled && (ifi->ifi_flags & IFF_UP)) { - wpa_printf(MSG_DEBUG, "WEXT: Interface up"); - drv->if_disabled = 0; - wpa_supplicant_event(drv->ctx, EVENT_INTERFACE_ENABLED, NULL); - } - - /* - * Some drivers send the association event before the operup event--in - * this case, lifting operstate in wpa_driver_wext_set_operstate() - * fails. This will hit us when wpa_supplicant does not need to do - * IEEE 802.1X authentication - */ - if (drv->operstate == 1 && - (ifi->ifi_flags & (IFF_LOWER_UP | IFF_DORMANT)) == IFF_LOWER_UP && - !(ifi->ifi_flags & IFF_RUNNING)) - netlink_send_oper_ifla(drv->netlink, drv->ifindex, - -1, IF_OPER_UP); - - attrlen = len; - attr = (struct rtattr *) buf; - - rta_len = RTA_ALIGN(sizeof(struct rtattr)); - while (RTA_OK(attr, attrlen)) { - if (attr->rta_type == IFLA_WIRELESS) { - wpa_driver_wext_event_wireless( - drv, ((char *) attr) + rta_len, - attr->rta_len - rta_len); - } else if (attr->rta_type == IFLA_IFNAME) { - wpa_driver_wext_event_link(drv, - ((char *) attr) + rta_len, - attr->rta_len - rta_len, 0); - } - attr = RTA_NEXT(attr, attrlen); - } -} - - -static void wpa_driver_wext_event_rtm_dellink(void *ctx, struct ifinfomsg *ifi, - u8 *buf, size_t len) -{ - struct wpa_driver_wext_data *drv = ctx; - int attrlen, rta_len; - struct rtattr *attr; - - attrlen = len; - attr = (struct rtattr *) buf; - - rta_len = RTA_ALIGN(sizeof(struct rtattr)); - while (RTA_OK(attr, attrlen)) { - if (attr->rta_type == IFLA_IFNAME) { - wpa_driver_wext_event_link(drv, - ((char *) attr) + rta_len, - attr->rta_len - rta_len, 1); - } - attr = RTA_NEXT(attr, attrlen); - } -} - - -static void wpa_driver_wext_rfkill_blocked(void *ctx) -{ - wpa_printf(MSG_DEBUG, "WEXT: RFKILL blocked"); - /* - * This may be for any interface; use ifdown event to disable - * interface. - */ -} - - -static void wpa_driver_wext_rfkill_unblocked(void *ctx) -{ - struct wpa_driver_wext_data *drv = ctx; - wpa_printf(MSG_DEBUG, "WEXT: RFKILL unblocked"); - if (linux_set_iface_flags(drv->ioctl_sock, drv->ifname, 1)) { - wpa_printf(MSG_DEBUG, "WEXT: Could not set interface UP " - "after rfkill unblock"); - return; - } - /* rtnetlink ifup handler will report interface as enabled */ -} - - -static void wext_get_phy_name(struct wpa_driver_wext_data *drv) -{ - /* Find phy (radio) to which this interface belongs */ - char buf[90], *pos; - int f, rv; - - drv->phyname[0] = '\0'; - snprintf(buf, sizeof(buf) - 1, "/sys/class/net/%s/phy80211/name", - drv->ifname); - f = open(buf, O_RDONLY); - if (f < 0) { - wpa_printf(MSG_DEBUG, "Could not open file %s: %s", - buf, strerror(errno)); - return; - } - - rv = read(f, drv->phyname, sizeof(drv->phyname) - 1); - close(f); - if (rv < 0) { - wpa_printf(MSG_DEBUG, "Could not read file %s: %s", - buf, strerror(errno)); - return; - } - - drv->phyname[rv] = '\0'; - pos = os_strchr(drv->phyname, '\n'); - if (pos) - *pos = '\0'; - wpa_printf(MSG_DEBUG, "wext: interface %s phy: %s", - drv->ifname, drv->phyname); -} - - -/** - * wpa_driver_wext_init - Initialize WE driver interface - * @ctx: context to be used when calling wpa_supplicant functions, - * e.g., wpa_supplicant_event() - * @ifname: interface name, e.g., wlan0 - * Returns: Pointer to private data, %NULL on failure - */ -void * wpa_driver_wext_init(void *ctx, const char *ifname) -{ - struct wpa_driver_wext_data *drv; - struct netlink_config *cfg; - struct rfkill_config *rcfg; - char path[128]; - struct stat buf; - - drv = os_zalloc(sizeof(*drv)); - if (drv == NULL) - return NULL; - drv->ctx = ctx; - os_strlcpy(drv->ifname, ifname, sizeof(drv->ifname)); - - os_snprintf(path, sizeof(path), "/sys/class/net/%s/phy80211", ifname); - if (stat(path, &buf) == 0) { - wpa_printf(MSG_DEBUG, "WEXT: cfg80211-based driver detected"); - drv->cfg80211 = 1; - wext_get_phy_name(drv); - } - - drv->ioctl_sock = socket(PF_INET, SOCK_DGRAM, 0); - if (drv->ioctl_sock < 0) { - perror("socket(PF_INET,SOCK_DGRAM)"); - goto err1; - } - - cfg = os_zalloc(sizeof(*cfg)); - if (cfg == NULL) - goto err1; - cfg->ctx = drv; - cfg->newlink_cb = wpa_driver_wext_event_rtm_newlink; - cfg->dellink_cb = wpa_driver_wext_event_rtm_dellink; - drv->netlink = netlink_init(cfg); - if (drv->netlink == NULL) { - os_free(cfg); - goto err2; - } - - rcfg = os_zalloc(sizeof(*rcfg)); - if (rcfg == NULL) - goto err3; - rcfg->ctx = drv; - os_strlcpy(rcfg->ifname, ifname, sizeof(rcfg->ifname)); - rcfg->blocked_cb = wpa_driver_wext_rfkill_blocked; - rcfg->unblocked_cb = wpa_driver_wext_rfkill_unblocked; - drv->rfkill = rfkill_init(rcfg); - if (drv->rfkill == NULL) { - wpa_printf(MSG_DEBUG, "WEXT: RFKILL status not available"); - os_free(rcfg); - } - - drv->mlme_sock = -1; - - if (wpa_driver_wext_finish_drv_init(drv) < 0) - goto err3; - - wpa_driver_wext_set_auth_param(drv, IW_AUTH_WPA_ENABLED, 1); - - return drv; - -err3: - rfkill_deinit(drv->rfkill); - netlink_deinit(drv->netlink); -err2: - close(drv->ioctl_sock); -err1: - os_free(drv); - return NULL; -} - - -static void wpa_driver_wext_send_rfkill(void *eloop_ctx, void *timeout_ctx) -{ - wpa_supplicant_event(timeout_ctx, EVENT_INTERFACE_DISABLED, NULL); -} - - -static int wpa_driver_wext_finish_drv_init(struct wpa_driver_wext_data *drv) -{ - int send_rfkill_event = 0; - - if (linux_set_iface_flags(drv->ioctl_sock, drv->ifname, 1) < 0) { - if (rfkill_is_blocked(drv->rfkill)) { - wpa_printf(MSG_DEBUG, "WEXT: Could not yet enable " - "interface '%s' due to rfkill", - drv->ifname); - drv->if_disabled = 1; - send_rfkill_event = 1; - } else { - wpa_printf(MSG_ERROR, "WEXT: Could not set " - "interface '%s' UP", drv->ifname); - return -1; - } - } - - /* - * Make sure that the driver does not have any obsolete PMKID entries. - */ - wpa_driver_wext_flush_pmkid(drv); - - if (wpa_driver_wext_set_mode(drv, 0) < 0) { - wpa_printf(MSG_DEBUG, "Could not configure driver to use " - "managed mode"); - /* Try to use it anyway */ - } - - wpa_driver_wext_get_range(drv); - - /* - * Unlock the driver's BSSID and force to a random SSID to clear any - * previous association the driver might have when the supplicant - * starts up. - */ - wpa_driver_wext_disconnect(drv); - - drv->ifindex = if_nametoindex(drv->ifname); - - if (os_strncmp(drv->ifname, "wlan", 4) == 0) { - /* - * Host AP driver may use both wlan# and wifi# interface in - * wireless events. Since some of the versions included WE-18 - * support, let's add the alternative ifindex also from - * driver_wext.c for the time being. This may be removed at - * some point once it is believed that old versions of the - * driver are not in use anymore. - */ - char ifname2[IFNAMSIZ + 1]; - os_strlcpy(ifname2, drv->ifname, sizeof(ifname2)); - os_memcpy(ifname2, "wifi", 4); - wpa_driver_wext_alternative_ifindex(drv, ifname2); - } - - netlink_send_oper_ifla(drv->netlink, drv->ifindex, - 1, IF_OPER_DORMANT); - - if (send_rfkill_event) { - eloop_register_timeout(0, 0, wpa_driver_wext_send_rfkill, - drv, drv->ctx); - } - - return 0; -} - - -/** - * wpa_driver_wext_deinit - Deinitialize WE driver interface - * @priv: Pointer to private wext data from wpa_driver_wext_init() - * - * Shut down driver interface and processing of driver events. Free - * private data buffer if one was allocated in wpa_driver_wext_init(). - */ -void wpa_driver_wext_deinit(void *priv) -{ - struct wpa_driver_wext_data *drv = priv; - - wpa_driver_wext_set_auth_param(drv, IW_AUTH_WPA_ENABLED, 0); - - eloop_cancel_timeout(wpa_driver_wext_scan_timeout, drv, drv->ctx); - - /* - * Clear possibly configured driver parameters in order to make it - * easier to use the driver after wpa_supplicant has been terminated. - */ - wpa_driver_wext_disconnect(drv); - - netlink_send_oper_ifla(drv->netlink, drv->ifindex, 0, IF_OPER_UP); - netlink_deinit(drv->netlink); - rfkill_deinit(drv->rfkill); - - if (drv->mlme_sock >= 0) - eloop_unregister_read_sock(drv->mlme_sock); - - (void) linux_set_iface_flags(drv->ioctl_sock, drv->ifname, 0); - - close(drv->ioctl_sock); - if (drv->mlme_sock >= 0) - close(drv->mlme_sock); - os_free(drv->assoc_req_ies); - os_free(drv->assoc_resp_ies); - os_free(drv); -} - - -/** - * wpa_driver_wext_scan_timeout - Scan timeout to report scan completion - * @eloop_ctx: Unused - * @timeout_ctx: ctx argument given to wpa_driver_wext_init() - * - * This function can be used as registered timeout when starting a scan to - * generate a scan completed event if the driver does not report this. - */ -void wpa_driver_wext_scan_timeout(void *eloop_ctx, void *timeout_ctx) -{ - wpa_printf(MSG_DEBUG, "Scan timeout - try to get results"); - wpa_supplicant_event(timeout_ctx, EVENT_SCAN_RESULTS, NULL); -} - - -//added for wps2.0 @20110519 -static int wpa_driver_wext_set_probe_req_ie(struct wpa_driver_wext_data *drv, const u8 *extra_ies, - size_t extra_ies_len) -{ - unsigned char *pbuf; - struct iwreq iwr; - int ret = 0; - - pbuf = os_malloc(extra_ies_len); - os_memset(pbuf, 0, extra_ies_len); - - os_memset(&iwr, 0, sizeof(iwr)); - os_strlcpy(iwr.ifr_name, drv->ifname, IFNAMSIZ); - - os_memcpy(pbuf, extra_ies, extra_ies_len); - - iwr.u.data.pointer = (caddr_t)pbuf; - iwr.u.data.length = extra_ies_len; - iwr.u.data.flags = 0x8766;//magic number - - if (ioctl(drv->ioctl_sock, SIOCSIWPRIV, &iwr) < 0) { - perror("ioctl[SIOCSIWMLME]"); - ret = -1; - } - - if(pbuf) - os_free(pbuf); - - return ret; - -} - -/** - * wpa_driver_wext_scan - Request the driver to initiate scan - * @priv: Pointer to private wext data from wpa_driver_wext_init() - * @param: Scan parameters (specific SSID to scan for (ProbeReq), etc.) - * Returns: 0 on success, -1 on failure - */ -int wpa_driver_wext_scan(void *priv, struct wpa_driver_scan_params *params) -{ - struct wpa_driver_wext_data *drv = priv; - struct iwreq iwr; - int ret = 0, timeout; - struct iw_scan_req req; - const u8 *ssid = params->ssids[0].ssid; - size_t ssid_len = params->ssids[0].ssid_len; - - if (ssid_len > IW_ESSID_MAX_SIZE) { - wpa_printf(MSG_DEBUG, "%s: too long SSID (%lu)", - __FUNCTION__, (unsigned long) ssid_len); - return -1; - } - - //added for wps2.0 @20110519 - wpa_driver_wext_set_probe_req_ie(drv, params->extra_ies, - params->extra_ies_len); - - os_memset(&iwr, 0, sizeof(iwr)); - os_strlcpy(iwr.ifr_name, drv->ifname, IFNAMSIZ); - - if (ssid && ssid_len) { - os_memset(&req, 0, sizeof(req)); - req.essid_len = ssid_len; - req.bssid.sa_family = ARPHRD_ETHER; - os_memset(req.bssid.sa_data, 0xff, ETH_ALEN); - os_memcpy(req.essid, ssid, ssid_len); - iwr.u.data.pointer = (caddr_t) &req; - iwr.u.data.length = sizeof(req); - iwr.u.data.flags = IW_SCAN_THIS_ESSID; - } - - if (ioctl(drv->ioctl_sock, SIOCSIWSCAN, &iwr) < 0) { - perror("ioctl[SIOCSIWSCAN]"); - ret = -1; - } - - /* Not all drivers generate "scan completed" wireless event, so try to - * read results after a timeout. */ - timeout = 5; - if (drv->scan_complete_events) { - /* - * The driver seems to deliver SIOCGIWSCAN events to notify - * when scan is complete, so use longer timeout to avoid race - * conditions with scanning and following association request. - */ - timeout = 30; - } - wpa_printf(MSG_DEBUG, "Scan requested (ret=%d) - scan timeout %d " - "seconds", ret, timeout); - eloop_cancel_timeout(wpa_driver_wext_scan_timeout, drv, drv->ctx); - eloop_register_timeout(timeout, 0, wpa_driver_wext_scan_timeout, drv, - drv->ctx); - - return ret; -} - - -static u8 * wpa_driver_wext_giwscan(struct wpa_driver_wext_data *drv, - size_t *len) -{ - struct iwreq iwr; - u8 *res_buf; - size_t res_buf_len; - - res_buf_len = IW_SCAN_MAX_DATA; - for (;;) { - res_buf = os_malloc(res_buf_len); - if (res_buf == NULL) - return NULL; - os_memset(&iwr, 0, sizeof(iwr)); - os_strlcpy(iwr.ifr_name, drv->ifname, IFNAMSIZ); - iwr.u.data.pointer = res_buf; - iwr.u.data.length = res_buf_len; - - if (ioctl(drv->ioctl_sock, SIOCGIWSCAN, &iwr) == 0) - break; - - if (errno == E2BIG && res_buf_len < 65535) { - os_free(res_buf); - res_buf = NULL; - res_buf_len *= 2; - if (res_buf_len > 65535) - res_buf_len = 65535; /* 16-bit length field */ - wpa_printf(MSG_DEBUG, "Scan results did not fit - " - "trying larger buffer (%lu bytes)", - (unsigned long) res_buf_len); - } else { - perror("ioctl[SIOCGIWSCAN]"); - os_free(res_buf); - return NULL; - } - } - - if (iwr.u.data.length > res_buf_len) { - os_free(res_buf); - return NULL; - } - *len = iwr.u.data.length; - - return res_buf; -} - - -/* - * Data structure for collecting WEXT scan results. This is needed to allow - * the various methods of reporting IEs to be combined into a single IE buffer. - */ -struct wext_scan_data { - struct wpa_scan_res res; - u8 *ie; - size_t ie_len; - u8 ssid[32]; - size_t ssid_len; - int maxrate; -}; - - -static void wext_get_scan_mode(struct iw_event *iwe, - struct wext_scan_data *res) -{ - if (iwe->u.mode == IW_MODE_ADHOC) - res->res.caps |= IEEE80211_CAP_IBSS; - else if (iwe->u.mode == IW_MODE_MASTER || iwe->u.mode == IW_MODE_INFRA) - res->res.caps |= IEEE80211_CAP_ESS; -} - - -static void wext_get_scan_ssid(struct iw_event *iwe, - struct wext_scan_data *res, char *custom, - char *end) -{ - int ssid_len = iwe->u.essid.length; - if (custom + ssid_len > end) - return; - if (iwe->u.essid.flags && - ssid_len > 0 && - ssid_len <= IW_ESSID_MAX_SIZE) { - os_memcpy(res->ssid, custom, ssid_len); - res->ssid_len = ssid_len; - } -} - - -static void wext_get_scan_freq(struct iw_event *iwe, - struct wext_scan_data *res) -{ - int divi = 1000000, i; - - if (iwe->u.freq.e == 0) { - /* - * Some drivers do not report frequency, but a channel. - * Try to map this to frequency by assuming they are using - * IEEE 802.11b/g. But don't overwrite a previously parsed - * frequency if the driver sends both frequency and channel, - * since the driver may be sending an A-band channel that we - * don't handle here. - */ - - if (res->res.freq) - return; - - if (iwe->u.freq.m >= 1 && iwe->u.freq.m <= 13) { - res->res.freq = 2407 + 5 * iwe->u.freq.m; - return; - } else if (iwe->u.freq.m == 14) { - res->res.freq = 2484; - return; - } - } - - if (iwe->u.freq.e > 6) { - wpa_printf(MSG_DEBUG, "Invalid freq in scan results (BSSID=" - MACSTR " m=%d e=%d)", - MAC2STR(res->res.bssid), iwe->u.freq.m, - iwe->u.freq.e); - return; - } - - for (i = 0; i < iwe->u.freq.e; i++) - divi /= 10; - res->res.freq = iwe->u.freq.m / divi; -} - - -static void wext_get_scan_qual(struct wpa_driver_wext_data *drv, - struct iw_event *iwe, - struct wext_scan_data *res) -{ - res->res.qual = iwe->u.qual.qual; - res->res.noise = iwe->u.qual.noise; - res->res.level = iwe->u.qual.level; - if (iwe->u.qual.updated & IW_QUAL_QUAL_INVALID) - res->res.flags |= WPA_SCAN_QUAL_INVALID; - if (iwe->u.qual.updated & IW_QUAL_LEVEL_INVALID) - res->res.flags |= WPA_SCAN_LEVEL_INVALID; - if (iwe->u.qual.updated & IW_QUAL_NOISE_INVALID) - res->res.flags |= WPA_SCAN_NOISE_INVALID; - if (iwe->u.qual.updated & IW_QUAL_DBM) - res->res.flags |= WPA_SCAN_LEVEL_DBM; - if ((iwe->u.qual.updated & IW_QUAL_DBM) || - ((iwe->u.qual.level != 0) && - (iwe->u.qual.level > drv->max_level))) { - if (iwe->u.qual.level >= 64) - res->res.level -= 0x100; - if (iwe->u.qual.noise >= 64) - res->res.noise -= 0x100; - } -} - - -static void wext_get_scan_encode(struct iw_event *iwe, - struct wext_scan_data *res) -{ - if (!(iwe->u.data.flags & IW_ENCODE_DISABLED)) - res->res.caps |= IEEE80211_CAP_PRIVACY; -} - - -static void wext_get_scan_rate(struct iw_event *iwe, - struct wext_scan_data *res, char *pos, - char *end) -{ - int maxrate; - char *custom = pos + IW_EV_LCP_LEN; - struct iw_param p; - size_t clen; - - clen = iwe->len; - if (custom + clen > end) - return; - maxrate = 0; - while (((ssize_t) clen) >= (ssize_t) sizeof(struct iw_param)) { - /* Note: may be misaligned, make a local, aligned copy */ - os_memcpy(&p, custom, sizeof(struct iw_param)); - if (p.value > maxrate) - maxrate = p.value; - clen -= sizeof(struct iw_param); - custom += sizeof(struct iw_param); - } - - /* Convert the maxrate from WE-style (b/s units) to - * 802.11 rates (500000 b/s units). - */ - res->maxrate = maxrate / 500000; -} - - -static void wext_get_scan_iwevgenie(struct iw_event *iwe, - struct wext_scan_data *res, char *custom, - char *end) -{ - char *genie, *gpos, *gend; - u8 *tmp; - - if (iwe->u.data.length == 0) - return; - - gpos = genie = custom; - gend = genie + iwe->u.data.length; - if (gend > end) { - wpa_printf(MSG_INFO, "IWEVGENIE overflow"); - return; - } - - tmp = os_realloc(res->ie, res->ie_len + gend - gpos); - if (tmp == NULL) - return; - os_memcpy(tmp + res->ie_len, gpos, gend - gpos); - res->ie = tmp; - res->ie_len += gend - gpos; -} - - -static void wext_get_scan_custom(struct iw_event *iwe, - struct wext_scan_data *res, char *custom, - char *end) -{ - size_t clen; - u8 *tmp; - - clen = iwe->u.data.length; - if (custom + clen > end) - return; - - if (clen > 7 && os_strncmp(custom, "wpa_ie=", 7) == 0) { - char *spos; - int bytes; - spos = custom + 7; - bytes = custom + clen - spos; - if (bytes & 1 || bytes == 0) - return; - bytes /= 2; - tmp = os_realloc(res->ie, res->ie_len + bytes); - if (tmp == NULL) - return; - res->ie = tmp; - if (hexstr2bin(spos, tmp + res->ie_len, bytes) < 0) - return; - res->ie_len += bytes; - } else if (clen > 7 && os_strncmp(custom, "rsn_ie=", 7) == 0) { - char *spos; - int bytes; - spos = custom + 7; - bytes = custom + clen - spos; - if (bytes & 1 || bytes == 0) - return; - bytes /= 2; - tmp = os_realloc(res->ie, res->ie_len + bytes); - if (tmp == NULL) - return; - res->ie = tmp; - if (hexstr2bin(spos, tmp + res->ie_len, bytes) < 0) - return; - res->ie_len += bytes; - } else if (clen > 4 && os_strncmp(custom, "tsf=", 4) == 0) { - char *spos; - int bytes; - u8 bin[8]; - spos = custom + 4; - bytes = custom + clen - spos; - if (bytes != 16) { - wpa_printf(MSG_INFO, "Invalid TSF length (%d)", bytes); - return; - } - bytes /= 2; - if (hexstr2bin(spos, bin, bytes) < 0) { - wpa_printf(MSG_DEBUG, "WEXT: Invalid TSF value"); - return; - } - res->res.tsf += WPA_GET_BE64(bin); - } -} - - -static int wext_19_iw_point(struct wpa_driver_wext_data *drv, u16 cmd) -{ - return drv->we_version_compiled > 18 && - (cmd == SIOCGIWESSID || cmd == SIOCGIWENCODE || - cmd == IWEVGENIE || cmd == IWEVCUSTOM); -} - - -static void wpa_driver_wext_add_scan_entry(struct wpa_scan_results *res, - struct wext_scan_data *data) -{ - struct wpa_scan_res **tmp; - struct wpa_scan_res *r; - size_t extra_len; - u8 *pos, *end, *ssid_ie = NULL, *rate_ie = NULL; - - /* Figure out whether we need to fake any IEs */ - pos = data->ie; - end = pos + data->ie_len; - while (pos && pos + 1 < end) { - if (pos + 2 + pos[1] > end) - break; - if (pos[0] == WLAN_EID_SSID) - ssid_ie = pos; - else if (pos[0] == WLAN_EID_SUPP_RATES) - rate_ie = pos; - else if (pos[0] == WLAN_EID_EXT_SUPP_RATES) - rate_ie = pos; - pos += 2 + pos[1]; - } - - extra_len = 0; - if (ssid_ie == NULL) - extra_len += 2 + data->ssid_len; - if (rate_ie == NULL && data->maxrate) - extra_len += 3; - - r = os_zalloc(sizeof(*r) + extra_len + data->ie_len); - if (r == NULL) - return; - os_memcpy(r, &data->res, sizeof(*r)); - r->ie_len = extra_len + data->ie_len; - pos = (u8 *) (r + 1); - if (ssid_ie == NULL) { - /* - * Generate a fake SSID IE since the driver did not report - * a full IE list. - */ - *pos++ = WLAN_EID_SSID; - *pos++ = data->ssid_len; - os_memcpy(pos, data->ssid, data->ssid_len); - pos += data->ssid_len; - } - if (rate_ie == NULL && data->maxrate) { - /* - * Generate a fake Supported Rates IE since the driver did not - * report a full IE list. - */ - *pos++ = WLAN_EID_SUPP_RATES; - *pos++ = 1; - *pos++ = data->maxrate; - } - if (data->ie) - os_memcpy(pos, data->ie, data->ie_len); - - tmp = os_realloc(res->res, - (res->num + 1) * sizeof(struct wpa_scan_res *)); - if (tmp == NULL) { - os_free(r); - return; - } - tmp[res->num++] = r; - res->res = tmp; -} - - -/** - * wpa_driver_wext_get_scan_results - Fetch the latest scan results - * @priv: Pointer to private wext data from wpa_driver_wext_init() - * Returns: Scan results on success, -1 on failure - */ -struct wpa_scan_results * wpa_driver_wext_get_scan_results(void *priv) -{ - struct wpa_driver_wext_data *drv = priv; - size_t ap_num = 0, len; - int first; - u8 *res_buf; - struct iw_event iwe_buf, *iwe = &iwe_buf; - char *pos, *end, *custom; - struct wpa_scan_results *res; - struct wext_scan_data data; - - res_buf = wpa_driver_wext_giwscan(drv, &len); - if (res_buf == NULL) - return NULL; - - ap_num = 0; - first = 1; - - res = os_zalloc(sizeof(*res)); - if (res == NULL) { - os_free(res_buf); - return NULL; - } - - pos = (char *) res_buf; - end = (char *) res_buf + len; - os_memset(&data, 0, sizeof(data)); - - while (pos + IW_EV_LCP_LEN <= end) { - /* Event data may be unaligned, so make a local, aligned copy - * before processing. */ - os_memcpy(&iwe_buf, pos, IW_EV_LCP_LEN); - if (iwe->len <= IW_EV_LCP_LEN) - break; - - custom = pos + IW_EV_POINT_LEN; - if (wext_19_iw_point(drv, iwe->cmd)) { - /* WE-19 removed the pointer from struct iw_point */ - char *dpos = (char *) &iwe_buf.u.data.length; - int dlen = dpos - (char *) &iwe_buf; - os_memcpy(dpos, pos + IW_EV_LCP_LEN, - sizeof(struct iw_event) - dlen); - } else { - os_memcpy(&iwe_buf, pos, sizeof(struct iw_event)); - custom += IW_EV_POINT_OFF; - } - - switch (iwe->cmd) { - case SIOCGIWAP: - if (!first) - wpa_driver_wext_add_scan_entry(res, &data); - first = 0; - os_free(data.ie); - os_memset(&data, 0, sizeof(data)); - os_memcpy(data.res.bssid, - iwe->u.ap_addr.sa_data, ETH_ALEN); - break; - case SIOCGIWMODE: - wext_get_scan_mode(iwe, &data); - break; - case SIOCGIWESSID: - wext_get_scan_ssid(iwe, &data, custom, end); - break; - case SIOCGIWFREQ: - wext_get_scan_freq(iwe, &data); - break; - case IWEVQUAL: - wext_get_scan_qual(drv, iwe, &data); - break; - case SIOCGIWENCODE: - wext_get_scan_encode(iwe, &data); - break; - case SIOCGIWRATE: - wext_get_scan_rate(iwe, &data, pos, end); - break; - case IWEVGENIE: - wext_get_scan_iwevgenie(iwe, &data, custom, end); - break; - case IWEVCUSTOM: - wext_get_scan_custom(iwe, &data, custom, end); - break; - } - - pos += iwe->len; - } - os_free(res_buf); - res_buf = NULL; - if (!first) - wpa_driver_wext_add_scan_entry(res, &data); - os_free(data.ie); - - wpa_printf(MSG_DEBUG, "Received %lu bytes of scan results (%lu BSSes)", - (unsigned long) len, (unsigned long) res->num); - - return res; -} - - -static int wpa_driver_wext_get_range(void *priv) -{ - struct wpa_driver_wext_data *drv = priv; - struct iw_range *range; - struct iwreq iwr; - int minlen; - size_t buflen; - - /* - * Use larger buffer than struct iw_range in order to allow the - * structure to grow in the future. - */ - buflen = sizeof(struct iw_range) + 500; - range = os_zalloc(buflen); - if (range == NULL) - return -1; - - os_memset(&iwr, 0, sizeof(iwr)); - os_strlcpy(iwr.ifr_name, drv->ifname, IFNAMSIZ); - iwr.u.data.pointer = (caddr_t) range; - iwr.u.data.length = buflen; - - minlen = ((char *) &range->enc_capa) - (char *) range + - sizeof(range->enc_capa); - - if (ioctl(drv->ioctl_sock, SIOCGIWRANGE, &iwr) < 0) { - perror("ioctl[SIOCGIWRANGE]"); - os_free(range); - return -1; - } else if (iwr.u.data.length >= minlen && - range->we_version_compiled >= 18) { - wpa_printf(MSG_DEBUG, "SIOCGIWRANGE: WE(compiled)=%d " - "WE(source)=%d enc_capa=0x%x", - range->we_version_compiled, - range->we_version_source, - range->enc_capa); - drv->has_capability = 1; - drv->we_version_compiled = range->we_version_compiled; - if (range->enc_capa & IW_ENC_CAPA_WPA) { - drv->capa.key_mgmt |= WPA_DRIVER_CAPA_KEY_MGMT_WPA | - WPA_DRIVER_CAPA_KEY_MGMT_WPA_PSK; - } - if (range->enc_capa & IW_ENC_CAPA_WPA2) { - drv->capa.key_mgmt |= WPA_DRIVER_CAPA_KEY_MGMT_WPA2 | - WPA_DRIVER_CAPA_KEY_MGMT_WPA2_PSK; - } - drv->capa.enc |= WPA_DRIVER_CAPA_ENC_WEP40 | - WPA_DRIVER_CAPA_ENC_WEP104; - if (range->enc_capa & IW_ENC_CAPA_CIPHER_TKIP) - drv->capa.enc |= WPA_DRIVER_CAPA_ENC_TKIP; - if (range->enc_capa & IW_ENC_CAPA_CIPHER_CCMP) - drv->capa.enc |= WPA_DRIVER_CAPA_ENC_CCMP; - if (range->enc_capa & IW_ENC_CAPA_4WAY_HANDSHAKE) - drv->capa.flags |= WPA_DRIVER_FLAGS_4WAY_HANDSHAKE; - drv->capa.auth = WPA_DRIVER_AUTH_OPEN | - WPA_DRIVER_AUTH_SHARED | - WPA_DRIVER_AUTH_LEAP; - drv->capa.max_scan_ssids = 1; - - wpa_printf(MSG_DEBUG, " capabilities: key_mgmt 0x%x enc 0x%x " - "flags 0x%x", - drv->capa.key_mgmt, drv->capa.enc, drv->capa.flags); - } else { - wpa_printf(MSG_DEBUG, "SIOCGIWRANGE: too old (short) data - " - "assuming WPA is not supported"); - } - - drv->max_level = range->max_qual.level; - - os_free(range); - return 0; -} - - -static int wpa_driver_wext_set_psk(struct wpa_driver_wext_data *drv, - const u8 *psk) -{ - struct iw_encode_ext *ext; - struct iwreq iwr; - int ret; - - wpa_printf(MSG_DEBUG, "%s", __FUNCTION__); - - if (!(drv->capa.flags & WPA_DRIVER_FLAGS_4WAY_HANDSHAKE)) - return 0; - - if (!psk) - return 0; - - os_memset(&iwr, 0, sizeof(iwr)); - os_strlcpy(iwr.ifr_name, drv->ifname, IFNAMSIZ); - - ext = os_zalloc(sizeof(*ext) + PMK_LEN); - if (ext == NULL) - return -1; - - iwr.u.encoding.pointer = (caddr_t) ext; - iwr.u.encoding.length = sizeof(*ext) + PMK_LEN; - ext->key_len = PMK_LEN; - os_memcpy(&ext->key, psk, ext->key_len); - ext->alg = IW_ENCODE_ALG_PMK; - - ret = ioctl(drv->ioctl_sock, SIOCSIWENCODEEXT, &iwr); - if (ret < 0) - perror("ioctl[SIOCSIWENCODEEXT] PMK"); - os_free(ext); - - return ret; -} - - -static int wpa_driver_wext_set_key_ext(void *priv, enum wpa_alg alg, - const u8 *addr, int key_idx, - int set_tx, const u8 *seq, - size_t seq_len, - const u8 *key, size_t key_len) -{ - struct wpa_driver_wext_data *drv = priv; - struct iwreq iwr; - int ret = 0; - struct iw_encode_ext *ext; - - if (seq_len > IW_ENCODE_SEQ_MAX_SIZE) { - wpa_printf(MSG_DEBUG, "%s: Invalid seq_len %lu", - __FUNCTION__, (unsigned long) seq_len); - return -1; - } - - ext = os_zalloc(sizeof(*ext) + key_len); - if (ext == NULL) - return -1; - os_memset(&iwr, 0, sizeof(iwr)); - os_strlcpy(iwr.ifr_name, drv->ifname, IFNAMSIZ); - iwr.u.encoding.flags = key_idx + 1; - iwr.u.encoding.flags |= IW_ENCODE_TEMP; - if (alg == WPA_ALG_NONE) - iwr.u.encoding.flags |= IW_ENCODE_DISABLED; - iwr.u.encoding.pointer = (caddr_t) ext; - iwr.u.encoding.length = sizeof(*ext) + key_len; - - if (addr == NULL || is_broadcast_ether_addr(addr)) - ext->ext_flags |= IW_ENCODE_EXT_GROUP_KEY; - if (set_tx) - ext->ext_flags |= IW_ENCODE_EXT_SET_TX_KEY; - - ext->addr.sa_family = ARPHRD_ETHER; - if (addr) - os_memcpy(ext->addr.sa_data, addr, ETH_ALEN); - else - os_memset(ext->addr.sa_data, 0xff, ETH_ALEN); - if (key && key_len) { - os_memcpy(ext + 1, key, key_len); - ext->key_len = key_len; - } - switch (alg) { - case WPA_ALG_NONE: - ext->alg = IW_ENCODE_ALG_NONE; - break; - case WPA_ALG_WEP: - ext->alg = IW_ENCODE_ALG_WEP; - break; - case WPA_ALG_TKIP: - ext->alg = IW_ENCODE_ALG_TKIP; - break; - case WPA_ALG_CCMP: - ext->alg = IW_ENCODE_ALG_CCMP; - break; - case WPA_ALG_PMK: - ext->alg = IW_ENCODE_ALG_PMK; - break; -#ifdef CONFIG_IEEE80211W - case WPA_ALG_IGTK: - ext->alg = IW_ENCODE_ALG_AES_CMAC; - break; -#endif /* CONFIG_IEEE80211W */ - default: - wpa_printf(MSG_DEBUG, "%s: Unknown algorithm %d", - __FUNCTION__, alg); - os_free(ext); - return -1; - } - - if (seq && seq_len) { - ext->ext_flags |= IW_ENCODE_EXT_RX_SEQ_VALID; - os_memcpy(ext->rx_seq, seq, seq_len); - } - - if (ioctl(drv->ioctl_sock, SIOCSIWENCODEEXT, &iwr) < 0) { - ret = errno == EOPNOTSUPP ? -2 : -1; - if (errno == ENODEV) { - /* - * ndiswrapper seems to be returning incorrect error - * code.. */ - ret = -2; - } - - perror("ioctl[SIOCSIWENCODEEXT]"); - } - - os_free(ext); - return ret; -} - - -/** - * wpa_driver_wext_set_key - Configure encryption key - * @priv: Pointer to private wext data from wpa_driver_wext_init() - * @priv: Private driver interface data - * @alg: Encryption algorithm (%WPA_ALG_NONE, %WPA_ALG_WEP, - * %WPA_ALG_TKIP, %WPA_ALG_CCMP); %WPA_ALG_NONE clears the key. - * @addr: Address of the peer STA or ff:ff:ff:ff:ff:ff for - * broadcast/default keys - * @key_idx: key index (0..3), usually 0 for unicast keys - * @set_tx: Configure this key as the default Tx key (only used when - * driver does not support separate unicast/individual key - * @seq: Sequence number/packet number, seq_len octets, the next - * packet number to be used for in replay protection; configured - * for Rx keys (in most cases, this is only used with broadcast - * keys and set to zero for unicast keys) - * @seq_len: Length of the seq, depends on the algorithm: - * TKIP: 6 octets, CCMP: 6 octets - * @key: Key buffer; TKIP: 16-byte temporal key, 8-byte Tx Mic key, - * 8-byte Rx Mic Key - * @key_len: Length of the key buffer in octets (WEP: 5 or 13, - * TKIP: 32, CCMP: 16) - * Returns: 0 on success, -1 on failure - * - * This function uses SIOCSIWENCODEEXT by default, but tries to use - * SIOCSIWENCODE if the extended ioctl fails when configuring a WEP key. - */ -int wpa_driver_wext_set_key(const char *ifname, void *priv, enum wpa_alg alg, - const u8 *addr, int key_idx, - int set_tx, const u8 *seq, size_t seq_len, - const u8 *key, size_t key_len) -{ - struct wpa_driver_wext_data *drv = priv; - struct iwreq iwr; - int ret = 0; - - wpa_printf(MSG_DEBUG, "%s: alg=%d key_idx=%d set_tx=%d seq_len=%lu " - "key_len=%lu", - __FUNCTION__, alg, key_idx, set_tx, - (unsigned long) seq_len, (unsigned long) key_len); - - ret = wpa_driver_wext_set_key_ext(drv, alg, addr, key_idx, set_tx, - seq, seq_len, key, key_len); - if (ret == 0) - return 0; - - if (ret == -2 && - (alg == WPA_ALG_NONE || alg == WPA_ALG_WEP)) { - wpa_printf(MSG_DEBUG, "Driver did not support " - "SIOCSIWENCODEEXT, trying SIOCSIWENCODE"); - ret = 0; - } else { - wpa_printf(MSG_DEBUG, "Driver did not support " - "SIOCSIWENCODEEXT"); - return ret; - } - - os_memset(&iwr, 0, sizeof(iwr)); - os_strlcpy(iwr.ifr_name, drv->ifname, IFNAMSIZ); - iwr.u.encoding.flags = key_idx + 1; - iwr.u.encoding.flags |= IW_ENCODE_TEMP; - if (alg == WPA_ALG_NONE) - iwr.u.encoding.flags |= IW_ENCODE_DISABLED; - iwr.u.encoding.pointer = (caddr_t) key; - iwr.u.encoding.length = key_len; - - if (ioctl(drv->ioctl_sock, SIOCSIWENCODE, &iwr) < 0) { - perror("ioctl[SIOCSIWENCODE]"); - ret = -1; - } - - if (set_tx && alg != WPA_ALG_NONE) { - os_memset(&iwr, 0, sizeof(iwr)); - os_strlcpy(iwr.ifr_name, drv->ifname, IFNAMSIZ); - iwr.u.encoding.flags = key_idx + 1; - iwr.u.encoding.flags |= IW_ENCODE_TEMP; - iwr.u.encoding.pointer = (caddr_t) NULL; - iwr.u.encoding.length = 0; - if (ioctl(drv->ioctl_sock, SIOCSIWENCODE, &iwr) < 0) { - perror("ioctl[SIOCSIWENCODE] (set_tx)"); - ret = -1; - } - } - - return ret; -} - - -static int wpa_driver_wext_set_countermeasures(void *priv, - int enabled) -{ - struct wpa_driver_wext_data *drv = priv; - wpa_printf(MSG_DEBUG, "%s", __FUNCTION__); - return wpa_driver_wext_set_auth_param(drv, - IW_AUTH_TKIP_COUNTERMEASURES, - enabled); -} - - -static int wpa_driver_wext_set_drop_unencrypted(void *priv, - int enabled) -{ - struct wpa_driver_wext_data *drv = priv; - wpa_printf(MSG_DEBUG, "%s", __FUNCTION__); - drv->use_crypt = enabled; - return wpa_driver_wext_set_auth_param(drv, IW_AUTH_DROP_UNENCRYPTED, - enabled); -} - - -static int wpa_driver_wext_mlme(struct wpa_driver_wext_data *drv, - const u8 *addr, int cmd, int reason_code) -{ - struct iwreq iwr; - struct iw_mlme mlme; - int ret = 0; - - os_memset(&iwr, 0, sizeof(iwr)); - os_strlcpy(iwr.ifr_name, drv->ifname, IFNAMSIZ); - os_memset(&mlme, 0, sizeof(mlme)); - mlme.cmd = cmd; - mlme.reason_code = reason_code; - mlme.addr.sa_family = ARPHRD_ETHER; - os_memcpy(mlme.addr.sa_data, addr, ETH_ALEN); - iwr.u.data.pointer = (caddr_t) &mlme; - iwr.u.data.length = sizeof(mlme); - - if (ioctl(drv->ioctl_sock, SIOCSIWMLME, &iwr) < 0) { - perror("ioctl[SIOCSIWMLME]"); - ret = -1; - } - - return ret; -} - - -static void wpa_driver_wext_disconnect(struct wpa_driver_wext_data *drv) -{ - struct iwreq iwr; - const u8 null_bssid[ETH_ALEN] = { 0, 0, 0, 0, 0, 0 }; - u8 ssid[32]; - int i; - - /* - * Only force-disconnect when the card is in infrastructure mode, - * otherwise the driver might interpret the cleared BSSID and random - * SSID as an attempt to create a new ad-hoc network. - */ - os_memset(&iwr, 0, sizeof(iwr)); - os_strlcpy(iwr.ifr_name, drv->ifname, IFNAMSIZ); - if (ioctl(drv->ioctl_sock, SIOCGIWMODE, &iwr) < 0) { - perror("ioctl[SIOCGIWMODE]"); - iwr.u.mode = IW_MODE_INFRA; - } - - if (iwr.u.mode == IW_MODE_INFRA) { - if (drv->cfg80211) { - /* - * cfg80211 supports SIOCSIWMLME commands, so there is - * no need for the random SSID hack, but clear the - * BSSID and SSID. - */ - if (wpa_driver_wext_set_bssid(drv, null_bssid) < 0 || - wpa_driver_wext_set_ssid(drv, (u8 *) "", 0) < 0) { - wpa_printf(MSG_DEBUG, "WEXT: Failed to clear " - "to disconnect"); - } - return; - } - /* - * Clear the BSSID selection and set a random SSID to make sure - * the driver will not be trying to associate with something - * even if it does not understand SIOCSIWMLME commands (or - * tries to associate automatically after deauth/disassoc). - */ - for (i = 0; i < 32; i++) - ssid[i] = rand() & 0xFF; - if (wpa_driver_wext_set_bssid(drv, null_bssid) < 0 || - wpa_driver_wext_set_ssid(drv, ssid, 32) < 0) { - wpa_printf(MSG_DEBUG, "WEXT: Failed to set bogus " - "BSSID/SSID to disconnect"); - } - } -} - - -static int wpa_driver_wext_deauthenticate(void *priv, const u8 *addr, - int reason_code) -{ - struct wpa_driver_wext_data *drv = priv; - int ret; - wpa_printf(MSG_DEBUG, "%s", __FUNCTION__); - ret = wpa_driver_wext_mlme(drv, addr, IW_MLME_DEAUTH, reason_code); - wpa_driver_wext_disconnect(drv); - return ret; -} - - -static int wpa_driver_wext_disassociate(void *priv, const u8 *addr, - int reason_code) -{ - struct wpa_driver_wext_data *drv = priv; - int ret; - wpa_printf(MSG_DEBUG, "%s", __FUNCTION__); - ret = wpa_driver_wext_mlme(drv, addr, IW_MLME_DISASSOC, reason_code); - wpa_driver_wext_disconnect(drv); - return ret; -} - - -static int wpa_driver_wext_set_gen_ie(void *priv, const u8 *ie, - size_t ie_len) -{ - struct wpa_driver_wext_data *drv = priv; - struct iwreq iwr; - int ret = 0; - - os_memset(&iwr, 0, sizeof(iwr)); - os_strlcpy(iwr.ifr_name, drv->ifname, IFNAMSIZ); - iwr.u.data.pointer = (caddr_t) ie; - iwr.u.data.length = ie_len; - - if (ioctl(drv->ioctl_sock, SIOCSIWGENIE, &iwr) < 0) { - perror("ioctl[SIOCSIWGENIE]"); - ret = -1; - } - - return ret; -} - - -int wpa_driver_wext_cipher2wext(int cipher) -{ - switch (cipher) { - case CIPHER_NONE: - return IW_AUTH_CIPHER_NONE; - case CIPHER_WEP40: - return IW_AUTH_CIPHER_WEP40; - case CIPHER_TKIP: - return IW_AUTH_CIPHER_TKIP; - case CIPHER_CCMP: - return IW_AUTH_CIPHER_CCMP; - case CIPHER_WEP104: - return IW_AUTH_CIPHER_WEP104; - default: - return 0; - } -} - - -int wpa_driver_wext_keymgmt2wext(int keymgmt) -{ - switch (keymgmt) { - case KEY_MGMT_802_1X: - case KEY_MGMT_802_1X_NO_WPA: - return IW_AUTH_KEY_MGMT_802_1X; - case KEY_MGMT_PSK: - return IW_AUTH_KEY_MGMT_PSK; - default: - return 0; - } -} - - -static int -wpa_driver_wext_auth_alg_fallback(struct wpa_driver_wext_data *drv, - struct wpa_driver_associate_params *params) -{ - struct iwreq iwr; - int ret = 0; - - wpa_printf(MSG_DEBUG, "WEXT: Driver did not support " - "SIOCSIWAUTH for AUTH_ALG, trying SIOCSIWENCODE"); - - os_memset(&iwr, 0, sizeof(iwr)); - os_strlcpy(iwr.ifr_name, drv->ifname, IFNAMSIZ); - /* Just changing mode, not actual keys */ - iwr.u.encoding.flags = 0; - iwr.u.encoding.pointer = (caddr_t) NULL; - iwr.u.encoding.length = 0; - - /* - * Note: IW_ENCODE_{OPEN,RESTRICTED} can be interpreted to mean two - * different things. Here they are used to indicate Open System vs. - * Shared Key authentication algorithm. However, some drivers may use - * them to select between open/restricted WEP encrypted (open = allow - * both unencrypted and encrypted frames; restricted = only allow - * encrypted frames). - */ - - if (!drv->use_crypt) { - iwr.u.encoding.flags |= IW_ENCODE_DISABLED; - } else { - if (params->auth_alg & WPA_AUTH_ALG_OPEN) - iwr.u.encoding.flags |= IW_ENCODE_OPEN; - if (params->auth_alg & WPA_AUTH_ALG_SHARED) - iwr.u.encoding.flags |= IW_ENCODE_RESTRICTED; - } - - if (ioctl(drv->ioctl_sock, SIOCSIWENCODE, &iwr) < 0) { - perror("ioctl[SIOCSIWENCODE]"); - ret = -1; - } - - return ret; -} - - -int wpa_driver_wext_associate(void *priv, - struct wpa_driver_associate_params *params) -{ - struct wpa_driver_wext_data *drv = priv; - int ret = 0; - int allow_unencrypted_eapol; - int value; - - wpa_printf(MSG_DEBUG, "%s", __FUNCTION__); - - if (drv->cfg80211) { - /* - * Stop cfg80211 from trying to associate before we are done - * with all parameters. - */ - wpa_driver_wext_set_ssid(drv, (u8 *) "", 0); - } - - if (wpa_driver_wext_set_drop_unencrypted(drv, params->drop_unencrypted) - < 0) - ret = -1; - if (wpa_driver_wext_set_auth_alg(drv, params->auth_alg) < 0) - ret = -1; - if (wpa_driver_wext_set_mode(drv, params->mode) < 0) - ret = -1; - - /* - * If the driver did not support SIOCSIWAUTH, fallback to - * SIOCSIWENCODE here. - */ - if (drv->auth_alg_fallback && - wpa_driver_wext_auth_alg_fallback(drv, params) < 0) - ret = -1; - - if (!params->bssid && - wpa_driver_wext_set_bssid(drv, NULL) < 0) - ret = -1; - - /* TODO: should consider getting wpa version and cipher/key_mgmt suites - * from configuration, not from here, where only the selected suite is - * available */ - if (wpa_driver_wext_set_gen_ie(drv, params->wpa_ie, params->wpa_ie_len) - < 0) - ret = -1; - if (params->wpa_ie == NULL || params->wpa_ie_len == 0) - value = IW_AUTH_WPA_VERSION_DISABLED; - else if (params->wpa_ie[0] == WLAN_EID_RSN) - value = IW_AUTH_WPA_VERSION_WPA2; - else - value = IW_AUTH_WPA_VERSION_WPA; - if (wpa_driver_wext_set_auth_param(drv, - IW_AUTH_WPA_VERSION, value) < 0) - ret = -1; - value = wpa_driver_wext_cipher2wext(params->pairwise_suite); - if (wpa_driver_wext_set_auth_param(drv, - IW_AUTH_CIPHER_PAIRWISE, value) < 0) - ret = -1; - value = wpa_driver_wext_cipher2wext(params->group_suite); - if (wpa_driver_wext_set_auth_param(drv, - IW_AUTH_CIPHER_GROUP, value) < 0) - ret = -1; - value = wpa_driver_wext_keymgmt2wext(params->key_mgmt_suite); - if (wpa_driver_wext_set_auth_param(drv, - IW_AUTH_KEY_MGMT, value) < 0) - ret = -1; - value = params->key_mgmt_suite != KEY_MGMT_NONE || - params->pairwise_suite != CIPHER_NONE || - params->group_suite != CIPHER_NONE || - params->wpa_ie_len; - if (wpa_driver_wext_set_auth_param(drv, - IW_AUTH_PRIVACY_INVOKED, value) < 0) - ret = -1; - - /* Allow unencrypted EAPOL messages even if pairwise keys are set when - * not using WPA. IEEE 802.1X specifies that these frames are not - * encrypted, but WPA encrypts them when pairwise keys are in use. */ - if (params->key_mgmt_suite == KEY_MGMT_802_1X || - params->key_mgmt_suite == KEY_MGMT_PSK) - allow_unencrypted_eapol = 0; - else - allow_unencrypted_eapol = 1; - - if (wpa_driver_wext_set_psk(drv, params->psk) < 0) - ret = -1; - if (wpa_driver_wext_set_auth_param(drv, - IW_AUTH_RX_UNENCRYPTED_EAPOL, - allow_unencrypted_eapol) < 0) - ret = -1; -#ifdef CONFIG_IEEE80211W - switch (params->mgmt_frame_protection) { - case NO_MGMT_FRAME_PROTECTION: - value = IW_AUTH_MFP_DISABLED; - break; - case MGMT_FRAME_PROTECTION_OPTIONAL: - value = IW_AUTH_MFP_OPTIONAL; - break; - case MGMT_FRAME_PROTECTION_REQUIRED: - value = IW_AUTH_MFP_REQUIRED; - break; - }; - if (wpa_driver_wext_set_auth_param(drv, IW_AUTH_MFP, value) < 0) - ret = -1; -#endif /* CONFIG_IEEE80211W */ - if (params->freq && wpa_driver_wext_set_freq(drv, params->freq) < 0) - ret = -1; - if (!drv->cfg80211 && - wpa_driver_wext_set_ssid(drv, params->ssid, params->ssid_len) < 0) - ret = -1; - if (params->bssid && - wpa_driver_wext_set_bssid(drv, params->bssid) < 0) - ret = -1; - if (drv->cfg80211 && - wpa_driver_wext_set_ssid(drv, params->ssid, params->ssid_len) < 0) - ret = -1; - - return ret; -} - - -static int wpa_driver_wext_set_auth_alg(void *priv, int auth_alg) -{ - struct wpa_driver_wext_data *drv = priv; - int algs = 0, res; - - if (auth_alg & WPA_AUTH_ALG_OPEN) - algs |= IW_AUTH_ALG_OPEN_SYSTEM; - if (auth_alg & WPA_AUTH_ALG_SHARED) - algs |= IW_AUTH_ALG_SHARED_KEY; - if (auth_alg & WPA_AUTH_ALG_LEAP) - algs |= IW_AUTH_ALG_LEAP; - if (algs == 0) { - /* at least one algorithm should be set */ - algs = IW_AUTH_ALG_OPEN_SYSTEM; - } - - res = wpa_driver_wext_set_auth_param(drv, IW_AUTH_80211_AUTH_ALG, - algs); - drv->auth_alg_fallback = res == -2; - return res; -} - - -/** - * wpa_driver_wext_set_mode - Set wireless mode (infra/adhoc), SIOCSIWMODE - * @priv: Pointer to private wext data from wpa_driver_wext_init() - * @mode: 0 = infra/BSS (associate with an AP), 1 = adhoc/IBSS - * Returns: 0 on success, -1 on failure - */ -int wpa_driver_wext_set_mode(void *priv, int mode) -{ - struct wpa_driver_wext_data *drv = priv; - struct iwreq iwr; - int ret = -1; - unsigned int new_mode = mode ? IW_MODE_ADHOC : IW_MODE_INFRA; - - os_memset(&iwr, 0, sizeof(iwr)); - os_strlcpy(iwr.ifr_name, drv->ifname, IFNAMSIZ); - iwr.u.mode = new_mode; - if (ioctl(drv->ioctl_sock, SIOCSIWMODE, &iwr) == 0) { - ret = 0; - goto done; - } - - if (errno != EBUSY) { - perror("ioctl[SIOCSIWMODE]"); - goto done; - } - - /* mac80211 doesn't allow mode changes while the device is up, so if - * the device isn't in the mode we're about to change to, take device - * down, try to set the mode again, and bring it back up. - */ - if (ioctl(drv->ioctl_sock, SIOCGIWMODE, &iwr) < 0) { - perror("ioctl[SIOCGIWMODE]"); - goto done; - } - - if (iwr.u.mode == new_mode) { - ret = 0; - goto done; - } - - if (linux_set_iface_flags(drv->ioctl_sock, drv->ifname, 0) == 0) { - /* Try to set the mode again while the interface is down */ - iwr.u.mode = new_mode; - if (ioctl(drv->ioctl_sock, SIOCSIWMODE, &iwr) < 0) - perror("ioctl[SIOCSIWMODE]"); - else - ret = 0; - - (void) linux_set_iface_flags(drv->ioctl_sock, drv->ifname, 1); - } - -done: - return ret; -} - - -static int wpa_driver_wext_pmksa(struct wpa_driver_wext_data *drv, - u32 cmd, const u8 *bssid, const u8 *pmkid) -{ - struct iwreq iwr; - struct iw_pmksa pmksa; - int ret = 0; - - os_memset(&iwr, 0, sizeof(iwr)); - os_strlcpy(iwr.ifr_name, drv->ifname, IFNAMSIZ); - os_memset(&pmksa, 0, sizeof(pmksa)); - pmksa.cmd = cmd; - pmksa.bssid.sa_family = ARPHRD_ETHER; - if (bssid) - os_memcpy(pmksa.bssid.sa_data, bssid, ETH_ALEN); - if (pmkid) - os_memcpy(pmksa.pmkid, pmkid, IW_PMKID_LEN); - iwr.u.data.pointer = (caddr_t) &pmksa; - iwr.u.data.length = sizeof(pmksa); - - if (ioctl(drv->ioctl_sock, SIOCSIWPMKSA, &iwr) < 0) { - if (errno != EOPNOTSUPP) - perror("ioctl[SIOCSIWPMKSA]"); - ret = -1; - } - - return ret; -} - - -static int wpa_driver_wext_add_pmkid(void *priv, const u8 *bssid, - const u8 *pmkid) -{ - struct wpa_driver_wext_data *drv = priv; - return wpa_driver_wext_pmksa(drv, IW_PMKSA_ADD, bssid, pmkid); -} - - -static int wpa_driver_wext_remove_pmkid(void *priv, const u8 *bssid, - const u8 *pmkid) -{ - struct wpa_driver_wext_data *drv = priv; - return wpa_driver_wext_pmksa(drv, IW_PMKSA_REMOVE, bssid, pmkid); -} - - -static int wpa_driver_wext_flush_pmkid(void *priv) -{ - struct wpa_driver_wext_data *drv = priv; - return wpa_driver_wext_pmksa(drv, IW_PMKSA_FLUSH, NULL, NULL); -} - - -int wpa_driver_wext_get_capa(void *priv, struct wpa_driver_capa *capa) -{ - struct wpa_driver_wext_data *drv = priv; - if (!drv->has_capability) - return -1; - os_memcpy(capa, &drv->capa, sizeof(*capa)); - return 0; -} - - -int wpa_driver_wext_alternative_ifindex(struct wpa_driver_wext_data *drv, - const char *ifname) -{ - if (ifname == NULL) { - drv->ifindex2 = -1; - return 0; - } - - drv->ifindex2 = if_nametoindex(ifname); - if (drv->ifindex2 <= 0) - return -1; - - wpa_printf(MSG_DEBUG, "Added alternative ifindex %d (%s) for " - "wireless events", drv->ifindex2, ifname); - - return 0; -} - - -int wpa_driver_wext_set_operstate(void *priv, int state) -{ - struct wpa_driver_wext_data *drv = priv; - - wpa_printf(MSG_DEBUG, "%s: operstate %d->%d (%s)", - __func__, drv->operstate, state, state ? "UP" : "DORMANT"); - drv->operstate = state; - return netlink_send_oper_ifla(drv->netlink, drv->ifindex, -1, - state ? IF_OPER_UP : IF_OPER_DORMANT); -} - - -int wpa_driver_wext_get_version(struct wpa_driver_wext_data *drv) -{ - return drv->we_version_compiled; -} - - -static const char * wext_get_radio_name(void *priv) -{ - struct wpa_driver_wext_data *drv = priv; - return drv->phyname; -} - - -const struct wpa_driver_ops wpa_driver_wext_ops = { - .name = "wext", - .desc = "Linux wireless extensions (generic)", - .get_bssid = wpa_driver_wext_get_bssid, - .get_ssid = wpa_driver_wext_get_ssid, - .set_key = wpa_driver_wext_set_key, - .set_countermeasures = wpa_driver_wext_set_countermeasures, - .scan2 = wpa_driver_wext_scan, - .get_scan_results2 = wpa_driver_wext_get_scan_results, - .deauthenticate = wpa_driver_wext_deauthenticate, - .disassociate = wpa_driver_wext_disassociate, - .associate = wpa_driver_wext_associate, - .init = wpa_driver_wext_init, - .deinit = wpa_driver_wext_deinit, - .add_pmkid = wpa_driver_wext_add_pmkid, - .remove_pmkid = wpa_driver_wext_remove_pmkid, - .flush_pmkid = wpa_driver_wext_flush_pmkid, - .get_capa = wpa_driver_wext_get_capa, - .set_operstate = wpa_driver_wext_set_operstate, - .get_radio_name = wext_get_radio_name, -}; diff --git a/hostapd-0.8/src/drivers/driver_wext.h b/hostapd-0.8/src/drivers/driver_wext.h deleted file mode 100644 index 89c13eb..0000000 --- a/hostapd-0.8/src/drivers/driver_wext.h +++ /dev/null @@ -1,87 +0,0 @@ -/* - * WPA Supplicant - driver_wext exported functions - * Copyright (c) 2003-2005, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#ifndef DRIVER_WEXT_H -#define DRIVER_WEXT_H - -#include - -struct wpa_driver_wext_data { - void *ctx; - struct netlink_data *netlink; - int ioctl_sock; - int mlme_sock; - char ifname[IFNAMSIZ + 1]; - char phyname[32]; - int ifindex; - int ifindex2; - int if_removed; - int if_disabled; - struct rfkill_data *rfkill; - u8 *assoc_req_ies; - size_t assoc_req_ies_len; - u8 *assoc_resp_ies; - size_t assoc_resp_ies_len; - struct wpa_driver_capa capa; - int has_capability; - int we_version_compiled; - - /* for set_auth_alg fallback */ - int use_crypt; - int auth_alg_fallback; - - int operstate; - - char mlmedev[IFNAMSIZ + 1]; - - int scan_complete_events; - - int cfg80211; /* whether driver is using cfg80211 */ - - u8 max_level; -}; - -int wpa_driver_wext_get_bssid(void *priv, u8 *bssid); -int wpa_driver_wext_set_bssid(void *priv, const u8 *bssid); -int wpa_driver_wext_get_ssid(void *priv, u8 *ssid); -int wpa_driver_wext_set_ssid(void *priv, const u8 *ssid, size_t ssid_len); -int wpa_driver_wext_set_freq(void *priv, int freq); -int wpa_driver_wext_set_mode(void *priv, int mode); -int wpa_driver_wext_set_key(const char *ifname, void *priv, enum wpa_alg alg, - const u8 *addr, int key_idx, - int set_tx, const u8 *seq, size_t seq_len, - const u8 *key, size_t key_len); -int wpa_driver_wext_scan(void *priv, struct wpa_driver_scan_params *params); -struct wpa_scan_results * wpa_driver_wext_get_scan_results(void *priv); - -void wpa_driver_wext_scan_timeout(void *eloop_ctx, void *timeout_ctx); - -int wpa_driver_wext_alternative_ifindex(struct wpa_driver_wext_data *drv, - const char *ifname); - -void * wpa_driver_wext_init(void *ctx, const char *ifname); -void wpa_driver_wext_deinit(void *priv); - -int wpa_driver_wext_set_operstate(void *priv, int state); -int wpa_driver_wext_get_version(struct wpa_driver_wext_data *drv); - -int wpa_driver_wext_associate(void *priv, - struct wpa_driver_associate_params *params); -int wpa_driver_wext_get_capa(void *priv, struct wpa_driver_capa *capa); -int wpa_driver_wext_set_auth_param(struct wpa_driver_wext_data *drv, - int idx, u32 value); -int wpa_driver_wext_cipher2wext(int cipher); -int wpa_driver_wext_keymgmt2wext(int keymgmt); - -#endif /* DRIVER_WEXT_H */ diff --git a/hostapd-0.8/src/drivers/driver_wired.c b/hostapd-0.8/src/drivers/driver_wired.c deleted file mode 100644 index 618db26..0000000 --- a/hostapd-0.8/src/drivers/driver_wired.c +++ /dev/null @@ -1,629 +0,0 @@ -/* - * Wired Ethernet driver interface - * Copyright (c) 2005-2009, Jouni Malinen - * Copyright (c) 2004, Gunter Burchardt - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#include "includes.h" -#include -#include -#ifdef __linux__ -#include -#include -#include -#endif /* __linux__ */ -#if defined(__FreeBSD__) || defined(__DragonFly__) || defined(__FreeBSD_kernel__) -#include -#endif /* defined(__FreeBSD__) || defined(__DragonFly__) || defined(__FreeBSD_kernel__) */ -#ifdef __sun__ -#include -#endif /* __sun__ */ - -#include "common.h" -#include "eloop.h" -#include "driver.h" - -#ifdef _MSC_VER -#pragma pack(push, 1) -#endif /* _MSC_VER */ - -struct ieee8023_hdr { - u8 dest[6]; - u8 src[6]; - u16 ethertype; -} STRUCT_PACKED; - -#ifdef _MSC_VER -#pragma pack(pop) -#endif /* _MSC_VER */ - -static const u8 pae_group_addr[ETH_ALEN] = -{ 0x01, 0x80, 0xc2, 0x00, 0x00, 0x03 }; - - -struct wpa_driver_wired_data { - char ifname[IFNAMSIZ + 1]; - void *ctx; - - int sock; /* raw packet socket for driver access */ - int dhcp_sock; /* socket for dhcp packets */ - int use_pae_group_addr; - - int pf_sock; - int membership, multi, iff_allmulti, iff_up; -}; - - -/* TODO: detecting new devices should eventually be changed from using DHCP - * snooping to trigger on any packet from a new layer 2 MAC address, e.g., - * based on ebtables, etc. */ - -struct dhcp_message { - u_int8_t op; - u_int8_t htype; - u_int8_t hlen; - u_int8_t hops; - u_int32_t xid; - u_int16_t secs; - u_int16_t flags; - u_int32_t ciaddr; - u_int32_t yiaddr; - u_int32_t siaddr; - u_int32_t giaddr; - u_int8_t chaddr[16]; - u_int8_t sname[64]; - u_int8_t file[128]; - u_int32_t cookie; - u_int8_t options[308]; /* 312 - cookie */ -}; - - -static int wired_multicast_membership(int sock, int ifindex, - const u8 *addr, int add) -{ -#ifdef __linux__ - struct packet_mreq mreq; - - if (sock < 0) - return -1; - - os_memset(&mreq, 0, sizeof(mreq)); - mreq.mr_ifindex = ifindex; - mreq.mr_type = PACKET_MR_MULTICAST; - mreq.mr_alen = ETH_ALEN; - os_memcpy(mreq.mr_address, addr, ETH_ALEN); - - if (setsockopt(sock, SOL_PACKET, - add ? PACKET_ADD_MEMBERSHIP : PACKET_DROP_MEMBERSHIP, - &mreq, sizeof(mreq)) < 0) { - perror("setsockopt"); - return -1; - } - return 0; -#else /* __linux__ */ - return -1; -#endif /* __linux__ */ -} - - -#ifdef __linux__ -static void handle_data(void *ctx, unsigned char *buf, size_t len) -{ -#ifdef HOSTAPD - struct ieee8023_hdr *hdr; - u8 *pos, *sa; - size_t left; - union wpa_event_data event; - - /* must contain at least ieee8023_hdr 6 byte source, 6 byte dest, - * 2 byte ethertype */ - if (len < 14) { - wpa_printf(MSG_MSGDUMP, "handle_data: too short (%lu)", - (unsigned long) len); - return; - } - - hdr = (struct ieee8023_hdr *) buf; - - switch (ntohs(hdr->ethertype)) { - case ETH_P_PAE: - wpa_printf(MSG_MSGDUMP, "Received EAPOL packet"); - sa = hdr->src; - os_memset(&event, 0, sizeof(event)); - event.new_sta.addr = sa; - wpa_supplicant_event(ctx, EVENT_NEW_STA, &event); - - pos = (u8 *) (hdr + 1); - left = len - sizeof(*hdr); - drv_event_eapol_rx(ctx, sa, pos, left); - break; - - default: - wpa_printf(MSG_DEBUG, "Unknown ethertype 0x%04x in data frame", - ntohs(hdr->ethertype)); - break; - } -#endif /* HOSTAPD */ -} - - -static void handle_read(int sock, void *eloop_ctx, void *sock_ctx) -{ - int len; - unsigned char buf[3000]; - - len = recv(sock, buf, sizeof(buf), 0); - if (len < 0) { - perror("recv"); - return; - } - - handle_data(eloop_ctx, buf, len); -} - - -static void handle_dhcp(int sock, void *eloop_ctx, void *sock_ctx) -{ - int len; - unsigned char buf[3000]; - struct dhcp_message *msg; - u8 *mac_address; - union wpa_event_data event; - - len = recv(sock, buf, sizeof(buf), 0); - if (len < 0) { - perror("recv"); - return; - } - - /* must contain at least dhcp_message->chaddr */ - if (len < 44) { - wpa_printf(MSG_MSGDUMP, "handle_dhcp: too short (%d)", len); - return; - } - - msg = (struct dhcp_message *) buf; - mac_address = (u8 *) &(msg->chaddr); - - wpa_printf(MSG_MSGDUMP, "Got DHCP broadcast packet from " MACSTR, - MAC2STR(mac_address)); - - os_memset(&event, 0, sizeof(event)); - event.new_sta.addr = mac_address; - wpa_supplicant_event(eloop_ctx, EVENT_NEW_STA, &event); -} -#endif /* __linux__ */ - - -static int wired_init_sockets(struct wpa_driver_wired_data *drv, u8 *own_addr) -{ -#ifdef __linux__ - struct ifreq ifr; - struct sockaddr_ll addr; - struct sockaddr_in addr2; - int n = 1; - - drv->sock = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_PAE)); - if (drv->sock < 0) { - perror("socket[PF_PACKET,SOCK_RAW]"); - return -1; - } - - if (eloop_register_read_sock(drv->sock, handle_read, drv->ctx, NULL)) { - printf("Could not register read socket\n"); - return -1; - } - - os_memset(&ifr, 0, sizeof(ifr)); - os_strlcpy(ifr.ifr_name, drv->ifname, sizeof(ifr.ifr_name)); - if (ioctl(drv->sock, SIOCGIFINDEX, &ifr) != 0) { - perror("ioctl(SIOCGIFINDEX)"); - return -1; - } - - os_memset(&addr, 0, sizeof(addr)); - addr.sll_family = AF_PACKET; - addr.sll_ifindex = ifr.ifr_ifindex; - wpa_printf(MSG_DEBUG, "Opening raw packet socket for ifindex %d", - addr.sll_ifindex); - - if (bind(drv->sock, (struct sockaddr *) &addr, sizeof(addr)) < 0) { - perror("bind"); - return -1; - } - - /* filter multicast address */ - if (wired_multicast_membership(drv->sock, ifr.ifr_ifindex, - pae_group_addr, 1) < 0) { - wpa_printf(MSG_ERROR, "wired: Failed to add multicast group " - "membership"); - return -1; - } - - os_memset(&ifr, 0, sizeof(ifr)); - os_strlcpy(ifr.ifr_name, drv->ifname, sizeof(ifr.ifr_name)); - if (ioctl(drv->sock, SIOCGIFHWADDR, &ifr) != 0) { - perror("ioctl(SIOCGIFHWADDR)"); - return -1; - } - - if (ifr.ifr_hwaddr.sa_family != ARPHRD_ETHER) { - printf("Invalid HW-addr family 0x%04x\n", - ifr.ifr_hwaddr.sa_family); - return -1; - } - os_memcpy(own_addr, ifr.ifr_hwaddr.sa_data, ETH_ALEN); - - /* setup dhcp listen socket for sta detection */ - if ((drv->dhcp_sock = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0) { - perror("socket call failed for dhcp"); - return -1; - } - - if (eloop_register_read_sock(drv->dhcp_sock, handle_dhcp, drv->ctx, - NULL)) { - printf("Could not register read socket\n"); - return -1; - } - - os_memset(&addr2, 0, sizeof(addr2)); - addr2.sin_family = AF_INET; - addr2.sin_port = htons(67); - addr2.sin_addr.s_addr = INADDR_ANY; - - if (setsockopt(drv->dhcp_sock, SOL_SOCKET, SO_REUSEADDR, (char *) &n, - sizeof(n)) == -1) { - perror("setsockopt[SOL_SOCKET,SO_REUSEADDR]"); - return -1; - } - if (setsockopt(drv->dhcp_sock, SOL_SOCKET, SO_BROADCAST, (char *) &n, - sizeof(n)) == -1) { - perror("setsockopt[SOL_SOCKET,SO_BROADCAST]"); - return -1; - } - - os_memset(&ifr, 0, sizeof(ifr)); - os_strlcpy(ifr.ifr_ifrn.ifrn_name, drv->ifname, IFNAMSIZ); - if (setsockopt(drv->dhcp_sock, SOL_SOCKET, SO_BINDTODEVICE, - (char *) &ifr, sizeof(ifr)) < 0) { - perror("setsockopt[SOL_SOCKET,SO_BINDTODEVICE]"); - return -1; - } - - if (bind(drv->dhcp_sock, (struct sockaddr *) &addr2, - sizeof(struct sockaddr)) == -1) { - perror("bind"); - return -1; - } - - return 0; -#else /* __linux__ */ - return -1; -#endif /* __linux__ */ -} - - -static int wired_send_eapol(void *priv, const u8 *addr, - const u8 *data, size_t data_len, int encrypt, - const u8 *own_addr, u32 flags) -{ - struct wpa_driver_wired_data *drv = priv; - struct ieee8023_hdr *hdr; - size_t len; - u8 *pos; - int res; - - len = sizeof(*hdr) + data_len; - hdr = os_zalloc(len); - if (hdr == NULL) { - printf("malloc() failed for wired_send_eapol(len=%lu)\n", - (unsigned long) len); - return -1; - } - - os_memcpy(hdr->dest, drv->use_pae_group_addr ? pae_group_addr : addr, - ETH_ALEN); - os_memcpy(hdr->src, own_addr, ETH_ALEN); - hdr->ethertype = htons(ETH_P_PAE); - - pos = (u8 *) (hdr + 1); - os_memcpy(pos, data, data_len); - - res = send(drv->sock, (u8 *) hdr, len, 0); - os_free(hdr); - - if (res < 0) { - perror("wired_send_eapol: send"); - printf("wired_send_eapol - packet len: %lu - failed\n", - (unsigned long) len); - } - - return res; -} - - -static void * wired_driver_hapd_init(struct hostapd_data *hapd, - struct wpa_init_params *params) -{ - struct wpa_driver_wired_data *drv; - - drv = os_zalloc(sizeof(struct wpa_driver_wired_data)); - if (drv == NULL) { - printf("Could not allocate memory for wired driver data\n"); - return NULL; - } - - drv->ctx = hapd; - os_strlcpy(drv->ifname, params->ifname, sizeof(drv->ifname)); - drv->use_pae_group_addr = params->use_pae_group_addr; - - if (wired_init_sockets(drv, params->own_addr)) { - os_free(drv); - return NULL; - } - - return drv; -} - - -static void wired_driver_hapd_deinit(void *priv) -{ - struct wpa_driver_wired_data *drv = priv; - - if (drv->sock >= 0) - close(drv->sock); - - if (drv->dhcp_sock >= 0) - close(drv->dhcp_sock); - - os_free(drv); -} - - -static int wpa_driver_wired_get_ssid(void *priv, u8 *ssid) -{ - ssid[0] = 0; - return 0; -} - - -static int wpa_driver_wired_get_bssid(void *priv, u8 *bssid) -{ - /* Report PAE group address as the "BSSID" for wired connection. */ - os_memcpy(bssid, pae_group_addr, ETH_ALEN); - return 0; -} - - -static int wpa_driver_wired_get_capa(void *priv, struct wpa_driver_capa *capa) -{ - os_memset(capa, 0, sizeof(*capa)); - capa->flags = WPA_DRIVER_FLAGS_WIRED; - return 0; -} - - -static int wpa_driver_wired_get_ifflags(const char *ifname, int *flags) -{ - struct ifreq ifr; - int s; - - s = socket(PF_INET, SOCK_DGRAM, 0); - if (s < 0) { - perror("socket"); - return -1; - } - - os_memset(&ifr, 0, sizeof(ifr)); - os_strlcpy(ifr.ifr_name, ifname, IFNAMSIZ); - if (ioctl(s, SIOCGIFFLAGS, (caddr_t) &ifr) < 0) { - perror("ioctl[SIOCGIFFLAGS]"); - close(s); - return -1; - } - close(s); - *flags = ifr.ifr_flags & 0xffff; - return 0; -} - - -static int wpa_driver_wired_set_ifflags(const char *ifname, int flags) -{ - struct ifreq ifr; - int s; - - s = socket(PF_INET, SOCK_DGRAM, 0); - if (s < 0) { - perror("socket"); - return -1; - } - - os_memset(&ifr, 0, sizeof(ifr)); - os_strlcpy(ifr.ifr_name, ifname, IFNAMSIZ); - ifr.ifr_flags = flags & 0xffff; - if (ioctl(s, SIOCSIFFLAGS, (caddr_t) &ifr) < 0) { - perror("ioctl[SIOCSIFFLAGS]"); - close(s); - return -1; - } - close(s); - return 0; -} - - -static int wpa_driver_wired_multi(const char *ifname, const u8 *addr, int add) -{ - struct ifreq ifr; - int s; - -#ifdef __sun__ - return -1; -#endif /* __sun__ */ - - s = socket(PF_INET, SOCK_DGRAM, 0); - if (s < 0) { - perror("socket"); - return -1; - } - - os_memset(&ifr, 0, sizeof(ifr)); - os_strlcpy(ifr.ifr_name, ifname, IFNAMSIZ); -#ifdef __linux__ - ifr.ifr_hwaddr.sa_family = AF_UNSPEC; - os_memcpy(ifr.ifr_hwaddr.sa_data, addr, ETH_ALEN); -#endif /* __linux__ */ -#if defined(__FreeBSD__) || defined(__DragonFly__) || defined(__FreeBSD_kernel__) - { - struct sockaddr_dl *dlp; - dlp = (struct sockaddr_dl *) &ifr.ifr_addr; - dlp->sdl_len = sizeof(struct sockaddr_dl); - dlp->sdl_family = AF_LINK; - dlp->sdl_index = 0; - dlp->sdl_nlen = 0; - dlp->sdl_alen = ETH_ALEN; - dlp->sdl_slen = 0; - os_memcpy(LLADDR(dlp), addr, ETH_ALEN); - } -#endif /* defined(__FreeBSD__) || defined(__DragonFly__) || defined(FreeBSD_kernel__) */ -#if defined(__NetBSD__) || defined(__OpenBSD__) || defined(__APPLE__) - { - struct sockaddr *sap; - sap = (struct sockaddr *) &ifr.ifr_addr; - sap->sa_len = sizeof(struct sockaddr); - sap->sa_family = AF_UNSPEC; - os_memcpy(sap->sa_data, addr, ETH_ALEN); - } -#endif /* defined(__NetBSD__) || defined(__OpenBSD__) || defined(__APPLE__) */ - - if (ioctl(s, add ? SIOCADDMULTI : SIOCDELMULTI, (caddr_t) &ifr) < 0) { - perror("ioctl[SIOC{ADD/DEL}MULTI]"); - close(s); - return -1; - } - close(s); - return 0; -} - - -static void * wpa_driver_wired_init(void *ctx, const char *ifname) -{ - struct wpa_driver_wired_data *drv; - int flags; - - drv = os_zalloc(sizeof(*drv)); - if (drv == NULL) - return NULL; - os_strlcpy(drv->ifname, ifname, sizeof(drv->ifname)); - drv->ctx = ctx; - -#ifdef __linux__ - drv->pf_sock = socket(PF_PACKET, SOCK_DGRAM, 0); - if (drv->pf_sock < 0) - perror("socket(PF_PACKET)"); -#else /* __linux__ */ - drv->pf_sock = -1; -#endif /* __linux__ */ - - if (wpa_driver_wired_get_ifflags(ifname, &flags) == 0 && - !(flags & IFF_UP) && - wpa_driver_wired_set_ifflags(ifname, flags | IFF_UP) == 0) { - drv->iff_up = 1; - } - - if (wired_multicast_membership(drv->pf_sock, - if_nametoindex(drv->ifname), - pae_group_addr, 1) == 0) { - wpa_printf(MSG_DEBUG, "%s: Added multicast membership with " - "packet socket", __func__); - drv->membership = 1; - } else if (wpa_driver_wired_multi(ifname, pae_group_addr, 1) == 0) { - wpa_printf(MSG_DEBUG, "%s: Added multicast membership with " - "SIOCADDMULTI", __func__); - drv->multi = 1; - } else if (wpa_driver_wired_get_ifflags(ifname, &flags) < 0) { - wpa_printf(MSG_INFO, "%s: Could not get interface " - "flags", __func__); - os_free(drv); - return NULL; - } else if (flags & IFF_ALLMULTI) { - wpa_printf(MSG_DEBUG, "%s: Interface is already configured " - "for multicast", __func__); - } else if (wpa_driver_wired_set_ifflags(ifname, - flags | IFF_ALLMULTI) < 0) { - wpa_printf(MSG_INFO, "%s: Failed to enable allmulti", - __func__); - os_free(drv); - return NULL; - } else { - wpa_printf(MSG_DEBUG, "%s: Enabled allmulti mode", - __func__); - drv->iff_allmulti = 1; - } - - return drv; -} - - -static void wpa_driver_wired_deinit(void *priv) -{ - struct wpa_driver_wired_data *drv = priv; - int flags; - - if (drv->membership && - wired_multicast_membership(drv->pf_sock, - if_nametoindex(drv->ifname), - pae_group_addr, 0) < 0) { - wpa_printf(MSG_DEBUG, "%s: Failed to remove PAE multicast " - "group (PACKET)", __func__); - } - - if (drv->multi && - wpa_driver_wired_multi(drv->ifname, pae_group_addr, 0) < 0) { - wpa_printf(MSG_DEBUG, "%s: Failed to remove PAE multicast " - "group (SIOCDELMULTI)", __func__); - } - - if (drv->iff_allmulti && - (wpa_driver_wired_get_ifflags(drv->ifname, &flags) < 0 || - wpa_driver_wired_set_ifflags(drv->ifname, - flags & ~IFF_ALLMULTI) < 0)) { - wpa_printf(MSG_DEBUG, "%s: Failed to disable allmulti mode", - __func__); - } - - if (drv->iff_up && - wpa_driver_wired_get_ifflags(drv->ifname, &flags) == 0 && - (flags & IFF_UP) && - wpa_driver_wired_set_ifflags(drv->ifname, flags & ~IFF_UP) < 0) { - wpa_printf(MSG_DEBUG, "%s: Failed to set the interface down", - __func__); - } - - if (drv->pf_sock != -1) - close(drv->pf_sock); - - os_free(drv); -} - - -const struct wpa_driver_ops wpa_driver_wired_ops = { - .name = "wired", - .desc = "Wired Ethernet driver", - .hapd_init = wired_driver_hapd_init, - .hapd_deinit = wired_driver_hapd_deinit, - .hapd_send_eapol = wired_send_eapol, - .get_ssid = wpa_driver_wired_get_ssid, - .get_bssid = wpa_driver_wired_get_bssid, - .get_capa = wpa_driver_wired_get_capa, - .init = wpa_driver_wired_init, - .deinit = wpa_driver_wired_deinit, -}; diff --git a/hostapd-0.8/src/drivers/drivers.c b/hostapd-0.8/src/drivers/drivers.c deleted file mode 100644 index 2d29452..0000000 --- a/hostapd-0.8/src/drivers/drivers.c +++ /dev/null @@ -1,120 +0,0 @@ -/* - * Driver interface list - * Copyright (c) 2004-2005, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#include "includes.h" - - -#ifdef CONFIG_DRIVER_WEXT -extern struct wpa_driver_ops wpa_driver_wext_ops; /* driver_wext.c */ -#endif /* CONFIG_DRIVER_WEXT */ -#ifdef CONFIG_DRIVER_NL80211 -extern struct wpa_driver_ops wpa_driver_nl80211_ops; /* driver_nl80211.c */ -#endif /* CONFIG_DRIVER_NL80211 */ -#ifdef CONFIG_DRIVER_HOSTAP -extern struct wpa_driver_ops wpa_driver_hostap_ops; /* driver_hostap.c */ -#endif /* CONFIG_DRIVER_HOSTAP */ -#ifdef CONFIG_DRIVER_MADWIFI -extern struct wpa_driver_ops wpa_driver_madwifi_ops; /* driver_madwifi.c */ -#endif /* CONFIG_DRIVER_MADWIFI */ -#ifdef CONFIG_DRIVER_BROADCOM -extern struct wpa_driver_ops wpa_driver_broadcom_ops; /* driver_broadcom.c */ -#endif /* CONFIG_DRIVER_BROADCOM */ -#ifdef CONFIG_DRIVER_BSD -extern struct wpa_driver_ops wpa_driver_bsd_ops; /* driver_bsd.c */ -#endif /* CONFIG_DRIVER_BSD */ -#ifdef CONFIG_DRIVER_NDIS -extern struct wpa_driver_ops wpa_driver_ndis_ops; /* driver_ndis.c */ -#endif /* CONFIG_DRIVER_NDIS */ -#ifdef CONFIG_DRIVER_WIRED -extern struct wpa_driver_ops wpa_driver_wired_ops; /* driver_wired.c */ -#endif /* CONFIG_DRIVER_WIRED */ -#ifdef CONFIG_DRIVER_TEST -extern struct wpa_driver_ops wpa_driver_test_ops; /* driver_test.c */ -#endif /* CONFIG_DRIVER_TEST */ -#ifdef CONFIG_DRIVER_RALINK -extern struct wpa_driver_ops wpa_driver_ralink_ops; /* driver_ralink.c */ -#endif /* CONFIG_DRIVER_RALINK */ -#ifdef CONFIG_DRIVER_OSX -extern struct wpa_driver_ops wpa_driver_osx_ops; /* driver_osx.m */ -#endif /* CONFIG_DRIVER_OSX */ -#ifdef CONFIG_DRIVER_IPHONE -extern struct wpa_driver_ops wpa_driver_iphone_ops; /* driver_iphone.m */ -#endif /* CONFIG_DRIVER_IPHONE */ -#ifdef CONFIG_DRIVER_ROBOSWITCH -/* driver_roboswitch.c */ -extern struct wpa_driver_ops wpa_driver_roboswitch_ops; -#endif /* CONFIG_DRIVER_ROBOSWITCH */ -#ifdef CONFIG_DRIVER_ATHEROS -extern struct wpa_driver_ops wpa_driver_atheros_ops; /* driver_atheros.c */ -#endif /* CONFIG_DRIVER_ATHEROS */ -#ifdef CONFIG_DRIVER_NONE -extern struct wpa_driver_ops wpa_driver_none_ops; /* driver_none.c */ -#endif /* CONFIG_DRIVER_NONE */ -#ifdef CONFIG_DRIVER_RTW -extern struct wpa_driver_ops wpa_driver_rtw_ops; /* driver_rtw.c */ -#endif /* CONFIG_DRIVER_RTW */ - - -struct wpa_driver_ops *wpa_drivers[] = -{ -#ifdef CONFIG_DRIVER_WEXT - &wpa_driver_wext_ops, -#endif /* CONFIG_DRIVER_WEXT */ -#ifdef CONFIG_DRIVER_NL80211 - &wpa_driver_nl80211_ops, -#endif /* CONFIG_DRIVER_NL80211 */ -#ifdef CONFIG_DRIVER_HOSTAP - &wpa_driver_hostap_ops, -#endif /* CONFIG_DRIVER_HOSTAP */ -#ifdef CONFIG_DRIVER_MADWIFI - &wpa_driver_madwifi_ops, -#endif /* CONFIG_DRIVER_MADWIFI */ -#ifdef CONFIG_DRIVER_BROADCOM - &wpa_driver_broadcom_ops, -#endif /* CONFIG_DRIVER_BROADCOM */ -#ifdef CONFIG_DRIVER_BSD - &wpa_driver_bsd_ops, -#endif /* CONFIG_DRIVER_BSD */ -#ifdef CONFIG_DRIVER_NDIS - &wpa_driver_ndis_ops, -#endif /* CONFIG_DRIVER_NDIS */ -#ifdef CONFIG_DRIVER_WIRED - &wpa_driver_wired_ops, -#endif /* CONFIG_DRIVER_WIRED */ -#ifdef CONFIG_DRIVER_TEST - &wpa_driver_test_ops, -#endif /* CONFIG_DRIVER_TEST */ -#ifdef CONFIG_DRIVER_RALINK - &wpa_driver_ralink_ops, -#endif /* CONFIG_DRIVER_RALINK */ -#ifdef CONFIG_DRIVER_OSX - &wpa_driver_osx_ops, -#endif /* CONFIG_DRIVER_OSX */ -#ifdef CONFIG_DRIVER_IPHONE - &wpa_driver_iphone_ops, -#endif /* CONFIG_DRIVER_IPHONE */ -#ifdef CONFIG_DRIVER_ROBOSWITCH - &wpa_driver_roboswitch_ops, -#endif /* CONFIG_DRIVER_ROBOSWITCH */ -#ifdef CONFIG_DRIVER_ATHEROS - &wpa_driver_atheros_ops, -#endif /* CONFIG_DRIVER_ATHEROS */ -#ifdef CONFIG_DRIVER_NONE - &wpa_driver_none_ops, -#endif /* CONFIG_DRIVER_NONE */ -#ifdef CONFIG_DRIVER_RTW - &wpa_driver_rtw_ops, -#endif /* CONFIG_DRIVER_RTW */ - NULL -}; diff --git a/hostapd-0.8/src/drivers/drivers.mak b/hostapd-0.8/src/drivers/drivers.mak deleted file mode 100644 index 98d4079..0000000 --- a/hostapd-0.8/src/drivers/drivers.mak +++ /dev/null @@ -1,191 +0,0 @@ -##### CLEAR VARS - -DRV_CFLAGS = -DRV_WPA_CFLAGS = -DRV_AP_CFLAGS = -DRV_OBJS = -DRV_WPA_OBJS = -DRV_AP_OBJS = -DRV_LIBS = -DRV_WPA_LIBS = -DRV_AP_LIBS = - -##### COMMON DRIVERS - -ifdef CONFIG_DRIVER_HOSTAP -DRV_CFLAGS += -DCONFIG_DRIVER_HOSTAP -DRV_OBJS += ../src/drivers/driver_hostap.o -CONFIG_WIRELESS_EXTENSION=y -NEED_AP_MLME=y -NEED_NETLINK=y -NEED_LINUX_IOCTL=y -endif - -ifdef CONFIG_DRIVER_WIRED -DRV_CFLAGS += -DCONFIG_DRIVER_WIRED -DRV_OBJS += ../src/drivers/driver_wired.o -endif - -ifdef CONFIG_DRIVER_MADWIFI -DRV_CFLAGS += -DCONFIG_DRIVER_MADWIFI -DRV_OBJS += ../src/drivers/driver_madwifi.o -CONFIG_WIRELESS_EXTENSION=y -CONFIG_L2_PACKET=linux -NEED_NETLINK=y -NEED_LINUX_IOCTL=y -endif - -ifdef CONFIG_DRIVER_NL80211 -DRV_CFLAGS += -DCONFIG_DRIVER_NL80211 -DRV_OBJS += ../src/drivers/driver_nl80211.o -DRV_OBJS += ../src/utils/radiotap.o -NEED_SME=y -NEED_AP_MLME=y -NEED_NETLINK=y -NEED_LINUX_IOCTL=y -NEED_RFKILL=y -ifdef CONFIG_LIBNL_TINY -DRV_LIBS += -lnl-tiny -else -DRV_LIBS += -lnl -endif - -ifdef CONFIG_LIBNL20 -DRV_LIBS += -lnl-genl -DRV_CFLAGS += -DCONFIG_LIBNL20 -endif -endif - -ifdef CONFIG_DRIVER_BSD -ifndef CONFIG_L2_PACKET -CONFIG_L2_PACKET=freebsd -endif -DRV_CFLAGS += -DCONFIG_DRIVER_BSD -DRV_OBJS += ../src/drivers/driver_bsd.o -CONFIG_L2_FREEBSD=y -CONFIG_DNET_PCAP=y -endif - -ifdef CONFIG_DRIVER_TEST -DRV_CFLAGS += -DCONFIG_DRIVER_TEST -DRV_OBJS += ../src/drivers/driver_test.o -NEED_AP_MLME=y -endif - -ifdef CONFIG_DRIVER_NONE -DRV_CFLAGS += -DCONFIG_DRIVER_NONE -DRV_OBJS += ../src/drivers/driver_none.o -endif - -##### PURE AP DRIVERS - -ifdef CONFIG_DRIVER_ATHEROS -DRV_AP_CFLAGS += -DCONFIG_DRIVER_ATHEROS -DRV_AP_OBJS += ../src/drivers/driver_atheros.o -CONFIG_L2_PACKET=linux -NEED_NETLINK=y -NEED_LINUX_IOCTL=y -endif - -ifdef CONFIG_DRIVER_RTW -#CFLAGS += -DCONFIG_DRIVER_RTL -#OBJS += driver_rtl.o -DRV_AP_CFLAGS += -DCONFIG_DRIVER_RTW -DRV_AP_OBJS += ../src/drivers/driver_rtw.o -CONFIG_L2_PACKET=linux -NEED_NETLINK=y -NEED_LINUX_IOCTL=y -NEED_AP_MLME=y -endif - -##### PURE CLIENT DRIVERS - -ifdef CONFIG_DRIVER_WEXT -DRV_WPA_CFLAGS += -DCONFIG_DRIVER_WEXT -CONFIG_WIRELESS_EXTENSION=y -NEED_NETLINK=y -NEED_LINUX_IOCTL=y -NEED_RFKILL=y -endif - -ifdef CONFIG_DRIVER_RALINK -DRV_WPA_CFLAGS += -DCONFIG_DRIVER_RALINK -DRV_WPA_OBJS += ../src/drivers/driver_ralink.o -NEED_NETLINK=y -NEED_LINUX_IOCTL=y -endif - -ifdef CONFIG_DRIVER_BROADCOM -DRV_WPA_CFLAGS += -DCONFIG_DRIVER_BROADCOM -DRV_WPA_OBJS += ../src/drivers/driver_broadcom.o -endif - -ifdef CONFIG_DRIVER_NDIS -DRV_WPA_CFLAGS += -DCONFIG_DRIVER_NDIS -DRV_WPA_OBJS += ../src/drivers/driver_ndis.o -ifdef CONFIG_NDIS_EVENTS_INTEGRATED -DRV_WPA_OBJS += ../src/drivers/driver_ndis_.o -endif -ifndef CONFIG_L2_PACKET -CONFIG_L2_PACKET=pcap -endif -CONFIG_WINPCAP=y -ifdef CONFIG_USE_NDISUIO -DRV_WPA_CFLAGS += -DCONFIG_USE_NDISUIO -endif -endif - -ifdef CONFIG_DRIVER_OSX -DRV_WPA_CFLAGS += -DCONFIG_DRIVER_OSX -DRV_WPA_OBJS += ../src/drivers/driver_osx.o -DRV_WPA_LDFLAGS += -framework CoreFoundation -DRV_WPA_LDFLAGS += -F/System/Library/PrivateFrameworks -framework Apple80211 -endif - -ifdef CONFIG_DRIVER_IPHONE -DRV_WPA_CFLAGS += -DCONFIG_DRIVER_IPHONE -DRV_WPA_OBJS += ../src/drivers/driver_iphone.o -DRV_WPA_OBJS += ../src/drivers/MobileApple80211.o -DRV_WPA_LDFLAGS += -framework CoreFoundation -endif - -ifdef CONFIG_DRIVER_ROBOSWITCH -DRV_WPA_CFLAGS += -DCONFIG_DRIVER_ROBOSWITCH -DRV_WPA_OBJS += ../src/drivers/driver_roboswitch.o -endif - -ifdef CONFIG_WIRELESS_EXTENSION -DRV_WPA_CFLAGS += -DCONFIG_WIRELESS_EXTENSION -DRV_WPA_OBJS += ../src/drivers/driver_wext.o -NEED_RFKILL=y -endif - -ifdef NEED_NETLINK -DRV_OBJS += ../src/drivers/netlink.o -endif - -ifdef NEED_LINUX_IOCTL -DRV_OBJS += ../src/drivers/linux_ioctl.o -endif - -ifdef NEED_RFKILL -DRV_OBJS += ../src/drivers/rfkill.o -endif - - -##### COMMON VARS -DRV_BOTH_CFLAGS := $(DRV_CFLAGS) $(DRV_WPA_CFLAGS) $(DRV_AP_CFLAGS) -DRV_WPA_CFLAGS += $(DRV_CFLAGS) -DRV_AP_CFLAGS += $(DRV_CFLAGS) - -DRV_BOTH_LIBS := $(DRV_LIBS) $(DRV_WPA_LIBS) $(DRV_AP_LIBS) -DRV_WPA_LIBS += $(DRV_LIBS) -DRV_AP_LIBS += $(DRV_LIBS) - -DRV_BOTH_OBJS := $(DRV_OBJS) $(DRV_WPA_OBJS) $(DRV_AP_OBJS) -DRV_WPA_OBJS += $(DRV_OBJS) -DRV_AP_OBJS += $(DRV_OBJS) - -DRV_BOTH_LDFLAGS := $(DRV_LDFLAGS) $(DRV_WPA_LDFLAGS) $(DRV_AP_LDFLAGS) -DRV_WPA_LDFLAGS += $(DRV_LDFLAGS) -DRV_AP_LDFLAGS += $(DRV_LDFLAGS) diff --git a/hostapd-0.8/src/drivers/drivers.mk b/hostapd-0.8/src/drivers/drivers.mk deleted file mode 100644 index c690e1c..0000000 --- a/hostapd-0.8/src/drivers/drivers.mk +++ /dev/null @@ -1,183 +0,0 @@ -##### CLEAR VARS - -DRV_CFLAGS = -DRV_WPA_CFLAGS = -DRV_AP_CFLAGS = -DRV_OBJS = -DRV_WPA_OBJS = -DRV_AP_OBJS = -DRV_LIBS = -DRV_WPA_LIBS = -DRV_AP_LIBS = - -##### COMMON DRIVERS - -ifdef CONFIG_DRIVER_HOSTAP -DRV_CFLAGS += -DCONFIG_DRIVER_HOSTAP -DRV_OBJS += src/drivers/driver_hostap.c -CONFIG_WIRELESS_EXTENSION=y -NEED_AP_MLME=y -NEED_NETLINK=y -NEED_LINUX_IOCTL=y -endif - -ifdef CONFIG_DRIVER_WIRED -DRV_CFLAGS += -DCONFIG_DRIVER_WIRED -DRV_OBJS += src/drivers/driver_wired.c -endif - -ifdef CONFIG_DRIVER_MADWIFI -DRV_CFLAGS += -DCONFIG_DRIVER_MADWIFI -DRV_OBJS += src/drivers/driver_madwifi.c -CONFIG_WIRELESS_EXTENSION=y -CONFIG_L2_PACKET=linux -NEED_NETLINK=y -NEED_LINUX_IOCTL=y -endif - -ifdef CONFIG_DRIVER_NL80211 -DRV_CFLAGS += -DCONFIG_DRIVER_NL80211 -DRV_OBJS += src/drivers/driver_nl80211.c -DRV_OBJS += src/utils/radiotap.c -NEED_SME=y -NEED_AP_MLME=y -NEED_NETLINK=y -NEED_LINUX_IOCTL=y -NEED_RFKILL=y -ifdef CONFIG_LIBNL_TINY -DRV_LIBS += -lnl-tiny -else -DRV_LIBS += -lnl -endif - -ifdef CONFIG_LIBNL20 -DRV_LIBS += -lnl-genl -DRV_CFLAGS += -DCONFIG_LIBNL20 -endif -endif - -ifdef CONFIG_DRIVER_BSD -ifndef CONFIG_L2_PACKET -CONFIG_L2_PACKET=freebsd -endif -DRV_CFLAGS += -DCONFIG_DRIVER_BSD -DRV_OBJS += src/drivers/driver_bsd.c -CONFIG_L2_FREEBSD=y -CONFIG_DNET_PCAP=y -endif - -ifdef CONFIG_DRIVER_TEST -DRV_CFLAGS += -DCONFIG_DRIVER_TEST -DRV_OBJS += src/drivers/driver_test.c -NEED_AP_MLME=y -endif - -ifdef CONFIG_DRIVER_NONE -DRV_CFLAGS += -DCONFIG_DRIVER_NONE -DRV_OBJS += src/drivers/driver_none.c -endif - -##### PURE AP DRIVERS - -ifdef CONFIG_DRIVER_ATHEROS -DRV_AP_CFLAGS += -DCONFIG_DRIVER_ATHEROS -DRV_AP_OBJS += src/drivers/driver_atheros.c -CONFIG_L2_PACKET=linux -NEED_NETLINK=y -NEED_LINUX_IOCTL=y -endif - -##### PURE CLIENT DRIVERS - -ifdef CONFIG_DRIVER_WEXT -DRV_WPA_CFLAGS += -DCONFIG_DRIVER_WEXT -CONFIG_WIRELESS_EXTENSION=y -NEED_NETLINK=y -NEED_LINUX_IOCTL=y -NEED_RFKILL=y -endif - -ifdef CONFIG_DRIVER_RALINK -DRV_WPA_CFLAGS += -DCONFIG_DRIVER_RALINK -DRV_WPA_OBJS += src/drivers/driver_ralink.c -NEED_NETLINK=y -NEED_LINUX_IOCTL=y -endif - -ifdef CONFIG_DRIVER_BROADCOM -DRV_WPA_CFLAGS += -DCONFIG_DRIVER_BROADCOM -DRV_WPA_OBJS += src/drivers/driver_broadcom.c -endif - -ifdef CONFIG_DRIVER_NDIS -DRV_WPA_CFLAGS += -DCONFIG_DRIVER_NDIS -DRV_WPA_OBJS += src/drivers/driver_ndis.c -ifdef CONFIG_NDIS_EVENTS_INTEGRATED -DRV_WPA_OBJS += src/drivers/driver_ndis_.c -endif -ifndef CONFIG_L2_PACKET -CONFIG_L2_PACKET=pcap -endif -CONFIG_WINPCAP=y -ifdef CONFIG_USE_NDISUIO -DRV_WPA_CFLAGS += -DCONFIG_USE_NDISUIO -endif -endif - -ifdef CONFIG_DRIVER_OSX -DRV_WPA_CFLAGS += -DCONFIG_DRIVER_OSX -DRV_WPA_OBJS += src/drivers/driver_osx.c -DRV_WPA_LDFLAGS += -framework CoreFoundation -DRV_WPA_LDFLAGS += -F/System/Library/PrivateFrameworks -framework Apple80211 -endif - -ifdef CONFIG_DRIVER_IPHONE -DRV_WPA_CFLAGS += -DCONFIG_DRIVER_IPHONE -DRV_WPA_OBJS += src/drivers/driver_iphone.c -DRV_WPA_OBJS += src/drivers/MobileApple80211.c -DRV_WPA_LDFLAGS += -framework CoreFoundation -endif - -ifdef CONFIG_DRIVER_ROBOSWITCH -DRV_WPA_CFLAGS += -DCONFIG_DRIVER_ROBOSWITCH -DRV_WPA_OBJS += src/drivers/driver_roboswitch.c -endif - -ifdef CONFIG_WIRELESS_EXTENSION -DRV_WPA_CFLAGS += -DCONFIG_WIRELESS_EXTENSION -DRV_WPA_OBJS += src/drivers/driver_wext.c -NEED_RFKILL=y -endif - -ifdef NEED_NETLINK -DRV_OBJS += src/drivers/netlink.c -endif - -ifdef NEED_LINUX_IOCTL -DRV_OBJS += src/drivers/linux_ioctl.c -endif - -ifdef NEED_RFKILL -DRV_OBJS += src/drivers/rfkill.c -endif - -ifdef CONFIG_DRIVER_CUSTOM -DRV_CFLAGS += -DCONFIG_DRIVER_CUSTOM -endif - -##### COMMON VARS -DRV_BOTH_CFLAGS := $(DRV_CFLAGS) $(DRV_WPA_CFLAGS) $(DRV_AP_CFLAGS) -DRV_WPA_CFLAGS += $(DRV_CFLAGS) -DRV_AP_CFLAGS += $(DRV_CFLAGS) - -DRV_BOTH_LIBS := $(DRV_LIBS) $(DRV_WPA_LIBS) $(DRV_AP_LIBS) -DRV_WPA_LIBS += $(DRV_LIBS) -DRV_AP_LIBS += $(DRV_LIBS) - -DRV_BOTH_OBJS := $(DRV_OBJS) $(DRV_WPA_OBJS) $(DRV_AP_OBJS) -DRV_WPA_OBJS += $(DRV_OBJS) -DRV_AP_OBJS += $(DRV_OBJS) - -DRV_BOTH_LDFLAGS := $(DRV_LDFLAGS) $(DRV_WPA_LDFLAGS) $(DRV_AP_LDFLAGS) -DRV_WPA_LDFLAGS += $(DRV_LDFLAGS) -DRV_AP_LDFLAGS += $(DRV_LDFLAGS) diff --git a/hostapd-0.8/src/drivers/linux_ioctl.c b/hostapd-0.8/src/drivers/linux_ioctl.c deleted file mode 100644 index 0d6cf54..0000000 --- a/hostapd-0.8/src/drivers/linux_ioctl.c +++ /dev/null @@ -1,198 +0,0 @@ -/* - * Linux ioctl helper functions for driver wrappers - * Copyright (c) 2002-2010, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#include "utils/includes.h" -#include -#include -#include - -#include "utils/common.h" -#include "linux_ioctl.h" - - -int linux_set_iface_flags(int sock, const char *ifname, int dev_up) -{ - struct ifreq ifr; - - if (sock < 0) - return -1; - - os_memset(&ifr, 0, sizeof(ifr)); - os_strlcpy(ifr.ifr_name, ifname, IFNAMSIZ); - - if (ioctl(sock, SIOCGIFFLAGS, &ifr) != 0) { - wpa_printf(MSG_ERROR, "Could not read interface %s flags: %s", - ifname, strerror(errno)); - return -1; - } - - if (dev_up) { - if (ifr.ifr_flags & IFF_UP) - return 0; - ifr.ifr_flags |= IFF_UP; - } else { - if (!(ifr.ifr_flags & IFF_UP)) - return 0; - ifr.ifr_flags &= ~IFF_UP; - } - - if (ioctl(sock, SIOCSIFFLAGS, &ifr) != 0) { - wpa_printf(MSG_ERROR, "Could not set interface %s flags: %s", - ifname, strerror(errno)); - return -1; - } - - return 0; -} - - -int linux_get_ifhwaddr(int sock, const char *ifname, u8 *addr) -{ - struct ifreq ifr; - - os_memset(&ifr, 0, sizeof(ifr)); - os_strlcpy(ifr.ifr_name, ifname, IFNAMSIZ); - if (ioctl(sock, SIOCGIFHWADDR, &ifr)) { - wpa_printf(MSG_ERROR, "Could not get interface %s hwaddr: %s", - ifname, strerror(errno)); - return -1; - } - - if (ifr.ifr_hwaddr.sa_family != ARPHRD_ETHER) { - wpa_printf(MSG_ERROR, "%s: Invalid HW-addr family 0x%04x", - ifname, ifr.ifr_hwaddr.sa_family); - return -1; - } - os_memcpy(addr, ifr.ifr_hwaddr.sa_data, ETH_ALEN); - - return 0; -} - - -int linux_set_ifhwaddr(int sock, const char *ifname, const u8 *addr) -{ - struct ifreq ifr; - - os_memset(&ifr, 0, sizeof(ifr)); - os_strlcpy(ifr.ifr_name, ifname, IFNAMSIZ); - os_memcpy(ifr.ifr_hwaddr.sa_data, addr, ETH_ALEN); - ifr.ifr_hwaddr.sa_family = ARPHRD_ETHER; - - if (ioctl(sock, SIOCSIFHWADDR, &ifr)) { - wpa_printf(MSG_DEBUG, "Could not set interface %s hwaddr: %s", - ifname, strerror(errno)); - return -1; - } - - return 0; -} - - -#ifndef SIOCBRADDBR -#define SIOCBRADDBR 0x89a0 -#endif -#ifndef SIOCBRDELBR -#define SIOCBRDELBR 0x89a1 -#endif -#ifndef SIOCBRADDIF -#define SIOCBRADDIF 0x89a2 -#endif -#ifndef SIOCBRDELIF -#define SIOCBRDELIF 0x89a3 -#endif - - -int linux_br_add(int sock, const char *brname) -{ - if (ioctl(sock, SIOCBRADDBR, brname) < 0) { - wpa_printf(MSG_DEBUG, "Could not add bridge %s: %s", - brname, strerror(errno)); - return -1; - } - - return 0; -} - - -int linux_br_del(int sock, const char *brname) -{ - if (ioctl(sock, SIOCBRDELBR, brname) < 0) { - wpa_printf(MSG_DEBUG, "Could not remove bridge %s: %s", - brname, strerror(errno)); - return -1; - } - - return 0; -} - - -int linux_br_add_if(int sock, const char *brname, const char *ifname) -{ - struct ifreq ifr; - int ifindex; - - ifindex = if_nametoindex(ifname); - if (ifindex == 0) - return -1; - - os_memset(&ifr, 0, sizeof(ifr)); - os_strlcpy(ifr.ifr_name, brname, IFNAMSIZ); - ifr.ifr_ifindex = ifindex; - if (ioctl(sock, SIOCBRADDIF, &ifr) < 0) { - wpa_printf(MSG_DEBUG, "Could not add interface %s into bridge " - "%s: %s", ifname, brname, strerror(errno)); - return -1; - } - - return 0; -} - - -int linux_br_del_if(int sock, const char *brname, const char *ifname) -{ - struct ifreq ifr; - int ifindex; - - ifindex = if_nametoindex(ifname); - if (ifindex == 0) - return -1; - - os_memset(&ifr, 0, sizeof(ifr)); - os_strlcpy(ifr.ifr_name, brname, IFNAMSIZ); - ifr.ifr_ifindex = ifindex; - if (ioctl(sock, SIOCBRDELIF, &ifr) < 0) { - wpa_printf(MSG_DEBUG, "Could not remove interface %s from " - "bridge %s: %s", ifname, brname, strerror(errno)); - return -1; - } - - return 0; -} - - -int linux_br_get(char *brname, const char *ifname) -{ - char path[128], brlink[128], *pos; - os_snprintf(path, sizeof(path), "/sys/class/net/%s/brport/bridge", - ifname); - os_memset(brlink, 0, sizeof(brlink)); - if (readlink(path, brlink, sizeof(brlink) - 1) < 0) - return -1; - pos = os_strrchr(brlink, '/'); - if (pos == NULL) - return -1; - pos++; - os_strlcpy(brname, pos, IFNAMSIZ); - return 0; -} diff --git a/hostapd-0.8/src/drivers/linux_ioctl.h b/hostapd-0.8/src/drivers/linux_ioctl.h deleted file mode 100644 index a555738..0000000 --- a/hostapd-0.8/src/drivers/linux_ioctl.h +++ /dev/null @@ -1,27 +0,0 @@ -/* - * Linux ioctl helper functions for driver wrappers - * Copyright (c) 2002-2010, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#ifndef LINUX_IOCTL_H -#define LINUX_IOCTL_H - -int linux_set_iface_flags(int sock, const char *ifname, int dev_up); -int linux_get_ifhwaddr(int sock, const char *ifname, u8 *addr); -int linux_set_ifhwaddr(int sock, const char *ifname, const u8 *addr); -int linux_br_add(int sock, const char *brname); -int linux_br_del(int sock, const char *brname); -int linux_br_add_if(int sock, const char *brname, const char *ifname); -int linux_br_del_if(int sock, const char *brname, const char *ifname); -int linux_br_get(char *brname, const char *ifname); - -#endif /* LINUX_IOCTL_H */ diff --git a/hostapd-0.8/src/drivers/ndis_events.c b/hostapd-0.8/src/drivers/ndis_events.c deleted file mode 100644 index f6eaa7c..0000000 --- a/hostapd-0.8/src/drivers/ndis_events.c +++ /dev/null @@ -1,808 +0,0 @@ -/* - * ndis_events - Receive NdisMIndicateStatus() events using WMI - * Copyright (c) 2004-2006, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#define _WIN32_WINNT 0x0400 - -#include "includes.h" - -#ifndef COBJMACROS -#define COBJMACROS -#endif /* COBJMACROS */ -#include - -#include "common.h" - - -static int wmi_refcnt = 0; -static int wmi_first = 1; - -struct ndis_events_data { - IWbemObjectSink sink; - IWbemObjectSinkVtbl sink_vtbl; - - IWbemServices *pSvc; - IWbemLocator *pLoc; - - HANDLE read_pipe, write_pipe, event_avail; - UINT ref; - int terminating; - char *ifname; /* {GUID..} */ - WCHAR *adapter_desc; -}; - -#define BstrAlloc(x) (x) ? SysAllocString(x) : NULL -#define BstrFree(x) if (x) SysFreeString(x) - -/* WBEM / WMI wrapper functions, to perform in-place conversion of WCHARs to - * BSTRs */ -HRESULT STDMETHODCALLTYPE call_IWbemServices_ExecQuery( - IWbemServices *pSvc, LPCWSTR strQueryLanguage, LPCWSTR strQuery, - long lFlags, IWbemContext *pCtx, IEnumWbemClassObject **ppEnum) -{ - BSTR bsQueryLanguage, bsQuery; - HRESULT hr; - - bsQueryLanguage = BstrAlloc(strQueryLanguage); - bsQuery = BstrAlloc(strQuery); - - hr = IWbemServices_ExecQuery(pSvc, bsQueryLanguage, bsQuery, lFlags, - pCtx, ppEnum); - - BstrFree(bsQueryLanguage); - BstrFree(bsQuery); - - return hr; -} - - -HRESULT STDMETHODCALLTYPE call_IWbemServices_ExecNotificationQueryAsync( - IWbemServices *pSvc, LPCWSTR strQueryLanguage, LPCWSTR strQuery, - long lFlags, IWbemContext *pCtx, IWbemObjectSink *pResponseHandler) -{ - BSTR bsQueryLanguage, bsQuery; - HRESULT hr; - - bsQueryLanguage = BstrAlloc(strQueryLanguage); - bsQuery = BstrAlloc(strQuery); - - hr = IWbemServices_ExecNotificationQueryAsync(pSvc, bsQueryLanguage, - bsQuery, lFlags, pCtx, - pResponseHandler); - - BstrFree(bsQueryLanguage); - BstrFree(bsQuery); - - return hr; -} - - -HRESULT STDMETHODCALLTYPE call_IWbemLocator_ConnectServer( - IWbemLocator *pLoc, LPCWSTR strNetworkResource, LPCWSTR strUser, - LPCWSTR strPassword, LPCWSTR strLocale, long lSecurityFlags, - LPCWSTR strAuthority, IWbemContext *pCtx, IWbemServices **ppNamespace) -{ - BSTR bsNetworkResource, bsUser, bsPassword, bsLocale, bsAuthority; - HRESULT hr; - - bsNetworkResource = BstrAlloc(strNetworkResource); - bsUser = BstrAlloc(strUser); - bsPassword = BstrAlloc(strPassword); - bsLocale = BstrAlloc(strLocale); - bsAuthority = BstrAlloc(strAuthority); - - hr = IWbemLocator_ConnectServer(pLoc, bsNetworkResource, bsUser, - bsPassword, bsLocale, lSecurityFlags, - bsAuthority, pCtx, ppNamespace); - - BstrFree(bsNetworkResource); - BstrFree(bsUser); - BstrFree(bsPassword); - BstrFree(bsLocale); - BstrFree(bsAuthority); - - return hr; -} - - -enum event_types { EVENT_CONNECT, EVENT_DISCONNECT, EVENT_MEDIA_SPECIFIC, - EVENT_ADAPTER_ARRIVAL, EVENT_ADAPTER_REMOVAL }; - -static int ndis_events_get_adapter(struct ndis_events_data *events, - const char *ifname, const char *desc); - - -static int ndis_events_constructor(struct ndis_events_data *events) -{ - events->ref = 1; - - if (!CreatePipe(&events->read_pipe, &events->write_pipe, NULL, 512)) { - wpa_printf(MSG_ERROR, "CreatePipe() failed: %d", - (int) GetLastError()); - return -1; - } - events->event_avail = CreateEvent(NULL, TRUE, FALSE, NULL); - if (events->event_avail == NULL) { - wpa_printf(MSG_ERROR, "CreateEvent() failed: %d", - (int) GetLastError()); - CloseHandle(events->read_pipe); - CloseHandle(events->write_pipe); - return -1; - } - - return 0; -} - - -static void ndis_events_destructor(struct ndis_events_data *events) -{ - CloseHandle(events->read_pipe); - CloseHandle(events->write_pipe); - CloseHandle(events->event_avail); - IWbemServices_Release(events->pSvc); - IWbemLocator_Release(events->pLoc); - if (--wmi_refcnt == 0) - CoUninitialize(); -} - - -static HRESULT STDMETHODCALLTYPE -ndis_events_query_interface(IWbemObjectSink *this, REFIID riid, void **obj) -{ - *obj = NULL; - - if (IsEqualIID(riid, &IID_IUnknown) || - IsEqualIID(riid, &IID_IWbemObjectSink)) { - *obj = this; - IWbemObjectSink_AddRef(this); - return NOERROR; - } - - return E_NOINTERFACE; -} - - -static ULONG STDMETHODCALLTYPE ndis_events_add_ref(IWbemObjectSink *this) -{ - struct ndis_events_data *events = (struct ndis_events_data *) this; - return ++events->ref; -} - - -static ULONG STDMETHODCALLTYPE ndis_events_release(IWbemObjectSink *this) -{ - struct ndis_events_data *events = (struct ndis_events_data *) this; - - if (--events->ref != 0) - return events->ref; - - ndis_events_destructor(events); - wpa_printf(MSG_DEBUG, "ndis_events: terminated"); - os_free(events->adapter_desc); - os_free(events->ifname); - os_free(events); - return 0; -} - - -static int ndis_events_send_event(struct ndis_events_data *events, - enum event_types type, - char *data, size_t data_len) -{ - char buf[512], *pos, *end; - int _type; - DWORD written; - - end = buf + sizeof(buf); - _type = (int) type; - os_memcpy(buf, &_type, sizeof(_type)); - pos = buf + sizeof(_type); - - if (data) { - if (2 + data_len > (size_t) (end - pos)) { - wpa_printf(MSG_DEBUG, "Not enough room for send_event " - "data (%d)", data_len); - return -1; - } - *pos++ = data_len >> 8; - *pos++ = data_len & 0xff; - os_memcpy(pos, data, data_len); - pos += data_len; - } - - if (WriteFile(events->write_pipe, buf, pos - buf, &written, NULL)) { - SetEvent(events->event_avail); - return 0; - } - wpa_printf(MSG_INFO, "WriteFile() failed: %d", (int) GetLastError()); - return -1; -} - - -static void ndis_events_media_connect(struct ndis_events_data *events) -{ - wpa_printf(MSG_DEBUG, "MSNdis_StatusMediaConnect"); - ndis_events_send_event(events, EVENT_CONNECT, NULL, 0); -} - - -static void ndis_events_media_disconnect(struct ndis_events_data *events) -{ - wpa_printf(MSG_DEBUG, "MSNdis_StatusMediaDisconnect"); - ndis_events_send_event(events, EVENT_DISCONNECT, NULL, 0); -} - - -static void ndis_events_media_specific(struct ndis_events_data *events, - IWbemClassObject *pObj) -{ - VARIANT vt; - HRESULT hr; - LONG lower, upper, k; - UCHAR ch; - char *data, *pos; - size_t data_len; - - wpa_printf(MSG_DEBUG, "MSNdis_StatusMediaSpecificIndication"); - - /* This is the StatusBuffer from NdisMIndicateStatus() call */ - hr = IWbemClassObject_Get(pObj, L"NdisStatusMediaSpecificIndication", - 0, &vt, NULL, NULL); - if (FAILED(hr)) { - wpa_printf(MSG_DEBUG, "Could not get " - "NdisStatusMediaSpecificIndication from " - "the object?!"); - return; - } - - SafeArrayGetLBound(V_ARRAY(&vt), 1, &lower); - SafeArrayGetUBound(V_ARRAY(&vt), 1, &upper); - data_len = upper - lower + 1; - data = os_malloc(data_len); - if (data == NULL) { - wpa_printf(MSG_DEBUG, "Failed to allocate buffer for event " - "data"); - VariantClear(&vt); - return; - } - - pos = data; - for (k = lower; k <= upper; k++) { - SafeArrayGetElement(V_ARRAY(&vt), &k, &ch); - *pos++ = ch; - } - wpa_hexdump(MSG_DEBUG, "MediaSpecificEvent", (u8 *) data, data_len); - - VariantClear(&vt); - - ndis_events_send_event(events, EVENT_MEDIA_SPECIFIC, data, data_len); - - os_free(data); -} - - -static void ndis_events_adapter_arrival(struct ndis_events_data *events) -{ - wpa_printf(MSG_DEBUG, "MSNdis_NotifyAdapterArrival"); - ndis_events_send_event(events, EVENT_ADAPTER_ARRIVAL, NULL, 0); -} - - -static void ndis_events_adapter_removal(struct ndis_events_data *events) -{ - wpa_printf(MSG_DEBUG, "MSNdis_NotifyAdapterRemoval"); - ndis_events_send_event(events, EVENT_ADAPTER_REMOVAL, NULL, 0); -} - - -static HRESULT STDMETHODCALLTYPE -ndis_events_indicate(IWbemObjectSink *this, long lObjectCount, - IWbemClassObject __RPC_FAR *__RPC_FAR *ppObjArray) -{ - struct ndis_events_data *events = (struct ndis_events_data *) this; - long i; - - if (events->terminating) { - wpa_printf(MSG_DEBUG, "ndis_events_indicate: Ignore " - "indication - terminating"); - return WBEM_NO_ERROR; - } - /* wpa_printf(MSG_DEBUG, "Notification received - %d object(s)", - lObjectCount); */ - - for (i = 0; i < lObjectCount; i++) { - IWbemClassObject *pObj = ppObjArray[i]; - HRESULT hr; - VARIANT vtClass, vt; - - hr = IWbemClassObject_Get(pObj, L"__CLASS", 0, &vtClass, NULL, - NULL); - if (FAILED(hr)) { - wpa_printf(MSG_DEBUG, "Failed to get __CLASS from " - "event."); - break; - } - /* wpa_printf(MSG_DEBUG, "CLASS: '%S'", vtClass.bstrVal); */ - - hr = IWbemClassObject_Get(pObj, L"InstanceName", 0, &vt, NULL, - NULL); - if (FAILED(hr)) { - wpa_printf(MSG_DEBUG, "Failed to get InstanceName " - "from event."); - VariantClear(&vtClass); - break; - } - - if (wcscmp(vtClass.bstrVal, - L"MSNdis_NotifyAdapterArrival") == 0) { - wpa_printf(MSG_DEBUG, "ndis_events_indicate: Try to " - "update adapter description since it may " - "have changed with new adapter instance"); - ndis_events_get_adapter(events, events->ifname, NULL); - } - - if (wcscmp(events->adapter_desc, vt.bstrVal) != 0) { - wpa_printf(MSG_DEBUG, "ndis_events_indicate: Ignore " - "indication for foreign adapter: " - "InstanceName: '%S' __CLASS: '%S'", - vt.bstrVal, vtClass.bstrVal); - VariantClear(&vtClass); - VariantClear(&vt); - continue; - } - VariantClear(&vt); - - if (wcscmp(vtClass.bstrVal, - L"MSNdis_StatusMediaSpecificIndication") == 0) { - ndis_events_media_specific(events, pObj); - } else if (wcscmp(vtClass.bstrVal, - L"MSNdis_StatusMediaConnect") == 0) { - ndis_events_media_connect(events); - } else if (wcscmp(vtClass.bstrVal, - L"MSNdis_StatusMediaDisconnect") == 0) { - ndis_events_media_disconnect(events); - } else if (wcscmp(vtClass.bstrVal, - L"MSNdis_NotifyAdapterArrival") == 0) { - ndis_events_adapter_arrival(events); - } else if (wcscmp(vtClass.bstrVal, - L"MSNdis_NotifyAdapterRemoval") == 0) { - ndis_events_adapter_removal(events); - } else { - wpa_printf(MSG_DEBUG, "Unepected event - __CLASS: " - "'%S'", vtClass.bstrVal); - } - - VariantClear(&vtClass); - } - - return WBEM_NO_ERROR; -} - - -static HRESULT STDMETHODCALLTYPE -ndis_events_set_status(IWbemObjectSink *this, long lFlags, HRESULT hResult, - BSTR strParam, IWbemClassObject __RPC_FAR *pObjParam) -{ - return WBEM_NO_ERROR; -} - - -static int notification_query(IWbemObjectSink *pDestSink, - IWbemServices *pSvc, const char *class_name) -{ - HRESULT hr; - WCHAR query[256]; - - _snwprintf(query, 256, - L"SELECT * FROM %S", class_name); - wpa_printf(MSG_DEBUG, "ndis_events: WMI: %S", query); - hr = call_IWbemServices_ExecNotificationQueryAsync( - pSvc, L"WQL", query, 0, 0, pDestSink); - if (FAILED(hr)) { - wpa_printf(MSG_DEBUG, "ExecNotificationQueryAsync for %s " - "failed with hresult of 0x%x", - class_name, (int) hr); - return -1; - } - - return 0; -} - - -static int register_async_notification(IWbemObjectSink *pDestSink, - IWbemServices *pSvc) -{ - int i; - const char *class_list[] = { - "MSNdis_StatusMediaConnect", - "MSNdis_StatusMediaDisconnect", - "MSNdis_StatusMediaSpecificIndication", - "MSNdis_NotifyAdapterArrival", - "MSNdis_NotifyAdapterRemoval", - NULL - }; - - for (i = 0; class_list[i]; i++) { - if (notification_query(pDestSink, pSvc, class_list[i]) < 0) - return -1; - } - - return 0; -} - - -void ndis_events_deinit(struct ndis_events_data *events) -{ - events->terminating = 1; - IWbemServices_CancelAsyncCall(events->pSvc, &events->sink); - IWbemObjectSink_Release(&events->sink); - /* - * Rest of deinitialization is done in ndis_events_destructor() once - * all reference count drops to zero. - */ -} - - -static int ndis_events_use_desc(struct ndis_events_data *events, - const char *desc) -{ - char *tmp, *pos; - size_t len; - - if (desc == NULL) { - if (events->adapter_desc == NULL) - return -1; - /* Continue using old description */ - return 0; - } - - tmp = os_strdup(desc); - if (tmp == NULL) - return -1; - - pos = os_strstr(tmp, " (Microsoft's Packet Scheduler)"); - if (pos) - *pos = '\0'; - - len = os_strlen(tmp); - events->adapter_desc = os_malloc((len + 1) * sizeof(WCHAR)); - if (events->adapter_desc == NULL) { - os_free(tmp); - return -1; - } - _snwprintf(events->adapter_desc, len + 1, L"%S", tmp); - os_free(tmp); - return 0; -} - - -static int ndis_events_get_adapter(struct ndis_events_data *events, - const char *ifname, const char *desc) -{ - HRESULT hr; - IWbemServices *pSvc; -#define MAX_QUERY_LEN 256 - WCHAR query[MAX_QUERY_LEN]; - IEnumWbemClassObject *pEnumerator; - IWbemClassObject *pObj; - ULONG uReturned; - VARIANT vt; - int len, pos; - - /* - * Try to get adapter descriptor through WMI CIMv2 Win32_NetworkAdapter - * to have better probability of matching with InstanceName from - * MSNdis events. If this fails, use the provided description. - */ - - os_free(events->adapter_desc); - events->adapter_desc = NULL; - - hr = call_IWbemLocator_ConnectServer( - events->pLoc, L"ROOT\\CIMV2", NULL, NULL, 0, 0, 0, 0, &pSvc); - if (FAILED(hr)) { - wpa_printf(MSG_ERROR, "ndis_events: Could not connect to WMI " - "server (ROOT\\CIMV2) - error 0x%x", (int) hr); - return ndis_events_use_desc(events, desc); - } - wpa_printf(MSG_DEBUG, "ndis_events: Connected to ROOT\\CIMV2."); - - _snwprintf(query, MAX_QUERY_LEN, - L"SELECT Index FROM Win32_NetworkAdapterConfiguration " - L"WHERE SettingID='%S'", ifname); - wpa_printf(MSG_DEBUG, "ndis_events: WMI: %S", query); - - hr = call_IWbemServices_ExecQuery( - pSvc, L"WQL", query, - WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY, - NULL, &pEnumerator); - if (!SUCCEEDED(hr)) { - wpa_printf(MSG_DEBUG, "ndis_events: Failed to query interface " - "GUID from Win32_NetworkAdapterConfiguration: " - "0x%x", (int) hr); - IWbemServices_Release(pSvc); - return ndis_events_use_desc(events, desc); - } - - uReturned = 0; - hr = IEnumWbemClassObject_Next(pEnumerator, WBEM_INFINITE, 1, - &pObj, &uReturned); - if (!SUCCEEDED(hr) || uReturned == 0) { - wpa_printf(MSG_DEBUG, "ndis_events: Failed to find interface " - "GUID from Win32_NetworkAdapterConfiguration: " - "0x%x", (int) hr); - IEnumWbemClassObject_Release(pEnumerator); - IWbemServices_Release(pSvc); - return ndis_events_use_desc(events, desc); - } - IEnumWbemClassObject_Release(pEnumerator); - - VariantInit(&vt); - hr = IWbemClassObject_Get(pObj, L"Index", 0, &vt, NULL, NULL); - if (!SUCCEEDED(hr)) { - wpa_printf(MSG_DEBUG, "ndis_events: Failed to get Index from " - "Win32_NetworkAdapterConfiguration: 0x%x", - (int) hr); - IWbemServices_Release(pSvc); - return ndis_events_use_desc(events, desc); - } - - _snwprintf(query, MAX_QUERY_LEN, - L"SELECT Name,PNPDeviceID FROM Win32_NetworkAdapter WHERE " - L"Index=%d", - vt.uintVal); - wpa_printf(MSG_DEBUG, "ndis_events: WMI: %S", query); - VariantClear(&vt); - IWbemClassObject_Release(pObj); - - hr = call_IWbemServices_ExecQuery( - pSvc, L"WQL", query, - WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY, - NULL, &pEnumerator); - if (!SUCCEEDED(hr)) { - wpa_printf(MSG_DEBUG, "ndis_events: Failed to query interface " - "from Win32_NetworkAdapter: 0x%x", (int) hr); - IWbemServices_Release(pSvc); - return ndis_events_use_desc(events, desc); - } - - uReturned = 0; - hr = IEnumWbemClassObject_Next(pEnumerator, WBEM_INFINITE, 1, - &pObj, &uReturned); - if (!SUCCEEDED(hr) || uReturned == 0) { - wpa_printf(MSG_DEBUG, "ndis_events: Failed to find interface " - "from Win32_NetworkAdapter: 0x%x", (int) hr); - IEnumWbemClassObject_Release(pEnumerator); - IWbemServices_Release(pSvc); - return ndis_events_use_desc(events, desc); - } - IEnumWbemClassObject_Release(pEnumerator); - - hr = IWbemClassObject_Get(pObj, L"Name", 0, &vt, NULL, NULL); - if (!SUCCEEDED(hr)) { - wpa_printf(MSG_DEBUG, "ndis_events: Failed to get Name from " - "Win32_NetworkAdapter: 0x%x", (int) hr); - IWbemClassObject_Release(pObj); - IWbemServices_Release(pSvc); - return ndis_events_use_desc(events, desc); - } - - wpa_printf(MSG_DEBUG, "ndis_events: Win32_NetworkAdapter::Name='%S'", - vt.bstrVal); - events->adapter_desc = _wcsdup(vt.bstrVal); - VariantClear(&vt); - - /* - * Try to get even better candidate for matching with InstanceName - * from Win32_PnPEntity. This is needed at least for some USB cards - * that can change the InstanceName whenever being unplugged and - * plugged again. - */ - - hr = IWbemClassObject_Get(pObj, L"PNPDeviceID", 0, &vt, NULL, NULL); - if (!SUCCEEDED(hr)) { - wpa_printf(MSG_DEBUG, "ndis_events: Failed to get PNPDeviceID " - "from Win32_NetworkAdapter: 0x%x", (int) hr); - IWbemClassObject_Release(pObj); - IWbemServices_Release(pSvc); - if (events->adapter_desc == NULL) - return ndis_events_use_desc(events, desc); - return 0; /* use Win32_NetworkAdapter::Name */ - } - - wpa_printf(MSG_DEBUG, "ndis_events: Win32_NetworkAdapter::PNPDeviceID=" - "'%S'", vt.bstrVal); - - len = _snwprintf(query, MAX_QUERY_LEN, - L"SELECT Name FROM Win32_PnPEntity WHERE DeviceID='"); - if (len < 0 || len >= MAX_QUERY_LEN - 1) { - VariantClear(&vt); - IWbemClassObject_Release(pObj); - IWbemServices_Release(pSvc); - if (events->adapter_desc == NULL) - return ndis_events_use_desc(events, desc); - return 0; /* use Win32_NetworkAdapter::Name */ - } - - /* Escape \ as \\ */ - for (pos = 0; vt.bstrVal[pos] && len < MAX_QUERY_LEN - 2; pos++) { - if (vt.bstrVal[pos] == '\\') { - if (len >= MAX_QUERY_LEN - 3) - break; - query[len++] = '\\'; - } - query[len++] = vt.bstrVal[pos]; - } - query[len++] = L'\''; - query[len] = L'\0'; - VariantClear(&vt); - IWbemClassObject_Release(pObj); - wpa_printf(MSG_DEBUG, "ndis_events: WMI: %S", query); - - hr = call_IWbemServices_ExecQuery( - pSvc, L"WQL", query, - WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY, - NULL, &pEnumerator); - if (!SUCCEEDED(hr)) { - wpa_printf(MSG_DEBUG, "ndis_events: Failed to query interface " - "Name from Win32_PnPEntity: 0x%x", (int) hr); - IWbemServices_Release(pSvc); - if (events->adapter_desc == NULL) - return ndis_events_use_desc(events, desc); - return 0; /* use Win32_NetworkAdapter::Name */ - } - - uReturned = 0; - hr = IEnumWbemClassObject_Next(pEnumerator, WBEM_INFINITE, 1, - &pObj, &uReturned); - if (!SUCCEEDED(hr) || uReturned == 0) { - wpa_printf(MSG_DEBUG, "ndis_events: Failed to find interface " - "from Win32_PnPEntity: 0x%x", (int) hr); - IEnumWbemClassObject_Release(pEnumerator); - IWbemServices_Release(pSvc); - if (events->adapter_desc == NULL) - return ndis_events_use_desc(events, desc); - return 0; /* use Win32_NetworkAdapter::Name */ - } - IEnumWbemClassObject_Release(pEnumerator); - - hr = IWbemClassObject_Get(pObj, L"Name", 0, &vt, NULL, NULL); - if (!SUCCEEDED(hr)) { - wpa_printf(MSG_DEBUG, "ndis_events: Failed to get Name from " - "Win32_PnPEntity: 0x%x", (int) hr); - IWbemClassObject_Release(pObj); - IWbemServices_Release(pSvc); - if (events->adapter_desc == NULL) - return ndis_events_use_desc(events, desc); - return 0; /* use Win32_NetworkAdapter::Name */ - } - - wpa_printf(MSG_DEBUG, "ndis_events: Win32_PnPEntity::Name='%S'", - vt.bstrVal); - os_free(events->adapter_desc); - events->adapter_desc = _wcsdup(vt.bstrVal); - VariantClear(&vt); - - IWbemClassObject_Release(pObj); - - IWbemServices_Release(pSvc); - - if (events->adapter_desc == NULL) - return ndis_events_use_desc(events, desc); - - return 0; -} - - -struct ndis_events_data * -ndis_events_init(HANDLE *read_pipe, HANDLE *event_avail, - const char *ifname, const char *desc) -{ - HRESULT hr; - IWbemObjectSink *pSink; - struct ndis_events_data *events; - - events = os_zalloc(sizeof(*events)); - if (events == NULL) { - wpa_printf(MSG_ERROR, "Could not allocate sink for events."); - return NULL; - } - events->ifname = os_strdup(ifname); - if (events->ifname == NULL) { - os_free(events); - return NULL; - } - - if (wmi_refcnt++ == 0) { - hr = CoInitializeEx(0, COINIT_MULTITHREADED); - if (FAILED(hr)) { - wpa_printf(MSG_ERROR, "CoInitializeEx() failed - " - "returned 0x%x", (int) hr); - os_free(events); - return NULL; - } - } - - if (wmi_first) { - /* CoInitializeSecurity() must be called once and only once - * per process, so let's use wmi_first flag to protect against - * multiple calls. */ - wmi_first = 0; - - hr = CoInitializeSecurity(NULL, -1, NULL, NULL, - RPC_C_AUTHN_LEVEL_PKT_PRIVACY, - RPC_C_IMP_LEVEL_IMPERSONATE, - NULL, EOAC_SECURE_REFS, NULL); - if (FAILED(hr)) { - wpa_printf(MSG_ERROR, "CoInitializeSecurity() failed " - "- returned 0x%x", (int) hr); - os_free(events); - return NULL; - } - } - - hr = CoCreateInstance(&CLSID_WbemLocator, 0, CLSCTX_INPROC_SERVER, - &IID_IWbemLocator, - (LPVOID *) (void *) &events->pLoc); - if (FAILED(hr)) { - wpa_printf(MSG_ERROR, "CoCreateInstance() failed - returned " - "0x%x", (int) hr); - CoUninitialize(); - os_free(events); - return NULL; - } - - if (ndis_events_get_adapter(events, ifname, desc) < 0) { - CoUninitialize(); - os_free(events); - return NULL; - } - wpa_printf(MSG_DEBUG, "ndis_events: use adapter descriptor '%S'", - events->adapter_desc); - - hr = call_IWbemLocator_ConnectServer( - events->pLoc, L"ROOT\\WMI", NULL, NULL, - 0, 0, 0, 0, &events->pSvc); - if (FAILED(hr)) { - wpa_printf(MSG_ERROR, "Could not connect to server - error " - "0x%x", (int) hr); - CoUninitialize(); - os_free(events->adapter_desc); - os_free(events); - return NULL; - } - wpa_printf(MSG_DEBUG, "Connected to ROOT\\WMI."); - - ndis_events_constructor(events); - pSink = &events->sink; - pSink->lpVtbl = &events->sink_vtbl; - events->sink_vtbl.QueryInterface = ndis_events_query_interface; - events->sink_vtbl.AddRef = ndis_events_add_ref; - events->sink_vtbl.Release = ndis_events_release; - events->sink_vtbl.Indicate = ndis_events_indicate; - events->sink_vtbl.SetStatus = ndis_events_set_status; - - if (register_async_notification(pSink, events->pSvc) < 0) { - wpa_printf(MSG_DEBUG, "Failed to register async " - "notifications"); - ndis_events_destructor(events); - os_free(events->adapter_desc); - os_free(events); - return NULL; - } - - *read_pipe = events->read_pipe; - *event_avail = events->event_avail; - - return events; -} diff --git a/hostapd-0.8/src/drivers/netlink.c b/hostapd-0.8/src/drivers/netlink.c deleted file mode 100644 index ad15b1d..0000000 --- a/hostapd-0.8/src/drivers/netlink.c +++ /dev/null @@ -1,204 +0,0 @@ -/* - * Netlink helper functions for driver wrappers - * Copyright (c) 2002-2009, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#include "includes.h" - -#include "common.h" -#include "eloop.h" -#include "priv_netlink.h" -#include "netlink.h" - - -struct netlink_data { - struct netlink_config *cfg; - int sock; -}; - - -static void netlink_receive_link(struct netlink_data *netlink, - void (*cb)(void *ctx, struct ifinfomsg *ifi, - u8 *buf, size_t len), - struct nlmsghdr *h) -{ - if (cb == NULL || NLMSG_PAYLOAD(h, 0) < sizeof(struct ifinfomsg)) - return; - cb(netlink->cfg->ctx, NLMSG_DATA(h), - NLMSG_DATA(h) + NLMSG_ALIGN(sizeof(struct ifinfomsg)), - NLMSG_PAYLOAD(h, sizeof(struct ifinfomsg))); -} - - -static void netlink_receive(int sock, void *eloop_ctx, void *sock_ctx) -{ - struct netlink_data *netlink = eloop_ctx; - char buf[8192]; - int left; - struct sockaddr_nl from; - socklen_t fromlen; - struct nlmsghdr *h; - int max_events = 10; - -try_again: - fromlen = sizeof(from); - left = recvfrom(sock, buf, sizeof(buf), MSG_DONTWAIT, - (struct sockaddr *) &from, &fromlen); - if (left < 0) { - if (errno != EINTR && errno != EAGAIN) - wpa_printf(MSG_INFO, "netlink: recvfrom failed: %s", - strerror(errno)); - return; - } - - h = (struct nlmsghdr *) buf; - while (NLMSG_OK(h, left)) { - switch (h->nlmsg_type) { - case RTM_NEWLINK: - netlink_receive_link(netlink, netlink->cfg->newlink_cb, - h); - break; - case RTM_DELLINK: - netlink_receive_link(netlink, netlink->cfg->dellink_cb, - h); - break; - } - - h = NLMSG_NEXT(h, left); - } - - if (left > 0) { - wpa_printf(MSG_DEBUG, "netlink: %d extra bytes in the end of " - "netlink message", left); - } - - if (--max_events > 0) { - /* - * Try to receive all events in one eloop call in order to - * limit race condition on cases where AssocInfo event, Assoc - * event, and EAPOL frames are received more or less at the - * same time. We want to process the event messages first - * before starting EAPOL processing. - */ - goto try_again; - } -} - - -struct netlink_data * netlink_init(struct netlink_config *cfg) -{ - struct netlink_data *netlink; - struct sockaddr_nl local; - - netlink = os_zalloc(sizeof(*netlink)); - if (netlink == NULL) - return NULL; - - netlink->cfg = cfg; - - netlink->sock = socket(PF_NETLINK, SOCK_RAW, NETLINK_ROUTE); - if (netlink->sock < 0) { - wpa_printf(MSG_ERROR, "netlink: Failed to open netlink " - "socket: %s", strerror(errno)); - netlink_deinit(netlink); - return NULL; - } - - os_memset(&local, 0, sizeof(local)); - local.nl_family = AF_NETLINK; - local.nl_groups = RTMGRP_LINK; - if (bind(netlink->sock, (struct sockaddr *) &local, sizeof(local)) < 0) - { - wpa_printf(MSG_ERROR, "netlink: Failed to bind netlink " - "socket: %s", strerror(errno)); - netlink_deinit(netlink); - return NULL; - } - - eloop_register_read_sock(netlink->sock, netlink_receive, netlink, - NULL); - - return netlink; -} - - -void netlink_deinit(struct netlink_data *netlink) -{ - if (netlink == NULL) - return; - if (netlink->sock >= 0) { - eloop_unregister_read_sock(netlink->sock); - close(netlink->sock); - } - os_free(netlink->cfg); - os_free(netlink); -} - -int netlink_send_oper_ifla(struct netlink_data *netlink, int ifindex, - int linkmode, int operstate) -{ - struct { - struct nlmsghdr hdr; - struct ifinfomsg ifinfo; - char opts[16]; - } req; - struct rtattr *rta; - static int nl_seq; - ssize_t ret; - - os_memset(&req, 0, sizeof(req)); - - req.hdr.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifinfomsg)); - req.hdr.nlmsg_type = RTM_SETLINK; - req.hdr.nlmsg_flags = NLM_F_REQUEST; - req.hdr.nlmsg_seq = ++nl_seq; - req.hdr.nlmsg_pid = 0; - - req.ifinfo.ifi_family = AF_UNSPEC; - req.ifinfo.ifi_type = 0; - req.ifinfo.ifi_index = ifindex; - req.ifinfo.ifi_flags = 0; - req.ifinfo.ifi_change = 0; - - if (linkmode != -1) { - rta = aliasing_hide_typecast( - ((char *) &req + NLMSG_ALIGN(req.hdr.nlmsg_len)), - struct rtattr); - rta->rta_type = IFLA_LINKMODE; - rta->rta_len = RTA_LENGTH(sizeof(char)); - *((char *) RTA_DATA(rta)) = linkmode; - req.hdr.nlmsg_len = NLMSG_ALIGN(req.hdr.nlmsg_len) + - RTA_LENGTH(sizeof(char)); - } - if (operstate != -1) { - rta = aliasing_hide_typecast( - ((char *) &req + NLMSG_ALIGN(req.hdr.nlmsg_len)), - struct rtattr); - rta->rta_type = IFLA_OPERSTATE; - rta->rta_len = RTA_LENGTH(sizeof(char)); - *((char *) RTA_DATA(rta)) = operstate; - req.hdr.nlmsg_len = NLMSG_ALIGN(req.hdr.nlmsg_len) + - RTA_LENGTH(sizeof(char)); - } - - wpa_printf(MSG_DEBUG, "netlink: Operstate: linkmode=%d, operstate=%d", - linkmode, operstate); - - ret = send(netlink->sock, &req, req.hdr.nlmsg_len, 0); - if (ret < 0) { - wpa_printf(MSG_DEBUG, "netlink: Sending operstate IFLA " - "failed: %s (assume operstate is not supported)", - strerror(errno)); - } - - return ret < 0 ? -1 : 0; -} diff --git a/hostapd-0.8/src/drivers/netlink.h b/hostapd-0.8/src/drivers/netlink.h deleted file mode 100644 index ccf12a5..0000000 --- a/hostapd-0.8/src/drivers/netlink.h +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Netlink helper functions for driver wrappers - * Copyright (c) 2002-2009, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#ifndef NETLINK_H -#define NETLINK_H - -struct netlink_data; -struct ifinfomsg; - -struct netlink_config { - void *ctx; - void (*newlink_cb)(void *ctx, struct ifinfomsg *ifi, u8 *buf, - size_t len); - void (*dellink_cb)(void *ctx, struct ifinfomsg *ifi, u8 *buf, - size_t len); -}; - -struct netlink_data * netlink_init(struct netlink_config *cfg); -void netlink_deinit(struct netlink_data *netlink); -int netlink_send_oper_ifla(struct netlink_data *netlink, int ifindex, - int linkmode, int operstate); - -#endif /* NETLINK_H */ diff --git a/hostapd-0.8/src/drivers/nl80211_copy.h b/hostapd-0.8/src/drivers/nl80211_copy.h deleted file mode 100644 index 7483a89..0000000 --- a/hostapd-0.8/src/drivers/nl80211_copy.h +++ /dev/null @@ -1,1939 +0,0 @@ -#ifndef __LINUX_NL80211_H -#define __LINUX_NL80211_H -/* - * 802.11 netlink interface public header - * - * Copyright 2006-2010 Johannes Berg - * Copyright 2008 Michael Wu - * Copyright 2008 Luis Carlos Cobo - * Copyright 2008 Michael Buesch - * Copyright 2008, 2009 Luis R. Rodriguez - * Copyright 2008 Jouni Malinen - * Copyright 2008 Colin McCabe - * - * Permission to use, copy, modify, and/or distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - * - */ - -#include - -/** - * DOC: Station handling - * - * Stations are added per interface, but a special case exists with VLAN - * interfaces. When a station is bound to an AP interface, it may be moved - * into a VLAN identified by a VLAN interface index (%NL80211_ATTR_STA_VLAN). - * The station is still assumed to belong to the AP interface it was added - * to. - * - * TODO: need more info? - */ - -/** - * DOC: Frame transmission/registration support - * - * Frame transmission and registration support exists to allow userspace - * management entities such as wpa_supplicant react to management frames - * that are not being handled by the kernel. This includes, for example, - * certain classes of action frames that cannot be handled in the kernel - * for various reasons. - * - * Frame registration is done on a per-interface basis and registrations - * cannot be removed other than by closing the socket. It is possible to - * specify a registration filter to register, for example, only for a - * certain type of action frame. In particular with action frames, those - * that userspace registers for will not be returned as unhandled by the - * driver, so that the registered application has to take responsibility - * for doing that. - * - * The type of frame that can be registered for is also dependent on the - * driver and interface type. The frame types are advertised in wiphy - * attributes so applications know what to expect. - * - * NOTE: When an interface changes type while registrations are active, - * these registrations are ignored until the interface type is - * changed again. This means that changing the interface type can - * lead to a situation that couldn't otherwise be produced, but - * any such registrations will be dormant in the sense that they - * will not be serviced, i.e. they will not receive any frames. - * - * Frame transmission allows userspace to send for example the required - * responses to action frames. It is subject to some sanity checking, - * but many frames can be transmitted. When a frame was transmitted, its - * status is indicated to the sending socket. - * - * For more technical details, see the corresponding command descriptions - * below. - */ - -/** - * enum nl80211_commands - supported nl80211 commands - * - * @NL80211_CMD_UNSPEC: unspecified command to catch errors - * - * @NL80211_CMD_GET_WIPHY: request information about a wiphy or dump request - * to get a list of all present wiphys. - * @NL80211_CMD_SET_WIPHY: set wiphy parameters, needs %NL80211_ATTR_WIPHY or - * %NL80211_ATTR_IFINDEX; can be used to set %NL80211_ATTR_WIPHY_NAME, - * %NL80211_ATTR_WIPHY_TXQ_PARAMS, %NL80211_ATTR_WIPHY_FREQ, - * %NL80211_ATTR_WIPHY_CHANNEL_TYPE, %NL80211_ATTR_WIPHY_RETRY_SHORT, - * %NL80211_ATTR_WIPHY_RETRY_LONG, %NL80211_ATTR_WIPHY_FRAG_THRESHOLD, - * and/or %NL80211_ATTR_WIPHY_RTS_THRESHOLD. - * However, for setting the channel, see %NL80211_CMD_SET_CHANNEL - * instead, the support here is for backward compatibility only. - * @NL80211_CMD_NEW_WIPHY: Newly created wiphy, response to get request - * or rename notification. Has attributes %NL80211_ATTR_WIPHY and - * %NL80211_ATTR_WIPHY_NAME. - * @NL80211_CMD_DEL_WIPHY: Wiphy deleted. Has attributes - * %NL80211_ATTR_WIPHY and %NL80211_ATTR_WIPHY_NAME. - * - * @NL80211_CMD_GET_INTERFACE: Request an interface's configuration; - * either a dump request on a %NL80211_ATTR_WIPHY or a specific get - * on an %NL80211_ATTR_IFINDEX is supported. - * @NL80211_CMD_SET_INTERFACE: Set type of a virtual interface, requires - * %NL80211_ATTR_IFINDEX and %NL80211_ATTR_IFTYPE. - * @NL80211_CMD_NEW_INTERFACE: Newly created virtual interface or response - * to %NL80211_CMD_GET_INTERFACE. Has %NL80211_ATTR_IFINDEX, - * %NL80211_ATTR_WIPHY and %NL80211_ATTR_IFTYPE attributes. Can also - * be sent from userspace to request creation of a new virtual interface, - * then requires attributes %NL80211_ATTR_WIPHY, %NL80211_ATTR_IFTYPE and - * %NL80211_ATTR_IFNAME. - * @NL80211_CMD_DEL_INTERFACE: Virtual interface was deleted, has attributes - * %NL80211_ATTR_IFINDEX and %NL80211_ATTR_WIPHY. Can also be sent from - * userspace to request deletion of a virtual interface, then requires - * attribute %NL80211_ATTR_IFINDEX. - * - * @NL80211_CMD_GET_KEY: Get sequence counter information for a key specified - * by %NL80211_ATTR_KEY_IDX and/or %NL80211_ATTR_MAC. - * @NL80211_CMD_SET_KEY: Set key attributes %NL80211_ATTR_KEY_DEFAULT, - * %NL80211_ATTR_KEY_DEFAULT_MGMT, or %NL80211_ATTR_KEY_THRESHOLD. - * @NL80211_CMD_NEW_KEY: add a key with given %NL80211_ATTR_KEY_DATA, - * %NL80211_ATTR_KEY_IDX, %NL80211_ATTR_MAC, %NL80211_ATTR_KEY_CIPHER, - * and %NL80211_ATTR_KEY_SEQ attributes. - * @NL80211_CMD_DEL_KEY: delete a key identified by %NL80211_ATTR_KEY_IDX - * or %NL80211_ATTR_MAC. - * - * @NL80211_CMD_GET_BEACON: retrieve beacon information (returned in a - * %NL80222_CMD_NEW_BEACON message) - * @NL80211_CMD_SET_BEACON: set the beacon on an access point interface - * using the %NL80211_ATTR_BEACON_INTERVAL, %NL80211_ATTR_DTIM_PERIOD, - * %NL80211_ATTR_BEACON_HEAD and %NL80211_ATTR_BEACON_TAIL attributes. - * @NL80211_CMD_NEW_BEACON: add a new beacon to an access point interface, - * parameters are like for %NL80211_CMD_SET_BEACON. - * @NL80211_CMD_DEL_BEACON: remove the beacon, stop sending it - * - * @NL80211_CMD_GET_STATION: Get station attributes for station identified by - * %NL80211_ATTR_MAC on the interface identified by %NL80211_ATTR_IFINDEX. - * @NL80211_CMD_SET_STATION: Set station attributes for station identified by - * %NL80211_ATTR_MAC on the interface identified by %NL80211_ATTR_IFINDEX. - * @NL80211_CMD_NEW_STATION: Add a station with given attributes to the - * the interface identified by %NL80211_ATTR_IFINDEX. - * @NL80211_CMD_DEL_STATION: Remove a station identified by %NL80211_ATTR_MAC - * or, if no MAC address given, all stations, on the interface identified - * by %NL80211_ATTR_IFINDEX. - * - * @NL80211_CMD_GET_MPATH: Get mesh path attributes for mesh path to - * destination %NL80211_ATTR_MAC on the interface identified by - * %NL80211_ATTR_IFINDEX. - * @NL80211_CMD_SET_MPATH: Set mesh path attributes for mesh path to - * destination %NL80211_ATTR_MAC on the interface identified by - * %NL80211_ATTR_IFINDEX. - * @NL80211_CMD_NEW_PATH: Add a mesh path with given attributes to the - * the interface identified by %NL80211_ATTR_IFINDEX. - * @NL80211_CMD_DEL_PATH: Remove a mesh path identified by %NL80211_ATTR_MAC - * or, if no MAC address given, all mesh paths, on the interface identified - * by %NL80211_ATTR_IFINDEX. - * @NL80211_CMD_SET_BSS: Set BSS attributes for BSS identified by - * %NL80211_ATTR_IFINDEX. - * - * @NL80211_CMD_GET_REG: ask the wireless core to send us its currently set - * regulatory domain. - * @NL80211_CMD_SET_REG: Set current regulatory domain. CRDA sends this command - * after being queried by the kernel. CRDA replies by sending a regulatory - * domain structure which consists of %NL80211_ATTR_REG_ALPHA set to our - * current alpha2 if it found a match. It also provides - * NL80211_ATTR_REG_RULE_FLAGS, and a set of regulatory rules. Each - * regulatory rule is a nested set of attributes given by - * %NL80211_ATTR_REG_RULE_FREQ_[START|END] and - * %NL80211_ATTR_FREQ_RANGE_MAX_BW with an attached power rule given by - * %NL80211_ATTR_REG_RULE_POWER_MAX_ANT_GAIN and - * %NL80211_ATTR_REG_RULE_POWER_MAX_EIRP. - * @NL80211_CMD_REQ_SET_REG: ask the wireless core to set the regulatory domain - * to the specified ISO/IEC 3166-1 alpha2 country code. The core will - * store this as a valid request and then query userspace for it. - * - * @NL80211_CMD_GET_MESH_PARAMS: Get mesh networking properties for the - * interface identified by %NL80211_ATTR_IFINDEX - * - * @NL80211_CMD_SET_MESH_PARAMS: Set mesh networking properties for the - * interface identified by %NL80211_ATTR_IFINDEX - * - * @NL80211_CMD_SET_MGMT_EXTRA_IE: Set extra IEs for management frames. The - * interface is identified with %NL80211_ATTR_IFINDEX and the management - * frame subtype with %NL80211_ATTR_MGMT_SUBTYPE. The extra IE data to be - * added to the end of the specified management frame is specified with - * %NL80211_ATTR_IE. If the command succeeds, the requested data will be - * added to all specified management frames generated by - * kernel/firmware/driver. - * Note: This command has been removed and it is only reserved at this - * point to avoid re-using existing command number. The functionality this - * command was planned for has been provided with cleaner design with the - * option to specify additional IEs in NL80211_CMD_TRIGGER_SCAN, - * NL80211_CMD_AUTHENTICATE, NL80211_CMD_ASSOCIATE, - * NL80211_CMD_DEAUTHENTICATE, and NL80211_CMD_DISASSOCIATE. - * - * @NL80211_CMD_GET_SCAN: get scan results - * @NL80211_CMD_TRIGGER_SCAN: trigger a new scan with the given parameters - * @NL80211_CMD_NEW_SCAN_RESULTS: scan notification (as a reply to - * NL80211_CMD_GET_SCAN and on the "scan" multicast group) - * @NL80211_CMD_SCAN_ABORTED: scan was aborted, for unspecified reasons, - * partial scan results may be available - * - * @NL80211_CMD_GET_SURVEY: get survey resuls, e.g. channel occupation - * or noise level - * @NL80211_CMD_NEW_SURVEY_RESULTS: survey data notification (as a reply to - * NL80211_CMD_GET_SURVEY and on the "scan" multicast group) - * - * @NL80211_CMD_REG_CHANGE: indicates to userspace the regulatory domain - * has been changed and provides details of the request information - * that caused the change such as who initiated the regulatory request - * (%NL80211_ATTR_REG_INITIATOR), the wiphy_idx - * (%NL80211_ATTR_REG_ALPHA2) on which the request was made from if - * the initiator was %NL80211_REGDOM_SET_BY_COUNTRY_IE or - * %NL80211_REGDOM_SET_BY_DRIVER, the type of regulatory domain - * set (%NL80211_ATTR_REG_TYPE), if the type of regulatory domain is - * %NL80211_REG_TYPE_COUNTRY the alpha2 to which we have moved on - * to (%NL80211_ATTR_REG_ALPHA2). - * @NL80211_CMD_REG_BEACON_HINT: indicates to userspace that an AP beacon - * has been found while world roaming thus enabling active scan or - * any mode of operation that initiates TX (beacons) on a channel - * where we would not have been able to do either before. As an example - * if you are world roaming (regulatory domain set to world or if your - * driver is using a custom world roaming regulatory domain) and while - * doing a passive scan on the 5 GHz band you find an AP there (if not - * on a DFS channel) you will now be able to actively scan for that AP - * or use AP mode on your card on that same channel. Note that this will - * never be used for channels 1-11 on the 2 GHz band as they are always - * enabled world wide. This beacon hint is only sent if your device had - * either disabled active scanning or beaconing on a channel. We send to - * userspace the wiphy on which we removed a restriction from - * (%NL80211_ATTR_WIPHY) and the channel on which this occurred - * before (%NL80211_ATTR_FREQ_BEFORE) and after (%NL80211_ATTR_FREQ_AFTER) - * the beacon hint was processed. - * - * @NL80211_CMD_AUTHENTICATE: authentication request and notification. - * This command is used both as a command (request to authenticate) and - * as an event on the "mlme" multicast group indicating completion of the - * authentication process. - * When used as a command, %NL80211_ATTR_IFINDEX is used to identify the - * interface. %NL80211_ATTR_MAC is used to specify PeerSTAAddress (and - * BSSID in case of station mode). %NL80211_ATTR_SSID is used to specify - * the SSID (mainly for association, but is included in authentication - * request, too, to help BSS selection. %NL80211_ATTR_WIPHY_FREQ is used - * to specify the frequence of the channel in MHz. %NL80211_ATTR_AUTH_TYPE - * is used to specify the authentication type. %NL80211_ATTR_IE is used to - * define IEs (VendorSpecificInfo, but also including RSN IE and FT IEs) - * to be added to the frame. - * When used as an event, this reports reception of an Authentication - * frame in station and IBSS modes when the local MLME processed the - * frame, i.e., it was for the local STA and was received in correct - * state. This is similar to MLME-AUTHENTICATE.confirm primitive in the - * MLME SAP interface (kernel providing MLME, userspace SME). The - * included %NL80211_ATTR_FRAME attribute contains the management frame - * (including both the header and frame body, but not FCS). This event is - * also used to indicate if the authentication attempt timed out. In that - * case the %NL80211_ATTR_FRAME attribute is replaced with a - * %NL80211_ATTR_TIMED_OUT flag (and %NL80211_ATTR_MAC to indicate which - * pending authentication timed out). - * @NL80211_CMD_ASSOCIATE: association request and notification; like - * NL80211_CMD_AUTHENTICATE but for Association and Reassociation - * (similar to MLME-ASSOCIATE.request, MLME-REASSOCIATE.request, - * MLME-ASSOCIATE.confirm or MLME-REASSOCIATE.confirm primitives). - * @NL80211_CMD_DEAUTHENTICATE: deauthentication request and notification; like - * NL80211_CMD_AUTHENTICATE but for Deauthentication frames (similar to - * MLME-DEAUTHENTICATION.request and MLME-DEAUTHENTICATE.indication - * primitives). - * @NL80211_CMD_DISASSOCIATE: disassociation request and notification; like - * NL80211_CMD_AUTHENTICATE but for Disassociation frames (similar to - * MLME-DISASSOCIATE.request and MLME-DISASSOCIATE.indication primitives). - * - * @NL80211_CMD_MICHAEL_MIC_FAILURE: notification of a locally detected Michael - * MIC (part of TKIP) failure; sent on the "mlme" multicast group; the - * event includes %NL80211_ATTR_MAC to describe the source MAC address of - * the frame with invalid MIC, %NL80211_ATTR_KEY_TYPE to show the key - * type, %NL80211_ATTR_KEY_IDX to indicate the key identifier, and - * %NL80211_ATTR_KEY_SEQ to indicate the TSC value of the frame; this - * event matches with MLME-MICHAELMICFAILURE.indication() primitive - * - * @NL80211_CMD_JOIN_IBSS: Join a new IBSS -- given at least an SSID and a - * FREQ attribute (for the initial frequency if no peer can be found) - * and optionally a MAC (as BSSID) and FREQ_FIXED attribute if those - * should be fixed rather than automatically determined. Can only be - * executed on a network interface that is UP, and fixed BSSID/FREQ - * may be rejected. Another optional parameter is the beacon interval, - * given in the %NL80211_ATTR_BEACON_INTERVAL attribute, which if not - * given defaults to 100 TU (102.4ms). - * @NL80211_CMD_LEAVE_IBSS: Leave the IBSS -- no special arguments, the IBSS is - * determined by the network interface. - * - * @NL80211_CMD_TESTMODE: testmode command, takes a wiphy (or ifindex) attribute - * to identify the device, and the TESTDATA blob attribute to pass through - * to the driver. - * - * @NL80211_CMD_CONNECT: connection request and notification; this command - * requests to connect to a specified network but without separating - * auth and assoc steps. For this, you need to specify the SSID in a - * %NL80211_ATTR_SSID attribute, and can optionally specify the association - * IEs in %NL80211_ATTR_IE, %NL80211_ATTR_AUTH_TYPE, %NL80211_ATTR_MAC, - * %NL80211_ATTR_WIPHY_FREQ, %NL80211_ATTR_CONTROL_PORT, - * %NL80211_ATTR_CONTROL_PORT_ETHERTYPE and - * %NL80211_ATTR_CONTROL_PORT_NO_ENCRYPT. - * It is also sent as an event, with the BSSID and response IEs when the - * connection is established or failed to be established. This can be - * determined by the STATUS_CODE attribute. - * @NL80211_CMD_ROAM: request that the card roam (currently not implemented), - * sent as an event when the card/driver roamed by itself. - * @NL80211_CMD_DISCONNECT: drop a given connection; also used to notify - * userspace that a connection was dropped by the AP or due to other - * reasons, for this the %NL80211_ATTR_DISCONNECTED_BY_AP and - * %NL80211_ATTR_REASON_CODE attributes are used. - * - * @NL80211_CMD_SET_WIPHY_NETNS: Set a wiphy's netns. Note that all devices - * associated with this wiphy must be down and will follow. - * - * @NL80211_CMD_REMAIN_ON_CHANNEL: Request to remain awake on the specified - * channel for the specified amount of time. This can be used to do - * off-channel operations like transmit a Public Action frame and wait for - * a response while being associated to an AP on another channel. - * %NL80211_ATTR_IFINDEX is used to specify which interface (and thus - * radio) is used. %NL80211_ATTR_WIPHY_FREQ is used to specify the - * frequency for the operation and %NL80211_ATTR_WIPHY_CHANNEL_TYPE may be - * optionally used to specify additional channel parameters. - * %NL80211_ATTR_DURATION is used to specify the duration in milliseconds - * to remain on the channel. This command is also used as an event to - * notify when the requested duration starts (it may take a while for the - * driver to schedule this time due to other concurrent needs for the - * radio). - * When called, this operation returns a cookie (%NL80211_ATTR_COOKIE) - * that will be included with any events pertaining to this request; - * the cookie is also used to cancel the request. - * @NL80211_CMD_CANCEL_REMAIN_ON_CHANNEL: This command can be used to cancel a - * pending remain-on-channel duration if the desired operation has been - * completed prior to expiration of the originally requested duration. - * %NL80211_ATTR_WIPHY or %NL80211_ATTR_IFINDEX is used to specify the - * radio. The %NL80211_ATTR_COOKIE attribute must be given as well to - * uniquely identify the request. - * This command is also used as an event to notify when a requested - * remain-on-channel duration has expired. - * - * @NL80211_CMD_SET_TX_BITRATE_MASK: Set the mask of rates to be used in TX - * rate selection. %NL80211_ATTR_IFINDEX is used to specify the interface - * and @NL80211_ATTR_TX_RATES the set of allowed rates. - * - * @NL80211_CMD_REGISTER_FRAME: Register for receiving certain mgmt frames - * (via @NL80211_CMD_FRAME) for processing in userspace. This command - * requires an interface index, a frame type attribute (optional for - * backward compatibility reasons, if not given assumes action frames) - * and a match attribute containing the first few bytes of the frame - * that should match, e.g. a single byte for only a category match or - * four bytes for vendor frames including the OUI. The registration - * cannot be dropped, but is removed automatically when the netlink - * socket is closed. Multiple registrations can be made. - * @NL80211_CMD_REGISTER_ACTION: Alias for @NL80211_CMD_REGISTER_FRAME for - * backward compatibility - * @NL80211_CMD_FRAME: Management frame TX request and RX notification. This - * command is used both as a request to transmit a management frame and - * as an event indicating reception of a frame that was not processed in - * kernel code, but is for us (i.e., which may need to be processed in a - * user space application). %NL80211_ATTR_FRAME is used to specify the - * frame contents (including header). %NL80211_ATTR_WIPHY_FREQ (and - * optionally %NL80211_ATTR_WIPHY_CHANNEL_TYPE) is used to indicate on - * which channel the frame is to be transmitted or was received. If this - * channel is not the current channel (remain-on-channel or the - * operational channel) the device will switch to the given channel and - * transmit the frame, optionally waiting for a response for the time - * specified using %NL80211_ATTR_DURATION. When called, this operation - * returns a cookie (%NL80211_ATTR_COOKIE) that will be included with the - * TX status event pertaining to the TX request. - * @NL80211_CMD_FRAME_WAIT_CANCEL: When an off-channel TX was requested, this - * command may be used with the corresponding cookie to cancel the wait - * time if it is known that it is no longer necessary. - * @NL80211_CMD_ACTION: Alias for @NL80211_CMD_FRAME for backward compatibility. - * @NL80211_CMD_FRAME_TX_STATUS: Report TX status of a management frame - * transmitted with %NL80211_CMD_FRAME. %NL80211_ATTR_COOKIE identifies - * the TX command and %NL80211_ATTR_FRAME includes the contents of the - * frame. %NL80211_ATTR_ACK flag is included if the recipient acknowledged - * the frame. - * @NL80211_CMD_ACTION_TX_STATUS: Alias for @NL80211_CMD_FRAME_TX_STATUS for - * backward compatibility. - * @NL80211_CMD_SET_CQM: Connection quality monitor configuration. This command - * is used to configure connection quality monitoring notification trigger - * levels. - * @NL80211_CMD_NOTIFY_CQM: Connection quality monitor notification. This - * command is used as an event to indicate the that a trigger level was - * reached. - * @NL80211_CMD_SET_CHANNEL: Set the channel (using %NL80211_ATTR_WIPHY_FREQ - * and %NL80211_ATTR_WIPHY_CHANNEL_TYPE) the given interface (identifed - * by %NL80211_ATTR_IFINDEX) shall operate on. - * In case multiple channels are supported by the device, the mechanism - * with which it switches channels is implementation-defined. - * When a monitor interface is given, it can only switch channel while - * no other interfaces are operating to avoid disturbing the operation - * of any other interfaces, and other interfaces will again take - * precedence when they are used. - * - * @NL80211_CMD_SET_WDS_PEER: Set the MAC address of the peer on a WDS interface. - * - * @NL80211_CMD_JOIN_MESH: Join a mesh. The mesh ID must be given, and initial - * mesh config parameters may be given. - * @NL80211_CMD_LEAVE_MESH: Leave the mesh network -- no special arguments, the - * network is determined by the network interface. - * - * @NL80211_CMD_UNPROT_DEAUTHENTICATE: Unprotected deauthentication frame - * notification. This event is used to indicate that an unprotected - * deauthentication frame was dropped when MFP is in use. - * @NL80211_CMD_UNPROT_DISASSOCIATE: Unprotected disassociation frame - * notification. This event is used to indicate that an unprotected - * disassociation frame was dropped when MFP is in use. - * - * @NL80211_CMD_MAX: highest used command number - * @__NL80211_CMD_AFTER_LAST: internal use - */ -enum nl80211_commands { -/* don't change the order or add anything inbetween, this is ABI! */ - NL80211_CMD_UNSPEC, - - NL80211_CMD_GET_WIPHY, /* can dump */ - NL80211_CMD_SET_WIPHY, - NL80211_CMD_NEW_WIPHY, - NL80211_CMD_DEL_WIPHY, - - NL80211_CMD_GET_INTERFACE, /* can dump */ - NL80211_CMD_SET_INTERFACE, - NL80211_CMD_NEW_INTERFACE, - NL80211_CMD_DEL_INTERFACE, - - NL80211_CMD_GET_KEY, - NL80211_CMD_SET_KEY, - NL80211_CMD_NEW_KEY, - NL80211_CMD_DEL_KEY, - - NL80211_CMD_GET_BEACON, - NL80211_CMD_SET_BEACON, - NL80211_CMD_NEW_BEACON, - NL80211_CMD_DEL_BEACON, - - NL80211_CMD_GET_STATION, - NL80211_CMD_SET_STATION, - NL80211_CMD_NEW_STATION, - NL80211_CMD_DEL_STATION, - - NL80211_CMD_GET_MPATH, - NL80211_CMD_SET_MPATH, - NL80211_CMD_NEW_MPATH, - NL80211_CMD_DEL_MPATH, - - NL80211_CMD_SET_BSS, - - NL80211_CMD_SET_REG, - NL80211_CMD_REQ_SET_REG, - - NL80211_CMD_GET_MESH_PARAMS, - NL80211_CMD_SET_MESH_PARAMS, - - NL80211_CMD_SET_MGMT_EXTRA_IE /* reserved; not used */, - - NL80211_CMD_GET_REG, - - NL80211_CMD_GET_SCAN, - NL80211_CMD_TRIGGER_SCAN, - NL80211_CMD_NEW_SCAN_RESULTS, - NL80211_CMD_SCAN_ABORTED, - - NL80211_CMD_REG_CHANGE, - - NL80211_CMD_AUTHENTICATE, - NL80211_CMD_ASSOCIATE, - NL80211_CMD_DEAUTHENTICATE, - NL80211_CMD_DISASSOCIATE, - - NL80211_CMD_MICHAEL_MIC_FAILURE, - - NL80211_CMD_REG_BEACON_HINT, - - NL80211_CMD_JOIN_IBSS, - NL80211_CMD_LEAVE_IBSS, - - NL80211_CMD_TESTMODE, - - NL80211_CMD_CONNECT, - NL80211_CMD_ROAM, - NL80211_CMD_DISCONNECT, - - NL80211_CMD_SET_WIPHY_NETNS, - - NL80211_CMD_GET_SURVEY, - NL80211_CMD_NEW_SURVEY_RESULTS, - - NL80211_CMD_SET_PMKSA, - NL80211_CMD_DEL_PMKSA, - NL80211_CMD_FLUSH_PMKSA, - - NL80211_CMD_REMAIN_ON_CHANNEL, - NL80211_CMD_CANCEL_REMAIN_ON_CHANNEL, - - NL80211_CMD_SET_TX_BITRATE_MASK, - - NL80211_CMD_REGISTER_FRAME, - NL80211_CMD_REGISTER_ACTION = NL80211_CMD_REGISTER_FRAME, - NL80211_CMD_FRAME, - NL80211_CMD_ACTION = NL80211_CMD_FRAME, - NL80211_CMD_FRAME_TX_STATUS, - NL80211_CMD_ACTION_TX_STATUS = NL80211_CMD_FRAME_TX_STATUS, - - NL80211_CMD_SET_POWER_SAVE, - NL80211_CMD_GET_POWER_SAVE, - - NL80211_CMD_SET_CQM, - NL80211_CMD_NOTIFY_CQM, - - NL80211_CMD_SET_CHANNEL, - NL80211_CMD_SET_WDS_PEER, - - NL80211_CMD_FRAME_WAIT_CANCEL, - - NL80211_CMD_JOIN_MESH, - NL80211_CMD_LEAVE_MESH, - - NL80211_CMD_UNPROT_DEAUTHENTICATE, - NL80211_CMD_UNPROT_DISASSOCIATE, - - /* add new commands above here */ - - /* used to define NL80211_CMD_MAX below */ - __NL80211_CMD_AFTER_LAST, - NL80211_CMD_MAX = __NL80211_CMD_AFTER_LAST - 1 -}; - -/* - * Allow user space programs to use #ifdef on new commands by defining them - * here - */ -#define NL80211_CMD_SET_BSS NL80211_CMD_SET_BSS -#define NL80211_CMD_SET_MGMT_EXTRA_IE NL80211_CMD_SET_MGMT_EXTRA_IE -#define NL80211_CMD_REG_CHANGE NL80211_CMD_REG_CHANGE -#define NL80211_CMD_AUTHENTICATE NL80211_CMD_AUTHENTICATE -#define NL80211_CMD_ASSOCIATE NL80211_CMD_ASSOCIATE -#define NL80211_CMD_DEAUTHENTICATE NL80211_CMD_DEAUTHENTICATE -#define NL80211_CMD_DISASSOCIATE NL80211_CMD_DISASSOCIATE -#define NL80211_CMD_REG_BEACON_HINT NL80211_CMD_REG_BEACON_HINT - -/** - * enum nl80211_attrs - nl80211 netlink attributes - * - * @NL80211_ATTR_UNSPEC: unspecified attribute to catch errors - * - * @NL80211_ATTR_WIPHY: index of wiphy to operate on, cf. - * /sys/class/ieee80211//index - * @NL80211_ATTR_WIPHY_NAME: wiphy name (used for renaming) - * @NL80211_ATTR_WIPHY_TXQ_PARAMS: a nested array of TX queue parameters - * @NL80211_ATTR_WIPHY_FREQ: frequency of the selected channel in MHz - * @NL80211_ATTR_WIPHY_CHANNEL_TYPE: included with NL80211_ATTR_WIPHY_FREQ - * if HT20 or HT40 are allowed (i.e., 802.11n disabled if not included): - * NL80211_CHAN_NO_HT = HT not allowed (i.e., same as not including - * this attribute) - * NL80211_CHAN_HT20 = HT20 only - * NL80211_CHAN_HT40MINUS = secondary channel is below the primary channel - * NL80211_CHAN_HT40PLUS = secondary channel is above the primary channel - * @NL80211_ATTR_WIPHY_RETRY_SHORT: TX retry limit for frames whose length is - * less than or equal to the RTS threshold; allowed range: 1..255; - * dot11ShortRetryLimit; u8 - * @NL80211_ATTR_WIPHY_RETRY_LONG: TX retry limit for frames whose length is - * greater than the RTS threshold; allowed range: 1..255; - * dot11ShortLongLimit; u8 - * @NL80211_ATTR_WIPHY_FRAG_THRESHOLD: fragmentation threshold, i.e., maximum - * length in octets for frames; allowed range: 256..8000, disable - * fragmentation with (u32)-1; dot11FragmentationThreshold; u32 - * @NL80211_ATTR_WIPHY_RTS_THRESHOLD: RTS threshold (TX frames with length - * larger than or equal to this use RTS/CTS handshake); allowed range: - * 0..65536, disable with (u32)-1; dot11RTSThreshold; u32 - * @NL80211_ATTR_WIPHY_COVERAGE_CLASS: Coverage Class as defined by IEEE 802.11 - * section 7.3.2.9; dot11CoverageClass; u8 - * - * @NL80211_ATTR_IFINDEX: network interface index of the device to operate on - * @NL80211_ATTR_IFNAME: network interface name - * @NL80211_ATTR_IFTYPE: type of virtual interface, see &enum nl80211_iftype - * - * @NL80211_ATTR_MAC: MAC address (various uses) - * - * @NL80211_ATTR_KEY_DATA: (temporal) key data; for TKIP this consists of - * 16 bytes encryption key followed by 8 bytes each for TX and RX MIC - * keys - * @NL80211_ATTR_KEY_IDX: key ID (u8, 0-3) - * @NL80211_ATTR_KEY_CIPHER: key cipher suite (u32, as defined by IEEE 802.11 - * section 7.3.2.25.1, e.g. 0x000FAC04) - * @NL80211_ATTR_KEY_SEQ: transmit key sequence number (IV/PN) for TKIP and - * CCMP keys, each six bytes in little endian - * - * @NL80211_ATTR_BEACON_INTERVAL: beacon interval in TU - * @NL80211_ATTR_DTIM_PERIOD: DTIM period for beaconing - * @NL80211_ATTR_BEACON_HEAD: portion of the beacon before the TIM IE - * @NL80211_ATTR_BEACON_TAIL: portion of the beacon after the TIM IE - * - * @NL80211_ATTR_STA_AID: Association ID for the station (u16) - * @NL80211_ATTR_STA_FLAGS: flags, nested element with NLA_FLAG attributes of - * &enum nl80211_sta_flags (deprecated, use %NL80211_ATTR_STA_FLAGS2) - * @NL80211_ATTR_STA_LISTEN_INTERVAL: listen interval as defined by - * IEEE 802.11 7.3.1.6 (u16). - * @NL80211_ATTR_STA_SUPPORTED_RATES: supported rates, array of supported - * rates as defined by IEEE 802.11 7.3.2.2 but without the length - * restriction (at most %NL80211_MAX_SUPP_RATES). - * @NL80211_ATTR_STA_VLAN: interface index of VLAN interface to move station - * to, or the AP interface the station was originally added to to. - * @NL80211_ATTR_STA_INFO: information about a station, part of station info - * given for %NL80211_CMD_GET_STATION, nested attribute containing - * info as possible, see &enum nl80211_sta_info. - * - * @NL80211_ATTR_WIPHY_BANDS: Information about an operating bands, - * consisting of a nested array. - * - * @NL80211_ATTR_MESH_ID: mesh id (1-32 bytes). - * @NL80211_ATTR_PLINK_ACTION: action to perform on the mesh peer link. - * @NL80211_ATTR_MPATH_NEXT_HOP: MAC address of the next hop for a mesh path. - * @NL80211_ATTR_MPATH_INFO: information about a mesh_path, part of mesh path - * info given for %NL80211_CMD_GET_MPATH, nested attribute described at - * &enum nl80211_mpath_info. - * - * @NL80211_ATTR_MNTR_FLAGS: flags, nested element with NLA_FLAG attributes of - * &enum nl80211_mntr_flags. - * - * @NL80211_ATTR_REG_ALPHA2: an ISO-3166-alpha2 country code for which the - * current regulatory domain should be set to or is already set to. - * For example, 'CR', for Costa Rica. This attribute is used by the kernel - * to query the CRDA to retrieve one regulatory domain. This attribute can - * also be used by userspace to query the kernel for the currently set - * regulatory domain. We chose an alpha2 as that is also used by the - * IEEE-802.11d country information element to identify a country. - * Users can also simply ask the wireless core to set regulatory domain - * to a specific alpha2. - * @NL80211_ATTR_REG_RULES: a nested array of regulatory domain regulatory - * rules. - * - * @NL80211_ATTR_BSS_CTS_PROT: whether CTS protection is enabled (u8, 0 or 1) - * @NL80211_ATTR_BSS_SHORT_PREAMBLE: whether short preamble is enabled - * (u8, 0 or 1) - * @NL80211_ATTR_BSS_SHORT_SLOT_TIME: whether short slot time enabled - * (u8, 0 or 1) - * @NL80211_ATTR_BSS_BASIC_RATES: basic rates, array of basic - * rates in format defined by IEEE 802.11 7.3.2.2 but without the length - * restriction (at most %NL80211_MAX_SUPP_RATES). - * - * @NL80211_ATTR_HT_CAPABILITY: HT Capability information element (from - * association request when used with NL80211_CMD_NEW_STATION) - * - * @NL80211_ATTR_SUPPORTED_IFTYPES: nested attribute containing all - * supported interface types, each a flag attribute with the number - * of the interface mode. - * - * @NL80211_ATTR_MGMT_SUBTYPE: Management frame subtype for - * %NL80211_CMD_SET_MGMT_EXTRA_IE. - * - * @NL80211_ATTR_IE: Information element(s) data (used, e.g., with - * %NL80211_CMD_SET_MGMT_EXTRA_IE). - * - * @NL80211_ATTR_MAX_NUM_SCAN_SSIDS: number of SSIDs you can scan with - * a single scan request, a wiphy attribute. - * @NL80211_ATTR_MAX_SCAN_IE_LEN: maximum length of information elements - * that can be added to a scan request - * - * @NL80211_ATTR_SCAN_FREQUENCIES: nested attribute with frequencies (in MHz) - * @NL80211_ATTR_SCAN_SSIDS: nested attribute with SSIDs, leave out for passive - * scanning and include a zero-length SSID (wildcard) for wildcard scan - * @NL80211_ATTR_BSS: scan result BSS - * - * @NL80211_ATTR_REG_INITIATOR: indicates who requested the regulatory domain - * currently in effect. This could be any of the %NL80211_REGDOM_SET_BY_* - * @NL80211_ATTR_REG_TYPE: indicates the type of the regulatory domain currently - * set. This can be one of the nl80211_reg_type (%NL80211_REGDOM_TYPE_*) - * - * @NL80211_ATTR_SUPPORTED_COMMANDS: wiphy attribute that specifies - * an array of command numbers (i.e. a mapping index to command number) - * that the driver for the given wiphy supports. - * - * @NL80211_ATTR_FRAME: frame data (binary attribute), including frame header - * and body, but not FCS; used, e.g., with NL80211_CMD_AUTHENTICATE and - * NL80211_CMD_ASSOCIATE events - * @NL80211_ATTR_SSID: SSID (binary attribute, 0..32 octets) - * @NL80211_ATTR_AUTH_TYPE: AuthenticationType, see &enum nl80211_auth_type, - * represented as a u32 - * @NL80211_ATTR_REASON_CODE: ReasonCode for %NL80211_CMD_DEAUTHENTICATE and - * %NL80211_CMD_DISASSOCIATE, u16 - * - * @NL80211_ATTR_KEY_TYPE: Key Type, see &enum nl80211_key_type, represented as - * a u32 - * - * @NL80211_ATTR_FREQ_BEFORE: A channel which has suffered a regulatory change - * due to considerations from a beacon hint. This attribute reflects - * the state of the channel _before_ the beacon hint processing. This - * attributes consists of a nested attribute containing - * NL80211_FREQUENCY_ATTR_* - * @NL80211_ATTR_FREQ_AFTER: A channel which has suffered a regulatory change - * due to considerations from a beacon hint. This attribute reflects - * the state of the channel _after_ the beacon hint processing. This - * attributes consists of a nested attribute containing - * NL80211_FREQUENCY_ATTR_* - * - * @NL80211_ATTR_CIPHER_SUITES: a set of u32 values indicating the supported - * cipher suites - * - * @NL80211_ATTR_FREQ_FIXED: a flag indicating the IBSS should not try to look - * for other networks on different channels - * - * @NL80211_ATTR_TIMED_OUT: a flag indicating than an operation timed out; this - * is used, e.g., with %NL80211_CMD_AUTHENTICATE event - * - * @NL80211_ATTR_USE_MFP: Whether management frame protection (IEEE 802.11w) is - * used for the association (&enum nl80211_mfp, represented as a u32); - * this attribute can be used - * with %NL80211_CMD_ASSOCIATE request - * - * @NL80211_ATTR_STA_FLAGS2: Attribute containing a - * &struct nl80211_sta_flag_update. - * - * @NL80211_ATTR_CONTROL_PORT: A flag indicating whether user space controls - * IEEE 802.1X port, i.e., sets/clears %NL80211_STA_FLAG_AUTHORIZED, in - * station mode. If the flag is included in %NL80211_CMD_ASSOCIATE - * request, the driver will assume that the port is unauthorized until - * authorized by user space. Otherwise, port is marked authorized by - * default in station mode. - * @NL80211_ATTR_CONTROL_PORT_ETHERTYPE: A 16-bit value indicating the - * ethertype that will be used for key negotiation. It can be - * specified with the associate and connect commands. If it is not - * specified, the value defaults to 0x888E (PAE, 802.1X). This - * attribute is also used as a flag in the wiphy information to - * indicate that protocols other than PAE are supported. - * @NL80211_ATTR_CONTROL_PORT_NO_ENCRYPT: When included along with - * %NL80211_ATTR_CONTROL_PORT_ETHERTYPE, indicates that the custom - * ethertype frames used for key negotiation must not be encrypted. - * - * @NL80211_ATTR_TESTDATA: Testmode data blob, passed through to the driver. - * We recommend using nested, driver-specific attributes within this. - * - * @NL80211_ATTR_DISCONNECTED_BY_AP: A flag indicating that the DISCONNECT - * event was due to the AP disconnecting the station, and not due to - * a local disconnect request. - * @NL80211_ATTR_STATUS_CODE: StatusCode for the %NL80211_CMD_CONNECT - * event (u16) - * @NL80211_ATTR_PRIVACY: Flag attribute, used with connect(), indicating - * that protected APs should be used. - * - * @NL80211_ATTR_CIPHERS_PAIRWISE: Used with CONNECT and ASSOCIATE to - * indicate which unicast key ciphers will be used with the connection - * (an array of u32). - * @NL80211_ATTR_CIPHER_GROUP: Used with CONNECT and ASSOCIATE to indicate - * which group key cipher will be used with the connection (a u32). - * @NL80211_ATTR_WPA_VERSIONS: Used with CONNECT and ASSOCIATE to indicate - * which WPA version(s) the AP we want to associate with is using - * (a u32 with flags from &enum nl80211_wpa_versions). - * @NL80211_ATTR_AKM_SUITES: Used with CONNECT and ASSOCIATE to indicate - * which key management algorithm(s) to use (an array of u32). - * - * @NL80211_ATTR_REQ_IE: (Re)association request information elements as - * sent out by the card, for ROAM and successful CONNECT events. - * @NL80211_ATTR_RESP_IE: (Re)association response information elements as - * sent by peer, for ROAM and successful CONNECT events. - * - * @NL80211_ATTR_PREV_BSSID: previous BSSID, to be used by in ASSOCIATE - * commands to specify using a reassociate frame - * - * @NL80211_ATTR_KEY: key information in a nested attribute with - * %NL80211_KEY_* sub-attributes - * @NL80211_ATTR_KEYS: array of keys for static WEP keys for connect() - * and join_ibss(), key information is in a nested attribute each - * with %NL80211_KEY_* sub-attributes - * - * @NL80211_ATTR_PID: Process ID of a network namespace. - * - * @NL80211_ATTR_GENERATION: Used to indicate consistent snapshots for - * dumps. This number increases whenever the object list being - * dumped changes, and as such userspace can verify that it has - * obtained a complete and consistent snapshot by verifying that - * all dump messages contain the same generation number. If it - * changed then the list changed and the dump should be repeated - * completely from scratch. - * - * @NL80211_ATTR_4ADDR: Use 4-address frames on a virtual interface - * - * @NL80211_ATTR_SURVEY_INFO: survey information about a channel, part of - * the survey response for %NL80211_CMD_GET_SURVEY, nested attribute - * containing info as possible, see &enum survey_info. - * - * @NL80211_ATTR_PMKID: PMK material for PMKSA caching. - * @NL80211_ATTR_MAX_NUM_PMKIDS: maximum number of PMKIDs a firmware can - * cache, a wiphy attribute. - * - * @NL80211_ATTR_DURATION: Duration of an operation in milliseconds, u32. - * @NL80211_ATTR_MAX_REMAIN_ON_CHANNEL_DURATION: Device attribute that - * specifies the maximum duration that can be requested with the - * remain-on-channel operation, in milliseconds, u32. - * - * @NL80211_ATTR_COOKIE: Generic 64-bit cookie to identify objects. - * - * @NL80211_ATTR_TX_RATES: Nested set of attributes - * (enum nl80211_tx_rate_attributes) describing TX rates per band. The - * enum nl80211_band value is used as the index (nla_type() of the nested - * data. If a band is not included, it will be configured to allow all - * rates based on negotiated supported rates information. This attribute - * is used with %NL80211_CMD_SET_TX_BITRATE_MASK. - * - * @NL80211_ATTR_FRAME_MATCH: A binary attribute which typically must contain - * at least one byte, currently used with @NL80211_CMD_REGISTER_FRAME. - * @NL80211_ATTR_FRAME_TYPE: A u16 indicating the frame type/subtype for the - * @NL80211_CMD_REGISTER_FRAME command. - * @NL80211_ATTR_TX_FRAME_TYPES: wiphy capability attribute, which is a - * nested attribute of %NL80211_ATTR_FRAME_TYPE attributes, containing - * information about which frame types can be transmitted with - * %NL80211_CMD_FRAME. - * @NL80211_ATTR_RX_FRAME_TYPES: wiphy capability attribute, which is a - * nested attribute of %NL80211_ATTR_FRAME_TYPE attributes, containing - * information about which frame types can be registered for RX. - * - * @NL80211_ATTR_ACK: Flag attribute indicating that the frame was - * acknowledged by the recipient. - * - * @NL80211_ATTR_CQM: connection quality monitor configuration in a - * nested attribute with %NL80211_ATTR_CQM_* sub-attributes. - * - * @NL80211_ATTR_LOCAL_STATE_CHANGE: Flag attribute to indicate that a command - * is requesting a local authentication/association state change without - * invoking actual management frame exchange. This can be used with - * NL80211_CMD_AUTHENTICATE, NL80211_CMD_DEAUTHENTICATE, - * NL80211_CMD_DISASSOCIATE. - * - * @NL80211_ATTR_AP_ISOLATE: (AP mode) Do not forward traffic between stations - * connected to this BSS. - * - * @NL80211_ATTR_WIPHY_TX_POWER_SETTING: Transmit power setting type. See - * &enum nl80211_tx_power_setting for possible values. - * @NL80211_ATTR_WIPHY_TX_POWER_LEVEL: Transmit power level in signed mBm units. - * This is used in association with @NL80211_ATTR_WIPHY_TX_POWER_SETTING - * for non-automatic settings. - * - * @NL80211_ATTR_SUPPORT_IBSS_RSN: The device supports IBSS RSN, which mostly - * means support for per-station GTKs. - * - * @NL80211_ATTR_WIPHY_ANTENNA_TX: Bitmap of allowed antennas for transmitting. - * This can be used to mask out antennas which are not attached or should - * not be used for transmitting. If an antenna is not selected in this - * bitmap the hardware is not allowed to transmit on this antenna. - * - * Each bit represents one antenna, starting with antenna 1 at the first - * bit. Depending on which antennas are selected in the bitmap, 802.11n - * drivers can derive which chainmasks to use (if all antennas belonging to - * a particular chain are disabled this chain should be disabled) and if - * a chain has diversity antennas wether diversity should be used or not. - * HT capabilities (STBC, TX Beamforming, Antenna selection) can be - * derived from the available chains after applying the antenna mask. - * Non-802.11n drivers can derive wether to use diversity or not. - * Drivers may reject configurations or RX/TX mask combinations they cannot - * support by returning -EINVAL. - * - * @NL80211_ATTR_WIPHY_ANTENNA_RX: Bitmap of allowed antennas for receiving. - * This can be used to mask out antennas which are not attached or should - * not be used for receiving. If an antenna is not selected in this bitmap - * the hardware should not be configured to receive on this antenna. - * For a more detailed descripton see @NL80211_ATTR_WIPHY_ANTENNA_TX. - * - * @NL80211_ATTR_MCAST_RATE: Multicast tx rate (in 100 kbps) for IBSS - * - * @NL80211_ATTR_OFFCHANNEL_TX_OK: For management frame TX, the frame may be - * transmitted on another channel when the channel given doesn't match - * the current channel. If the current channel doesn't match and this - * flag isn't set, the frame will be rejected. This is also used as an - * nl80211 capability flag. - * - * @NL80211_ATTR_BSS_HTOPMODE: HT operation mode (u16) - * - * @NL80211_ATTR_KEY_DEFAULT_TYPES: A nested attribute containing flags - * attributes, specifying what a key should be set as default as. - * See &enum nl80211_key_default_types. - * - * @NL80211_ATTR_MAX: highest attribute number currently defined - * @__NL80211_ATTR_AFTER_LAST: internal use - */ -enum nl80211_attrs { -/* don't change the order or add anything inbetween, this is ABI! */ - NL80211_ATTR_UNSPEC, - - NL80211_ATTR_WIPHY, - NL80211_ATTR_WIPHY_NAME, - - NL80211_ATTR_IFINDEX, - NL80211_ATTR_IFNAME, - NL80211_ATTR_IFTYPE, - - NL80211_ATTR_MAC, - - NL80211_ATTR_KEY_DATA, - NL80211_ATTR_KEY_IDX, - NL80211_ATTR_KEY_CIPHER, - NL80211_ATTR_KEY_SEQ, - NL80211_ATTR_KEY_DEFAULT, - - NL80211_ATTR_BEACON_INTERVAL, - NL80211_ATTR_DTIM_PERIOD, - NL80211_ATTR_BEACON_HEAD, - NL80211_ATTR_BEACON_TAIL, - - NL80211_ATTR_STA_AID, - NL80211_ATTR_STA_FLAGS, - NL80211_ATTR_STA_LISTEN_INTERVAL, - NL80211_ATTR_STA_SUPPORTED_RATES, - NL80211_ATTR_STA_VLAN, - NL80211_ATTR_STA_INFO, - - NL80211_ATTR_WIPHY_BANDS, - - NL80211_ATTR_MNTR_FLAGS, - - NL80211_ATTR_MESH_ID, - NL80211_ATTR_STA_PLINK_ACTION, - NL80211_ATTR_MPATH_NEXT_HOP, - NL80211_ATTR_MPATH_INFO, - - NL80211_ATTR_BSS_CTS_PROT, - NL80211_ATTR_BSS_SHORT_PREAMBLE, - NL80211_ATTR_BSS_SHORT_SLOT_TIME, - - NL80211_ATTR_HT_CAPABILITY, - - NL80211_ATTR_SUPPORTED_IFTYPES, - - NL80211_ATTR_REG_ALPHA2, - NL80211_ATTR_REG_RULES, - - NL80211_ATTR_MESH_PARAMS, - - NL80211_ATTR_BSS_BASIC_RATES, - - NL80211_ATTR_WIPHY_TXQ_PARAMS, - NL80211_ATTR_WIPHY_FREQ, - NL80211_ATTR_WIPHY_CHANNEL_TYPE, - - NL80211_ATTR_KEY_DEFAULT_MGMT, - - NL80211_ATTR_MGMT_SUBTYPE, - NL80211_ATTR_IE, - - NL80211_ATTR_MAX_NUM_SCAN_SSIDS, - - NL80211_ATTR_SCAN_FREQUENCIES, - NL80211_ATTR_SCAN_SSIDS, - NL80211_ATTR_GENERATION, /* replaces old SCAN_GENERATION */ - NL80211_ATTR_BSS, - - NL80211_ATTR_REG_INITIATOR, - NL80211_ATTR_REG_TYPE, - - NL80211_ATTR_SUPPORTED_COMMANDS, - - NL80211_ATTR_FRAME, - NL80211_ATTR_SSID, - NL80211_ATTR_AUTH_TYPE, - NL80211_ATTR_REASON_CODE, - - NL80211_ATTR_KEY_TYPE, - - NL80211_ATTR_MAX_SCAN_IE_LEN, - NL80211_ATTR_CIPHER_SUITES, - - NL80211_ATTR_FREQ_BEFORE, - NL80211_ATTR_FREQ_AFTER, - - NL80211_ATTR_FREQ_FIXED, - - - NL80211_ATTR_WIPHY_RETRY_SHORT, - NL80211_ATTR_WIPHY_RETRY_LONG, - NL80211_ATTR_WIPHY_FRAG_THRESHOLD, - NL80211_ATTR_WIPHY_RTS_THRESHOLD, - - NL80211_ATTR_TIMED_OUT, - - NL80211_ATTR_USE_MFP, - - NL80211_ATTR_STA_FLAGS2, - - NL80211_ATTR_CONTROL_PORT, - - NL80211_ATTR_TESTDATA, - - NL80211_ATTR_PRIVACY, - - NL80211_ATTR_DISCONNECTED_BY_AP, - NL80211_ATTR_STATUS_CODE, - - NL80211_ATTR_CIPHER_SUITES_PAIRWISE, - NL80211_ATTR_CIPHER_SUITE_GROUP, - NL80211_ATTR_WPA_VERSIONS, - NL80211_ATTR_AKM_SUITES, - - NL80211_ATTR_REQ_IE, - NL80211_ATTR_RESP_IE, - - NL80211_ATTR_PREV_BSSID, - - NL80211_ATTR_KEY, - NL80211_ATTR_KEYS, - - NL80211_ATTR_PID, - - NL80211_ATTR_4ADDR, - - NL80211_ATTR_SURVEY_INFO, - - NL80211_ATTR_PMKID, - NL80211_ATTR_MAX_NUM_PMKIDS, - - NL80211_ATTR_DURATION, - - NL80211_ATTR_COOKIE, - - NL80211_ATTR_WIPHY_COVERAGE_CLASS, - - NL80211_ATTR_TX_RATES, - - NL80211_ATTR_FRAME_MATCH, - - NL80211_ATTR_ACK, - - NL80211_ATTR_PS_STATE, - - NL80211_ATTR_CQM, - - NL80211_ATTR_LOCAL_STATE_CHANGE, - - NL80211_ATTR_AP_ISOLATE, - - NL80211_ATTR_WIPHY_TX_POWER_SETTING, - NL80211_ATTR_WIPHY_TX_POWER_LEVEL, - - NL80211_ATTR_TX_FRAME_TYPES, - NL80211_ATTR_RX_FRAME_TYPES, - NL80211_ATTR_FRAME_TYPE, - - NL80211_ATTR_CONTROL_PORT_ETHERTYPE, - NL80211_ATTR_CONTROL_PORT_NO_ENCRYPT, - - NL80211_ATTR_SUPPORT_IBSS_RSN, - - NL80211_ATTR_WIPHY_ANTENNA_TX, - NL80211_ATTR_WIPHY_ANTENNA_RX, - - NL80211_ATTR_MCAST_RATE, - - NL80211_ATTR_OFFCHANNEL_TX_OK, - - NL80211_ATTR_BSS_HT_OPMODE, - - NL80211_ATTR_KEY_DEFAULT_TYPES, - - NL80211_ATTR_MAX_REMAIN_ON_CHANNEL_DURATION, - - /* add attributes here, update the policy in nl80211.c */ - - __NL80211_ATTR_AFTER_LAST, - NL80211_ATTR_MAX = __NL80211_ATTR_AFTER_LAST - 1 -}; - -/* source-level API compatibility */ -#define NL80211_ATTR_SCAN_GENERATION NL80211_ATTR_GENERATION - -/* - * Allow user space programs to use #ifdef on new attributes by defining them - * here - */ -#define NL80211_CMD_CONNECT NL80211_CMD_CONNECT -#define NL80211_ATTR_HT_CAPABILITY NL80211_ATTR_HT_CAPABILITY -#define NL80211_ATTR_BSS_BASIC_RATES NL80211_ATTR_BSS_BASIC_RATES -#define NL80211_ATTR_WIPHY_TXQ_PARAMS NL80211_ATTR_WIPHY_TXQ_PARAMS -#define NL80211_ATTR_WIPHY_FREQ NL80211_ATTR_WIPHY_FREQ -#define NL80211_ATTR_WIPHY_CHANNEL_TYPE NL80211_ATTR_WIPHY_CHANNEL_TYPE -#define NL80211_ATTR_MGMT_SUBTYPE NL80211_ATTR_MGMT_SUBTYPE -#define NL80211_ATTR_IE NL80211_ATTR_IE -#define NL80211_ATTR_REG_INITIATOR NL80211_ATTR_REG_INITIATOR -#define NL80211_ATTR_REG_TYPE NL80211_ATTR_REG_TYPE -#define NL80211_ATTR_FRAME NL80211_ATTR_FRAME -#define NL80211_ATTR_SSID NL80211_ATTR_SSID -#define NL80211_ATTR_AUTH_TYPE NL80211_ATTR_AUTH_TYPE -#define NL80211_ATTR_REASON_CODE NL80211_ATTR_REASON_CODE -#define NL80211_ATTR_CIPHER_SUITES_PAIRWISE NL80211_ATTR_CIPHER_SUITES_PAIRWISE -#define NL80211_ATTR_CIPHER_SUITE_GROUP NL80211_ATTR_CIPHER_SUITE_GROUP -#define NL80211_ATTR_WPA_VERSIONS NL80211_ATTR_WPA_VERSIONS -#define NL80211_ATTR_AKM_SUITES NL80211_ATTR_AKM_SUITES -#define NL80211_ATTR_KEY NL80211_ATTR_KEY -#define NL80211_ATTR_KEYS NL80211_ATTR_KEYS - -#define NL80211_MAX_SUPP_RATES 32 -#define NL80211_MAX_SUPP_REG_RULES 32 -#define NL80211_TKIP_DATA_OFFSET_ENCR_KEY 0 -#define NL80211_TKIP_DATA_OFFSET_TX_MIC_KEY 16 -#define NL80211_TKIP_DATA_OFFSET_RX_MIC_KEY 24 -#define NL80211_HT_CAPABILITY_LEN 26 - -#define NL80211_MAX_NR_CIPHER_SUITES 5 -#define NL80211_MAX_NR_AKM_SUITES 2 - -/** - * enum nl80211_iftype - (virtual) interface types - * - * @NL80211_IFTYPE_UNSPECIFIED: unspecified type, driver decides - * @NL80211_IFTYPE_ADHOC: independent BSS member - * @NL80211_IFTYPE_STATION: managed BSS member - * @NL80211_IFTYPE_AP: access point - * @NL80211_IFTYPE_AP_VLAN: VLAN interface for access points - * @NL80211_IFTYPE_WDS: wireless distribution interface - * @NL80211_IFTYPE_MONITOR: monitor interface receiving all frames - * @NL80211_IFTYPE_MESH_POINT: mesh point - * @NL80211_IFTYPE_P2P_CLIENT: P2P client - * @NL80211_IFTYPE_P2P_GO: P2P group owner - * @NL80211_IFTYPE_MAX: highest interface type number currently defined - * @NUM_NL80211_IFTYPES: number of defined interface types - * - * These values are used with the %NL80211_ATTR_IFTYPE - * to set the type of an interface. - * - */ -enum nl80211_iftype { - NL80211_IFTYPE_UNSPECIFIED, - NL80211_IFTYPE_ADHOC, - NL80211_IFTYPE_STATION, - NL80211_IFTYPE_AP, - NL80211_IFTYPE_AP_VLAN, - NL80211_IFTYPE_WDS, - NL80211_IFTYPE_MONITOR, - NL80211_IFTYPE_MESH_POINT, - NL80211_IFTYPE_P2P_CLIENT, - NL80211_IFTYPE_P2P_GO, - - /* keep last */ - NUM_NL80211_IFTYPES, - NL80211_IFTYPE_MAX = NUM_NL80211_IFTYPES - 1 -}; - -/** - * enum nl80211_sta_flags - station flags - * - * Station flags. When a station is added to an AP interface, it is - * assumed to be already associated (and hence authenticated.) - * - * @__NL80211_STA_FLAG_INVALID: attribute number 0 is reserved - * @NL80211_STA_FLAG_AUTHORIZED: station is authorized (802.1X) - * @NL80211_STA_FLAG_SHORT_PREAMBLE: station is capable of receiving frames - * with short barker preamble - * @NL80211_STA_FLAG_WME: station is WME/QoS capable - * @NL80211_STA_FLAG_MFP: station uses management frame protection - * @NL80211_STA_FLAG_MAX: highest station flag number currently defined - * @__NL80211_STA_FLAG_AFTER_LAST: internal use - */ -enum nl80211_sta_flags { - __NL80211_STA_FLAG_INVALID, - NL80211_STA_FLAG_AUTHORIZED, - NL80211_STA_FLAG_SHORT_PREAMBLE, - NL80211_STA_FLAG_WME, - NL80211_STA_FLAG_MFP, - - /* keep last */ - __NL80211_STA_FLAG_AFTER_LAST, - NL80211_STA_FLAG_MAX = __NL80211_STA_FLAG_AFTER_LAST - 1 -}; - -/** - * struct nl80211_sta_flag_update - station flags mask/set - * @mask: mask of station flags to set - * @set: which values to set them to - * - * Both mask and set contain bits as per &enum nl80211_sta_flags. - */ -struct nl80211_sta_flag_update { - __u32 mask; - __u32 set; -} __attribute__((packed)); - -/** - * enum nl80211_rate_info - bitrate information - * - * These attribute types are used with %NL80211_STA_INFO_TXRATE - * when getting information about the bitrate of a station. - * - * @__NL80211_RATE_INFO_INVALID: attribute number 0 is reserved - * @NL80211_RATE_INFO_BITRATE: total bitrate (u16, 100kbit/s) - * @NL80211_RATE_INFO_MCS: mcs index for 802.11n (u8) - * @NL80211_RATE_INFO_40_MHZ_WIDTH: 40 Mhz dualchannel bitrate - * @NL80211_RATE_INFO_SHORT_GI: 400ns guard interval - * @NL80211_RATE_INFO_MAX: highest rate_info number currently defined - * @__NL80211_RATE_INFO_AFTER_LAST: internal use - */ -enum nl80211_rate_info { - __NL80211_RATE_INFO_INVALID, - NL80211_RATE_INFO_BITRATE, - NL80211_RATE_INFO_MCS, - NL80211_RATE_INFO_40_MHZ_WIDTH, - NL80211_RATE_INFO_SHORT_GI, - - /* keep last */ - __NL80211_RATE_INFO_AFTER_LAST, - NL80211_RATE_INFO_MAX = __NL80211_RATE_INFO_AFTER_LAST - 1 -}; - -/** - * enum nl80211_sta_info - station information - * - * These attribute types are used with %NL80211_ATTR_STA_INFO - * when getting information about a station. - * - * @__NL80211_STA_INFO_INVALID: attribute number 0 is reserved - * @NL80211_STA_INFO_INACTIVE_TIME: time since last activity (u32, msecs) - * @NL80211_STA_INFO_RX_BYTES: total received bytes (u32, from this station) - * @NL80211_STA_INFO_TX_BYTES: total transmitted bytes (u32, to this station) - * @__NL80211_STA_INFO_AFTER_LAST: internal - * @NL80211_STA_INFO_MAX: highest possible station info attribute - * @NL80211_STA_INFO_SIGNAL: signal strength of last received PPDU (u8, dBm) - * @NL80211_STA_INFO_TX_BITRATE: current unicast tx rate, nested attribute - * containing info as possible, see &enum nl80211_sta_info_txrate. - * @NL80211_STA_INFO_RX_PACKETS: total received packet (u32, from this station) - * @NL80211_STA_INFO_TX_PACKETS: total transmitted packets (u32, to this - * station) - * @NL80211_STA_INFO_TX_RETRIES: total retries (u32, to this station) - * @NL80211_STA_INFO_TX_FAILED: total failed packets (u32, to this station) - * @NL80211_STA_INFO_SIGNAL_AVG: signal strength average (u8, dBm) - */ -enum nl80211_sta_info { - __NL80211_STA_INFO_INVALID, - NL80211_STA_INFO_INACTIVE_TIME, - NL80211_STA_INFO_RX_BYTES, - NL80211_STA_INFO_TX_BYTES, - NL80211_STA_INFO_LLID, - NL80211_STA_INFO_PLID, - NL80211_STA_INFO_PLINK_STATE, - NL80211_STA_INFO_SIGNAL, - NL80211_STA_INFO_TX_BITRATE, - NL80211_STA_INFO_RX_PACKETS, - NL80211_STA_INFO_TX_PACKETS, - NL80211_STA_INFO_TX_RETRIES, - NL80211_STA_INFO_TX_FAILED, - NL80211_STA_INFO_SIGNAL_AVG, - - /* keep last */ - __NL80211_STA_INFO_AFTER_LAST, - NL80211_STA_INFO_MAX = __NL80211_STA_INFO_AFTER_LAST - 1 -}; - -/** - * enum nl80211_mpath_flags - nl80211 mesh path flags - * - * @NL80211_MPATH_FLAG_ACTIVE: the mesh path is active - * @NL80211_MPATH_FLAG_RESOLVING: the mesh path discovery process is running - * @NL80211_MPATH_FLAG_SN_VALID: the mesh path contains a valid SN - * @NL80211_MPATH_FLAG_FIXED: the mesh path has been manually set - * @NL80211_MPATH_FLAG_RESOLVED: the mesh path discovery process succeeded - */ -enum nl80211_mpath_flags { - NL80211_MPATH_FLAG_ACTIVE = 1<<0, - NL80211_MPATH_FLAG_RESOLVING = 1<<1, - NL80211_MPATH_FLAG_SN_VALID = 1<<2, - NL80211_MPATH_FLAG_FIXED = 1<<3, - NL80211_MPATH_FLAG_RESOLVED = 1<<4, -}; - -/** - * enum nl80211_mpath_info - mesh path information - * - * These attribute types are used with %NL80211_ATTR_MPATH_INFO when getting - * information about a mesh path. - * - * @__NL80211_MPATH_INFO_INVALID: attribute number 0 is reserved - * @NL80211_MPATH_INFO_FRAME_QLEN: number of queued frames for this destination - * @NL80211_MPATH_INFO_SN: destination sequence number - * @NL80211_MPATH_INFO_METRIC: metric (cost) of this mesh path - * @NL80211_MPATH_INFO_EXPTIME: expiration time for the path, in msec from now - * @NL80211_MPATH_INFO_FLAGS: mesh path flags, enumerated in - * &enum nl80211_mpath_flags; - * @NL80211_MPATH_INFO_DISCOVERY_TIMEOUT: total path discovery timeout, in msec - * @NL80211_MPATH_INFO_DISCOVERY_RETRIES: mesh path discovery retries - * @NL80211_MPATH_INFO_MAX: highest mesh path information attribute number - * currently defind - * @__NL80211_MPATH_INFO_AFTER_LAST: internal use - */ -enum nl80211_mpath_info { - __NL80211_MPATH_INFO_INVALID, - NL80211_MPATH_INFO_FRAME_QLEN, - NL80211_MPATH_INFO_SN, - NL80211_MPATH_INFO_METRIC, - NL80211_MPATH_INFO_EXPTIME, - NL80211_MPATH_INFO_FLAGS, - NL80211_MPATH_INFO_DISCOVERY_TIMEOUT, - NL80211_MPATH_INFO_DISCOVERY_RETRIES, - - /* keep last */ - __NL80211_MPATH_INFO_AFTER_LAST, - NL80211_MPATH_INFO_MAX = __NL80211_MPATH_INFO_AFTER_LAST - 1 -}; - -/** - * enum nl80211_band_attr - band attributes - * @__NL80211_BAND_ATTR_INVALID: attribute number 0 is reserved - * @NL80211_BAND_ATTR_FREQS: supported frequencies in this band, - * an array of nested frequency attributes - * @NL80211_BAND_ATTR_RATES: supported bitrates in this band, - * an array of nested bitrate attributes - * @NL80211_BAND_ATTR_HT_MCS_SET: 16-byte attribute containing the MCS set as - * defined in 802.11n - * @NL80211_BAND_ATTR_HT_CAPA: HT capabilities, as in the HT information IE - * @NL80211_BAND_ATTR_HT_AMPDU_FACTOR: A-MPDU factor, as in 11n - * @NL80211_BAND_ATTR_HT_AMPDU_DENSITY: A-MPDU density, as in 11n - * @NL80211_BAND_ATTR_MAX: highest band attribute currently defined - * @__NL80211_BAND_ATTR_AFTER_LAST: internal use - */ -enum nl80211_band_attr { - __NL80211_BAND_ATTR_INVALID, - NL80211_BAND_ATTR_FREQS, - NL80211_BAND_ATTR_RATES, - - NL80211_BAND_ATTR_HT_MCS_SET, - NL80211_BAND_ATTR_HT_CAPA, - NL80211_BAND_ATTR_HT_AMPDU_FACTOR, - NL80211_BAND_ATTR_HT_AMPDU_DENSITY, - - /* keep last */ - __NL80211_BAND_ATTR_AFTER_LAST, - NL80211_BAND_ATTR_MAX = __NL80211_BAND_ATTR_AFTER_LAST - 1 -}; - -#define NL80211_BAND_ATTR_HT_CAPA NL80211_BAND_ATTR_HT_CAPA - -/** - * enum nl80211_frequency_attr - frequency attributes - * @__NL80211_FREQUENCY_ATTR_INVALID: attribute number 0 is reserved - * @NL80211_FREQUENCY_ATTR_FREQ: Frequency in MHz - * @NL80211_FREQUENCY_ATTR_DISABLED: Channel is disabled in current - * regulatory domain. - * @NL80211_FREQUENCY_ATTR_PASSIVE_SCAN: Only passive scanning is - * permitted on this channel in current regulatory domain. - * @NL80211_FREQUENCY_ATTR_NO_IBSS: IBSS networks are not permitted - * on this channel in current regulatory domain. - * @NL80211_FREQUENCY_ATTR_RADAR: Radar detection is mandatory - * on this channel in current regulatory domain. - * @NL80211_FREQUENCY_ATTR_MAX_TX_POWER: Maximum transmission power in mBm - * (100 * dBm). - * @NL80211_FREQUENCY_ATTR_MAX: highest frequency attribute number - * currently defined - * @__NL80211_FREQUENCY_ATTR_AFTER_LAST: internal use - */ -enum nl80211_frequency_attr { - __NL80211_FREQUENCY_ATTR_INVALID, - NL80211_FREQUENCY_ATTR_FREQ, - NL80211_FREQUENCY_ATTR_DISABLED, - NL80211_FREQUENCY_ATTR_PASSIVE_SCAN, - NL80211_FREQUENCY_ATTR_NO_IBSS, - NL80211_FREQUENCY_ATTR_RADAR, - NL80211_FREQUENCY_ATTR_MAX_TX_POWER, - - /* keep last */ - __NL80211_FREQUENCY_ATTR_AFTER_LAST, - NL80211_FREQUENCY_ATTR_MAX = __NL80211_FREQUENCY_ATTR_AFTER_LAST - 1 -}; - -#define NL80211_FREQUENCY_ATTR_MAX_TX_POWER NL80211_FREQUENCY_ATTR_MAX_TX_POWER - -/** - * enum nl80211_bitrate_attr - bitrate attributes - * @__NL80211_BITRATE_ATTR_INVALID: attribute number 0 is reserved - * @NL80211_BITRATE_ATTR_RATE: Bitrate in units of 100 kbps - * @NL80211_BITRATE_ATTR_2GHZ_SHORTPREAMBLE: Short preamble supported - * in 2.4 GHz band. - * @NL80211_BITRATE_ATTR_MAX: highest bitrate attribute number - * currently defined - * @__NL80211_BITRATE_ATTR_AFTER_LAST: internal use - */ -enum nl80211_bitrate_attr { - __NL80211_BITRATE_ATTR_INVALID, - NL80211_BITRATE_ATTR_RATE, - NL80211_BITRATE_ATTR_2GHZ_SHORTPREAMBLE, - - /* keep last */ - __NL80211_BITRATE_ATTR_AFTER_LAST, - NL80211_BITRATE_ATTR_MAX = __NL80211_BITRATE_ATTR_AFTER_LAST - 1 -}; - -/** - * enum nl80211_initiator - Indicates the initiator of a reg domain request - * @NL80211_REGDOM_SET_BY_CORE: Core queried CRDA for a dynamic world - * regulatory domain. - * @NL80211_REGDOM_SET_BY_USER: User asked the wireless core to set the - * regulatory domain. - * @NL80211_REGDOM_SET_BY_DRIVER: a wireless drivers has hinted to the - * wireless core it thinks its knows the regulatory domain we should be in. - * @NL80211_REGDOM_SET_BY_COUNTRY_IE: the wireless core has received an - * 802.11 country information element with regulatory information it - * thinks we should consider. cfg80211 only processes the country - * code from the IE, and relies on the regulatory domain information - * structure pased by userspace (CRDA) from our wireless-regdb. - * If a channel is enabled but the country code indicates it should - * be disabled we disable the channel and re-enable it upon disassociation. - */ -enum nl80211_reg_initiator { - NL80211_REGDOM_SET_BY_CORE, - NL80211_REGDOM_SET_BY_USER, - NL80211_REGDOM_SET_BY_DRIVER, - NL80211_REGDOM_SET_BY_COUNTRY_IE, -}; - -/** - * enum nl80211_reg_type - specifies the type of regulatory domain - * @NL80211_REGDOM_TYPE_COUNTRY: the regulatory domain set is one that pertains - * to a specific country. When this is set you can count on the - * ISO / IEC 3166 alpha2 country code being valid. - * @NL80211_REGDOM_TYPE_WORLD: the regulatory set domain is the world regulatory - * domain. - * @NL80211_REGDOM_TYPE_CUSTOM_WORLD: the regulatory domain set is a custom - * driver specific world regulatory domain. These do not apply system-wide - * and are only applicable to the individual devices which have requested - * them to be applied. - * @NL80211_REGDOM_TYPE_INTERSECTION: the regulatory domain set is the product - * of an intersection between two regulatory domains -- the previously - * set regulatory domain on the system and the last accepted regulatory - * domain request to be processed. - */ -enum nl80211_reg_type { - NL80211_REGDOM_TYPE_COUNTRY, - NL80211_REGDOM_TYPE_WORLD, - NL80211_REGDOM_TYPE_CUSTOM_WORLD, - NL80211_REGDOM_TYPE_INTERSECTION, -}; - -/** - * enum nl80211_reg_rule_attr - regulatory rule attributes - * @__NL80211_REG_RULE_ATTR_INVALID: attribute number 0 is reserved - * @NL80211_ATTR_REG_RULE_FLAGS: a set of flags which specify additional - * considerations for a given frequency range. These are the - * &enum nl80211_reg_rule_flags. - * @NL80211_ATTR_FREQ_RANGE_START: starting frequencry for the regulatory - * rule in KHz. This is not a center of frequency but an actual regulatory - * band edge. - * @NL80211_ATTR_FREQ_RANGE_END: ending frequency for the regulatory rule - * in KHz. This is not a center a frequency but an actual regulatory - * band edge. - * @NL80211_ATTR_FREQ_RANGE_MAX_BW: maximum allowed bandwidth for this - * frequency range, in KHz. - * @NL80211_ATTR_POWER_RULE_MAX_ANT_GAIN: the maximum allowed antenna gain - * for a given frequency range. The value is in mBi (100 * dBi). - * If you don't have one then don't send this. - * @NL80211_ATTR_POWER_RULE_MAX_EIRP: the maximum allowed EIRP for - * a given frequency range. The value is in mBm (100 * dBm). - * @NL80211_REG_RULE_ATTR_MAX: highest regulatory rule attribute number - * currently defined - * @__NL80211_REG_RULE_ATTR_AFTER_LAST: internal use - */ -enum nl80211_reg_rule_attr { - __NL80211_REG_RULE_ATTR_INVALID, - NL80211_ATTR_REG_RULE_FLAGS, - - NL80211_ATTR_FREQ_RANGE_START, - NL80211_ATTR_FREQ_RANGE_END, - NL80211_ATTR_FREQ_RANGE_MAX_BW, - - NL80211_ATTR_POWER_RULE_MAX_ANT_GAIN, - NL80211_ATTR_POWER_RULE_MAX_EIRP, - - /* keep last */ - __NL80211_REG_RULE_ATTR_AFTER_LAST, - NL80211_REG_RULE_ATTR_MAX = __NL80211_REG_RULE_ATTR_AFTER_LAST - 1 -}; - -/** - * enum nl80211_reg_rule_flags - regulatory rule flags - * - * @NL80211_RRF_NO_OFDM: OFDM modulation not allowed - * @NL80211_RRF_NO_CCK: CCK modulation not allowed - * @NL80211_RRF_NO_INDOOR: indoor operation not allowed - * @NL80211_RRF_NO_OUTDOOR: outdoor operation not allowed - * @NL80211_RRF_DFS: DFS support is required to be used - * @NL80211_RRF_PTP_ONLY: this is only for Point To Point links - * @NL80211_RRF_PTMP_ONLY: this is only for Point To Multi Point links - * @NL80211_RRF_PASSIVE_SCAN: passive scan is required - * @NL80211_RRF_NO_IBSS: no IBSS is allowed - */ -enum nl80211_reg_rule_flags { - NL80211_RRF_NO_OFDM = 1<<0, - NL80211_RRF_NO_CCK = 1<<1, - NL80211_RRF_NO_INDOOR = 1<<2, - NL80211_RRF_NO_OUTDOOR = 1<<3, - NL80211_RRF_DFS = 1<<4, - NL80211_RRF_PTP_ONLY = 1<<5, - NL80211_RRF_PTMP_ONLY = 1<<6, - NL80211_RRF_PASSIVE_SCAN = 1<<7, - NL80211_RRF_NO_IBSS = 1<<8, -}; - -/** - * enum nl80211_survey_info - survey information - * - * These attribute types are used with %NL80211_ATTR_SURVEY_INFO - * when getting information about a survey. - * - * @__NL80211_SURVEY_INFO_INVALID: attribute number 0 is reserved - * @NL80211_SURVEY_INFO_FREQUENCY: center frequency of channel - * @NL80211_SURVEY_INFO_NOISE: noise level of channel (u8, dBm) - * @NL80211_SURVEY_INFO_IN_USE: channel is currently being used - * @NL80211_SURVEY_INFO_CHANNEL_TIME: amount of time (in ms) that the radio - * spent on this channel - * @NL80211_SURVEY_INFO_CHANNEL_TIME_BUSY: amount of the time the primary - * channel was sensed busy (either due to activity or energy detect) - * @NL80211_SURVEY_INFO_CHANNEL_TIME_EXT_BUSY: amount of time the extension - * channel was sensed busy - * @NL80211_SURVEY_INFO_CHANNEL_TIME_RX: amount of time the radio spent - * receiving data - * @NL80211_SURVEY_INFO_CHANNEL_TIME_TX: amount of time the radio spent - * transmitting data - * @NL80211_SURVEY_INFO_MAX: highest survey info attribute number - * currently defined - * @__NL80211_SURVEY_INFO_AFTER_LAST: internal use - */ -enum nl80211_survey_info { - __NL80211_SURVEY_INFO_INVALID, - NL80211_SURVEY_INFO_FREQUENCY, - NL80211_SURVEY_INFO_NOISE, - NL80211_SURVEY_INFO_IN_USE, - NL80211_SURVEY_INFO_CHANNEL_TIME, - NL80211_SURVEY_INFO_CHANNEL_TIME_BUSY, - NL80211_SURVEY_INFO_CHANNEL_TIME_EXT_BUSY, - NL80211_SURVEY_INFO_CHANNEL_TIME_RX, - NL80211_SURVEY_INFO_CHANNEL_TIME_TX, - - /* keep last */ - __NL80211_SURVEY_INFO_AFTER_LAST, - NL80211_SURVEY_INFO_MAX = __NL80211_SURVEY_INFO_AFTER_LAST - 1 -}; - -/** - * enum nl80211_mntr_flags - monitor configuration flags - * - * Monitor configuration flags. - * - * @__NL80211_MNTR_FLAG_INVALID: reserved - * - * @NL80211_MNTR_FLAG_FCSFAIL: pass frames with bad FCS - * @NL80211_MNTR_FLAG_PLCPFAIL: pass frames with bad PLCP - * @NL80211_MNTR_FLAG_CONTROL: pass control frames - * @NL80211_MNTR_FLAG_OTHER_BSS: disable BSSID filtering - * @NL80211_MNTR_FLAG_COOK_FRAMES: report frames after processing. - * overrides all other flags. - * - * @__NL80211_MNTR_FLAG_AFTER_LAST: internal use - * @NL80211_MNTR_FLAG_MAX: highest possible monitor flag - */ -enum nl80211_mntr_flags { - __NL80211_MNTR_FLAG_INVALID, - NL80211_MNTR_FLAG_FCSFAIL, - NL80211_MNTR_FLAG_PLCPFAIL, - NL80211_MNTR_FLAG_CONTROL, - NL80211_MNTR_FLAG_OTHER_BSS, - NL80211_MNTR_FLAG_COOK_FRAMES, - - /* keep last */ - __NL80211_MNTR_FLAG_AFTER_LAST, - NL80211_MNTR_FLAG_MAX = __NL80211_MNTR_FLAG_AFTER_LAST - 1 -}; - -/** - * enum nl80211_meshconf_params - mesh configuration parameters - * - * Mesh configuration parameters - * - * @__NL80211_MESHCONF_INVALID: internal use - * - * @NL80211_MESHCONF_RETRY_TIMEOUT: specifies the initial retry timeout in - * millisecond units, used by the Peer Link Open message - * - * @NL80211_MESHCONF_CONFIRM_TIMEOUT: specifies the inital confirm timeout, in - * millisecond units, used by the peer link management to close a peer link - * - * @NL80211_MESHCONF_HOLDING_TIMEOUT: specifies the holding timeout, in - * millisecond units - * - * @NL80211_MESHCONF_MAX_PEER_LINKS: maximum number of peer links allowed - * on this mesh interface - * - * @NL80211_MESHCONF_MAX_RETRIES: specifies the maximum number of peer link - * open retries that can be sent to establish a new peer link instance in a - * mesh - * - * @NL80211_MESHCONF_TTL: specifies the value of TTL field set at a source mesh - * point. - * - * @NL80211_MESHCONF_ELEMENT_TTL: specifies the value of TTL field set at a - * source mesh point for path selection elements. - * - * @NL80211_MESHCONF_AUTO_OPEN_PLINKS: whether we should automatically - * open peer links when we detect compatible mesh peers. - * - * @NL80211_MESHCONF_HWMP_MAX_PREQ_RETRIES: the number of action frames - * containing a PREQ that an MP can send to a particular destination (path - * target) - * - * @NL80211_MESHCONF_PATH_REFRESH_TIME: how frequently to refresh mesh paths - * (in milliseconds) - * - * @NL80211_MESHCONF_MIN_DISCOVERY_TIMEOUT: minimum length of time to wait - * until giving up on a path discovery (in milliseconds) - * - * @NL80211_MESHCONF_HWMP_ACTIVE_PATH_TIMEOUT: The time (in TUs) for which mesh - * points receiving a PREQ shall consider the forwarding information from the - * root to be valid. (TU = time unit) - * - * @NL80211_MESHCONF_HWMP_PREQ_MIN_INTERVAL: The minimum interval of time (in - * TUs) during which an MP can send only one action frame containing a PREQ - * reference element - * - * @NL80211_MESHCONF_HWMP_NET_DIAM_TRVS_TIME: The interval of time (in TUs) - * that it takes for an HWMP information element to propagate across the mesh - * - * @NL80211_MESHCONF_ROOTMODE: whether root mode is enabled or not - * - * @NL80211_MESHCONF_ATTR_MAX: highest possible mesh configuration attribute - * - * @__NL80211_MESHCONF_ATTR_AFTER_LAST: internal use - */ -enum nl80211_meshconf_params { - __NL80211_MESHCONF_INVALID, - NL80211_MESHCONF_RETRY_TIMEOUT, - NL80211_MESHCONF_CONFIRM_TIMEOUT, - NL80211_MESHCONF_HOLDING_TIMEOUT, - NL80211_MESHCONF_MAX_PEER_LINKS, - NL80211_MESHCONF_MAX_RETRIES, - NL80211_MESHCONF_TTL, - NL80211_MESHCONF_AUTO_OPEN_PLINKS, - NL80211_MESHCONF_HWMP_MAX_PREQ_RETRIES, - NL80211_MESHCONF_PATH_REFRESH_TIME, - NL80211_MESHCONF_MIN_DISCOVERY_TIMEOUT, - NL80211_MESHCONF_HWMP_ACTIVE_PATH_TIMEOUT, - NL80211_MESHCONF_HWMP_PREQ_MIN_INTERVAL, - NL80211_MESHCONF_HWMP_NET_DIAM_TRVS_TIME, - NL80211_MESHCONF_HWMP_ROOTMODE, - NL80211_MESHCONF_ELEMENT_TTL, - - /* keep last */ - __NL80211_MESHCONF_ATTR_AFTER_LAST, - NL80211_MESHCONF_ATTR_MAX = __NL80211_MESHCONF_ATTR_AFTER_LAST - 1 -}; - -/** - * enum nl80211_txq_attr - TX queue parameter attributes - * @__NL80211_TXQ_ATTR_INVALID: Attribute number 0 is reserved - * @NL80211_TXQ_ATTR_QUEUE: TX queue identifier (NL80211_TXQ_Q_*) - * @NL80211_TXQ_ATTR_TXOP: Maximum burst time in units of 32 usecs, 0 meaning - * disabled - * @NL80211_TXQ_ATTR_CWMIN: Minimum contention window [a value of the form - * 2^n-1 in the range 1..32767] - * @NL80211_TXQ_ATTR_CWMAX: Maximum contention window [a value of the form - * 2^n-1 in the range 1..32767] - * @NL80211_TXQ_ATTR_AIFS: Arbitration interframe space [0..255] - * @__NL80211_TXQ_ATTR_AFTER_LAST: Internal - * @NL80211_TXQ_ATTR_MAX: Maximum TXQ attribute number - */ -enum nl80211_txq_attr { - __NL80211_TXQ_ATTR_INVALID, - NL80211_TXQ_ATTR_QUEUE, - NL80211_TXQ_ATTR_TXOP, - NL80211_TXQ_ATTR_CWMIN, - NL80211_TXQ_ATTR_CWMAX, - NL80211_TXQ_ATTR_AIFS, - - /* keep last */ - __NL80211_TXQ_ATTR_AFTER_LAST, - NL80211_TXQ_ATTR_MAX = __NL80211_TXQ_ATTR_AFTER_LAST - 1 -}; - -enum nl80211_txq_q { - NL80211_TXQ_Q_VO, - NL80211_TXQ_Q_VI, - NL80211_TXQ_Q_BE, - NL80211_TXQ_Q_BK -}; - -enum nl80211_channel_type { - NL80211_CHAN_NO_HT, - NL80211_CHAN_HT20, - NL80211_CHAN_HT40MINUS, - NL80211_CHAN_HT40PLUS -}; - -/** - * enum nl80211_bss - netlink attributes for a BSS - * - * @__NL80211_BSS_INVALID: invalid - * @NL80211_BSS_BSSID: BSSID of the BSS (6 octets) - * @NL80211_BSS_FREQUENCY: frequency in MHz (u32) - * @NL80211_BSS_TSF: TSF of the received probe response/beacon (u64) - * @NL80211_BSS_BEACON_INTERVAL: beacon interval of the (I)BSS (u16) - * @NL80211_BSS_CAPABILITY: capability field (CPU order, u16) - * @NL80211_BSS_INFORMATION_ELEMENTS: binary attribute containing the - * raw information elements from the probe response/beacon (bin); - * if the %NL80211_BSS_BEACON_IES attribute is present, the IEs here are - * from a Probe Response frame; otherwise they are from a Beacon frame. - * However, if the driver does not indicate the source of the IEs, these - * IEs may be from either frame subtype. - * @NL80211_BSS_SIGNAL_MBM: signal strength of probe response/beacon - * in mBm (100 * dBm) (s32) - * @NL80211_BSS_SIGNAL_UNSPEC: signal strength of the probe response/beacon - * in unspecified units, scaled to 0..100 (u8) - * @NL80211_BSS_STATUS: status, if this BSS is "used" - * @NL80211_BSS_SEEN_MS_AGO: age of this BSS entry in ms - * @NL80211_BSS_BEACON_IES: binary attribute containing the raw information - * elements from a Beacon frame (bin); not present if no Beacon frame has - * yet been received - * @__NL80211_BSS_AFTER_LAST: internal - * @NL80211_BSS_MAX: highest BSS attribute - */ -enum nl80211_bss { - __NL80211_BSS_INVALID, - NL80211_BSS_BSSID, - NL80211_BSS_FREQUENCY, - NL80211_BSS_TSF, - NL80211_BSS_BEACON_INTERVAL, - NL80211_BSS_CAPABILITY, - NL80211_BSS_INFORMATION_ELEMENTS, - NL80211_BSS_SIGNAL_MBM, - NL80211_BSS_SIGNAL_UNSPEC, - NL80211_BSS_STATUS, - NL80211_BSS_SEEN_MS_AGO, - NL80211_BSS_BEACON_IES, - - /* keep last */ - __NL80211_BSS_AFTER_LAST, - NL80211_BSS_MAX = __NL80211_BSS_AFTER_LAST - 1 -}; - -/** - * enum nl80211_bss_status - BSS "status" - * @NL80211_BSS_STATUS_AUTHENTICATED: Authenticated with this BSS. - * @NL80211_BSS_STATUS_ASSOCIATED: Associated with this BSS. - * @NL80211_BSS_STATUS_IBSS_JOINED: Joined to this IBSS. - * - * The BSS status is a BSS attribute in scan dumps, which - * indicates the status the interface has wrt. this BSS. - */ -enum nl80211_bss_status { - NL80211_BSS_STATUS_AUTHENTICATED, - NL80211_BSS_STATUS_ASSOCIATED, - NL80211_BSS_STATUS_IBSS_JOINED, -}; - -/** - * enum nl80211_auth_type - AuthenticationType - * - * @NL80211_AUTHTYPE_OPEN_SYSTEM: Open System authentication - * @NL80211_AUTHTYPE_SHARED_KEY: Shared Key authentication (WEP only) - * @NL80211_AUTHTYPE_FT: Fast BSS Transition (IEEE 802.11r) - * @NL80211_AUTHTYPE_NETWORK_EAP: Network EAP (some Cisco APs and mainly LEAP) - * @__NL80211_AUTHTYPE_NUM: internal - * @NL80211_AUTHTYPE_MAX: maximum valid auth algorithm - * @NL80211_AUTHTYPE_AUTOMATIC: determine automatically (if necessary by - * trying multiple times); this is invalid in netlink -- leave out - * the attribute for this on CONNECT commands. - */ -enum nl80211_auth_type { - NL80211_AUTHTYPE_OPEN_SYSTEM, - NL80211_AUTHTYPE_SHARED_KEY, - NL80211_AUTHTYPE_FT, - NL80211_AUTHTYPE_NETWORK_EAP, - - /* keep last */ - __NL80211_AUTHTYPE_NUM, - NL80211_AUTHTYPE_MAX = __NL80211_AUTHTYPE_NUM - 1, - NL80211_AUTHTYPE_AUTOMATIC -}; - -/** - * enum nl80211_key_type - Key Type - * @NL80211_KEYTYPE_GROUP: Group (broadcast/multicast) key - * @NL80211_KEYTYPE_PAIRWISE: Pairwise (unicast/individual) key - * @NL80211_KEYTYPE_PEERKEY: PeerKey (DLS) - * @NUM_NL80211_KEYTYPES: number of defined key types - */ -enum nl80211_key_type { - NL80211_KEYTYPE_GROUP, - NL80211_KEYTYPE_PAIRWISE, - NL80211_KEYTYPE_PEERKEY, - - NUM_NL80211_KEYTYPES -}; - -/** - * enum nl80211_mfp - Management frame protection state - * @NL80211_MFP_NO: Management frame protection not used - * @NL80211_MFP_REQUIRED: Management frame protection required - */ -enum nl80211_mfp { - NL80211_MFP_NO, - NL80211_MFP_REQUIRED, -}; - -enum nl80211_wpa_versions { - NL80211_WPA_VERSION_1 = 1 << 0, - NL80211_WPA_VERSION_2 = 1 << 1, -}; - -/** - * enum nl80211_key_default_types - key default types - * @__NL80211_KEY_DEFAULT_TYPE_INVALID: invalid - * @NL80211_KEY_DEFAULT_TYPE_UNICAST: key should be used as default - * unicast key - * @NL80211_KEY_DEFAULT_TYPE_MULTICAST: key should be used as default - * multicast key - * @NUM_NL80211_KEY_DEFAULT_TYPES: number of default types - */ -enum nl80211_key_default_types { - __NL80211_KEY_DEFAULT_TYPE_INVALID, - NL80211_KEY_DEFAULT_TYPE_UNICAST, - NL80211_KEY_DEFAULT_TYPE_MULTICAST, - - NUM_NL80211_KEY_DEFAULT_TYPES -}; - -/** - * enum nl80211_key_attributes - key attributes - * @__NL80211_KEY_INVALID: invalid - * @NL80211_KEY_DATA: (temporal) key data; for TKIP this consists of - * 16 bytes encryption key followed by 8 bytes each for TX and RX MIC - * keys - * @NL80211_KEY_IDX: key ID (u8, 0-3) - * @NL80211_KEY_CIPHER: key cipher suite (u32, as defined by IEEE 802.11 - * section 7.3.2.25.1, e.g. 0x000FAC04) - * @NL80211_KEY_SEQ: transmit key sequence number (IV/PN) for TKIP and - * CCMP keys, each six bytes in little endian - * @NL80211_KEY_DEFAULT: flag indicating default key - * @NL80211_KEY_DEFAULT_MGMT: flag indicating default management key - * @NL80211_KEY_TYPE: the key type from enum nl80211_key_type, if not - * specified the default depends on whether a MAC address was - * given with the command using the key or not (u32) - * @NL80211_KEY_DEFAULT_TYPES: A nested attribute containing flags - * attributes, specifying what a key should be set as default as. - * See &enum nl80211_key_default_types. - * @__NL80211_KEY_AFTER_LAST: internal - * @NL80211_KEY_MAX: highest key attribute - */ -enum nl80211_key_attributes { - __NL80211_KEY_INVALID, - NL80211_KEY_DATA, - NL80211_KEY_IDX, - NL80211_KEY_CIPHER, - NL80211_KEY_SEQ, - NL80211_KEY_DEFAULT, - NL80211_KEY_DEFAULT_MGMT, - NL80211_KEY_TYPE, - NL80211_KEY_DEFAULT_TYPES, - - /* keep last */ - __NL80211_KEY_AFTER_LAST, - NL80211_KEY_MAX = __NL80211_KEY_AFTER_LAST - 1 -}; - -/** - * enum nl80211_tx_rate_attributes - TX rate set attributes - * @__NL80211_TXRATE_INVALID: invalid - * @NL80211_TXRATE_LEGACY: Legacy (non-MCS) rates allowed for TX rate selection - * in an array of rates as defined in IEEE 802.11 7.3.2.2 (u8 values with - * 1 = 500 kbps) but without the IE length restriction (at most - * %NL80211_MAX_SUPP_RATES in a single array). - * @__NL80211_TXRATE_AFTER_LAST: internal - * @NL80211_TXRATE_MAX: highest TX rate attribute - */ -enum nl80211_tx_rate_attributes { - __NL80211_TXRATE_INVALID, - NL80211_TXRATE_LEGACY, - - /* keep last */ - __NL80211_TXRATE_AFTER_LAST, - NL80211_TXRATE_MAX = __NL80211_TXRATE_AFTER_LAST - 1 -}; - -/** - * enum nl80211_band - Frequency band - * @NL80211_BAND_2GHZ: 2.4 GHz ISM band - * @NL80211_BAND_5GHZ: around 5 GHz band (4.9 - 5.7 GHz) - */ -enum nl80211_band { - NL80211_BAND_2GHZ, - NL80211_BAND_5GHZ, -}; - -enum nl80211_ps_state { - NL80211_PS_DISABLED, - NL80211_PS_ENABLED, -}; - -/** - * enum nl80211_attr_cqm - connection quality monitor attributes - * @__NL80211_ATTR_CQM_INVALID: invalid - * @NL80211_ATTR_CQM_RSSI_THOLD: RSSI threshold in dBm. This value specifies - * the threshold for the RSSI level at which an event will be sent. Zero - * to disable. - * @NL80211_ATTR_CQM_RSSI_HYST: RSSI hysteresis in dBm. This value specifies - * the minimum amount the RSSI level must change after an event before a - * new event may be issued (to reduce effects of RSSI oscillation). - * @NL80211_ATTR_CQM_RSSI_THRESHOLD_EVENT: RSSI threshold event - * @NL80211_ATTR_CQM_PKT_LOSS_EVENT: a u32 value indicating that this many - * consecutive packets were not acknowledged by the peer - * @__NL80211_ATTR_CQM_AFTER_LAST: internal - * @NL80211_ATTR_CQM_MAX: highest key attribute - */ -enum nl80211_attr_cqm { - __NL80211_ATTR_CQM_INVALID, - NL80211_ATTR_CQM_RSSI_THOLD, - NL80211_ATTR_CQM_RSSI_HYST, - NL80211_ATTR_CQM_RSSI_THRESHOLD_EVENT, - NL80211_ATTR_CQM_PKT_LOSS_EVENT, - - /* keep last */ - __NL80211_ATTR_CQM_AFTER_LAST, - NL80211_ATTR_CQM_MAX = __NL80211_ATTR_CQM_AFTER_LAST - 1 -}; - -/** - * enum nl80211_cqm_rssi_threshold_event - RSSI threshold event - * @NL80211_CQM_RSSI_THRESHOLD_EVENT_LOW: The RSSI level is lower than the - * configured threshold - * @NL80211_CQM_RSSI_THRESHOLD_EVENT_HIGH: The RSSI is higher than the - * configured threshold - */ -enum nl80211_cqm_rssi_threshold_event { - NL80211_CQM_RSSI_THRESHOLD_EVENT_LOW, - NL80211_CQM_RSSI_THRESHOLD_EVENT_HIGH, -}; - - -/** - * enum nl80211_tx_power_setting - TX power adjustment - * @NL80211_TX_POWER_AUTOMATIC: automatically determine transmit power - * @NL80211_TX_POWER_LIMITED: limit TX power by the mBm parameter - * @NL80211_TX_POWER_FIXED: fix TX power to the mBm parameter - */ -enum nl80211_tx_power_setting { - NL80211_TX_POWER_AUTOMATIC, - NL80211_TX_POWER_LIMITED, - NL80211_TX_POWER_FIXED, -}; - -#endif /* __LINUX_NL80211_H */ diff --git a/hostapd-0.8/src/drivers/priv_netlink.h b/hostapd-0.8/src/drivers/priv_netlink.h deleted file mode 100644 index 23eff83..0000000 --- a/hostapd-0.8/src/drivers/priv_netlink.h +++ /dev/null @@ -1,113 +0,0 @@ -/* - * wpa_supplicant - Private copy of Linux netlink/rtnetlink definitions. - * Copyright (c) 2003-2005, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#ifndef PRIV_NETLINK_H -#define PRIV_NETLINK_H - -/* - * This should be replaced with user space header once one is available with C - * library, etc.. - */ - -#ifndef IFF_LOWER_UP -#define IFF_LOWER_UP 0x10000 /* driver signals L1 up */ -#endif -#ifndef IFF_DORMANT -#define IFF_DORMANT 0x20000 /* driver signals dormant */ -#endif - -#ifndef IFLA_IFNAME -#define IFLA_IFNAME 3 -#endif -#ifndef IFLA_WIRELESS -#define IFLA_WIRELESS 11 -#endif -#ifndef IFLA_OPERSTATE -#define IFLA_OPERSTATE 16 -#endif -#ifndef IFLA_LINKMODE -#define IFLA_LINKMODE 17 -#define IF_OPER_DORMANT 5 -#define IF_OPER_UP 6 -#endif - -#define NLM_F_REQUEST 1 - -#define NETLINK_ROUTE 0 -#define RTMGRP_LINK 1 -#define RTM_BASE 0x10 -#define RTM_NEWLINK (RTM_BASE + 0) -#define RTM_DELLINK (RTM_BASE + 1) -#define RTM_SETLINK (RTM_BASE + 3) - -#define NLMSG_ALIGNTO 4 -#define NLMSG_ALIGN(len) (((len) + NLMSG_ALIGNTO - 1) & ~(NLMSG_ALIGNTO - 1)) -#define NLMSG_HDRLEN ((int) NLMSG_ALIGN(sizeof(struct nlmsghdr))) -#define NLMSG_LENGTH(len) ((len) + NLMSG_ALIGN(sizeof(struct nlmsghdr))) -#define NLMSG_SPACE(len) NLMSG_ALIGN(NLMSG_LENGTH(len)) -#define NLMSG_DATA(nlh) ((void*) (((char*) nlh) + NLMSG_LENGTH(0))) -#define NLMSG_NEXT(nlh,len) ((len) -= NLMSG_ALIGN((nlh)->nlmsg_len), \ - (struct nlmsghdr *) \ - (((char *)(nlh)) + NLMSG_ALIGN((nlh)->nlmsg_len))) -#define NLMSG_OK(nlh,len) ((len) >= (int) sizeof(struct nlmsghdr) && \ - (nlh)->nlmsg_len >= sizeof(struct nlmsghdr) && \ - (int) (nlh)->nlmsg_len <= (len)) -#define NLMSG_PAYLOAD(nlh,len) ((nlh)->nlmsg_len - NLMSG_SPACE((len))) - -#define RTA_ALIGNTO 4 -#define RTA_ALIGN(len) (((len) + RTA_ALIGNTO - 1) & ~(RTA_ALIGNTO - 1)) -#define RTA_OK(rta,len) \ -((len) > 0 && (rta)->rta_len >= sizeof(struct rtattr) && \ -(rta)->rta_len <= (len)) -#define RTA_NEXT(rta,attrlen) \ -((attrlen) -= RTA_ALIGN((rta)->rta_len), \ -(struct rtattr *) (((char *)(rta)) + RTA_ALIGN((rta)->rta_len))) -#define RTA_LENGTH(len) (RTA_ALIGN(sizeof(struct rtattr)) + (len)) -#define RTA_DATA(rta) ((void *) (((char *) (rta)) + RTA_LENGTH(0))) - - -struct sockaddr_nl -{ - sa_family_t nl_family; - unsigned short nl_pad; - u32 nl_pid; - u32 nl_groups; -}; - -struct nlmsghdr -{ - u32 nlmsg_len; - u16 nlmsg_type; - u16 nlmsg_flags; - u32 nlmsg_seq; - u32 nlmsg_pid; -}; - -struct ifinfomsg -{ - unsigned char ifi_family; - unsigned char __ifi_pad; - unsigned short ifi_type; - int ifi_index; - unsigned ifi_flags; - unsigned ifi_change; -}; - -struct rtattr -{ - unsigned short rta_len; - unsigned short rta_type; -}; - -#endif /* PRIV_NETLINK_H */ diff --git a/hostapd-0.8/src/drivers/rfkill.c b/hostapd-0.8/src/drivers/rfkill.c deleted file mode 100644 index 8818311..0000000 --- a/hostapd-0.8/src/drivers/rfkill.c +++ /dev/null @@ -1,194 +0,0 @@ -/* - * Linux rfkill helper functions for driver wrappers - * Copyright (c) 2010, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#include "includes.h" -#include - -#include "utils/common.h" -#include "utils/eloop.h" -#include "rfkill.h" - -#define RFKILL_EVENT_SIZE_V1 8 - -struct rfkill_event { - u32 idx; - u8 type; - u8 op; - u8 soft; - u8 hard; -} STRUCT_PACKED; - -enum rfkill_operation { - RFKILL_OP_ADD = 0, - RFKILL_OP_DEL, - RFKILL_OP_CHANGE, - RFKILL_OP_CHANGE_ALL, -}; - -enum rfkill_type { - RFKILL_TYPE_ALL = 0, - RFKILL_TYPE_WLAN, - RFKILL_TYPE_BLUETOOTH, - RFKILL_TYPE_UWB, - RFKILL_TYPE_WIMAX, - RFKILL_TYPE_WWAN, - RFKILL_TYPE_GPS, - RFKILL_TYPE_FM, - NUM_RFKILL_TYPES, -}; - - -struct rfkill_data { - struct rfkill_config *cfg; - int fd; - int blocked; -}; - - -static void rfkill_receive(int sock, void *eloop_ctx, void *sock_ctx) -{ - struct rfkill_data *rfkill = eloop_ctx; - struct rfkill_event event; - ssize_t len; - int new_blocked; - - len = read(rfkill->fd, &event, sizeof(event)); - if (len < 0) { - wpa_printf(MSG_ERROR, "rfkill: Event read failed: %s", - strerror(errno)); - return; - } - if (len != RFKILL_EVENT_SIZE_V1) { - wpa_printf(MSG_DEBUG, "rfkill: Unexpected event size " - "%d (expected %d)", - (int) len, RFKILL_EVENT_SIZE_V1); - return; - } - wpa_printf(MSG_DEBUG, "rfkill: event: idx=%u type=%d " - "op=%u soft=%u hard=%u", - event.idx, event.type, event.op, event.soft, - event.hard); - if (event.op != RFKILL_OP_CHANGE || event.type != RFKILL_TYPE_WLAN) - return; - - if (event.hard) { - wpa_printf(MSG_INFO, "rfkill: WLAN hard blocked"); - new_blocked = 1; - } else if (event.soft) { - wpa_printf(MSG_INFO, "rfkill: WLAN soft blocked"); - new_blocked = 1; - } else { - wpa_printf(MSG_INFO, "rfkill: WLAN unblocked"); - new_blocked = 0; - } - - if (new_blocked != rfkill->blocked) { - rfkill->blocked = new_blocked; - if (new_blocked) - rfkill->cfg->blocked_cb(rfkill->cfg->ctx); - else - rfkill->cfg->unblocked_cb(rfkill->cfg->ctx); - } -} - - -struct rfkill_data * rfkill_init(struct rfkill_config *cfg) -{ - struct rfkill_data *rfkill; - struct rfkill_event event; - ssize_t len; - - rfkill = os_zalloc(sizeof(*rfkill)); - if (rfkill == NULL) - return NULL; - - rfkill->cfg = cfg; - rfkill->fd = open("/dev/rfkill", O_RDONLY); - if (rfkill->fd < 0) { - wpa_printf(MSG_INFO, "rfkill: Cannot open RFKILL control " - "device"); - goto fail; - } - - if (fcntl(rfkill->fd, F_SETFL, O_NONBLOCK) < 0) { - wpa_printf(MSG_ERROR, "rfkill: Cannot set non-blocking mode: " - "%s", strerror(errno)); - goto fail2; - } - - for (;;) { - len = read(rfkill->fd, &event, sizeof(event)); - if (len < 0) { - if (errno == EAGAIN) - break; /* No more entries */ - wpa_printf(MSG_ERROR, "rfkill: Event read failed: %s", - strerror(errno)); - break; - } - if (len != RFKILL_EVENT_SIZE_V1) { - wpa_printf(MSG_DEBUG, "rfkill: Unexpected event size " - "%d (expected %d)", - (int) len, RFKILL_EVENT_SIZE_V1); - continue; - } - wpa_printf(MSG_DEBUG, "rfkill: initial event: idx=%u type=%d " - "op=%u soft=%u hard=%u", - event.idx, event.type, event.op, event.soft, - event.hard); - if (event.op != RFKILL_OP_ADD || - event.type != RFKILL_TYPE_WLAN) - continue; - if (event.hard) { - wpa_printf(MSG_INFO, "rfkill: WLAN hard blocked"); - rfkill->blocked = 1; - } else if (event.soft) { - wpa_printf(MSG_INFO, "rfkill: WLAN soft blocked"); - rfkill->blocked = 1; - } - } - - eloop_register_read_sock(rfkill->fd, rfkill_receive, rfkill, NULL); - - return rfkill; - -fail2: - close(rfkill->fd); -fail: - os_free(rfkill); - return NULL; -} - - -void rfkill_deinit(struct rfkill_data *rfkill) -{ - if (rfkill == NULL) - return; - - if (rfkill->fd >= 0) { - eloop_unregister_read_sock(rfkill->fd); - close(rfkill->fd); - } - - os_free(rfkill->cfg); - os_free(rfkill); -} - - -int rfkill_is_blocked(struct rfkill_data *rfkill) -{ - if (rfkill == NULL) - return 0; - - return rfkill->blocked; -} diff --git a/hostapd-0.8/src/drivers/rfkill.h b/hostapd-0.8/src/drivers/rfkill.h deleted file mode 100644 index 7a984a6..0000000 --- a/hostapd-0.8/src/drivers/rfkill.h +++ /dev/null @@ -1,31 +0,0 @@ -/* - * Linux rfkill helper functions for driver wrappers - * Copyright (c) 2010, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#ifndef RFKILL_H -#define RFKILL_H - -struct rfkill_data; - -struct rfkill_config { - void *ctx; - char ifname[IFNAMSIZ]; - void (*blocked_cb)(void *ctx); - void (*unblocked_cb)(void *ctx); -}; - -struct rfkill_data * rfkill_init(struct rfkill_config *cfg); -void rfkill_deinit(struct rfkill_data *rfkill); -int rfkill_is_blocked(struct rfkill_data *rfkill); - -#endif /* RFKILL_H */ diff --git a/hostapd-0.8/src/drivers/wireless_copy.h b/hostapd-0.8/src/drivers/wireless_copy.h deleted file mode 100644 index 201719b..0000000 --- a/hostapd-0.8/src/drivers/wireless_copy.h +++ /dev/null @@ -1,1185 +0,0 @@ -/* This is based on Linux Wireless Extensions header file from WIRELESS_EXT 22. - * I have just removed kernel related headers and added some typedefs etc. to - * make this easier to include into user space programs. - * Jouni Malinen, 2005-03-12. - */ - - -/* - * This file define a set of standard wireless extensions - * - * Version : 22 16.3.07 - * - * Authors : Jean Tourrilhes - HPL - - * Copyright (c) 1997-2007 Jean Tourrilhes, All Rights Reserved. - */ - -#ifndef _LINUX_WIRELESS_H -#define _LINUX_WIRELESS_H - -/************************** DOCUMENTATION **************************/ -/* - * Initial APIs (1996 -> onward) : - * ----------------------------- - * Basically, the wireless extensions are for now a set of standard ioctl - * call + /proc/net/wireless - * - * The entry /proc/net/wireless give statistics and information on the - * driver. - * This is better than having each driver having its entry because - * its centralised and we may remove the driver module safely. - * - * Ioctl are used to configure the driver and issue commands. This is - * better than command line options of insmod because we may want to - * change dynamically (while the driver is running) some parameters. - * - * The ioctl mechanimsm are copied from standard devices ioctl. - * We have the list of command plus a structure descibing the - * data exchanged... - * Note that to add these ioctl, I was obliged to modify : - * # net/core/dev.c (two place + add include) - * # net/ipv4/af_inet.c (one place + add include) - * - * /proc/net/wireless is a copy of /proc/net/dev. - * We have a structure for data passed from the driver to /proc/net/wireless - * Too add this, I've modified : - * # net/core/dev.c (two other places) - * # include/linux/netdevice.h (one place) - * # include/linux/proc_fs.h (one place) - * - * New driver API (2002 -> onward) : - * ------------------------------- - * This file is only concerned with the user space API and common definitions. - * The new driver API is defined and documented in : - * # include/net/iw_handler.h - * - * Note as well that /proc/net/wireless implementation has now moved in : - * # net/core/wireless.c - * - * Wireless Events (2002 -> onward) : - * -------------------------------- - * Events are defined at the end of this file, and implemented in : - * # net/core/wireless.c - * - * Other comments : - * -------------- - * Do not add here things that are redundant with other mechanisms - * (drivers init, ifconfig, /proc/net/dev, ...) and with are not - * wireless specific. - * - * These wireless extensions are not magic : each driver has to provide - * support for them... - * - * IMPORTANT NOTE : As everything in the kernel, this is very much a - * work in progress. Contact me if you have ideas of improvements... - */ - -/***************************** INCLUDES *****************************/ - - /* jkm - replaced linux headers with C library headers, added typedefs */ -#if 0 -#include /* for __u* and __s* typedefs */ -#include /* for "struct sockaddr" et al */ -#include /* for IFNAMSIZ and co... */ -#else -#include -#include -#ifndef ANDROID -typedef __uint32_t __u32; -typedef __int32_t __s32; -typedef __uint16_t __u16; -typedef __int16_t __s16; -typedef __uint8_t __u8; -#endif /* ANDROID */ -#ifndef __user -#define __user -#endif /* __user */ -#endif - -/***************************** VERSION *****************************/ -/* - * This constant is used to know the availability of the wireless - * extensions and to know which version of wireless extensions it is - * (there is some stuff that will be added in the future...) - * I just plan to increment with each new version. - */ -#define WIRELESS_EXT 22 - -/* - * Changes : - * - * V2 to V3 - * -------- - * Alan Cox start some incompatibles changes. I've integrated a bit more. - * - Encryption renamed to Encode to avoid US regulation problems - * - Frequency changed from float to struct to avoid problems on old 386 - * - * V3 to V4 - * -------- - * - Add sensitivity - * - * V4 to V5 - * -------- - * - Missing encoding definitions in range - * - Access points stuff - * - * V5 to V6 - * -------- - * - 802.11 support (ESSID ioctls) - * - * V6 to V7 - * -------- - * - define IW_ESSID_MAX_SIZE and IW_MAX_AP - * - * V7 to V8 - * -------- - * - Changed my e-mail address - * - More 802.11 support (nickname, rate, rts, frag) - * - List index in frequencies - * - * V8 to V9 - * -------- - * - Support for 'mode of operation' (ad-hoc, managed...) - * - Support for unicast and multicast power saving - * - Change encoding to support larger tokens (>64 bits) - * - Updated iw_params (disable, flags) and use it for NWID - * - Extracted iw_point from iwreq for clarity - * - * V9 to V10 - * --------- - * - Add PM capability to range structure - * - Add PM modifier : MAX/MIN/RELATIVE - * - Add encoding option : IW_ENCODE_NOKEY - * - Add TxPower ioctls (work like TxRate) - * - * V10 to V11 - * ---------- - * - Add WE version in range (help backward/forward compatibility) - * - Add retry ioctls (work like PM) - * - * V11 to V12 - * ---------- - * - Add SIOCSIWSTATS to get /proc/net/wireless programatically - * - Add DEV PRIVATE IOCTL to avoid collisions in SIOCDEVPRIVATE space - * - Add new statistics (frag, retry, beacon) - * - Add average quality (for user space calibration) - * - * V12 to V13 - * ---------- - * - Document creation of new driver API. - * - Extract union iwreq_data from struct iwreq (for new driver API). - * - Rename SIOCSIWNAME as SIOCSIWCOMMIT - * - * V13 to V14 - * ---------- - * - Wireless Events support : define struct iw_event - * - Define additional specific event numbers - * - Add "addr" and "param" fields in union iwreq_data - * - AP scanning stuff (SIOCSIWSCAN and friends) - * - * V14 to V15 - * ---------- - * - Add IW_PRIV_TYPE_ADDR for struct sockaddr private arg - * - Make struct iw_freq signed (both m & e), add explicit padding - * - Add IWEVCUSTOM for driver specific event/scanning token - * - Add IW_MAX_GET_SPY for driver returning a lot of addresses - * - Add IW_TXPOW_RANGE for range of Tx Powers - * - Add IWEVREGISTERED & IWEVEXPIRED events for Access Points - * - Add IW_MODE_MONITOR for passive monitor - * - * V15 to V16 - * ---------- - * - Increase the number of bitrates in iw_range to 32 (for 802.11g) - * - Increase the number of frequencies in iw_range to 32 (for 802.11b+a) - * - Reshuffle struct iw_range for increases, add filler - * - Increase IW_MAX_AP to 64 for driver returning a lot of addresses - * - Remove IW_MAX_GET_SPY because conflict with enhanced spy support - * - Add SIOCSIWTHRSPY/SIOCGIWTHRSPY and "struct iw_thrspy" - * - Add IW_ENCODE_TEMP and iw_range->encoding_login_index - * - * V16 to V17 - * ---------- - * - Add flags to frequency -> auto/fixed - * - Document (struct iw_quality *)->updated, add new flags (INVALID) - * - Wireless Event capability in struct iw_range - * - Add support for relative TxPower (yick !) - * - * V17 to V18 (From Jouni Malinen ) - * ---------- - * - Add support for WPA/WPA2 - * - Add extended encoding configuration (SIOCSIWENCODEEXT and - * SIOCGIWENCODEEXT) - * - Add SIOCSIWGENIE/SIOCGIWGENIE - * - Add SIOCSIWMLME - * - Add SIOCSIWPMKSA - * - Add struct iw_range bit field for supported encoding capabilities - * - Add optional scan request parameters for SIOCSIWSCAN - * - Add SIOCSIWAUTH/SIOCGIWAUTH for setting authentication and WPA - * related parameters (extensible up to 4096 parameter values) - * - Add wireless events: IWEVGENIE, IWEVMICHAELMICFAILURE, - * IWEVASSOCREQIE, IWEVASSOCRESPIE, IWEVPMKIDCAND - * - * V18 to V19 - * ---------- - * - Remove (struct iw_point *)->pointer from events and streams - * - Remove header includes to help user space - * - Increase IW_ENCODING_TOKEN_MAX from 32 to 64 - * - Add IW_QUAL_ALL_UPDATED and IW_QUAL_ALL_INVALID macros - * - Add explicit flag to tell stats are in dBm : IW_QUAL_DBM - * - Add IW_IOCTL_IDX() and IW_EVENT_IDX() macros - * - * V19 to V20 - * ---------- - * - RtNetlink requests support (SET/GET) - * - * V20 to V21 - * ---------- - * - Remove (struct net_device *)->get_wireless_stats() - * - Change length in ESSID and NICK to strlen() instead of strlen()+1 - * - Add IW_RETRY_SHORT/IW_RETRY_LONG retry modifiers - * - Power/Retry relative values no longer * 100000 - * - Add explicit flag to tell stats are in 802.11k RCPI : IW_QUAL_RCPI - * - * V21 to V22 - * ---------- - * - Prevent leaking of kernel space in stream on 64 bits. - */ - -/**************************** CONSTANTS ****************************/ - -/* -------------------------- IOCTL LIST -------------------------- */ - -/* Wireless Identification */ -#define SIOCSIWCOMMIT 0x8B00 /* Commit pending changes to driver */ -#define SIOCGIWNAME 0x8B01 /* get name == wireless protocol */ -/* SIOCGIWNAME is used to verify the presence of Wireless Extensions. - * Common values : "IEEE 802.11-DS", "IEEE 802.11-FH", "IEEE 802.11b"... - * Don't put the name of your driver there, it's useless. */ - -/* Basic operations */ -#define SIOCSIWNWID 0x8B02 /* set network id (pre-802.11) */ -#define SIOCGIWNWID 0x8B03 /* get network id (the cell) */ -#define SIOCSIWFREQ 0x8B04 /* set channel/frequency (Hz) */ -#define SIOCGIWFREQ 0x8B05 /* get channel/frequency (Hz) */ -#define SIOCSIWMODE 0x8B06 /* set operation mode */ -#define SIOCGIWMODE 0x8B07 /* get operation mode */ -#define SIOCSIWSENS 0x8B08 /* set sensitivity (dBm) */ -#define SIOCGIWSENS 0x8B09 /* get sensitivity (dBm) */ - -/* Informative stuff */ -#define SIOCSIWRANGE 0x8B0A /* Unused */ -#define SIOCGIWRANGE 0x8B0B /* Get range of parameters */ -#define SIOCSIWPRIV 0x8B0C /* Unused */ -#define SIOCGIWPRIV 0x8B0D /* get private ioctl interface info */ -#define SIOCSIWSTATS 0x8B0E /* Unused */ -#define SIOCGIWSTATS 0x8B0F /* Get /proc/net/wireless stats */ -/* SIOCGIWSTATS is strictly used between user space and the kernel, and - * is never passed to the driver (i.e. the driver will never see it). */ - -/* Spy support (statistics per MAC address - used for Mobile IP support) */ -#define SIOCSIWSPY 0x8B10 /* set spy addresses */ -#define SIOCGIWSPY 0x8B11 /* get spy info (quality of link) */ -#define SIOCSIWTHRSPY 0x8B12 /* set spy threshold (spy event) */ -#define SIOCGIWTHRSPY 0x8B13 /* get spy threshold */ - -/* Access Point manipulation */ -#define SIOCSIWAP 0x8B14 /* set access point MAC addresses */ -#define SIOCGIWAP 0x8B15 /* get access point MAC addresses */ -#define SIOCGIWAPLIST 0x8B17 /* Deprecated in favor of scanning */ -#define SIOCSIWSCAN 0x8B18 /* trigger scanning (list cells) */ -#define SIOCGIWSCAN 0x8B19 /* get scanning results */ - -/* 802.11 specific support */ -#define SIOCSIWESSID 0x8B1A /* set ESSID (network name) */ -#define SIOCGIWESSID 0x8B1B /* get ESSID */ -#define SIOCSIWNICKN 0x8B1C /* set node name/nickname */ -#define SIOCGIWNICKN 0x8B1D /* get node name/nickname */ -/* As the ESSID and NICKN are strings up to 32 bytes long, it doesn't fit - * within the 'iwreq' structure, so we need to use the 'data' member to - * point to a string in user space, like it is done for RANGE... */ - -/* Other parameters useful in 802.11 and some other devices */ -#define SIOCSIWRATE 0x8B20 /* set default bit rate (bps) */ -#define SIOCGIWRATE 0x8B21 /* get default bit rate (bps) */ -#define SIOCSIWRTS 0x8B22 /* set RTS/CTS threshold (bytes) */ -#define SIOCGIWRTS 0x8B23 /* get RTS/CTS threshold (bytes) */ -#define SIOCSIWFRAG 0x8B24 /* set fragmentation thr (bytes) */ -#define SIOCGIWFRAG 0x8B25 /* get fragmentation thr (bytes) */ -#define SIOCSIWTXPOW 0x8B26 /* set transmit power (dBm) */ -#define SIOCGIWTXPOW 0x8B27 /* get transmit power (dBm) */ -#define SIOCSIWRETRY 0x8B28 /* set retry limits and lifetime */ -#define SIOCGIWRETRY 0x8B29 /* get retry limits and lifetime */ - -/* Encoding stuff (scrambling, hardware security, WEP...) */ -#define SIOCSIWENCODE 0x8B2A /* set encoding token & mode */ -#define SIOCGIWENCODE 0x8B2B /* get encoding token & mode */ -/* Power saving stuff (power management, unicast and multicast) */ -#define SIOCSIWPOWER 0x8B2C /* set Power Management settings */ -#define SIOCGIWPOWER 0x8B2D /* get Power Management settings */ - -/* WPA : Generic IEEE 802.11 informatiom element (e.g., for WPA/RSN/WMM). - * This ioctl uses struct iw_point and data buffer that includes IE id and len - * fields. More than one IE may be included in the request. Setting the generic - * IE to empty buffer (len=0) removes the generic IE from the driver. Drivers - * are allowed to generate their own WPA/RSN IEs, but in these cases, drivers - * are required to report the used IE as a wireless event, e.g., when - * associating with an AP. */ -#define SIOCSIWGENIE 0x8B30 /* set generic IE */ -#define SIOCGIWGENIE 0x8B31 /* get generic IE */ - -/* WPA : IEEE 802.11 MLME requests */ -#define SIOCSIWMLME 0x8B16 /* request MLME operation; uses - * struct iw_mlme */ -/* WPA : Authentication mode parameters */ -#define SIOCSIWAUTH 0x8B32 /* set authentication mode params */ -#define SIOCGIWAUTH 0x8B33 /* get authentication mode params */ - -/* WPA : Extended version of encoding configuration */ -#define SIOCSIWENCODEEXT 0x8B34 /* set encoding token & mode */ -#define SIOCGIWENCODEEXT 0x8B35 /* get encoding token & mode */ - -/* WPA2 : PMKSA cache management */ -#define SIOCSIWPMKSA 0x8B36 /* PMKSA cache operation */ - -/* -------------------- DEV PRIVATE IOCTL LIST -------------------- */ - -/* These 32 ioctl are wireless device private, for 16 commands. - * Each driver is free to use them for whatever purpose it chooses, - * however the driver *must* export the description of those ioctls - * with SIOCGIWPRIV and *must* use arguments as defined below. - * If you don't follow those rules, DaveM is going to hate you (reason : - * it make mixed 32/64bit operation impossible). - */ -#define SIOCIWFIRSTPRIV 0x8BE0 -#define SIOCIWLASTPRIV 0x8BFF -/* Previously, we were using SIOCDEVPRIVATE, but we now have our - * separate range because of collisions with other tools such as - * 'mii-tool'. - * We now have 32 commands, so a bit more space ;-). - * Also, all 'even' commands are only usable by root and don't return the - * content of ifr/iwr to user (but you are not obliged to use the set/get - * convention, just use every other two command). More details in iwpriv.c. - * And I repeat : you are not forced to use them with iwpriv, but you - * must be compliant with it. - */ - -/* ------------------------- IOCTL STUFF ------------------------- */ - -/* The first and the last (range) */ -#define SIOCIWFIRST 0x8B00 -#define SIOCIWLAST SIOCIWLASTPRIV /* 0x8BFF */ -#define IW_IOCTL_IDX(cmd) ((cmd) - SIOCIWFIRST) -#define IW_HANDLER(id, func) \ - [IW_IOCTL_IDX(id)] = func - -/* Odd : get (world access), even : set (root access) */ -#define IW_IS_SET(cmd) (!((cmd) & 0x1)) -#define IW_IS_GET(cmd) ((cmd) & 0x1) - -/* ----------------------- WIRELESS EVENTS ----------------------- */ -/* Those are *NOT* ioctls, do not issue request on them !!! */ -/* Most events use the same identifier as ioctl requests */ - -#define IWEVTXDROP 0x8C00 /* Packet dropped to excessive retry */ -#define IWEVQUAL 0x8C01 /* Quality part of statistics (scan) */ -#define IWEVCUSTOM 0x8C02 /* Driver specific ascii string */ -#define IWEVREGISTERED 0x8C03 /* Discovered a new node (AP mode) */ -#define IWEVEXPIRED 0x8C04 /* Expired a node (AP mode) */ -#define IWEVGENIE 0x8C05 /* Generic IE (WPA, RSN, WMM, ..) - * (scan results); This includes id and - * length fields. One IWEVGENIE may - * contain more than one IE. Scan - * results may contain one or more - * IWEVGENIE events. */ -#define IWEVMICHAELMICFAILURE 0x8C06 /* Michael MIC failure - * (struct iw_michaelmicfailure) - */ -#define IWEVASSOCREQIE 0x8C07 /* IEs used in (Re)Association Request. - * The data includes id and length - * fields and may contain more than one - * IE. This event is required in - * Managed mode if the driver - * generates its own WPA/RSN IE. This - * should be sent just before - * IWEVREGISTERED event for the - * association. */ -#define IWEVASSOCRESPIE 0x8C08 /* IEs used in (Re)Association - * Response. The data includes id and - * length fields and may contain more - * than one IE. This may be sent - * between IWEVASSOCREQIE and - * IWEVREGISTERED events for the - * association. */ -#define IWEVPMKIDCAND 0x8C09 /* PMKID candidate for RSN - * pre-authentication - * (struct iw_pmkid_cand) */ - -#define IWEVFIRST 0x8C00 -#define IW_EVENT_IDX(cmd) ((cmd) - IWEVFIRST) - -/* ------------------------- PRIVATE INFO ------------------------- */ -/* - * The following is used with SIOCGIWPRIV. It allow a driver to define - * the interface (name, type of data) for its private ioctl. - * Privates ioctl are SIOCIWFIRSTPRIV -> SIOCIWLASTPRIV - */ - -#define IW_PRIV_TYPE_MASK 0x7000 /* Type of arguments */ -#define IW_PRIV_TYPE_NONE 0x0000 -#define IW_PRIV_TYPE_BYTE 0x1000 /* Char as number */ -#define IW_PRIV_TYPE_CHAR 0x2000 /* Char as character */ -#define IW_PRIV_TYPE_INT 0x4000 /* 32 bits int */ -#define IW_PRIV_TYPE_FLOAT 0x5000 /* struct iw_freq */ -#define IW_PRIV_TYPE_ADDR 0x6000 /* struct sockaddr */ - -#define IW_PRIV_SIZE_FIXED 0x0800 /* Variable or fixed number of args */ - -#define IW_PRIV_SIZE_MASK 0x07FF /* Max number of those args */ - -/* - * Note : if the number of args is fixed and the size < 16 octets, - * instead of passing a pointer we will put args in the iwreq struct... - */ - -/* ----------------------- OTHER CONSTANTS ----------------------- */ - -/* Maximum frequencies in the range struct */ -#define IW_MAX_FREQUENCIES 32 -/* Note : if you have something like 80 frequencies, - * don't increase this constant and don't fill the frequency list. - * The user will be able to set by channel anyway... */ - -/* Maximum bit rates in the range struct */ -#define IW_MAX_BITRATES 32 - -/* Maximum tx powers in the range struct */ -#define IW_MAX_TXPOWER 8 -/* Note : if you more than 8 TXPowers, just set the max and min or - * a few of them in the struct iw_range. */ - -/* Maximum of address that you may set with SPY */ -#define IW_MAX_SPY 8 - -/* Maximum of address that you may get in the - list of access points in range */ -#define IW_MAX_AP 64 - -/* Maximum size of the ESSID and NICKN strings */ -#define IW_ESSID_MAX_SIZE 32 - -/* Modes of operation */ -#define IW_MODE_AUTO 0 /* Let the driver decides */ -#define IW_MODE_ADHOC 1 /* Single cell network */ -#define IW_MODE_INFRA 2 /* Multi cell network, roaming, ... */ -#define IW_MODE_MASTER 3 /* Synchronisation master or Access Point */ -#define IW_MODE_REPEAT 4 /* Wireless Repeater (forwarder) */ -#define IW_MODE_SECOND 5 /* Secondary master/repeater (backup) */ -#define IW_MODE_MONITOR 6 /* Passive monitor (listen only) */ -#define IW_MODE_MESH 7 /* Mesh (IEEE 802.11s) network */ - -/* Statistics flags (bitmask in updated) */ -#define IW_QUAL_QUAL_UPDATED 0x01 /* Value was updated since last read */ -#define IW_QUAL_LEVEL_UPDATED 0x02 -#define IW_QUAL_NOISE_UPDATED 0x04 -#define IW_QUAL_ALL_UPDATED 0x07 -#define IW_QUAL_DBM 0x08 /* Level + Noise are dBm */ -#define IW_QUAL_QUAL_INVALID 0x10 /* Driver doesn't provide value */ -#define IW_QUAL_LEVEL_INVALID 0x20 -#define IW_QUAL_NOISE_INVALID 0x40 -#define IW_QUAL_RCPI 0x80 /* Level + Noise are 802.11k RCPI */ -#define IW_QUAL_ALL_INVALID 0x70 - -/* Frequency flags */ -#define IW_FREQ_AUTO 0x00 /* Let the driver decides */ -#define IW_FREQ_FIXED 0x01 /* Force a specific value */ - -/* Maximum number of size of encoding token available - * they are listed in the range structure */ -#define IW_MAX_ENCODING_SIZES 8 - -/* Maximum size of the encoding token in bytes */ -#define IW_ENCODING_TOKEN_MAX 64 /* 512 bits (for now) */ - -/* Flags for encoding (along with the token) */ -#define IW_ENCODE_INDEX 0x00FF /* Token index (if needed) */ -#define IW_ENCODE_FLAGS 0xFF00 /* Flags defined below */ -#define IW_ENCODE_MODE 0xF000 /* Modes defined below */ -#define IW_ENCODE_DISABLED 0x8000 /* Encoding disabled */ -#define IW_ENCODE_ENABLED 0x0000 /* Encoding enabled */ -#define IW_ENCODE_RESTRICTED 0x4000 /* Refuse non-encoded packets */ -#define IW_ENCODE_OPEN 0x2000 /* Accept non-encoded packets */ -#define IW_ENCODE_NOKEY 0x0800 /* Key is write only, so not present */ -#define IW_ENCODE_TEMP 0x0400 /* Temporary key */ - -/* Power management flags available (along with the value, if any) */ -#define IW_POWER_ON 0x0000 /* No details... */ -#define IW_POWER_TYPE 0xF000 /* Type of parameter */ -#define IW_POWER_PERIOD 0x1000 /* Value is a period/duration of */ -#define IW_POWER_TIMEOUT 0x2000 /* Value is a timeout (to go asleep) */ -#define IW_POWER_MODE 0x0F00 /* Power Management mode */ -#define IW_POWER_UNICAST_R 0x0100 /* Receive only unicast messages */ -#define IW_POWER_MULTICAST_R 0x0200 /* Receive only multicast messages */ -#define IW_POWER_ALL_R 0x0300 /* Receive all messages though PM */ -#define IW_POWER_FORCE_S 0x0400 /* Force PM procedure for sending unicast */ -#define IW_POWER_REPEATER 0x0800 /* Repeat broadcast messages in PM period */ -#define IW_POWER_MODIFIER 0x000F /* Modify a parameter */ -#define IW_POWER_MIN 0x0001 /* Value is a minimum */ -#define IW_POWER_MAX 0x0002 /* Value is a maximum */ -#define IW_POWER_RELATIVE 0x0004 /* Value is not in seconds/ms/us */ - -/* Transmit Power flags available */ -#define IW_TXPOW_TYPE 0x00FF /* Type of value */ -#define IW_TXPOW_DBM 0x0000 /* Value is in dBm */ -#define IW_TXPOW_MWATT 0x0001 /* Value is in mW */ -#define IW_TXPOW_RELATIVE 0x0002 /* Value is in arbitrary units */ -#define IW_TXPOW_RANGE 0x1000 /* Range of value between min/max */ - -/* Retry limits and lifetime flags available */ -#define IW_RETRY_ON 0x0000 /* No details... */ -#define IW_RETRY_TYPE 0xF000 /* Type of parameter */ -#define IW_RETRY_LIMIT 0x1000 /* Maximum number of retries*/ -#define IW_RETRY_LIFETIME 0x2000 /* Maximum duration of retries in us */ -#define IW_RETRY_MODIFIER 0x00FF /* Modify a parameter */ -#define IW_RETRY_MIN 0x0001 /* Value is a minimum */ -#define IW_RETRY_MAX 0x0002 /* Value is a maximum */ -#define IW_RETRY_RELATIVE 0x0004 /* Value is not in seconds/ms/us */ -#define IW_RETRY_SHORT 0x0010 /* Value is for short packets */ -#define IW_RETRY_LONG 0x0020 /* Value is for long packets */ - -/* Scanning request flags */ -#define IW_SCAN_DEFAULT 0x0000 /* Default scan of the driver */ -#define IW_SCAN_ALL_ESSID 0x0001 /* Scan all ESSIDs */ -#define IW_SCAN_THIS_ESSID 0x0002 /* Scan only this ESSID */ -#define IW_SCAN_ALL_FREQ 0x0004 /* Scan all Frequencies */ -#define IW_SCAN_THIS_FREQ 0x0008 /* Scan only this Frequency */ -#define IW_SCAN_ALL_MODE 0x0010 /* Scan all Modes */ -#define IW_SCAN_THIS_MODE 0x0020 /* Scan only this Mode */ -#define IW_SCAN_ALL_RATE 0x0040 /* Scan all Bit-Rates */ -#define IW_SCAN_THIS_RATE 0x0080 /* Scan only this Bit-Rate */ -/* struct iw_scan_req scan_type */ -#define IW_SCAN_TYPE_ACTIVE 0 -#define IW_SCAN_TYPE_PASSIVE 1 -/* Maximum size of returned data */ -#define IW_SCAN_MAX_DATA 4096 /* In bytes */ - -/* Scan capability flags - in (struct iw_range *)->scan_capa */ -#define IW_SCAN_CAPA_NONE 0x00 -#define IW_SCAN_CAPA_ESSID 0x01 -#define IW_SCAN_CAPA_BSSID 0x02 -#define IW_SCAN_CAPA_CHANNEL 0x04 -#define IW_SCAN_CAPA_MODE 0x08 -#define IW_SCAN_CAPA_RATE 0x10 -#define IW_SCAN_CAPA_TYPE 0x20 -#define IW_SCAN_CAPA_TIME 0x40 - -/* Max number of char in custom event - use multiple of them if needed */ -#define IW_CUSTOM_MAX 256 /* In bytes */ - -/* Generic information element */ -#define IW_GENERIC_IE_MAX 1024 - -/* MLME requests (SIOCSIWMLME / struct iw_mlme) */ -#define IW_MLME_DEAUTH 0 -#define IW_MLME_DISASSOC 1 -#define IW_MLME_AUTH 2 -#define IW_MLME_ASSOC 3 - -/* SIOCSIWAUTH/SIOCGIWAUTH struct iw_param flags */ -#define IW_AUTH_INDEX 0x0FFF -#define IW_AUTH_FLAGS 0xF000 -/* SIOCSIWAUTH/SIOCGIWAUTH parameters (0 .. 4095) - * (IW_AUTH_INDEX mask in struct iw_param flags; this is the index of the - * parameter that is being set/get to; value will be read/written to - * struct iw_param value field) */ -#define IW_AUTH_WPA_VERSION 0 -#define IW_AUTH_CIPHER_PAIRWISE 1 -#define IW_AUTH_CIPHER_GROUP 2 -#define IW_AUTH_KEY_MGMT 3 -#define IW_AUTH_TKIP_COUNTERMEASURES 4 -#define IW_AUTH_DROP_UNENCRYPTED 5 -#define IW_AUTH_80211_AUTH_ALG 6 -#define IW_AUTH_WPA_ENABLED 7 -#define IW_AUTH_RX_UNENCRYPTED_EAPOL 8 -#define IW_AUTH_ROAMING_CONTROL 9 -#define IW_AUTH_PRIVACY_INVOKED 10 -#define IW_AUTH_CIPHER_GROUP_MGMT 11 -#define IW_AUTH_MFP 12 - -/* IW_AUTH_WPA_VERSION values (bit field) */ -#define IW_AUTH_WPA_VERSION_DISABLED 0x00000001 -#define IW_AUTH_WPA_VERSION_WPA 0x00000002 -#define IW_AUTH_WPA_VERSION_WPA2 0x00000004 - -/* IW_AUTH_PAIRWISE_CIPHER, IW_AUTH_GROUP_CIPHER, and IW_AUTH_CIPHER_GROUP_MGMT - * values (bit field) */ -#define IW_AUTH_CIPHER_NONE 0x00000001 -#define IW_AUTH_CIPHER_WEP40 0x00000002 -#define IW_AUTH_CIPHER_TKIP 0x00000004 -#define IW_AUTH_CIPHER_CCMP 0x00000008 -#define IW_AUTH_CIPHER_WEP104 0x00000010 -#define IW_AUTH_CIPHER_AES_CMAC 0x00000020 - -/* IW_AUTH_KEY_MGMT values (bit field) */ -#define IW_AUTH_KEY_MGMT_802_1X 1 -#define IW_AUTH_KEY_MGMT_PSK 2 - -/* IW_AUTH_80211_AUTH_ALG values (bit field) */ -#define IW_AUTH_ALG_OPEN_SYSTEM 0x00000001 -#define IW_AUTH_ALG_SHARED_KEY 0x00000002 -#define IW_AUTH_ALG_LEAP 0x00000004 - -/* IW_AUTH_ROAMING_CONTROL values */ -#define IW_AUTH_ROAMING_ENABLE 0 /* driver/firmware based roaming */ -#define IW_AUTH_ROAMING_DISABLE 1 /* user space program used for roaming - * control */ - -/* IW_AUTH_MFP (management frame protection) values */ -#define IW_AUTH_MFP_DISABLED 0 /* MFP disabled */ -#define IW_AUTH_MFP_OPTIONAL 1 /* MFP optional */ -#define IW_AUTH_MFP_REQUIRED 2 /* MFP required */ - -/* SIOCSIWENCODEEXT definitions */ -#define IW_ENCODE_SEQ_MAX_SIZE 8 -/* struct iw_encode_ext ->alg */ -#define IW_ENCODE_ALG_NONE 0 -#define IW_ENCODE_ALG_WEP 1 -#define IW_ENCODE_ALG_TKIP 2 -#define IW_ENCODE_ALG_CCMP 3 -#define IW_ENCODE_ALG_PMK 4 -#define IW_ENCODE_ALG_AES_CMAC 5 -/* struct iw_encode_ext ->ext_flags */ -#define IW_ENCODE_EXT_TX_SEQ_VALID 0x00000001 -#define IW_ENCODE_EXT_RX_SEQ_VALID 0x00000002 -#define IW_ENCODE_EXT_GROUP_KEY 0x00000004 -#define IW_ENCODE_EXT_SET_TX_KEY 0x00000008 - -/* IWEVMICHAELMICFAILURE : struct iw_michaelmicfailure ->flags */ -#define IW_MICFAILURE_KEY_ID 0x00000003 /* Key ID 0..3 */ -#define IW_MICFAILURE_GROUP 0x00000004 -#define IW_MICFAILURE_PAIRWISE 0x00000008 -#define IW_MICFAILURE_STAKEY 0x00000010 -#define IW_MICFAILURE_COUNT 0x00000060 /* 1 or 2 (0 = count not supported) - */ - -/* Bit field values for enc_capa in struct iw_range */ -#define IW_ENC_CAPA_WPA 0x00000001 -#define IW_ENC_CAPA_WPA2 0x00000002 -#define IW_ENC_CAPA_CIPHER_TKIP 0x00000004 -#define IW_ENC_CAPA_CIPHER_CCMP 0x00000008 -#define IW_ENC_CAPA_4WAY_HANDSHAKE 0x00000010 - -/* Event capability macros - in (struct iw_range *)->event_capa - * Because we have more than 32 possible events, we use an array of - * 32 bit bitmasks. Note : 32 bits = 0x20 = 2^5. */ -#define IW_EVENT_CAPA_BASE(cmd) ((cmd >= SIOCIWFIRSTPRIV) ? \ - (cmd - SIOCIWFIRSTPRIV + 0x60) : \ - (cmd - SIOCIWFIRST)) -#define IW_EVENT_CAPA_INDEX(cmd) (IW_EVENT_CAPA_BASE(cmd) >> 5) -#define IW_EVENT_CAPA_MASK(cmd) (1 << (IW_EVENT_CAPA_BASE(cmd) & 0x1F)) -/* Event capability constants - event autogenerated by the kernel - * This list is valid for most 802.11 devices, customise as needed... */ -#define IW_EVENT_CAPA_K_0 (IW_EVENT_CAPA_MASK(0x8B04) | \ - IW_EVENT_CAPA_MASK(0x8B06) | \ - IW_EVENT_CAPA_MASK(0x8B1A)) -#define IW_EVENT_CAPA_K_1 (IW_EVENT_CAPA_MASK(0x8B2A)) -/* "Easy" macro to set events in iw_range (less efficient) */ -#define IW_EVENT_CAPA_SET(event_capa, cmd) (event_capa[IW_EVENT_CAPA_INDEX(cmd)] |= IW_EVENT_CAPA_MASK(cmd)) -#define IW_EVENT_CAPA_SET_KERNEL(event_capa) {event_capa[0] |= IW_EVENT_CAPA_K_0; event_capa[1] |= IW_EVENT_CAPA_K_1; } - - -/****************************** TYPES ******************************/ - -/* --------------------------- SUBTYPES --------------------------- */ -/* - * Generic format for most parameters that fit in an int - */ -struct iw_param -{ - __s32 value; /* The value of the parameter itself */ - __u8 fixed; /* Hardware should not use auto select */ - __u8 disabled; /* Disable the feature */ - __u16 flags; /* Various specifc flags (if any) */ -}; - -/* - * For all data larger than 16 octets, we need to use a - * pointer to memory allocated in user space. - */ -struct iw_point -{ - void __user *pointer; /* Pointer to the data (in user space) */ - __u16 length; /* number of fields or size in bytes */ - __u16 flags; /* Optional params */ -}; - -#ifdef __KERNEL__ -#ifdef CONFIG_COMPAT - -#include - -struct compat_iw_point { - compat_caddr_t pointer; - __u16 length; - __u16 flags; -}; -#endif -#endif - -/* - * A frequency - * For numbers lower than 10^9, we encode the number in 'm' and - * set 'e' to 0 - * For number greater than 10^9, we divide it by the lowest power - * of 10 to get 'm' lower than 10^9, with 'm'= f / (10^'e')... - * The power of 10 is in 'e', the result of the division is in 'm'. - */ -struct iw_freq -{ - __s32 m; /* Mantissa */ - __s16 e; /* Exponent */ - __u8 i; /* List index (when in range struct) */ - __u8 flags; /* Flags (fixed/auto) */ -}; - -/* - * Quality of the link - */ -struct iw_quality -{ - __u8 qual; /* link quality (%retries, SNR, - %missed beacons or better...) */ - __u8 level; /* signal level (dBm) */ - __u8 noise; /* noise level (dBm) */ - __u8 updated; /* Flags to know if updated */ -}; - -/* - * Packet discarded in the wireless adapter due to - * "wireless" specific problems... - * Note : the list of counter and statistics in net_device_stats - * is already pretty exhaustive, and you should use that first. - * This is only additional stats... - */ -struct iw_discarded -{ - __u32 nwid; /* Rx : Wrong nwid/essid */ - __u32 code; /* Rx : Unable to code/decode (WEP) */ - __u32 fragment; /* Rx : Can't perform MAC reassembly */ - __u32 retries; /* Tx : Max MAC retries num reached */ - __u32 misc; /* Others cases */ -}; - -/* - * Packet/Time period missed in the wireless adapter due to - * "wireless" specific problems... - */ -struct iw_missed -{ - __u32 beacon; /* Missed beacons/superframe */ -}; - -/* - * Quality range (for spy threshold) - */ -struct iw_thrspy -{ - struct sockaddr addr; /* Source address (hw/mac) */ - struct iw_quality qual; /* Quality of the link */ - struct iw_quality low; /* Low threshold */ - struct iw_quality high; /* High threshold */ -}; - -/* - * Optional data for scan request - * - * Note: these optional parameters are controlling parameters for the - * scanning behavior, these do not apply to getting scan results - * (SIOCGIWSCAN). Drivers are expected to keep a local BSS table and - * provide a merged results with all BSSes even if the previous scan - * request limited scanning to a subset, e.g., by specifying an SSID. - * Especially, scan results are required to include an entry for the - * current BSS if the driver is in Managed mode and associated with an AP. - */ -struct iw_scan_req -{ - __u8 scan_type; /* IW_SCAN_TYPE_{ACTIVE,PASSIVE} */ - __u8 essid_len; - __u8 num_channels; /* num entries in channel_list; - * 0 = scan all allowed channels */ - __u8 flags; /* reserved as padding; use zero, this may - * be used in the future for adding flags - * to request different scan behavior */ - struct sockaddr bssid; /* ff:ff:ff:ff:ff:ff for broadcast BSSID or - * individual address of a specific BSS */ - - /* - * Use this ESSID if IW_SCAN_THIS_ESSID flag is used instead of using - * the current ESSID. This allows scan requests for specific ESSID - * without having to change the current ESSID and potentially breaking - * the current association. - */ - __u8 essid[IW_ESSID_MAX_SIZE]; - - /* - * Optional parameters for changing the default scanning behavior. - * These are based on the MLME-SCAN.request from IEEE Std 802.11. - * TU is 1.024 ms. If these are set to 0, driver is expected to use - * reasonable default values. min_channel_time defines the time that - * will be used to wait for the first reply on each channel. If no - * replies are received, next channel will be scanned after this. If - * replies are received, total time waited on the channel is defined by - * max_channel_time. - */ - __u32 min_channel_time; /* in TU */ - __u32 max_channel_time; /* in TU */ - - struct iw_freq channel_list[IW_MAX_FREQUENCIES]; -}; - -/* ------------------------- WPA SUPPORT ------------------------- */ - -/* - * Extended data structure for get/set encoding (this is used with - * SIOCSIWENCODEEXT/SIOCGIWENCODEEXT. struct iw_point and IW_ENCODE_* - * flags are used in the same way as with SIOCSIWENCODE/SIOCGIWENCODE and - * only the data contents changes (key data -> this structure, including - * key data). - * - * If the new key is the first group key, it will be set as the default - * TX key. Otherwise, default TX key index is only changed if - * IW_ENCODE_EXT_SET_TX_KEY flag is set. - * - * Key will be changed with SIOCSIWENCODEEXT in all cases except for - * special "change TX key index" operation which is indicated by setting - * key_len = 0 and ext_flags |= IW_ENCODE_EXT_SET_TX_KEY. - * - * tx_seq/rx_seq are only used when respective - * IW_ENCODE_EXT_{TX,RX}_SEQ_VALID flag is set in ext_flags. Normal - * TKIP/CCMP operation is to set RX seq with SIOCSIWENCODEEXT and start - * TX seq from zero whenever key is changed. SIOCGIWENCODEEXT is normally - * used only by an Authenticator (AP or an IBSS station) to get the - * current TX sequence number. Using TX_SEQ_VALID for SIOCSIWENCODEEXT and - * RX_SEQ_VALID for SIOCGIWENCODEEXT are optional, but can be useful for - * debugging/testing. - */ -struct iw_encode_ext -{ - __u32 ext_flags; /* IW_ENCODE_EXT_* */ - __u8 tx_seq[IW_ENCODE_SEQ_MAX_SIZE]; /* LSB first */ - __u8 rx_seq[IW_ENCODE_SEQ_MAX_SIZE]; /* LSB first */ - struct sockaddr addr; /* ff:ff:ff:ff:ff:ff for broadcast/multicast - * (group) keys or unicast address for - * individual keys */ - __u16 alg; /* IW_ENCODE_ALG_* */ - __u16 key_len; - __u8 key[0]; -}; - -/* SIOCSIWMLME data */ -struct iw_mlme -{ - __u16 cmd; /* IW_MLME_* */ - __u16 reason_code; - struct sockaddr addr; -}; - -/* SIOCSIWPMKSA data */ -#define IW_PMKSA_ADD 1 -#define IW_PMKSA_REMOVE 2 -#define IW_PMKSA_FLUSH 3 - -#define IW_PMKID_LEN 16 - -struct iw_pmksa -{ - __u32 cmd; /* IW_PMKSA_* */ - struct sockaddr bssid; - __u8 pmkid[IW_PMKID_LEN]; -}; - -/* IWEVMICHAELMICFAILURE data */ -struct iw_michaelmicfailure -{ - __u32 flags; - struct sockaddr src_addr; - __u8 tsc[IW_ENCODE_SEQ_MAX_SIZE]; /* LSB first */ -}; - -/* IWEVPMKIDCAND data */ -#define IW_PMKID_CAND_PREAUTH 0x00000001 /* RNS pre-authentication enabled */ -struct iw_pmkid_cand -{ - __u32 flags; /* IW_PMKID_CAND_* */ - __u32 index; /* the smaller the index, the higher the - * priority */ - struct sockaddr bssid; -}; - -/* ------------------------ WIRELESS STATS ------------------------ */ -/* - * Wireless statistics (used for /proc/net/wireless) - */ -struct iw_statistics -{ - __u16 status; /* Status - * - device dependent for now */ - - struct iw_quality qual; /* Quality of the link - * (instant/mean/max) */ - struct iw_discarded discard; /* Packet discarded counts */ - struct iw_missed miss; /* Packet missed counts */ -}; - -/* ------------------------ IOCTL REQUEST ------------------------ */ -/* - * This structure defines the payload of an ioctl, and is used - * below. - * - * Note that this structure should fit on the memory footprint - * of iwreq (which is the same as ifreq), which mean a max size of - * 16 octets = 128 bits. Warning, pointers might be 64 bits wide... - * You should check this when increasing the structures defined - * above in this file... - */ -union iwreq_data -{ - /* Config - generic */ - char name[IFNAMSIZ]; - /* Name : used to verify the presence of wireless extensions. - * Name of the protocol/provider... */ - - struct iw_point essid; /* Extended network name */ - struct iw_param nwid; /* network id (or domain - the cell) */ - struct iw_freq freq; /* frequency or channel : - * 0-1000 = channel - * > 1000 = frequency in Hz */ - - struct iw_param sens; /* signal level threshold */ - struct iw_param bitrate; /* default bit rate */ - struct iw_param txpower; /* default transmit power */ - struct iw_param rts; /* RTS threshold threshold */ - struct iw_param frag; /* Fragmentation threshold */ - __u32 mode; /* Operation mode */ - struct iw_param retry; /* Retry limits & lifetime */ - - struct iw_point encoding; /* Encoding stuff : tokens */ - struct iw_param power; /* PM duration/timeout */ - struct iw_quality qual; /* Quality part of statistics */ - - struct sockaddr ap_addr; /* Access point address */ - struct sockaddr addr; /* Destination address (hw/mac) */ - - struct iw_param param; /* Other small parameters */ - struct iw_point data; /* Other large parameters */ -}; - -/* - * The structure to exchange data for ioctl. - * This structure is the same as 'struct ifreq', but (re)defined for - * convenience... - * Do I need to remind you about structure size (32 octets) ? - */ -struct iwreq -{ - union - { - char ifrn_name[IFNAMSIZ]; /* if name, e.g. "eth0" */ - } ifr_ifrn; - - /* Data part (defined just above) */ - union iwreq_data u; -}; - -/* -------------------------- IOCTL DATA -------------------------- */ -/* - * For those ioctl which want to exchange mode data that what could - * fit in the above structure... - */ - -/* - * Range of parameters - */ - -struct iw_range -{ - /* Informative stuff (to choose between different interface) */ - __u32 throughput; /* To give an idea... */ - /* In theory this value should be the maximum benchmarked - * TCP/IP throughput, because with most of these devices the - * bit rate is meaningless (overhead an co) to estimate how - * fast the connection will go and pick the fastest one. - * I suggest people to play with Netperf or any benchmark... - */ - - /* NWID (or domain id) */ - __u32 min_nwid; /* Minimal NWID we are able to set */ - __u32 max_nwid; /* Maximal NWID we are able to set */ - - /* Old Frequency (backward compat - moved lower ) */ - __u16 old_num_channels; - __u8 old_num_frequency; - - /* Scan capabilities */ - __u8 scan_capa; /* IW_SCAN_CAPA_* bit field */ - - /* Wireless event capability bitmasks */ - __u32 event_capa[6]; - - /* signal level threshold range */ - __s32 sensitivity; - - /* Quality of link & SNR stuff */ - /* Quality range (link, level, noise) - * If the quality is absolute, it will be in the range [0 ; max_qual], - * if the quality is dBm, it will be in the range [max_qual ; 0]. - * Don't forget that we use 8 bit arithmetics... */ - struct iw_quality max_qual; /* Quality of the link */ - /* This should contain the average/typical values of the quality - * indicator. This should be the threshold between a "good" and - * a "bad" link (example : monitor going from green to orange). - * Currently, user space apps like quality monitors don't have any - * way to calibrate the measurement. With this, they can split - * the range between 0 and max_qual in different quality level - * (using a geometric subdivision centered on the average). - * I expect that people doing the user space apps will feedback - * us on which value we need to put in each driver... */ - struct iw_quality avg_qual; /* Quality of the link */ - - /* Rates */ - __u8 num_bitrates; /* Number of entries in the list */ - __s32 bitrate[IW_MAX_BITRATES]; /* list, in bps */ - - /* RTS threshold */ - __s32 min_rts; /* Minimal RTS threshold */ - __s32 max_rts; /* Maximal RTS threshold */ - - /* Frag threshold */ - __s32 min_frag; /* Minimal frag threshold */ - __s32 max_frag; /* Maximal frag threshold */ - - /* Power Management duration & timeout */ - __s32 min_pmp; /* Minimal PM period */ - __s32 max_pmp; /* Maximal PM period */ - __s32 min_pmt; /* Minimal PM timeout */ - __s32 max_pmt; /* Maximal PM timeout */ - __u16 pmp_flags; /* How to decode max/min PM period */ - __u16 pmt_flags; /* How to decode max/min PM timeout */ - __u16 pm_capa; /* What PM options are supported */ - - /* Encoder stuff */ - __u16 encoding_size[IW_MAX_ENCODING_SIZES]; /* Different token sizes */ - __u8 num_encoding_sizes; /* Number of entry in the list */ - __u8 max_encoding_tokens; /* Max number of tokens */ - /* For drivers that need a "login/passwd" form */ - __u8 encoding_login_index; /* token index for login token */ - - /* Transmit power */ - __u16 txpower_capa; /* What options are supported */ - __u8 num_txpower; /* Number of entries in the list */ - __s32 txpower[IW_MAX_TXPOWER]; /* list, in bps */ - - /* Wireless Extension version info */ - __u8 we_version_compiled; /* Must be WIRELESS_EXT */ - __u8 we_version_source; /* Last update of source */ - - /* Retry limits and lifetime */ - __u16 retry_capa; /* What retry options are supported */ - __u16 retry_flags; /* How to decode max/min retry limit */ - __u16 r_time_flags; /* How to decode max/min retry life */ - __s32 min_retry; /* Minimal number of retries */ - __s32 max_retry; /* Maximal number of retries */ - __s32 min_r_time; /* Minimal retry lifetime */ - __s32 max_r_time; /* Maximal retry lifetime */ - - /* Frequency */ - __u16 num_channels; /* Number of channels [0; num - 1] */ - __u8 num_frequency; /* Number of entry in the list */ - struct iw_freq freq[IW_MAX_FREQUENCIES]; /* list */ - /* Note : this frequency list doesn't need to fit channel numbers, - * because each entry contain its channel index */ - - __u32 enc_capa; /* IW_ENC_CAPA_* bit field */ -}; - -/* - * Private ioctl interface information - */ - -struct iw_priv_args -{ - __u32 cmd; /* Number of the ioctl to issue */ - __u16 set_args; /* Type and number of args */ - __u16 get_args; /* Type and number of args */ - char name[IFNAMSIZ]; /* Name of the extension */ -}; - -/* ----------------------- WIRELESS EVENTS ----------------------- */ -/* - * Wireless events are carried through the rtnetlink socket to user - * space. They are encapsulated in the IFLA_WIRELESS field of - * a RTM_NEWLINK message. - */ - -/* - * A Wireless Event. Contains basically the same data as the ioctl... - */ -struct iw_event -{ - __u16 len; /* Real length of this stuff */ - __u16 cmd; /* Wireless IOCTL */ - union iwreq_data u; /* IOCTL fixed payload */ -}; - -/* Size of the Event prefix (including padding and alignement junk) */ -#define IW_EV_LCP_LEN (sizeof(struct iw_event) - sizeof(union iwreq_data)) -/* Size of the various events */ -#define IW_EV_CHAR_LEN (IW_EV_LCP_LEN + IFNAMSIZ) -#define IW_EV_UINT_LEN (IW_EV_LCP_LEN + sizeof(__u32)) -#define IW_EV_FREQ_LEN (IW_EV_LCP_LEN + sizeof(struct iw_freq)) -#define IW_EV_PARAM_LEN (IW_EV_LCP_LEN + sizeof(struct iw_param)) -#define IW_EV_ADDR_LEN (IW_EV_LCP_LEN + sizeof(struct sockaddr)) -#define IW_EV_QUAL_LEN (IW_EV_LCP_LEN + sizeof(struct iw_quality)) - -/* iw_point events are special. First, the payload (extra data) come at - * the end of the event, so they are bigger than IW_EV_POINT_LEN. Second, - * we omit the pointer, so start at an offset. */ -#define IW_EV_POINT_OFF (((char *) &(((struct iw_point *) NULL)->length)) - \ - (char *) NULL) -#define IW_EV_POINT_LEN (IW_EV_LCP_LEN + sizeof(struct iw_point) - \ - IW_EV_POINT_OFF) - -#ifdef __KERNEL__ -#ifdef CONFIG_COMPAT -struct __compat_iw_event { - __u16 len; /* Real length of this stuff */ - __u16 cmd; /* Wireless IOCTL */ - compat_caddr_t pointer; -}; -#define IW_EV_COMPAT_LCP_LEN offsetof(struct __compat_iw_event, pointer) -#define IW_EV_COMPAT_POINT_OFF offsetof(struct compat_iw_point, length) - -/* Size of the various events for compat */ -#define IW_EV_COMPAT_CHAR_LEN (IW_EV_COMPAT_LCP_LEN + IFNAMSIZ) -#define IW_EV_COMPAT_UINT_LEN (IW_EV_COMPAT_LCP_LEN + sizeof(__u32)) -#define IW_EV_COMPAT_FREQ_LEN (IW_EV_COMPAT_LCP_LEN + sizeof(struct iw_freq)) -#define IW_EV_COMPAT_PARAM_LEN (IW_EV_COMPAT_LCP_LEN + sizeof(struct iw_param)) -#define IW_EV_COMPAT_ADDR_LEN (IW_EV_COMPAT_LCP_LEN + sizeof(struct sockaddr)) -#define IW_EV_COMPAT_QUAL_LEN (IW_EV_COMPAT_LCP_LEN + sizeof(struct iw_quality)) -#define IW_EV_COMPAT_POINT_LEN \ - (IW_EV_COMPAT_LCP_LEN + sizeof(struct compat_iw_point) - \ - IW_EV_COMPAT_POINT_OFF) -#endif -#endif - -/* Size of the Event prefix when packed in stream */ -#define IW_EV_LCP_PK_LEN (4) -/* Size of the various events when packed in stream */ -#define IW_EV_CHAR_PK_LEN (IW_EV_LCP_PK_LEN + IFNAMSIZ) -#define IW_EV_UINT_PK_LEN (IW_EV_LCP_PK_LEN + sizeof(__u32)) -#define IW_EV_FREQ_PK_LEN (IW_EV_LCP_PK_LEN + sizeof(struct iw_freq)) -#define IW_EV_PARAM_PK_LEN (IW_EV_LCP_PK_LEN + sizeof(struct iw_param)) -#define IW_EV_ADDR_PK_LEN (IW_EV_LCP_PK_LEN + sizeof(struct sockaddr)) -#define IW_EV_QUAL_PK_LEN (IW_EV_LCP_PK_LEN + sizeof(struct iw_quality)) -#define IW_EV_POINT_PK_LEN (IW_EV_LCP_PK_LEN + 4) - -#endif /* _LINUX_WIRELESS_H */ diff --git a/hostapd-0.8/src/eap_common/Makefile b/hostapd-0.8/src/eap_common/Makefile deleted file mode 100644 index 9c41962..0000000 --- a/hostapd-0.8/src/eap_common/Makefile +++ /dev/null @@ -1,8 +0,0 @@ -all: - @echo Nothing to be made. - -clean: - rm -f *~ *.o *.d - -install: - @echo Nothing to be made. diff --git a/hostapd-0.8/src/eap_common/chap.c b/hostapd-0.8/src/eap_common/chap.c deleted file mode 100644 index 60bfc1c..0000000 --- a/hostapd-0.8/src/eap_common/chap.c +++ /dev/null @@ -1,34 +0,0 @@ -/* - * CHAP-MD5 (RFC 1994) - * Copyright (c) 2007-2009, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#include "includes.h" - -#include "common.h" -#include "crypto/crypto.h" -#include "chap.h" - -int chap_md5(u8 id, const u8 *secret, size_t secret_len, const u8 *challenge, - size_t challenge_len, u8 *response) -{ - const u8 *addr[3]; - size_t len[3]; - - addr[0] = &id; - len[0] = 1; - addr[1] = secret; - len[1] = secret_len; - addr[2] = challenge; - len[2] = challenge_len; - return md5_vector(3, addr, len, response); -} diff --git a/hostapd-0.8/src/eap_common/chap.h b/hostapd-0.8/src/eap_common/chap.h deleted file mode 100644 index b9c400c..0000000 --- a/hostapd-0.8/src/eap_common/chap.h +++ /dev/null @@ -1,23 +0,0 @@ -/* - * CHAP-MD5 (RFC 1994) - * Copyright (c) 2007-2009, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#ifndef CHAP_H -#define CHAP_H - -#define CHAP_MD5_LEN 16 - -int chap_md5(u8 id, const u8 *secret, size_t secret_len, const u8 *challenge, - size_t challenge_len, u8 *response); - -#endif /* CHAP_H */ diff --git a/hostapd-0.8/src/eap_common/eap_common.c b/hostapd-0.8/src/eap_common/eap_common.c deleted file mode 100644 index 4afa1dd..0000000 --- a/hostapd-0.8/src/eap_common/eap_common.c +++ /dev/null @@ -1,184 +0,0 @@ -/* - * EAP common peer/server definitions - * Copyright (c) 2004-2007, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#include "includes.h" - -#include "common.h" -#include "eap_defs.h" -#include "eap_common.h" - -/** - * eap_hdr_validate - Validate EAP header - * @vendor: Expected EAP Vendor-Id (0 = IETF) - * @eap_type: Expected EAP type number - * @msg: EAP frame (starting with EAP header) - * @plen: Pointer to variable to contain the returned payload length - * Returns: Pointer to EAP payload (after type field), or %NULL on failure - * - * This is a helper function for EAP method implementations. This is usually - * called in the beginning of struct eap_method::process() function to verify - * that the received EAP request packet has a valid header. This function is - * able to process both legacy and expanded EAP headers and in most cases, the - * caller can just use the returned payload pointer (into *plen) for processing - * the payload regardless of whether the packet used the expanded EAP header or - * not. - */ -const u8 * eap_hdr_validate(int vendor, EapType eap_type, - const struct wpabuf *msg, size_t *plen) -{ - const struct eap_hdr *hdr; - const u8 *pos; - size_t len; - - hdr = wpabuf_head(msg); - - if (wpabuf_len(msg) < sizeof(*hdr)) { - wpa_printf(MSG_INFO, "EAP: Too short EAP frame"); - return NULL; - } - - len = be_to_host16(hdr->length); - if (len < sizeof(*hdr) + 1 || len > wpabuf_len(msg)) { - wpa_printf(MSG_INFO, "EAP: Invalid EAP length"); - return NULL; - } - - pos = (const u8 *) (hdr + 1); - - if (*pos == EAP_TYPE_EXPANDED) { - int exp_vendor; - u32 exp_type; - if (len < sizeof(*hdr) + 8) { - wpa_printf(MSG_INFO, "EAP: Invalid expanded EAP " - "length"); - return NULL; - } - pos++; - exp_vendor = WPA_GET_BE24(pos); - pos += 3; - exp_type = WPA_GET_BE32(pos); - pos += 4; - if (exp_vendor != vendor || exp_type != (u32) eap_type) { - wpa_printf(MSG_INFO, "EAP: Invalid expanded frame " - "type"); - return NULL; - } - - *plen = len - sizeof(*hdr) - 8; - return pos; - } else { - if (vendor != EAP_VENDOR_IETF || *pos != eap_type) { - wpa_printf(MSG_INFO, "EAP: Invalid frame type"); - return NULL; - } - *plen = len - sizeof(*hdr) - 1; - return pos + 1; - } -} - - -/** - * eap_msg_alloc - Allocate a buffer for an EAP message - * @vendor: Vendor-Id (0 = IETF) - * @type: EAP type - * @payload_len: Payload length in bytes (data after Type) - * @code: Message Code (EAP_CODE_*) - * @identifier: Identifier - * Returns: Pointer to the allocated message buffer or %NULL on error - * - * This function can be used to allocate a buffer for an EAP message and fill - * in the EAP header. This function is automatically using expanded EAP header - * if the selected Vendor-Id is not IETF. In other words, most EAP methods do - * not need to separately select which header type to use when using this - * function to allocate the message buffers. The returned buffer has room for - * payload_len bytes and has the EAP header and Type field already filled in. - */ -struct wpabuf * eap_msg_alloc(int vendor, EapType type, size_t payload_len, - u8 code, u8 identifier) -{ - struct wpabuf *buf; - struct eap_hdr *hdr; - size_t len; - - len = sizeof(struct eap_hdr) + (vendor == EAP_VENDOR_IETF ? 1 : 8) + - payload_len; - buf = wpabuf_alloc(len); - if (buf == NULL) - return NULL; - - hdr = wpabuf_put(buf, sizeof(*hdr)); - hdr->code = code; - hdr->identifier = identifier; - hdr->length = host_to_be16(len); - - if (vendor == EAP_VENDOR_IETF) { - wpabuf_put_u8(buf, type); - } else { - wpabuf_put_u8(buf, EAP_TYPE_EXPANDED); - wpabuf_put_be24(buf, vendor); - wpabuf_put_be32(buf, type); - } - - return buf; -} - - -/** - * eap_update_len - Update EAP header length - * @msg: EAP message from eap_msg_alloc - * - * This function updates the length field in the EAP header to match with the - * current length for the buffer. This allows eap_msg_alloc() to be used to - * allocate a larger buffer than the exact message length (e.g., if exact - * message length is not yet known). - */ -void eap_update_len(struct wpabuf *msg) -{ - struct eap_hdr *hdr; - hdr = wpabuf_mhead(msg); - if (wpabuf_len(msg) < sizeof(*hdr)) - return; - hdr->length = host_to_be16(wpabuf_len(msg)); -} - - -/** - * eap_get_id - Get EAP Identifier from wpabuf - * @msg: Buffer starting with an EAP header - * Returns: The Identifier field from the EAP header - */ -u8 eap_get_id(const struct wpabuf *msg) -{ - const struct eap_hdr *eap; - - if (wpabuf_len(msg) < sizeof(*eap)) - return 0; - - eap = wpabuf_head(msg); - return eap->identifier; -} - - -/** - * eap_get_id - Get EAP Type from wpabuf - * @msg: Buffer starting with an EAP header - * Returns: The EAP Type after the EAP header - */ -EapType eap_get_type(const struct wpabuf *msg) -{ - if (wpabuf_len(msg) < sizeof(struct eap_hdr) + 1) - return EAP_TYPE_NONE; - - return ((const u8 *) wpabuf_head(msg))[sizeof(struct eap_hdr)]; -} diff --git a/hostapd-0.8/src/eap_common/eap_common.h b/hostapd-0.8/src/eap_common/eap_common.h deleted file mode 100644 index b95e76b..0000000 --- a/hostapd-0.8/src/eap_common/eap_common.h +++ /dev/null @@ -1,28 +0,0 @@ -/* - * EAP common peer/server definitions - * Copyright (c) 2004-2007, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#ifndef EAP_COMMON_H -#define EAP_COMMON_H - -#include "wpabuf.h" - -const u8 * eap_hdr_validate(int vendor, EapType eap_type, - const struct wpabuf *msg, size_t *plen); -struct wpabuf * eap_msg_alloc(int vendor, EapType type, size_t payload_len, - u8 code, u8 identifier); -void eap_update_len(struct wpabuf *msg); -u8 eap_get_id(const struct wpabuf *msg); -EapType eap_get_type(const struct wpabuf *msg); - -#endif /* EAP_COMMON_H */ diff --git a/hostapd-0.8/src/eap_common/eap_defs.h b/hostapd-0.8/src/eap_common/eap_defs.h deleted file mode 100644 index 3035301..0000000 --- a/hostapd-0.8/src/eap_common/eap_defs.h +++ /dev/null @@ -1,86 +0,0 @@ -/* - * EAP server/peer: Shared EAP definitions - * Copyright (c) 2004-2007, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#ifndef EAP_DEFS_H -#define EAP_DEFS_H - -/* RFC 3748 - Extensible Authentication Protocol (EAP) */ - -#ifdef _MSC_VER -#pragma pack(push, 1) -#endif /* _MSC_VER */ - -struct eap_hdr { - u8 code; - u8 identifier; - be16 length; /* including code and identifier; network byte order */ - /* followed by length-4 octets of data */ -} STRUCT_PACKED; - -#ifdef _MSC_VER -#pragma pack(pop) -#endif /* _MSC_VER */ - -enum { EAP_CODE_REQUEST = 1, EAP_CODE_RESPONSE = 2, EAP_CODE_SUCCESS = 3, - EAP_CODE_FAILURE = 4 }; - -/* EAP Request and Response data begins with one octet Type. Success and - * Failure do not have additional data. */ - -/* - * EAP Method Types as allocated by IANA: - * http://www.iana.org/assignments/eap-numbers - */ -typedef enum { - EAP_TYPE_NONE = 0, - EAP_TYPE_IDENTITY = 1 /* RFC 3748 */, - EAP_TYPE_NOTIFICATION = 2 /* RFC 3748 */, - EAP_TYPE_NAK = 3 /* Response only, RFC 3748 */, - EAP_TYPE_MD5 = 4, /* RFC 3748 */ - EAP_TYPE_OTP = 5 /* RFC 3748 */, - EAP_TYPE_GTC = 6, /* RFC 3748 */ - EAP_TYPE_TLS = 13 /* RFC 2716 */, - EAP_TYPE_LEAP = 17 /* Cisco proprietary */, - EAP_TYPE_SIM = 18 /* RFC 4186 */, - EAP_TYPE_TTLS = 21 /* RFC 5281 */, - EAP_TYPE_AKA = 23 /* RFC 4187 */, - EAP_TYPE_PEAP = 25 /* draft-josefsson-pppext-eap-tls-eap-06.txt */, - EAP_TYPE_MSCHAPV2 = 26 /* draft-kamath-pppext-eap-mschapv2-00.txt */, - EAP_TYPE_TLV = 33 /* draft-josefsson-pppext-eap-tls-eap-07.txt */, - EAP_TYPE_TNC = 38 /* TNC IF-T v1.0-r3; note: tentative assignment; - * type 38 has previously been allocated for - * EAP-HTTP Digest, (funk.com) */, - EAP_TYPE_FAST = 43 /* RFC 4851 */, - EAP_TYPE_PAX = 46 /* RFC 4746 */, - EAP_TYPE_PSK = 47 /* RFC 4764 */, - EAP_TYPE_SAKE = 48 /* RFC 4763 */, - EAP_TYPE_IKEV2 = 49 /* RFC 5106 */, - EAP_TYPE_AKA_PRIME = 50 /* draft-arkko-eap-aka-kdf-10.txt */, - EAP_TYPE_GPSK = 51 /* RFC 5433 */, - EAP_TYPE_PWD = 52 /* RFC 5931 */, - EAP_TYPE_EXPANDED = 254 /* RFC 3748 */ -} EapType; - - -/* SMI Network Management Private Enterprise Code for vendor specific types */ -enum { - EAP_VENDOR_IETF = 0, - EAP_VENDOR_MICROSOFT = 0x000137 /* Microsoft */, - EAP_VENDOR_WFA = 0x00372A /* Wi-Fi Alliance */ -}; - -#define EAP_MSK_LEN 64 -#define EAP_EMSK_LEN 64 - -#endif /* EAP_DEFS_H */ diff --git a/hostapd-0.8/src/eap_common/eap_fast_common.c b/hostapd-0.8/src/eap_common/eap_fast_common.c deleted file mode 100644 index 4de34a8..0000000 --- a/hostapd-0.8/src/eap_common/eap_fast_common.c +++ /dev/null @@ -1,304 +0,0 @@ -/* - * EAP-FAST common helper functions (RFC 4851) - * Copyright (c) 2008, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#include "includes.h" - -#include "common.h" -#include "crypto/sha1.h" -#include "crypto/tls.h" -#include "eap_defs.h" -#include "eap_tlv_common.h" -#include "eap_fast_common.h" - - -void eap_fast_put_tlv_hdr(struct wpabuf *buf, u16 type, u16 len) -{ - struct pac_tlv_hdr hdr; - hdr.type = host_to_be16(type); - hdr.len = host_to_be16(len); - wpabuf_put_data(buf, &hdr, sizeof(hdr)); -} - - -void eap_fast_put_tlv(struct wpabuf *buf, u16 type, const void *data, - u16 len) -{ - eap_fast_put_tlv_hdr(buf, type, len); - wpabuf_put_data(buf, data, len); -} - - -void eap_fast_put_tlv_buf(struct wpabuf *buf, u16 type, - const struct wpabuf *data) -{ - eap_fast_put_tlv_hdr(buf, type, wpabuf_len(data)); - wpabuf_put_buf(buf, data); -} - - -struct wpabuf * eap_fast_tlv_eap_payload(struct wpabuf *buf) -{ - struct wpabuf *e; - - if (buf == NULL) - return NULL; - - /* Encapsulate EAP packet in EAP-Payload TLV */ - wpa_printf(MSG_DEBUG, "EAP-FAST: Add EAP-Payload TLV"); - e = wpabuf_alloc(sizeof(struct pac_tlv_hdr) + wpabuf_len(buf)); - if (e == NULL) { - wpa_printf(MSG_DEBUG, "EAP-FAST: Failed to allocate memory " - "for TLV encapsulation"); - wpabuf_free(buf); - return NULL; - } - eap_fast_put_tlv_buf(e, - EAP_TLV_TYPE_MANDATORY | EAP_TLV_EAP_PAYLOAD_TLV, - buf); - wpabuf_free(buf); - return e; -} - - -void eap_fast_derive_master_secret(const u8 *pac_key, const u8 *server_random, - const u8 *client_random, u8 *master_secret) -{ -#define TLS_RANDOM_LEN 32 -#define TLS_MASTER_SECRET_LEN 48 - u8 seed[2 * TLS_RANDOM_LEN]; - - wpa_hexdump(MSG_DEBUG, "EAP-FAST: client_random", - client_random, TLS_RANDOM_LEN); - wpa_hexdump(MSG_DEBUG, "EAP-FAST: server_random", - server_random, TLS_RANDOM_LEN); - - /* - * RFC 4851, Section 5.1: - * master_secret = T-PRF(PAC-Key, "PAC to master secret label hash", - * server_random + client_random, 48) - */ - os_memcpy(seed, server_random, TLS_RANDOM_LEN); - os_memcpy(seed + TLS_RANDOM_LEN, client_random, TLS_RANDOM_LEN); - sha1_t_prf(pac_key, EAP_FAST_PAC_KEY_LEN, - "PAC to master secret label hash", - seed, sizeof(seed), master_secret, TLS_MASTER_SECRET_LEN); - - wpa_hexdump_key(MSG_DEBUG, "EAP-FAST: master_secret", - master_secret, TLS_MASTER_SECRET_LEN); -} - - -u8 * eap_fast_derive_key(void *ssl_ctx, struct tls_connection *conn, - const char *label, size_t len) -{ - struct tls_keys keys; - u8 *rnd = NULL, *out; - int block_size; - - block_size = tls_connection_get_keyblock_size(ssl_ctx, conn); - if (block_size < 0) - return NULL; - - out = os_malloc(block_size + len); - if (out == NULL) - return NULL; - - if (tls_connection_prf(ssl_ctx, conn, label, 1, out, block_size + len) - == 0) { - os_memmove(out, out + block_size, len); - return out; - } - - if (tls_connection_get_keys(ssl_ctx, conn, &keys)) - goto fail; - - rnd = os_malloc(keys.client_random_len + keys.server_random_len); - if (rnd == NULL) - goto fail; - - os_memcpy(rnd, keys.server_random, keys.server_random_len); - os_memcpy(rnd + keys.server_random_len, keys.client_random, - keys.client_random_len); - - wpa_hexdump_key(MSG_MSGDUMP, "EAP-FAST: master_secret for key " - "expansion", keys.master_key, keys.master_key_len); - if (tls_prf(keys.master_key, keys.master_key_len, - label, rnd, keys.client_random_len + - keys.server_random_len, out, block_size + len)) - goto fail; - os_free(rnd); - os_memmove(out, out + block_size, len); - return out; - -fail: - os_free(rnd); - os_free(out); - return NULL; -} - - -void eap_fast_derive_eap_msk(const u8 *simck, u8 *msk) -{ - /* - * RFC 4851, Section 5.4: EAP Master Session Key Generation - * MSK = T-PRF(S-IMCK[j], "Session Key Generating Function", 64) - */ - - sha1_t_prf(simck, EAP_FAST_SIMCK_LEN, - "Session Key Generating Function", (u8 *) "", 0, - msk, EAP_FAST_KEY_LEN); - wpa_hexdump_key(MSG_DEBUG, "EAP-FAST: Derived key (MSK)", - msk, EAP_FAST_KEY_LEN); -} - - -void eap_fast_derive_eap_emsk(const u8 *simck, u8 *emsk) -{ - /* - * RFC 4851, Section 5.4: EAP Master Session Key Genreration - * EMSK = T-PRF(S-IMCK[j], - * "Extended Session Key Generating Function", 64) - */ - - sha1_t_prf(simck, EAP_FAST_SIMCK_LEN, - "Extended Session Key Generating Function", (u8 *) "", 0, - emsk, EAP_EMSK_LEN); - wpa_hexdump_key(MSG_DEBUG, "EAP-FAST: Derived key (EMSK)", - emsk, EAP_EMSK_LEN); -} - - -int eap_fast_parse_tlv(struct eap_fast_tlv_parse *tlv, - int tlv_type, u8 *pos, int len) -{ - switch (tlv_type) { - case EAP_TLV_EAP_PAYLOAD_TLV: - wpa_hexdump(MSG_MSGDUMP, "EAP-FAST: EAP-Payload TLV", - pos, len); - if (tlv->eap_payload_tlv) { - wpa_printf(MSG_DEBUG, "EAP-FAST: More than one " - "EAP-Payload TLV in the message"); - tlv->iresult = EAP_TLV_RESULT_FAILURE; - return -2; - } - tlv->eap_payload_tlv = pos; - tlv->eap_payload_tlv_len = len; - break; - case EAP_TLV_RESULT_TLV: - wpa_hexdump(MSG_MSGDUMP, "EAP-FAST: Result TLV", pos, len); - if (tlv->result) { - wpa_printf(MSG_DEBUG, "EAP-FAST: More than one " - "Result TLV in the message"); - tlv->result = EAP_TLV_RESULT_FAILURE; - return -2; - } - if (len < 2) { - wpa_printf(MSG_DEBUG, "EAP-FAST: Too short " - "Result TLV"); - tlv->result = EAP_TLV_RESULT_FAILURE; - break; - } - tlv->result = WPA_GET_BE16(pos); - if (tlv->result != EAP_TLV_RESULT_SUCCESS && - tlv->result != EAP_TLV_RESULT_FAILURE) { - wpa_printf(MSG_DEBUG, "EAP-FAST: Unknown Result %d", - tlv->result); - tlv->result = EAP_TLV_RESULT_FAILURE; - } - wpa_printf(MSG_DEBUG, "EAP-FAST: Result: %s", - tlv->result == EAP_TLV_RESULT_SUCCESS ? - "Success" : "Failure"); - break; - case EAP_TLV_INTERMEDIATE_RESULT_TLV: - wpa_hexdump(MSG_MSGDUMP, "EAP-FAST: Intermediate Result TLV", - pos, len); - if (len < 2) { - wpa_printf(MSG_DEBUG, "EAP-FAST: Too short " - "Intermediate-Result TLV"); - tlv->iresult = EAP_TLV_RESULT_FAILURE; - break; - } - if (tlv->iresult) { - wpa_printf(MSG_DEBUG, "EAP-FAST: More than one " - "Intermediate-Result TLV in the message"); - tlv->iresult = EAP_TLV_RESULT_FAILURE; - return -2; - } - tlv->iresult = WPA_GET_BE16(pos); - if (tlv->iresult != EAP_TLV_RESULT_SUCCESS && - tlv->iresult != EAP_TLV_RESULT_FAILURE) { - wpa_printf(MSG_DEBUG, "EAP-FAST: Unknown Intermediate " - "Result %d", tlv->iresult); - tlv->iresult = EAP_TLV_RESULT_FAILURE; - } - wpa_printf(MSG_DEBUG, "EAP-FAST: Intermediate Result: %s", - tlv->iresult == EAP_TLV_RESULT_SUCCESS ? - "Success" : "Failure"); - break; - case EAP_TLV_CRYPTO_BINDING_TLV: - wpa_hexdump(MSG_MSGDUMP, "EAP-FAST: Crypto-Binding TLV", - pos, len); - if (tlv->crypto_binding) { - wpa_printf(MSG_DEBUG, "EAP-FAST: More than one " - "Crypto-Binding TLV in the message"); - tlv->iresult = EAP_TLV_RESULT_FAILURE; - return -2; - } - tlv->crypto_binding_len = sizeof(struct eap_tlv_hdr) + len; - if (tlv->crypto_binding_len < sizeof(*tlv->crypto_binding)) { - wpa_printf(MSG_DEBUG, "EAP-FAST: Too short " - "Crypto-Binding TLV"); - tlv->iresult = EAP_TLV_RESULT_FAILURE; - return -2; - } - tlv->crypto_binding = (struct eap_tlv_crypto_binding_tlv *) - (pos - sizeof(struct eap_tlv_hdr)); - break; - case EAP_TLV_REQUEST_ACTION_TLV: - wpa_hexdump(MSG_MSGDUMP, "EAP-FAST: Request-Action TLV", - pos, len); - if (tlv->request_action) { - wpa_printf(MSG_DEBUG, "EAP-FAST: More than one " - "Request-Action TLV in the message"); - tlv->iresult = EAP_TLV_RESULT_FAILURE; - return -2; - } - if (len < 2) { - wpa_printf(MSG_DEBUG, "EAP-FAST: Too short " - "Request-Action TLV"); - tlv->iresult = EAP_TLV_RESULT_FAILURE; - break; - } - tlv->request_action = WPA_GET_BE16(pos); - wpa_printf(MSG_DEBUG, "EAP-FAST: Request-Action: %d", - tlv->request_action); - break; - case EAP_TLV_PAC_TLV: - wpa_hexdump(MSG_MSGDUMP, "EAP-FAST: PAC TLV", pos, len); - if (tlv->pac) { - wpa_printf(MSG_DEBUG, "EAP-FAST: More than one " - "PAC TLV in the message"); - tlv->iresult = EAP_TLV_RESULT_FAILURE; - return -2; - } - tlv->pac = pos; - tlv->pac_len = len; - break; - default: - /* Unknown TLV */ - return -1; - } - - return 0; -} diff --git a/hostapd-0.8/src/eap_common/eap_fast_common.h b/hostapd-0.8/src/eap_common/eap_fast_common.h deleted file mode 100644 index c85fd37..0000000 --- a/hostapd-0.8/src/eap_common/eap_fast_common.h +++ /dev/null @@ -1,113 +0,0 @@ -/* - * EAP-FAST definitions (RFC 4851) - * Copyright (c) 2004-2008, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#ifndef EAP_FAST_H -#define EAP_FAST_H - -#define EAP_FAST_VERSION 1 -#define EAP_FAST_KEY_LEN 64 -#define EAP_FAST_SIMCK_LEN 40 -#define EAP_FAST_SKS_LEN 40 -#define EAP_FAST_CMK_LEN 20 - -#define TLS_EXT_PAC_OPAQUE 35 - -/* - * RFC 5422: Section 4.2.1 - Formats for PAC TLV Attributes / Type Field - * Note: bit 0x8000 (Mandatory) and bit 0x4000 (Reserved) are also defined - * in the general PAC TLV format (Section 4.2). - */ -#define PAC_TYPE_PAC_KEY 1 -#define PAC_TYPE_PAC_OPAQUE 2 -#define PAC_TYPE_CRED_LIFETIME 3 -#define PAC_TYPE_A_ID 4 -#define PAC_TYPE_I_ID 5 -/* - * 6 was previous assigned for SERVER_PROTECTED_DATA, but - * draft-cam-winget-eap-fast-provisioning-02.txt changed this to Reserved. - */ -#define PAC_TYPE_A_ID_INFO 7 -#define PAC_TYPE_PAC_ACKNOWLEDGEMENT 8 -#define PAC_TYPE_PAC_INFO 9 -#define PAC_TYPE_PAC_TYPE 10 - -#ifdef _MSC_VER -#pragma pack(push, 1) -#endif /* _MSC_VER */ - -struct pac_tlv_hdr { - be16 type; - be16 len; -} STRUCT_PACKED; - -#ifdef _MSC_VER -#pragma pack(pop) -#endif /* _MSC_VER */ - - -#define EAP_FAST_PAC_KEY_LEN 32 - -/* RFC 5422: 4.2.6 PAC-Type TLV */ -#define PAC_TYPE_TUNNEL_PAC 1 -/* Application Specific Short Lived PACs (only in volatile storage) */ -/* User Authorization PAC */ -#define PAC_TYPE_USER_AUTHORIZATION 3 -/* Application Specific Long Lived PACs */ -/* Machine Authentication PAC */ -#define PAC_TYPE_MACHINE_AUTHENTICATION 2 - - -/* - * RFC 5422: - * Section 3.3 - Key Derivations Used in the EAP-FAST Provisioning Exchange - */ -struct eap_fast_key_block_provisioning { - /* Extra key material after TLS key_block */ - u8 session_key_seed[EAP_FAST_SKS_LEN]; - u8 server_challenge[16]; /* MSCHAPv2 ServerChallenge */ - u8 client_challenge[16]; /* MSCHAPv2 ClientChallenge */ -}; - - -struct wpabuf; -struct tls_connection; - -struct eap_fast_tlv_parse { - u8 *eap_payload_tlv; - size_t eap_payload_tlv_len; - struct eap_tlv_crypto_binding_tlv *crypto_binding; - size_t crypto_binding_len; - int iresult; - int result; - int request_action; - u8 *pac; - size_t pac_len; -}; - -void eap_fast_put_tlv_hdr(struct wpabuf *buf, u16 type, u16 len); -void eap_fast_put_tlv(struct wpabuf *buf, u16 type, const void *data, - u16 len); -void eap_fast_put_tlv_buf(struct wpabuf *buf, u16 type, - const struct wpabuf *data); -struct wpabuf * eap_fast_tlv_eap_payload(struct wpabuf *buf); -void eap_fast_derive_master_secret(const u8 *pac_key, const u8 *server_random, - const u8 *client_random, u8 *master_secret); -u8 * eap_fast_derive_key(void *ssl_ctx, struct tls_connection *conn, - const char *label, size_t len); -void eap_fast_derive_eap_msk(const u8 *simck, u8 *msk); -void eap_fast_derive_eap_emsk(const u8 *simck, u8 *emsk); -int eap_fast_parse_tlv(struct eap_fast_tlv_parse *tlv, - int tlv_type, u8 *pos, int len); - -#endif /* EAP_FAST_H */ diff --git a/hostapd-0.8/src/eap_common/eap_gpsk_common.c b/hostapd-0.8/src/eap_common/eap_gpsk_common.c deleted file mode 100644 index 4076262..0000000 --- a/hostapd-0.8/src/eap_common/eap_gpsk_common.c +++ /dev/null @@ -1,423 +0,0 @@ -/* - * EAP server/peer: EAP-GPSK shared routines - * Copyright (c) 2006-2007, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#include "includes.h" - -#include "common.h" -#include "crypto/aes_wrap.h" -#include "crypto/sha256.h" -#include "eap_defs.h" -#include "eap_gpsk_common.h" - - -/** - * eap_gpsk_supported_ciphersuite - Check whether ciphersuite is supported - * @vendor: CSuite/Vendor - * @specifier: CSuite/Specifier - * Returns: 1 if ciphersuite is support, or 0 if not - */ -int eap_gpsk_supported_ciphersuite(int vendor, int specifier) -{ - if (vendor == EAP_GPSK_VENDOR_IETF && - specifier == EAP_GPSK_CIPHER_AES) - return 1; -#ifdef EAP_GPSK_SHA256 - if (vendor == EAP_GPSK_VENDOR_IETF && - specifier == EAP_GPSK_CIPHER_SHA256) - return 1; -#endif /* EAP_GPSK_SHA256 */ - return 0; -} - - -static int eap_gpsk_gkdf_cmac(const u8 *psk /* Y */, - const u8 *data /* Z */, size_t data_len, - u8 *buf, size_t len /* X */) -{ - u8 *opos; - size_t i, n, hashlen, left, clen; - u8 ibuf[2], hash[16]; - const u8 *addr[2]; - size_t vlen[2]; - - hashlen = sizeof(hash); - /* M_i = MAC_Y (i || Z); (MAC = AES-CMAC-128) */ - addr[0] = ibuf; - vlen[0] = sizeof(ibuf); - addr[1] = data; - vlen[1] = data_len; - - opos = buf; - left = len; - n = (len + hashlen - 1) / hashlen; - for (i = 1; i <= n; i++) { - WPA_PUT_BE16(ibuf, i); - if (omac1_aes_128_vector(psk, 2, addr, vlen, hash)) - return -1; - clen = left > hashlen ? hashlen : left; - os_memcpy(opos, hash, clen); - opos += clen; - left -= clen; - } - - return 0; -} - - -#ifdef EAP_GPSK_SHA256 -static int eap_gpsk_gkdf_sha256(const u8 *psk /* Y */, - const u8 *data /* Z */, size_t data_len, - u8 *buf, size_t len /* X */) -{ - u8 *opos; - size_t i, n, hashlen, left, clen; - u8 ibuf[2], hash[SHA256_MAC_LEN]; - const u8 *addr[2]; - size_t vlen[2]; - - hashlen = SHA256_MAC_LEN; - /* M_i = MAC_Y (i || Z); (MAC = HMAC-SHA256) */ - addr[0] = ibuf; - vlen[0] = sizeof(ibuf); - addr[1] = data; - vlen[1] = data_len; - - opos = buf; - left = len; - n = (len + hashlen - 1) / hashlen; - for (i = 1; i <= n; i++) { - WPA_PUT_BE16(ibuf, i); - hmac_sha256_vector(psk, 32, 2, addr, vlen, hash); - clen = left > hashlen ? hashlen : left; - os_memcpy(opos, hash, clen); - opos += clen; - left -= clen; - } - - return 0; -} -#endif /* EAP_GPSK_SHA256 */ - - -static int eap_gpsk_derive_keys_helper(u32 csuite_specifier, - u8 *kdf_out, size_t kdf_out_len, - const u8 *psk, size_t psk_len, - const u8 *seed, size_t seed_len, - u8 *msk, u8 *emsk, - u8 *sk, size_t sk_len, - u8 *pk, size_t pk_len) -{ - u8 mk[32], *pos, *data; - size_t data_len, mk_len; - int (*gkdf)(const u8 *_psk, const u8 *_data, size_t _data_len, - u8 *buf, size_t len); - - gkdf = NULL; - switch (csuite_specifier) { - case EAP_GPSK_CIPHER_AES: - gkdf = eap_gpsk_gkdf_cmac; - mk_len = 16; - break; -#ifdef EAP_GPSK_SHA256 - case EAP_GPSK_CIPHER_SHA256: - gkdf = eap_gpsk_gkdf_sha256; - mk_len = SHA256_MAC_LEN; - break; -#endif /* EAP_GPSK_SHA256 */ - default: - return -1; - } - - if (psk_len < mk_len) - return -1; - - data_len = 2 + psk_len + 6 + seed_len; - data = os_malloc(data_len); - if (data == NULL) - return -1; - pos = data; - WPA_PUT_BE16(pos, psk_len); - pos += 2; - os_memcpy(pos, psk, psk_len); - pos += psk_len; - WPA_PUT_BE32(pos, EAP_GPSK_VENDOR_IETF); /* CSuite/Vendor = IETF */ - pos += 4; - WPA_PUT_BE16(pos, csuite_specifier); /* CSuite/Specifier */ - pos += 2; - os_memcpy(pos, seed, seed_len); /* inputString */ - wpa_hexdump_key(MSG_DEBUG, "EAP-GPSK: Data to MK derivation", - data, data_len); - - if (gkdf(psk, data, data_len, mk, mk_len) < 0) { - os_free(data); - return -1; - } - os_free(data); - wpa_hexdump_key(MSG_DEBUG, "EAP-GPSK: MK", mk, mk_len); - - if (gkdf(mk, seed, seed_len, kdf_out, kdf_out_len) < 0) - return -1; - - pos = kdf_out; - wpa_hexdump_key(MSG_DEBUG, "EAP-GPSK: MSK", pos, EAP_MSK_LEN); - os_memcpy(msk, pos, EAP_MSK_LEN); - pos += EAP_MSK_LEN; - - wpa_hexdump_key(MSG_DEBUG, "EAP-GPSK: EMSK", pos, EAP_EMSK_LEN); - os_memcpy(emsk, pos, EAP_EMSK_LEN); - pos += EAP_EMSK_LEN; - - wpa_hexdump_key(MSG_DEBUG, "EAP-GPSK: SK", pos, sk_len); - os_memcpy(sk, pos, sk_len); - pos += sk_len; - - if (pk) { - wpa_hexdump_key(MSG_DEBUG, "EAP-GPSK: PK", pos, pk_len); - os_memcpy(pk, pos, pk_len); - } - - return 0; -} - - -static int eap_gpsk_derive_keys_aes(const u8 *psk, size_t psk_len, - const u8 *seed, size_t seed_len, - u8 *msk, u8 *emsk, u8 *sk, size_t *sk_len, - u8 *pk, size_t *pk_len) -{ -#define EAP_GPSK_SK_LEN_AES 16 -#define EAP_GPSK_PK_LEN_AES 16 - u8 kdf_out[EAP_MSK_LEN + EAP_EMSK_LEN + EAP_GPSK_SK_LEN_AES + - EAP_GPSK_PK_LEN_AES]; - - /* - * inputString = RAND_Peer || ID_Peer || RAND_Server || ID_Server - * (= seed) - * KS = 16, PL = psk_len, CSuite_Sel = 0x00000000 0x0001 - * MK = GKDF-16 (PSK[0..15], PL || PSK || CSuite_Sel || inputString) - * MSK = GKDF-160 (MK, inputString)[0..63] - * EMSK = GKDF-160 (MK, inputString)[64..127] - * SK = GKDF-160 (MK, inputString)[128..143] - * PK = GKDF-160 (MK, inputString)[144..159] - * zero = 0x00 || 0x00 || ... || 0x00 (16 times) - * Method-ID = GKDF-16 (zero, "Method ID" || EAP_Method_Type || - * CSuite_Sel || inputString) - */ - - *sk_len = EAP_GPSK_SK_LEN_AES; - *pk_len = EAP_GPSK_PK_LEN_AES; - - return eap_gpsk_derive_keys_helper(EAP_GPSK_CIPHER_AES, - kdf_out, sizeof(kdf_out), - psk, psk_len, seed, seed_len, - msk, emsk, sk, *sk_len, - pk, *pk_len); -} - - -#ifdef EAP_GPSK_SHA256 -static int eap_gpsk_derive_keys_sha256(const u8 *psk, size_t psk_len, - const u8 *seed, size_t seed_len, - u8 *msk, u8 *emsk, - u8 *sk, size_t *sk_len) -{ -#define EAP_GPSK_SK_LEN_SHA256 SHA256_MAC_LEN -#define EAP_GPSK_PK_LEN_SHA256 SHA256_MAC_LEN - u8 kdf_out[EAP_MSK_LEN + EAP_EMSK_LEN + EAP_GPSK_SK_LEN_SHA256 + - EAP_GPSK_PK_LEN_SHA256]; - - /* - * inputString = RAND_Peer || ID_Peer || RAND_Server || ID_Server - * (= seed) - * KS = 32, PL = psk_len, CSuite_Sel = 0x00000000 0x0002 - * MK = GKDF-32 (PSK[0..31], PL || PSK || CSuite_Sel || inputString) - * MSK = GKDF-160 (MK, inputString)[0..63] - * EMSK = GKDF-160 (MK, inputString)[64..127] - * SK = GKDF-160 (MK, inputString)[128..159] - * zero = 0x00 || 0x00 || ... || 0x00 (32 times) - * Method-ID = GKDF-16 (zero, "Method ID" || EAP_Method_Type || - * CSuite_Sel || inputString) - */ - - *sk_len = EAP_GPSK_SK_LEN_SHA256; - - return eap_gpsk_derive_keys_helper(EAP_GPSK_CIPHER_SHA256, - kdf_out, sizeof(kdf_out), - psk, psk_len, seed, seed_len, - msk, emsk, sk, *sk_len, - NULL, 0); -} -#endif /* EAP_GPSK_SHA256 */ - - -/** - * eap_gpsk_derive_keys - Derive EAP-GPSK keys - * @psk: Pre-shared key - * @psk_len: Length of psk in bytes - * @vendor: CSuite/Vendor - * @specifier: CSuite/Specifier - * @rand_peer: 32-byte RAND_Peer - * @rand_server: 32-byte RAND_Server - * @id_peer: ID_Peer - * @id_peer_len: Length of ID_Peer - * @id_server: ID_Server - * @id_server_len: Length of ID_Server - * @msk: Buffer for 64-byte MSK - * @emsk: Buffer for 64-byte EMSK - * @sk: Buffer for SK (at least EAP_GPSK_MAX_SK_LEN bytes) - * @sk_len: Buffer for returning length of SK - * @pk: Buffer for PK (at least EAP_GPSK_MAX_PK_LEN bytes) - * @pk_len: Buffer for returning length of PK - * Returns: 0 on success, -1 on failure - */ -int eap_gpsk_derive_keys(const u8 *psk, size_t psk_len, int vendor, - int specifier, - const u8 *rand_peer, const u8 *rand_server, - const u8 *id_peer, size_t id_peer_len, - const u8 *id_server, size_t id_server_len, - u8 *msk, u8 *emsk, u8 *sk, size_t *sk_len, - u8 *pk, size_t *pk_len) -{ - u8 *seed, *pos; - size_t seed_len; - int ret; - - wpa_printf(MSG_DEBUG, "EAP-GPSK: Deriving keys (%d:%d)", - vendor, specifier); - - if (vendor != EAP_GPSK_VENDOR_IETF) - return -1; - - wpa_hexdump_key(MSG_DEBUG, "EAP-GPSK: PSK", psk, psk_len); - - /* Seed = RAND_Peer || ID_Peer || RAND_Server || ID_Server */ - seed_len = 2 * EAP_GPSK_RAND_LEN + id_server_len + id_peer_len; - seed = os_malloc(seed_len); - if (seed == NULL) { - wpa_printf(MSG_DEBUG, "EAP-GPSK: Failed to allocate memory " - "for key derivation"); - return -1; - } - - pos = seed; - os_memcpy(pos, rand_peer, EAP_GPSK_RAND_LEN); - pos += EAP_GPSK_RAND_LEN; - os_memcpy(pos, id_peer, id_peer_len); - pos += id_peer_len; - os_memcpy(pos, rand_server, EAP_GPSK_RAND_LEN); - pos += EAP_GPSK_RAND_LEN; - os_memcpy(pos, id_server, id_server_len); - pos += id_server_len; - wpa_hexdump(MSG_DEBUG, "EAP-GPSK: Seed", seed, seed_len); - - switch (specifier) { - case EAP_GPSK_CIPHER_AES: - ret = eap_gpsk_derive_keys_aes(psk, psk_len, seed, seed_len, - msk, emsk, sk, sk_len, - pk, pk_len); - break; -#ifdef EAP_GPSK_SHA256 - case EAP_GPSK_CIPHER_SHA256: - ret = eap_gpsk_derive_keys_sha256(psk, psk_len, seed, seed_len, - msk, emsk, sk, sk_len); - break; -#endif /* EAP_GPSK_SHA256 */ - default: - wpa_printf(MSG_DEBUG, "EAP-GPSK: Unknown cipher %d:%d used in " - "key derivation", vendor, specifier); - ret = -1; - break; - } - - os_free(seed); - - return ret; -} - - -/** - * eap_gpsk_mic_len - Get the length of the MIC - * @vendor: CSuite/Vendor - * @specifier: CSuite/Specifier - * Returns: MIC length in bytes - */ -size_t eap_gpsk_mic_len(int vendor, int specifier) -{ - if (vendor != EAP_GPSK_VENDOR_IETF) - return 0; - - switch (specifier) { - case EAP_GPSK_CIPHER_AES: - return 16; -#ifdef EAP_GPSK_SHA256 - case EAP_GPSK_CIPHER_SHA256: - return 32; -#endif /* EAP_GPSK_SHA256 */ - default: - return 0; - } -} - - -static int eap_gpsk_compute_mic_aes(const u8 *sk, size_t sk_len, - const u8 *data, size_t len, u8 *mic) -{ - if (sk_len != 16) { - wpa_printf(MSG_DEBUG, "EAP-GPSK: Invalid SK length %lu for " - "AES-CMAC MIC", (unsigned long) sk_len); - return -1; - } - - return omac1_aes_128(sk, data, len, mic); -} - - -/** - * eap_gpsk_compute_mic - Compute EAP-GPSK MIC for an EAP packet - * @sk: Session key SK from eap_gpsk_derive_keys() - * @sk_len: SK length in bytes from eap_gpsk_derive_keys() - * @vendor: CSuite/Vendor - * @specifier: CSuite/Specifier - * @data: Input data to MIC - * @len: Input data length in bytes - * @mic: Buffer for the computed MIC, eap_gpsk_mic_len(cipher) bytes - * Returns: 0 on success, -1 on failure - */ -int eap_gpsk_compute_mic(const u8 *sk, size_t sk_len, int vendor, - int specifier, const u8 *data, size_t len, u8 *mic) -{ - int ret; - - if (vendor != EAP_GPSK_VENDOR_IETF) - return -1; - - switch (specifier) { - case EAP_GPSK_CIPHER_AES: - ret = eap_gpsk_compute_mic_aes(sk, sk_len, data, len, mic); - break; -#ifdef EAP_GPSK_SHA256 - case EAP_GPSK_CIPHER_SHA256: - hmac_sha256(sk, sk_len, data, len, mic); - ret = 0; - break; -#endif /* EAP_GPSK_SHA256 */ - default: - wpa_printf(MSG_DEBUG, "EAP-GPSK: Unknown cipher %d:%d used in " - "MIC computation", vendor, specifier); - ret = -1; - break; - } - - return ret; -} diff --git a/hostapd-0.8/src/eap_common/eap_gpsk_common.h b/hostapd-0.8/src/eap_common/eap_gpsk_common.h deleted file mode 100644 index a30ab97..0000000 --- a/hostapd-0.8/src/eap_common/eap_gpsk_common.h +++ /dev/null @@ -1,66 +0,0 @@ -/* - * EAP server/peer: EAP-GPSK shared routines - * Copyright (c) 2006-2007, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#ifndef EAP_GPSK_COMMON_H -#define EAP_GPSK_COMMON_H - -#define EAP_GPSK_OPCODE_GPSK_1 1 -#define EAP_GPSK_OPCODE_GPSK_2 2 -#define EAP_GPSK_OPCODE_GPSK_3 3 -#define EAP_GPSK_OPCODE_GPSK_4 4 -#define EAP_GPSK_OPCODE_FAIL 5 -#define EAP_GPSK_OPCODE_PROTECTED_FAIL 6 - -/* Failure-Code in GPSK-Fail and GPSK-Protected-Fail */ -#define EAP_GPSK_FAIL_PSK_NOT_FOUND 0x00000001 -#define EAP_GPSK_FAIL_AUTHENTICATION_FAILURE 0x00000002 -#define EAP_GPSK_FAIL_AUTHORIZATION_FAILURE 0x00000003 - -#define EAP_GPSK_RAND_LEN 32 -#define EAP_GPSK_MAX_SK_LEN 32 -#define EAP_GPSK_MAX_PK_LEN 32 -#define EAP_GPSK_MAX_MIC_LEN 32 - -#define EAP_GPSK_VENDOR_IETF 0x00000000 -#define EAP_GPSK_CIPHER_RESERVED 0x000000 -#define EAP_GPSK_CIPHER_AES 0x000001 -#define EAP_GPSK_CIPHER_SHA256 0x000002 - - -#ifdef _MSC_VER -#pragma pack(push, 1) -#endif /* _MSC_VER */ - -struct eap_gpsk_csuite { - u8 vendor[4]; - u8 specifier[2]; -} STRUCT_PACKED; - -#ifdef _MSC_VER -#pragma pack(pop) -#endif /* _MSC_VER */ - -int eap_gpsk_supported_ciphersuite(int vendor, int specifier); -int eap_gpsk_derive_keys(const u8 *psk, size_t psk_len, int vendor, - int specifier, - const u8 *rand_client, const u8 *rand_server, - const u8 *id_client, size_t id_client_len, - const u8 *id_server, size_t id_server_len, - u8 *msk, u8 *emsk, u8 *sk, size_t *sk_len, - u8 *pk, size_t *pk_len); -size_t eap_gpsk_mic_len(int vendor, int specifier); -int eap_gpsk_compute_mic(const u8 *sk, size_t sk_len, int vendor, - int specifier, const u8 *data, size_t len, u8 *mic); - -#endif /* EAP_GPSK_COMMON_H */ diff --git a/hostapd-0.8/src/eap_common/eap_ikev2_common.c b/hostapd-0.8/src/eap_common/eap_ikev2_common.c deleted file mode 100644 index e9a9c55..0000000 --- a/hostapd-0.8/src/eap_common/eap_ikev2_common.c +++ /dev/null @@ -1,132 +0,0 @@ -/* - * EAP-IKEv2 common routines - * Copyright (c) 2007, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#include "includes.h" - -#include "common.h" -#include "eap_defs.h" -#include "eap_common.h" -#include "ikev2_common.h" -#include "eap_ikev2_common.h" - - -int eap_ikev2_derive_keymat(int prf, struct ikev2_keys *keys, - const u8 *i_nonce, size_t i_nonce_len, - const u8 *r_nonce, size_t r_nonce_len, - u8 *keymat) -{ - u8 *nonces; - size_t nlen; - - /* KEYMAT = prf+(SK_d, Ni | Nr) */ - if (keys->SK_d == NULL || i_nonce == NULL || r_nonce == NULL) - return -1; - - nlen = i_nonce_len + r_nonce_len; - nonces = os_malloc(nlen); - if (nonces == NULL) - return -1; - os_memcpy(nonces, i_nonce, i_nonce_len); - os_memcpy(nonces + i_nonce_len, r_nonce, r_nonce_len); - - if (ikev2_prf_plus(prf, keys->SK_d, keys->SK_d_len, nonces, nlen, - keymat, EAP_MSK_LEN + EAP_EMSK_LEN)) { - os_free(nonces); - return -1; - } - os_free(nonces); - - wpa_hexdump_key(MSG_DEBUG, "EAP-IKEV2: KEYMAT", - keymat, EAP_MSK_LEN + EAP_EMSK_LEN); - - return 0; -} - - -struct wpabuf * eap_ikev2_build_frag_ack(u8 id, u8 code) -{ - struct wpabuf *msg; - -#ifdef CCNS_PL - msg = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_IKEV2, 1, code, id); - if (msg == NULL) { - wpa_printf(MSG_ERROR, "EAP-IKEV2: Failed to allocate memory " - "for fragment ack"); - return NULL; - } - wpabuf_put_u8(msg, 0); /* Flags */ -#else /* CCNS_PL */ - msg = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_IKEV2, 0, code, id); - if (msg == NULL) { - wpa_printf(MSG_ERROR, "EAP-IKEV2: Failed to allocate memory " - "for fragment ack"); - return NULL; - } -#endif /* CCNS_PL */ - - wpa_printf(MSG_DEBUG, "EAP-IKEV2: Send fragment ack"); - - return msg; -} - - -int eap_ikev2_validate_icv(int integ_alg, struct ikev2_keys *keys, - int initiator, const struct wpabuf *msg, - const u8 *pos, const u8 *end) -{ - const struct ikev2_integ_alg *integ; - size_t icv_len; - u8 icv[IKEV2_MAX_HASH_LEN]; - const u8 *SK_a = initiator ? keys->SK_ai : keys->SK_ar; - - integ = ikev2_get_integ(integ_alg); - if (integ == NULL) { - wpa_printf(MSG_DEBUG, "EAP-IKEV2: Unknown INTEG " - "transform / cannot validate ICV"); - return -1; - } - icv_len = integ->hash_len; - - if (end - pos < (int) icv_len) { - wpa_printf(MSG_DEBUG, "EAP-IKEV2: Not enough room in the " - "message for Integrity Checksum Data"); - return -1; - } - - if (SK_a == NULL) { - wpa_printf(MSG_DEBUG, "EAP-IKEV2: No SK_a for ICV validation"); - return -1; - } - - if (ikev2_integ_hash(integ_alg, SK_a, keys->SK_integ_len, - wpabuf_head(msg), - wpabuf_len(msg) - icv_len, icv) < 0) { - wpa_printf(MSG_INFO, "EAP-IKEV2: Could not calculate ICV"); - return -1; - } - - if (os_memcmp(icv, end - icv_len, icv_len) != 0) { - wpa_printf(MSG_INFO, "EAP-IKEV2: Invalid ICV"); - wpa_hexdump(MSG_DEBUG, "EAP-IKEV2: Calculated ICV", - icv, icv_len); - wpa_hexdump(MSG_DEBUG, "EAP-IKEV2: Received ICV", - end - icv_len, icv_len); - return -1; - } - - wpa_printf(MSG_DEBUG, "EAP-IKEV2: Valid Integrity Checksum Data in " - "the received message"); - - return icv_len; -} diff --git a/hostapd-0.8/src/eap_common/eap_ikev2_common.h b/hostapd-0.8/src/eap_common/eap_ikev2_common.h deleted file mode 100644 index a9fc2ca..0000000 --- a/hostapd-0.8/src/eap_common/eap_ikev2_common.h +++ /dev/null @@ -1,42 +0,0 @@ -/* - * EAP-IKEv2 definitions - * Copyright (c) 2007, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#ifndef EAP_IKEV2_COMMON_H -#define EAP_IKEV2_COMMON_H - -#ifdef CCNS_PL -/* incorrect bit order */ -#define IKEV2_FLAGS_LENGTH_INCLUDED 0x01 -#define IKEV2_FLAGS_MORE_FRAGMENTS 0x02 -#define IKEV2_FLAGS_ICV_INCLUDED 0x04 -#else /* CCNS_PL */ -#define IKEV2_FLAGS_LENGTH_INCLUDED 0x80 -#define IKEV2_FLAGS_MORE_FRAGMENTS 0x40 -#define IKEV2_FLAGS_ICV_INCLUDED 0x20 -#endif /* CCNS_PL */ - -#define IKEV2_FRAGMENT_SIZE 1400 - -struct ikev2_keys; - -int eap_ikev2_derive_keymat(int prf, struct ikev2_keys *keys, - const u8 *i_nonce, size_t i_nonce_len, - const u8 *r_nonce, size_t r_nonce_len, - u8 *keymat); -struct wpabuf * eap_ikev2_build_frag_ack(u8 id, u8 code); -int eap_ikev2_validate_icv(int integ_alg, struct ikev2_keys *keys, - int initiator, const struct wpabuf *msg, - const u8 *pos, const u8 *end); - -#endif /* EAP_IKEV2_COMMON_H */ diff --git a/hostapd-0.8/src/eap_common/eap_pax_common.c b/hostapd-0.8/src/eap_common/eap_pax_common.c deleted file mode 100644 index 32dc80c..0000000 --- a/hostapd-0.8/src/eap_common/eap_pax_common.c +++ /dev/null @@ -1,150 +0,0 @@ -/* - * EAP server/peer: EAP-PAX shared routines - * Copyright (c) 2005, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#include "includes.h" - -#include "common.h" -#include "crypto/sha1.h" -#include "eap_pax_common.h" - - -/** - * eap_pax_kdf - PAX Key Derivation Function - * @mac_id: MAC ID (EAP_PAX_MAC_*) / currently, only HMAC_SHA1_128 is supported - * @key: Secret key (X) - * @key_len: Length of the secret key in bytes - * @identifier: Public identifier for the key (Y) - * @entropy: Exchanged entropy to seed the KDF (Z) - * @entropy_len: Length of the entropy in bytes - * @output_len: Output len in bytes (W) - * @output: Buffer for the derived key - * Returns: 0 on success, -1 failed - * - * RFC 4746, Section 2.6: PAX-KDF-W(X, Y, Z) - */ -int eap_pax_kdf(u8 mac_id, const u8 *key, size_t key_len, - const char *identifier, - const u8 *entropy, size_t entropy_len, - size_t output_len, u8 *output) -{ - u8 mac[SHA1_MAC_LEN]; - u8 counter, *pos; - const u8 *addr[3]; - size_t len[3]; - size_t num_blocks, left; - - num_blocks = (output_len + EAP_PAX_MAC_LEN - 1) / EAP_PAX_MAC_LEN; - if (identifier == NULL || num_blocks >= 255) - return -1; - - /* TODO: add support for EAP_PAX_HMAC_SHA256_128 */ - if (mac_id != EAP_PAX_MAC_HMAC_SHA1_128) - return -1; - - addr[0] = (const u8 *) identifier; - len[0] = os_strlen(identifier); - addr[1] = entropy; - len[1] = entropy_len; - addr[2] = &counter; - len[2] = 1; - - pos = output; - left = output_len; - for (counter = 1; counter <= (u8) num_blocks; counter++) { - size_t clen = left > EAP_PAX_MAC_LEN ? EAP_PAX_MAC_LEN : left; - hmac_sha1_vector(key, key_len, 3, addr, len, mac); - os_memcpy(pos, mac, clen); - pos += clen; - left -= clen; - } - - return 0; -} - - -/** - * eap_pax_mac - EAP-PAX MAC - * @mac_id: MAC ID (EAP_PAX_MAC_*) / currently, only HMAC_SHA1_128 is supported - * @key: Secret key - * @key_len: Length of the secret key in bytes - * @data1: Optional data, first block; %NULL if not used - * @data1_len: Length of data1 in bytes - * @data2: Optional data, second block; %NULL if not used - * @data2_len: Length of data2 in bytes - * @data3: Optional data, third block; %NULL if not used - * @data3_len: Length of data3 in bytes - * @mac: Buffer for the MAC value (EAP_PAX_MAC_LEN = 16 bytes) - * Returns: 0 on success, -1 on failure - * - * Wrapper function to calculate EAP-PAX MAC. - */ -int eap_pax_mac(u8 mac_id, const u8 *key, size_t key_len, - const u8 *data1, size_t data1_len, - const u8 *data2, size_t data2_len, - const u8 *data3, size_t data3_len, - u8 *mac) -{ - u8 hash[SHA1_MAC_LEN]; - const u8 *addr[3]; - size_t len[3]; - size_t count; - - /* TODO: add support for EAP_PAX_HMAC_SHA256_128 */ - if (mac_id != EAP_PAX_MAC_HMAC_SHA1_128) - return -1; - - addr[0] = data1; - len[0] = data1_len; - addr[1] = data2; - len[1] = data2_len; - addr[2] = data3; - len[2] = data3_len; - - count = (data1 ? 1 : 0) + (data2 ? 1 : 0) + (data3 ? 1 : 0); - hmac_sha1_vector(key, key_len, count, addr, len, hash); - os_memcpy(mac, hash, EAP_PAX_MAC_LEN); - - return 0; -} - - -/** - * eap_pax_initial_key_derivation - EAP-PAX initial key derivation - * @mac_id: MAC ID (EAP_PAX_MAC_*) / currently, only HMAC_SHA1_128 is supported - * @ak: Authentication Key - * @e: Entropy - * @mk: Buffer for the derived Master Key - * @ck: Buffer for the derived Confirmation Key - * @ick: Buffer for the derived Integrity Check Key - * Returns: 0 on success, -1 on failure - */ -int eap_pax_initial_key_derivation(u8 mac_id, const u8 *ak, const u8 *e, - u8 *mk, u8 *ck, u8 *ick) -{ - wpa_printf(MSG_DEBUG, "EAP-PAX: initial key derivation"); - if (eap_pax_kdf(mac_id, ak, EAP_PAX_AK_LEN, "Master Key", - e, 2 * EAP_PAX_RAND_LEN, EAP_PAX_MK_LEN, mk) || - eap_pax_kdf(mac_id, mk, EAP_PAX_MK_LEN, "Confirmation Key", - e, 2 * EAP_PAX_RAND_LEN, EAP_PAX_CK_LEN, ck) || - eap_pax_kdf(mac_id, mk, EAP_PAX_MK_LEN, "Integrity Check Key", - e, 2 * EAP_PAX_RAND_LEN, EAP_PAX_ICK_LEN, ick)) - return -1; - - wpa_hexdump_key(MSG_MSGDUMP, "EAP-PAX: AK", ak, EAP_PAX_AK_LEN); - wpa_hexdump_key(MSG_MSGDUMP, "EAP-PAX: MK", mk, EAP_PAX_MK_LEN); - wpa_hexdump_key(MSG_MSGDUMP, "EAP-PAX: CK", ck, EAP_PAX_CK_LEN); - wpa_hexdump_key(MSG_MSGDUMP, "EAP-PAX: ICK", ick, EAP_PAX_ICK_LEN); - - return 0; -} diff --git a/hostapd-0.8/src/eap_common/eap_pax_common.h b/hostapd-0.8/src/eap_common/eap_pax_common.h deleted file mode 100644 index dcc171e..0000000 --- a/hostapd-0.8/src/eap_common/eap_pax_common.h +++ /dev/null @@ -1,97 +0,0 @@ -/* - * EAP server/peer: EAP-PAX shared routines - * Copyright (c) 2005-2007, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#ifndef EAP_PAX_COMMON_H -#define EAP_PAX_COMMON_H - -#ifdef _MSC_VER -#pragma pack(push, 1) -#endif /* _MSC_VER */ - -struct eap_pax_hdr { - u8 op_code; - u8 flags; - u8 mac_id; - u8 dh_group_id; - u8 public_key_id; - /* Followed by variable length payload and ICV */ -} STRUCT_PACKED; - -#ifdef _MSC_VER -#pragma pack(pop) -#endif /* _MSC_VER */ - - -/* op_code: */ -enum { - EAP_PAX_OP_STD_1 = 0x01, - EAP_PAX_OP_STD_2 = 0x02, - EAP_PAX_OP_STD_3 = 0x03, - EAP_PAX_OP_SEC_1 = 0x11, - EAP_PAX_OP_SEC_2 = 0x12, - EAP_PAX_OP_SEC_3 = 0x13, - EAP_PAX_OP_SEC_4 = 0x14, - EAP_PAX_OP_SEC_5 = 0x15, - EAP_PAX_OP_ACK = 0x21 -}; - -/* flags: */ -#define EAP_PAX_FLAGS_MF 0x01 -#define EAP_PAX_FLAGS_CE 0x02 -#define EAP_PAX_FLAGS_AI 0x04 - -/* mac_id: */ -#define EAP_PAX_MAC_HMAC_SHA1_128 0x01 -#define EAP_PAX_HMAC_SHA256_128 0x02 - -/* dh_group_id: */ -#define EAP_PAX_DH_GROUP_NONE 0x00 -#define EAP_PAX_DH_GROUP_2048_MODP 0x01 -#define EAP_PAX_DH_GROUP_3072_MODP 0x02 -#define EAP_PAX_DH_GROUP_NIST_ECC_P_256 0x03 - -/* public_key_id: */ -#define EAP_PAX_PUBLIC_KEY_NONE 0x00 -#define EAP_PAX_PUBLIC_KEY_RSAES_OAEP 0x01 -#define EAP_PAX_PUBLIC_KEY_RSA_PKCS1_V1_5 0x02 -#define EAP_PAX_PUBLIC_KEY_EL_GAMAL_NIST_ECC 0x03 - -/* ADE type: */ -#define EAP_PAX_ADE_VENDOR_SPECIFIC 0x01 -#define EAP_PAX_ADE_CLIENT_CHANNEL_BINDING 0x02 -#define EAP_PAX_ADE_SERVER_CHANNEL_BINDING 0x03 - - -#define EAP_PAX_RAND_LEN 32 -#define EAP_PAX_MAC_LEN 16 -#define EAP_PAX_ICV_LEN 16 -#define EAP_PAX_AK_LEN 16 -#define EAP_PAX_MK_LEN 16 -#define EAP_PAX_CK_LEN 16 -#define EAP_PAX_ICK_LEN 16 - - -int eap_pax_kdf(u8 mac_id, const u8 *key, size_t key_len, - const char *identifier, - const u8 *entropy, size_t entropy_len, - size_t output_len, u8 *output); -int eap_pax_mac(u8 mac_id, const u8 *key, size_t key_len, - const u8 *data1, size_t data1_len, - const u8 *data2, size_t data2_len, - const u8 *data3, size_t data3_len, - u8 *mac); -int eap_pax_initial_key_derivation(u8 mac_id, const u8 *ak, const u8 *e, - u8 *mk, u8 *ck, u8 *ick); - -#endif /* EAP_PAX_COMMON_H */ diff --git a/hostapd-0.8/src/eap_common/eap_peap_common.c b/hostapd-0.8/src/eap_common/eap_peap_common.c deleted file mode 100644 index 3a64b8e..0000000 --- a/hostapd-0.8/src/eap_common/eap_peap_common.c +++ /dev/null @@ -1,88 +0,0 @@ -/* - * EAP-PEAP common routines - * Copyright (c) 2008, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#include "includes.h" - -#include "common.h" -#include "crypto/sha1.h" -#include "eap_peap_common.h" - -void peap_prfplus(int version, const u8 *key, size_t key_len, - const char *label, const u8 *seed, size_t seed_len, - u8 *buf, size_t buf_len) -{ - unsigned char counter = 0; - size_t pos, plen; - u8 hash[SHA1_MAC_LEN]; - size_t label_len = os_strlen(label); - u8 extra[2]; - const unsigned char *addr[5]; - size_t len[5]; - - addr[0] = hash; - len[0] = 0; - addr[1] = (unsigned char *) label; - len[1] = label_len; - addr[2] = seed; - len[2] = seed_len; - - if (version == 0) { - /* - * PRF+(K, S, LEN) = T1 | T2 | ... | Tn - * T1 = HMAC-SHA1(K, S | 0x01 | 0x00 | 0x00) - * T2 = HMAC-SHA1(K, T1 | S | 0x02 | 0x00 | 0x00) - * ... - * Tn = HMAC-SHA1(K, Tn-1 | S | n | 0x00 | 0x00) - */ - - extra[0] = 0; - extra[1] = 0; - - addr[3] = &counter; - len[3] = 1; - addr[4] = extra; - len[4] = 2; - } else { - /* - * PRF (K,S,LEN) = T1 | T2 | T3 | T4 | ... where: - * T1 = HMAC-SHA1(K, S | LEN | 0x01) - * T2 = HMAC-SHA1 (K, T1 | S | LEN | 0x02) - * T3 = HMAC-SHA1 (K, T2 | S | LEN | 0x03) - * T4 = HMAC-SHA1 (K, T3 | S | LEN | 0x04) - * ... - */ - - extra[0] = buf_len & 0xff; - - addr[3] = extra; - len[3] = 1; - addr[4] = &counter; - len[4] = 1; - } - - pos = 0; - while (pos < buf_len) { - counter++; - plen = buf_len - pos; - hmac_sha1_vector(key, key_len, 5, addr, len, hash); - if (plen >= SHA1_MAC_LEN) { - os_memcpy(&buf[pos], hash, SHA1_MAC_LEN); - pos += SHA1_MAC_LEN; - } else { - os_memcpy(&buf[pos], hash, plen); - break; - } - len[0] = SHA1_MAC_LEN; - } -} diff --git a/hostapd-0.8/src/eap_common/eap_peap_common.h b/hostapd-0.8/src/eap_common/eap_peap_common.h deleted file mode 100644 index f59afb0..0000000 --- a/hostapd-0.8/src/eap_common/eap_peap_common.h +++ /dev/null @@ -1,22 +0,0 @@ -/* - * EAP-PEAP common routines - * Copyright (c) 2008, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#ifndef EAP_PEAP_COMMON_H -#define EAP_PEAP_COMMON_H - -void peap_prfplus(int version, const u8 *key, size_t key_len, - const char *label, const u8 *seed, size_t seed_len, - u8 *buf, size_t buf_len); - -#endif /* EAP_PEAP_COMMON_H */ diff --git a/hostapd-0.8/src/eap_common/eap_psk_common.c b/hostapd-0.8/src/eap_common/eap_psk_common.c deleted file mode 100644 index 7417d5c..0000000 --- a/hostapd-0.8/src/eap_common/eap_psk_common.c +++ /dev/null @@ -1,74 +0,0 @@ -/* - * EAP server/peer: EAP-PSK shared routines - * Copyright (c) 2004-2006, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#include "includes.h" - -#include "common.h" -#include "crypto/aes_wrap.h" -#include "eap_defs.h" -#include "eap_psk_common.h" - -#define aes_block_size 16 - - -int eap_psk_key_setup(const u8 *psk, u8 *ak, u8 *kdk) -{ - os_memset(ak, 0, aes_block_size); - if (aes_128_encrypt_block(psk, ak, ak)) - return -1; - os_memcpy(kdk, ak, aes_block_size); - ak[aes_block_size - 1] ^= 0x01; - kdk[aes_block_size - 1] ^= 0x02; - if (aes_128_encrypt_block(psk, ak, ak) || - aes_128_encrypt_block(psk, kdk, kdk)) - return -1; - return 0; -} - - -int eap_psk_derive_keys(const u8 *kdk, const u8 *rand_p, u8 *tek, u8 *msk, - u8 *emsk) -{ - u8 hash[aes_block_size]; - u8 counter = 1; - int i; - - if (aes_128_encrypt_block(kdk, rand_p, hash)) - return -1; - - hash[aes_block_size - 1] ^= counter; - if (aes_128_encrypt_block(kdk, hash, tek)) - return -1; - hash[aes_block_size - 1] ^= counter; - counter++; - - for (i = 0; i < EAP_MSK_LEN / aes_block_size; i++) { - hash[aes_block_size - 1] ^= counter; - if (aes_128_encrypt_block(kdk, hash, &msk[i * aes_block_size])) - return -1; - hash[aes_block_size - 1] ^= counter; - counter++; - } - - for (i = 0; i < EAP_EMSK_LEN / aes_block_size; i++) { - hash[aes_block_size - 1] ^= counter; - if (aes_128_encrypt_block(kdk, hash, - &emsk[i * aes_block_size])) - return -1; - hash[aes_block_size - 1] ^= counter; - counter++; - } - - return 0; -} diff --git a/hostapd-0.8/src/eap_common/eap_psk_common.h b/hostapd-0.8/src/eap_common/eap_psk_common.h deleted file mode 100644 index 8adc054..0000000 --- a/hostapd-0.8/src/eap_common/eap_psk_common.h +++ /dev/null @@ -1,78 +0,0 @@ -/* - * EAP server/peer: EAP-PSK shared routines - * Copyright (c) 2004-2007, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#ifndef EAP_PSK_COMMON_H -#define EAP_PSK_COMMON_H - - -#define EAP_PSK_RAND_LEN 16 -#define EAP_PSK_MAC_LEN 16 -#define EAP_PSK_TEK_LEN 16 -#define EAP_PSK_PSK_LEN 16 -#define EAP_PSK_AK_LEN 16 -#define EAP_PSK_KDK_LEN 16 - -#define EAP_PSK_R_FLAG_CONT 1 -#define EAP_PSK_R_FLAG_DONE_SUCCESS 2 -#define EAP_PSK_R_FLAG_DONE_FAILURE 3 -#define EAP_PSK_E_FLAG 0x20 - -#define EAP_PSK_FLAGS_GET_T(flags) (((flags) & 0xc0) >> 6) -#define EAP_PSK_FLAGS_SET_T(t) ((u8) (t) << 6) - -#ifdef _MSC_VER -#pragma pack(push, 1) -#endif /* _MSC_VER */ - -/* EAP-PSK First Message (AS -> Supplicant) */ -struct eap_psk_hdr_1 { - u8 flags; - u8 rand_s[EAP_PSK_RAND_LEN]; - /* Followed by variable length ID_S */ -} STRUCT_PACKED; - -/* EAP-PSK Second Message (Supplicant -> AS) */ -struct eap_psk_hdr_2 { - u8 flags; - u8 rand_s[EAP_PSK_RAND_LEN]; - u8 rand_p[EAP_PSK_RAND_LEN]; - u8 mac_p[EAP_PSK_MAC_LEN]; - /* Followed by variable length ID_P */ -} STRUCT_PACKED; - -/* EAP-PSK Third Message (AS -> Supplicant) */ -struct eap_psk_hdr_3 { - u8 flags; - u8 rand_s[EAP_PSK_RAND_LEN]; - u8 mac_s[EAP_PSK_MAC_LEN]; - /* Followed by variable length PCHANNEL */ -} STRUCT_PACKED; - -/* EAP-PSK Fourth Message (Supplicant -> AS) */ -struct eap_psk_hdr_4 { - u8 flags; - u8 rand_s[EAP_PSK_RAND_LEN]; - /* Followed by variable length PCHANNEL */ -} STRUCT_PACKED; - -#ifdef _MSC_VER -#pragma pack(pop) -#endif /* _MSC_VER */ - - -int __must_check eap_psk_key_setup(const u8 *psk, u8 *ak, u8 *kdk); -int __must_check eap_psk_derive_keys(const u8 *kdk, const u8 *rand_p, u8 *tek, - u8 *msk, u8 *emsk); - -#endif /* EAP_PSK_COMMON_H */ diff --git a/hostapd-0.8/src/eap_common/eap_pwd_common.c b/hostapd-0.8/src/eap_common/eap_pwd_common.c deleted file mode 100644 index c24b146..0000000 --- a/hostapd-0.8/src/eap_common/eap_pwd_common.c +++ /dev/null @@ -1,312 +0,0 @@ -/* - * EAP server/peer: EAP-pwd shared routines - * Copyright (c) 2010, Dan Harkins - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the BSD license. - * - * Alternatively, this software may be distributed under the terms of the - * GNU General Public License version 2 as published by the Free Software - * Foundation. - * - * See README and COPYING for more details. - */ - -#include "includes.h" -#include "common.h" -#include "eap_defs.h" -#include "eap_pwd_common.h" - -/* The random function H(x) = HMAC-SHA256(0^32, x) */ -void H_Init(HMAC_CTX *ctx) -{ - u8 allzero[SHA256_DIGEST_LENGTH]; - - os_memset(allzero, 0, SHA256_DIGEST_LENGTH); - HMAC_Init(ctx, allzero, SHA256_DIGEST_LENGTH, EVP_sha256()); -} - - -void H_Update(HMAC_CTX *ctx, const u8 *data, int len) -{ - HMAC_Update(ctx, data, len); -} - - -void H_Final(HMAC_CTX *ctx, u8 *digest) -{ - unsigned int mdlen = SHA256_DIGEST_LENGTH; - - HMAC_Final(ctx, digest, &mdlen); - HMAC_CTX_cleanup(ctx); -} - - -/* a counter-based KDF based on NIST SP800-108 */ -void eap_pwd_kdf(u8 *key, int keylen, u8 *label, int labellen, - u8 *result, int resultbitlen) -{ - HMAC_CTX hctx; - unsigned char digest[SHA256_DIGEST_LENGTH]; - u16 i, ctr, L; - int resultbytelen, len = 0; - unsigned int mdlen = SHA256_DIGEST_LENGTH; - unsigned char mask = 0xff; - - resultbytelen = (resultbitlen + 7)/8; - ctr = 0; - L = htons(resultbitlen); - while (len < resultbytelen) { - ctr++; i = htons(ctr); - HMAC_Init(&hctx, key, keylen, EVP_sha256()); - if (ctr > 1) - HMAC_Update(&hctx, digest, mdlen); - HMAC_Update(&hctx, (u8 *) &i, sizeof(u16)); - HMAC_Update(&hctx, label, labellen); - HMAC_Update(&hctx, (u8 *) &L, sizeof(u16)); - HMAC_Final(&hctx, digest, &mdlen); - if ((len + (int) mdlen) > resultbytelen) - os_memcpy(result + len, digest, resultbytelen - len); - else - os_memcpy(result + len, digest, mdlen); - len += mdlen; - HMAC_CTX_cleanup(&hctx); - } - - /* since we're expanding to a bit length, mask off the excess */ - if (resultbitlen % 8) { - mask >>= ((resultbytelen * 8) - resultbitlen); - result[0] &= mask; - } -} - - -/* - * compute a "random" secret point on an elliptic curve based - * on the password and identities. - */ -int compute_password_element(EAP_PWD_group *grp, u16 num, - u8 *password, int password_len, - u8 *id_server, int id_server_len, - u8 *id_peer, int id_peer_len, u8 *token) -{ - BIGNUM *x_candidate = NULL, *rnd = NULL, *cofactor = NULL; - HMAC_CTX ctx; - unsigned char pwe_digest[SHA256_DIGEST_LENGTH], *prfbuf = NULL, ctr; - int nid, is_odd, primebitlen, primebytelen, ret = 0; - - switch (num) { /* from IANA registry for IKE D-H groups */ - case 19: - nid = NID_X9_62_prime256v1; - break; - case 20: - nid = NID_secp384r1; - break; - case 21: - nid = NID_secp521r1; - break; - case 25: - nid = NID_X9_62_prime192v1; - break; - case 26: - nid = NID_secp224r1; - break; - default: - wpa_printf(MSG_INFO, "EAP-pwd: unsupported group %d", num); - return -1; - } - - grp->pwe = NULL; - grp->order = NULL; - grp->prime = NULL; - - if ((grp->group = EC_GROUP_new_by_curve_name(nid)) == NULL) { - wpa_printf(MSG_INFO, "EAP-pwd: unable to create EC_GROUP"); - goto fail; - } - - if (((rnd = BN_new()) == NULL) || - ((cofactor = BN_new()) == NULL) || - ((grp->pwe = EC_POINT_new(grp->group)) == NULL) || - ((grp->order = BN_new()) == NULL) || - ((grp->prime = BN_new()) == NULL) || - ((x_candidate = BN_new()) == NULL)) { - wpa_printf(MSG_INFO, "EAP-pwd: unable to create bignums"); - goto fail; - } - - if (!EC_GROUP_get_curve_GFp(grp->group, grp->prime, NULL, NULL, NULL)) - { - wpa_printf(MSG_INFO, "EAP-pwd: unable to get prime for GFp " - "curve"); - goto fail; - } - if (!EC_GROUP_get_order(grp->group, grp->order, NULL)) { - wpa_printf(MSG_INFO, "EAP-pwd: unable to get order for curve"); - goto fail; - } - if (!EC_GROUP_get_cofactor(grp->group, cofactor, NULL)) { - wpa_printf(MSG_INFO, "EAP-pwd: unable to get cofactor for " - "curve"); - goto fail; - } - primebitlen = BN_num_bits(grp->prime); - primebytelen = BN_num_bytes(grp->prime); - if ((prfbuf = os_malloc(primebytelen)) == NULL) { - wpa_printf(MSG_INFO, "EAP-pwd: unable to malloc space for prf " - "buffer"); - goto fail; - } - os_memset(prfbuf, 0, primebytelen); - ctr = 0; - while (1) { - if (ctr > 10) { - wpa_printf(MSG_INFO, "EAP-pwd: unable to find random " - "point on curve for group %d, something's " - "fishy", num); - goto fail; - } - ctr++; - - /* - * compute counter-mode password value and stretch to prime - * pwd-seed = H(token | peer-id | server-id | password | - * counter) - */ - H_Init(&ctx); - H_Update(&ctx, token, sizeof(u32)); - H_Update(&ctx, id_peer, id_peer_len); - H_Update(&ctx, id_server, id_server_len); - H_Update(&ctx, password, password_len); - H_Update(&ctx, &ctr, sizeof(ctr)); - H_Final(&ctx, pwe_digest); - - BN_bin2bn(pwe_digest, SHA256_DIGEST_LENGTH, rnd); - - eap_pwd_kdf(pwe_digest, SHA256_DIGEST_LENGTH, - (unsigned char *) "EAP-pwd Hunting And Pecking", - os_strlen("EAP-pwd Hunting And Pecking"), - prfbuf, primebitlen); - - BN_bin2bn(prfbuf, primebytelen, x_candidate); - if (BN_ucmp(x_candidate, grp->prime) >= 0) - continue; - - wpa_hexdump(MSG_DEBUG, "EAP-pwd: x_candidate", - prfbuf, primebytelen); - - /* - * need to unambiguously identify the solution, if there is - * one... - */ - if (BN_is_odd(rnd)) - is_odd = 1; - else - is_odd = 0; - - /* - * solve the quadratic equation, if it's not solvable then we - * don't have a point - */ - if (!EC_POINT_set_compressed_coordinates_GFp(grp->group, - grp->pwe, - x_candidate, - is_odd, NULL)) - continue; - /* - * If there's a solution to the equation then the point must be - * on the curve so why check again explicitly? OpenSSL code - * says this is required by X9.62. We're not X9.62 but it can't - * hurt just to be sure. - */ - if (!EC_POINT_is_on_curve(grp->group, grp->pwe, NULL)) { - wpa_printf(MSG_INFO, "EAP-pwd: point is not on curve"); - continue; - } - - if (BN_cmp(cofactor, BN_value_one())) { - /* make sure the point is not in a small sub-group */ - if (!EC_POINT_mul(grp->group, grp->pwe, NULL, grp->pwe, - cofactor, NULL)) { - wpa_printf(MSG_INFO, "EAP-pwd: cannot " - "multiply generator by order"); - continue; - } - if (EC_POINT_is_at_infinity(grp->group, grp->pwe)) { - wpa_printf(MSG_INFO, "EAP-pwd: point is at " - "infinity"); - continue; - } - } - /* if we got here then we have a new generator. */ - break; - } - wpa_printf(MSG_DEBUG, "EAP-pwd: found a PWE in %d tries", ctr); - grp->group_num = num; - if (0) { - fail: - EC_GROUP_free(grp->group); - EC_POINT_free(grp->pwe); - BN_free(grp->order); - BN_free(grp->prime); - os_free(grp); - grp = NULL; - ret = 1; - } - /* cleanliness and order.... */ - BN_free(cofactor); - BN_free(x_candidate); - BN_free(rnd); - os_free(prfbuf); - - return ret; -} - - -int compute_keys(EAP_PWD_group *grp, BN_CTX *bnctx, BIGNUM *k, - BIGNUM *peer_scalar, BIGNUM *server_scalar, - u8 *commit_peer, u8 *commit_server, - u32 *ciphersuite, u8 *msk, u8 *emsk) -{ - HMAC_CTX ctx; - u8 mk[SHA256_DIGEST_LENGTH], *cruft; - u8 session_id[SHA256_DIGEST_LENGTH + 1]; - u8 msk_emsk[EAP_MSK_LEN + EAP_EMSK_LEN]; - - if ((cruft = os_malloc(BN_num_bytes(grp->prime))) == NULL) - return -1; - - /* - * first compute the session-id = TypeCode | H(ciphersuite | scal_p | - * scal_s) - */ - session_id[0] = EAP_TYPE_PWD; - H_Init(&ctx); - H_Update(&ctx, (u8 *)ciphersuite, sizeof(u32)); - BN_bn2bin(peer_scalar, cruft); - H_Update(&ctx, cruft, BN_num_bytes(grp->order)); - BN_bn2bin(server_scalar, cruft); - H_Update(&ctx, cruft, BN_num_bytes(grp->order)); - H_Final(&ctx, &session_id[1]); - - /* then compute MK = H(k | commit-peer | commit-server) */ - H_Init(&ctx); - os_memset(cruft, 0, BN_num_bytes(grp->prime)); - BN_bn2bin(k, cruft); - H_Update(&ctx, cruft, BN_num_bytes(grp->prime)); - H_Update(&ctx, commit_peer, SHA256_DIGEST_LENGTH); - H_Update(&ctx, commit_server, SHA256_DIGEST_LENGTH); - H_Final(&ctx, mk); - - /* stretch the mk with the session-id to get MSK | EMSK */ - eap_pwd_kdf(mk, SHA256_DIGEST_LENGTH, - session_id, SHA256_DIGEST_LENGTH+1, - msk_emsk, (EAP_MSK_LEN + EAP_EMSK_LEN) * 8); - - os_memcpy(msk, msk_emsk, EAP_MSK_LEN); - os_memcpy(emsk, msk_emsk + EAP_MSK_LEN, EAP_EMSK_LEN); - - os_free(cruft); - - return 1; -} diff --git a/hostapd-0.8/src/eap_common/eap_pwd_common.h b/hostapd-0.8/src/eap_common/eap_pwd_common.h deleted file mode 100644 index 971386d..0000000 --- a/hostapd-0.8/src/eap_common/eap_pwd_common.h +++ /dev/null @@ -1,79 +0,0 @@ -/* - * EAP server/peer: EAP-pwd shared definitions - * Copyright (c) 2009, Dan Harkins - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the BSD license. - * - * Alternatively, this software may be distributed under the terms of the - * GNU General Public License version 2 as published by the Free Software - * Foundation. - * - * See README and COPYING for more details. - */ - -#ifndef EAP_PWD_COMMON_H -#define EAP_PWD_COMMON_H - -#include -#include -#include -#include -#include - -/* - * definition of a finite cyclic group - * TODO: support one based on a prime field - */ -typedef struct group_definition_ { - u16 group_num; - EC_GROUP *group; - EC_POINT *pwe; - BIGNUM *order; - BIGNUM *prime; -} EAP_PWD_group; - -/* - * EAP-pwd header, included on all payloads - */ -struct eap_pwd_hdr { - u8 l_bit:1; - u8 m_bit:1; - u8 exch:6; - u8 total_length[0]; /* included when l_bit is set */ -} STRUCT_PACKED; - -#define EAP_PWD_OPCODE_ID_EXCH 1 -#define EAP_PWD_OPCODE_COMMIT_EXCH 2 -#define EAP_PWD_OPCODE_CONFIRM_EXCH 3 -#define EAP_PWD_GET_LENGTH_BIT(x) ((x)->lm_exch & 0x80) -#define EAP_PWD_SET_LENGTH_BIT(x) ((x)->lm_exch |= 0x80) -#define EAP_PWD_GET_MORE_BIT(x) ((x)->lm_exch & 0x40) -#define EAP_PWD_SET_MORE_BIT(x) ((x)->lm_exch |= 0x40) -#define EAP_PWD_GET_EXCHANGE(x) ((x)->lm_exch & 0x3f) -#define EAP_PWD_SET_EXCHANGE(x,y) ((x)->lm_exch |= (y)) - -/* EAP-pwd-ID payload */ -struct eap_pwd_id { - be16 group_num; - u8 random_function; -#define EAP_PWD_DEFAULT_RAND_FUNC 1 - u8 prf; -#define EAP_PWD_DEFAULT_PRF 1 - u8 token[4]; - u8 prep; -#define EAP_PWD_PREP_NONE 0 -#define EAP_PWD_PREP_MS 1 - u8 identity[0]; /* length inferred from payload */ -} STRUCT_PACKED; - -/* common routines */ -int compute_password_element(EAP_PWD_group *, u16, u8 *, int, u8 *, int, u8 *, - int, u8 *); -int compute_keys(EAP_PWD_group *, BN_CTX *, BIGNUM *, BIGNUM *, BIGNUM *, - u8 *, u8 *, u32 *, u8 *, u8 *); -void H_Init(HMAC_CTX *); -void H_Update(HMAC_CTX *, const u8 *, int); -void H_Final(HMAC_CTX *, u8 *); - -#endif /* EAP_PWD_COMMON_H */ diff --git a/hostapd-0.8/src/eap_common/eap_sake_common.c b/hostapd-0.8/src/eap_common/eap_sake_common.c deleted file mode 100644 index 9002b0c..0000000 --- a/hostapd-0.8/src/eap_common/eap_sake_common.c +++ /dev/null @@ -1,393 +0,0 @@ -/* - * EAP server/peer: EAP-SAKE shared routines - * Copyright (c) 2006-2007, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#include "includes.h" - -#include "common.h" -#include "wpabuf.h" -#include "crypto/sha1.h" -#include "eap_defs.h" -#include "eap_sake_common.h" - - -static int eap_sake_parse_add_attr(struct eap_sake_parse_attr *attr, - const u8 *pos) -{ - size_t i; - - switch (pos[0]) { - case EAP_SAKE_AT_RAND_S: - wpa_printf(MSG_DEBUG, "EAP-SAKE: Parse: AT_RAND_S"); - if (pos[1] != 2 + EAP_SAKE_RAND_LEN) { - wpa_printf(MSG_DEBUG, "EAP-SAKE: AT_RAND_S with " - "invalid length %d", pos[1]); - return -1; - } - attr->rand_s = pos + 2; - break; - case EAP_SAKE_AT_RAND_P: - wpa_printf(MSG_DEBUG, "EAP-SAKE: Parse: AT_RAND_P"); - if (pos[1] != 2 + EAP_SAKE_RAND_LEN) { - wpa_printf(MSG_DEBUG, "EAP-SAKE: AT_RAND_P with " - "invalid length %d", pos[1]); - return -1; - } - attr->rand_p = pos + 2; - break; - case EAP_SAKE_AT_MIC_S: - wpa_printf(MSG_DEBUG, "EAP-SAKE: Parse: AT_MIC_S"); - if (pos[1] != 2 + EAP_SAKE_MIC_LEN) { - wpa_printf(MSG_DEBUG, "EAP-SAKE: AT_MIC_S with " - "invalid length %d", pos[1]); - return -1; - } - attr->mic_s = pos + 2; - break; - case EAP_SAKE_AT_MIC_P: - wpa_printf(MSG_DEBUG, "EAP-SAKE: Parse: AT_MIC_P"); - if (pos[1] != 2 + EAP_SAKE_MIC_LEN) { - wpa_printf(MSG_DEBUG, "EAP-SAKE: AT_MIC_P with " - "invalid length %d", pos[1]); - return -1; - } - attr->mic_p = pos + 2; - break; - case EAP_SAKE_AT_SERVERID: - wpa_printf(MSG_DEBUG, "EAP-SAKE: Parse: AT_SERVERID"); - attr->serverid = pos + 2; - attr->serverid_len = pos[1] - 2; - break; - case EAP_SAKE_AT_PEERID: - wpa_printf(MSG_DEBUG, "EAP-SAKE: Parse: AT_PEERID"); - attr->peerid = pos + 2; - attr->peerid_len = pos[1] - 2; - break; - case EAP_SAKE_AT_SPI_S: - wpa_printf(MSG_DEBUG, "EAP-SAKE: Parse: AT_SPI_S"); - attr->spi_s = pos + 2; - attr->spi_s_len = pos[1] - 2; - break; - case EAP_SAKE_AT_SPI_P: - wpa_printf(MSG_DEBUG, "EAP-SAKE: Parse: AT_SPI_P"); - attr->spi_p = pos + 2; - attr->spi_p_len = pos[1] - 2; - break; - case EAP_SAKE_AT_ANY_ID_REQ: - wpa_printf(MSG_DEBUG, "EAP-SAKE: Parse: AT_ANY_ID_REQ"); - if (pos[1] != 4) { - wpa_printf(MSG_DEBUG, "EAP-SAKE: Invalid AT_ANY_ID_REQ" - " length %d", pos[1]); - return -1; - } - attr->any_id_req = pos + 2; - break; - case EAP_SAKE_AT_PERM_ID_REQ: - wpa_printf(MSG_DEBUG, "EAP-SAKE: Parse: AT_PERM_ID_REQ"); - if (pos[1] != 4) { - wpa_printf(MSG_DEBUG, "EAP-SAKE: Invalid " - "AT_PERM_ID_REQ length %d", pos[1]); - return -1; - } - attr->perm_id_req = pos + 2; - break; - case EAP_SAKE_AT_ENCR_DATA: - wpa_printf(MSG_DEBUG, "EAP-SAKE: Parse: AT_ENCR_DATA"); - attr->encr_data = pos + 2; - attr->encr_data_len = pos[1] - 2; - break; - case EAP_SAKE_AT_IV: - wpa_printf(MSG_DEBUG, "EAP-SAKE: Parse: AT_IV"); - attr->iv = pos + 2; - attr->iv_len = pos[1] - 2; - break; - case EAP_SAKE_AT_PADDING: - wpa_printf(MSG_DEBUG, "EAP-SAKE: Parse: AT_PADDING"); - for (i = 2; i < pos[1]; i++) { - if (pos[i]) { - wpa_printf(MSG_DEBUG, "EAP-SAKE: AT_PADDING " - "with non-zero pad byte"); - return -1; - } - } - break; - case EAP_SAKE_AT_NEXT_TMPID: - wpa_printf(MSG_DEBUG, "EAP-SAKE: Parse: AT_NEXT_TMPID"); - attr->next_tmpid = pos + 2; - attr->next_tmpid_len = pos[1] - 2; - break; - case EAP_SAKE_AT_MSK_LIFE: - wpa_printf(MSG_DEBUG, "EAP-SAKE: Parse: AT_IV"); - if (pos[1] != 6) { - wpa_printf(MSG_DEBUG, "EAP-SAKE: Invalid " - "AT_MSK_LIFE length %d", pos[1]); - return -1; - } - attr->msk_life = pos + 2; - break; - default: - if (pos[0] < 128) { - wpa_printf(MSG_DEBUG, "EAP-SAKE: Unknown non-skippable" - " attribute %d", pos[0]); - return -1; - } - wpa_printf(MSG_DEBUG, "EAP-SAKE: Ignoring unknown skippable " - "attribute %d", pos[0]); - break; - } - - if (attr->iv && !attr->encr_data) { - wpa_printf(MSG_DEBUG, "EAP-SAKE: AT_IV included without " - "AT_ENCR_DATA"); - return -1; - } - - return 0; -} - - -/** - * eap_sake_parse_attributes - Parse EAP-SAKE attributes - * @buf: Packet payload (starting with the first attribute) - * @len: Payload length - * @attr: Structure to be filled with found attributes - * Returns: 0 on success or -1 on failure - */ -int eap_sake_parse_attributes(const u8 *buf, size_t len, - struct eap_sake_parse_attr *attr) -{ - const u8 *pos = buf, *end = buf + len; - - os_memset(attr, 0, sizeof(*attr)); - while (pos < end) { - if (end - pos < 2) { - wpa_printf(MSG_DEBUG, "EAP-SAKE: Too short attribute"); - return -1; - } - - if (pos[1] < 2) { - wpa_printf(MSG_DEBUG, "EAP-SAKE: Invalid attribute " - "length (%d)", pos[1]); - return -1; - } - - if (pos + pos[1] > end) { - wpa_printf(MSG_DEBUG, "EAP-SAKE: Attribute underflow"); - return -1; - } - - if (eap_sake_parse_add_attr(attr, pos)) - return -1; - - pos += pos[1]; - } - - return 0; -} - - -/** - * eap_sake_kdf - EAP-SAKE Key Derivation Function (KDF) - * @key: Key for KDF - * @key_len: Length of the key in bytes - * @label: A unique label for each purpose of the KDF - * @data: Extra data (start) to bind into the key - * @data_len: Length of the data - * @data2: Extra data (end) to bind into the key - * @data2_len: Length of the data2 - * @buf: Buffer for the generated pseudo-random key - * @buf_len: Number of bytes of key to generate - * - * This function is used to derive new, cryptographically separate keys from a - * given key (e.g., SMS). This is identical to the PRF used in IEEE 802.11i. - */ -static void eap_sake_kdf(const u8 *key, size_t key_len, const char *label, - const u8 *data, size_t data_len, - const u8 *data2, size_t data2_len, - u8 *buf, size_t buf_len) -{ - u8 counter = 0; - size_t pos, plen; - u8 hash[SHA1_MAC_LEN]; - size_t label_len = os_strlen(label) + 1; - const unsigned char *addr[4]; - size_t len[4]; - - addr[0] = (u8 *) label; /* Label | Y */ - len[0] = label_len; - addr[1] = data; /* Msg[start] */ - len[1] = data_len; - addr[2] = data2; /* Msg[end] */ - len[2] = data2_len; - addr[3] = &counter; /* Length */ - len[3] = 1; - - pos = 0; - while (pos < buf_len) { - plen = buf_len - pos; - if (plen >= SHA1_MAC_LEN) { - hmac_sha1_vector(key, key_len, 4, addr, len, - &buf[pos]); - pos += SHA1_MAC_LEN; - } else { - hmac_sha1_vector(key, key_len, 4, addr, len, - hash); - os_memcpy(&buf[pos], hash, plen); - break; - } - counter++; - } -} - - -/** - * eap_sake_derive_keys - Derive EAP-SAKE keys - * @root_secret_a: 16-byte Root-Secret-A - * @root_secret_b: 16-byte Root-Secret-B - * @rand_s: 16-byte RAND_S - * @rand_p: 16-byte RAND_P - * @tek: Buffer for Temporary EAK Keys (TEK-Auth[16] | TEK-Cipher[16]) - * @msk: Buffer for 64-byte MSK - * @emsk: Buffer for 64-byte EMSK - * - * This function derives EAP-SAKE keys as defined in RFC 4763, section 3.2.6. - */ -void eap_sake_derive_keys(const u8 *root_secret_a, const u8 *root_secret_b, - const u8 *rand_s, const u8 *rand_p, u8 *tek, u8 *msk, - u8 *emsk) -{ - u8 sms_a[EAP_SAKE_SMS_LEN]; - u8 sms_b[EAP_SAKE_SMS_LEN]; - u8 key_buf[EAP_MSK_LEN + EAP_EMSK_LEN]; - - wpa_printf(MSG_DEBUG, "EAP-SAKE: Deriving keys"); - - wpa_hexdump_key(MSG_DEBUG, "EAP-SAKE: Root-Secret-A", - root_secret_a, EAP_SAKE_ROOT_SECRET_LEN); - eap_sake_kdf(root_secret_a, EAP_SAKE_ROOT_SECRET_LEN, - "SAKE Master Secret A", - rand_p, EAP_SAKE_RAND_LEN, rand_s, EAP_SAKE_RAND_LEN, - sms_a, EAP_SAKE_SMS_LEN); - wpa_hexdump_key(MSG_DEBUG, "EAP-SAKE: SMS-A", sms_a, EAP_SAKE_SMS_LEN); - eap_sake_kdf(sms_a, EAP_SAKE_SMS_LEN, "Transient EAP Key", - rand_s, EAP_SAKE_RAND_LEN, rand_p, EAP_SAKE_RAND_LEN, - tek, EAP_SAKE_TEK_LEN); - wpa_hexdump_key(MSG_DEBUG, "EAP-SAKE: TEK-Auth", - tek, EAP_SAKE_TEK_AUTH_LEN); - wpa_hexdump_key(MSG_DEBUG, "EAP-SAKE: TEK-Cipher", - tek + EAP_SAKE_TEK_AUTH_LEN, EAP_SAKE_TEK_CIPHER_LEN); - - wpa_hexdump_key(MSG_DEBUG, "EAP-SAKE: Root-Secret-B", - root_secret_b, EAP_SAKE_ROOT_SECRET_LEN); - eap_sake_kdf(root_secret_b, EAP_SAKE_ROOT_SECRET_LEN, - "SAKE Master Secret B", - rand_p, EAP_SAKE_RAND_LEN, rand_s, EAP_SAKE_RAND_LEN, - sms_b, EAP_SAKE_SMS_LEN); - wpa_hexdump_key(MSG_DEBUG, "EAP-SAKE: SMS-B", sms_b, EAP_SAKE_SMS_LEN); - eap_sake_kdf(sms_b, EAP_SAKE_SMS_LEN, "Master Session Key", - rand_s, EAP_SAKE_RAND_LEN, rand_p, EAP_SAKE_RAND_LEN, - key_buf, sizeof(key_buf)); - os_memcpy(msk, key_buf, EAP_MSK_LEN); - os_memcpy(emsk, key_buf + EAP_MSK_LEN, EAP_EMSK_LEN); - wpa_hexdump_key(MSG_DEBUG, "EAP-SAKE: MSK", msk, EAP_MSK_LEN); - wpa_hexdump_key(MSG_DEBUG, "EAP-SAKE: EMSK", emsk, EAP_EMSK_LEN); -} - - -/** - * eap_sake_compute_mic - Compute EAP-SAKE MIC for an EAP packet - * @tek_auth: 16-byte TEK-Auth - * @rand_s: 16-byte RAND_S - * @rand_p: 16-byte RAND_P - * @serverid: SERVERID - * @serverid_len: SERVERID length - * @peerid: PEERID - * @peerid_len: PEERID length - * @peer: MIC calculation for 0 = Server, 1 = Peer message - * @eap: EAP packet - * @eap_len: EAP packet length - * @mic_pos: MIC position in the EAP packet (must be [eap .. eap + eap_len]) - * @mic: Buffer for the computed 16-byte MIC - */ -int eap_sake_compute_mic(const u8 *tek_auth, - const u8 *rand_s, const u8 *rand_p, - const u8 *serverid, size_t serverid_len, - const u8 *peerid, size_t peerid_len, - int peer, const u8 *eap, size_t eap_len, - const u8 *mic_pos, u8 *mic) -{ - u8 _rand[2 * EAP_SAKE_RAND_LEN]; - u8 *tmp, *pos; - size_t tmplen; - - tmplen = serverid_len + 1 + peerid_len + 1 + eap_len; - tmp = os_malloc(tmplen); - if (tmp == NULL) - return -1; - pos = tmp; - if (peer) { - if (peerid) { - os_memcpy(pos, peerid, peerid_len); - pos += peerid_len; - } - *pos++ = 0x00; - if (serverid) { - os_memcpy(pos, serverid, serverid_len); - pos += serverid_len; - } - *pos++ = 0x00; - - os_memcpy(_rand, rand_s, EAP_SAKE_RAND_LEN); - os_memcpy(_rand + EAP_SAKE_RAND_LEN, rand_p, - EAP_SAKE_RAND_LEN); - } else { - if (serverid) { - os_memcpy(pos, serverid, serverid_len); - pos += serverid_len; - } - *pos++ = 0x00; - if (peerid) { - os_memcpy(pos, peerid, peerid_len); - pos += peerid_len; - } - *pos++ = 0x00; - - os_memcpy(_rand, rand_p, EAP_SAKE_RAND_LEN); - os_memcpy(_rand + EAP_SAKE_RAND_LEN, rand_s, - EAP_SAKE_RAND_LEN); - } - - os_memcpy(pos, eap, eap_len); - os_memset(pos + (mic_pos - eap), 0, EAP_SAKE_MIC_LEN); - - eap_sake_kdf(tek_auth, EAP_SAKE_TEK_AUTH_LEN, - peer ? "Peer MIC" : "Server MIC", - _rand, 2 * EAP_SAKE_RAND_LEN, tmp, tmplen, - mic, EAP_SAKE_MIC_LEN); - - os_free(tmp); - - return 0; -} - - -void eap_sake_add_attr(struct wpabuf *buf, u8 type, const u8 *data, - size_t len) -{ - wpabuf_put_u8(buf, type); - wpabuf_put_u8(buf, 2 + len); /* Length; including attr header */ - if (data) - wpabuf_put_data(buf, data, len); - else - os_memset(wpabuf_put(buf, len), 0, len); -} diff --git a/hostapd-0.8/src/eap_common/eap_sake_common.h b/hostapd-0.8/src/eap_common/eap_sake_common.h deleted file mode 100644 index 201e207..0000000 --- a/hostapd-0.8/src/eap_common/eap_sake_common.h +++ /dev/null @@ -1,102 +0,0 @@ -/* - * EAP server/peer: EAP-SAKE shared routines - * Copyright (c) 2006-2007, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#ifndef EAP_SAKE_COMMON_H -#define EAP_SAKE_COMMON_H - -#define EAP_SAKE_VERSION 2 - -#define EAP_SAKE_SUBTYPE_CHALLENGE 1 -#define EAP_SAKE_SUBTYPE_CONFIRM 2 -#define EAP_SAKE_SUBTYPE_AUTH_REJECT 3 -#define EAP_SAKE_SUBTYPE_IDENTITY 4 - -#define EAP_SAKE_AT_RAND_S 1 -#define EAP_SAKE_AT_RAND_P 2 -#define EAP_SAKE_AT_MIC_S 3 -#define EAP_SAKE_AT_MIC_P 4 -#define EAP_SAKE_AT_SERVERID 5 -#define EAP_SAKE_AT_PEERID 6 -#define EAP_SAKE_AT_SPI_S 7 -#define EAP_SAKE_AT_SPI_P 8 -#define EAP_SAKE_AT_ANY_ID_REQ 9 -#define EAP_SAKE_AT_PERM_ID_REQ 10 -#define EAP_SAKE_AT_ENCR_DATA 128 -#define EAP_SAKE_AT_IV 129 -#define EAP_SAKE_AT_PADDING 130 -#define EAP_SAKE_AT_NEXT_TMPID 131 -#define EAP_SAKE_AT_MSK_LIFE 132 - -#define EAP_SAKE_RAND_LEN 16 -#define EAP_SAKE_MIC_LEN 16 -#define EAP_SAKE_ROOT_SECRET_LEN 16 -#define EAP_SAKE_SMS_LEN 16 -#define EAP_SAKE_TEK_AUTH_LEN 16 -#define EAP_SAKE_TEK_CIPHER_LEN 16 -#define EAP_SAKE_TEK_LEN (EAP_SAKE_TEK_AUTH_LEN + EAP_SAKE_TEK_CIPHER_LEN) - -#ifdef _MSC_VER -#pragma pack(push, 1) -#endif /* _MSC_VER */ - -struct eap_sake_hdr { - u8 version; /* EAP_SAKE_VERSION */ - u8 session_id; - u8 subtype; -} STRUCT_PACKED; - -#ifdef _MSC_VER -#pragma pack(pop) -#endif /* _MSC_VER */ - - -struct eap_sake_parse_attr { - const u8 *rand_s; - const u8 *rand_p; - const u8 *mic_s; - const u8 *mic_p; - const u8 *serverid; - size_t serverid_len; - const u8 *peerid; - size_t peerid_len; - const u8 *spi_s; - size_t spi_s_len; - const u8 *spi_p; - size_t spi_p_len; - const u8 *any_id_req; - const u8 *perm_id_req; - const u8 *encr_data; - size_t encr_data_len; - const u8 *iv; - size_t iv_len; - const u8 *next_tmpid; - size_t next_tmpid_len; - const u8 *msk_life; -}; - -int eap_sake_parse_attributes(const u8 *buf, size_t len, - struct eap_sake_parse_attr *attr); -void eap_sake_derive_keys(const u8 *root_secret_a, const u8 *root_secret_b, - const u8 *rand_s, const u8 *rand_p, - u8 *tek, u8 *msk, u8 *emsk); -int eap_sake_compute_mic(const u8 *tek_auth, - const u8 *rand_s, const u8 *rand_p, - const u8 *serverid, size_t serverid_len, - const u8 *peerid, size_t peerid_len, - int peer, const u8 *eap, size_t eap_len, - const u8 *mic_pos, u8 *mic); -void eap_sake_add_attr(struct wpabuf *buf, u8 type, const u8 *data, - size_t len); - -#endif /* EAP_SAKE_COMMON_H */ diff --git a/hostapd-0.8/src/eap_common/eap_sim_common.c b/hostapd-0.8/src/eap_common/eap_sim_common.c deleted file mode 100644 index 0b37b0b..0000000 --- a/hostapd-0.8/src/eap_common/eap_sim_common.c +++ /dev/null @@ -1,1215 +0,0 @@ -/* - * EAP peer/server: EAP-SIM/AKA/AKA' shared routines - * Copyright (c) 2004-2008, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#include "includes.h" - -#include "common.h" -#include "wpabuf.h" -#include "crypto/aes_wrap.h" -#include "crypto/crypto.h" -#include "crypto/sha1.h" -#include "crypto/sha256.h" -#include "crypto/random.h" -#include "eap_common/eap_defs.h" -#include "eap_common/eap_sim_common.h" - - -static int eap_sim_prf(const u8 *key, u8 *x, size_t xlen) -{ - return fips186_2_prf(key, EAP_SIM_MK_LEN, x, xlen); -} - - -void eap_sim_derive_mk(const u8 *identity, size_t identity_len, - const u8 *nonce_mt, u16 selected_version, - const u8 *ver_list, size_t ver_list_len, - int num_chal, const u8 *kc, u8 *mk) -{ - u8 sel_ver[2]; - const unsigned char *addr[5]; - size_t len[5]; - - addr[0] = identity; - len[0] = identity_len; - addr[1] = kc; - len[1] = num_chal * EAP_SIM_KC_LEN; - addr[2] = nonce_mt; - len[2] = EAP_SIM_NONCE_MT_LEN; - addr[3] = ver_list; - len[3] = ver_list_len; - addr[4] = sel_ver; - len[4] = 2; - - WPA_PUT_BE16(sel_ver, selected_version); - - /* MK = SHA1(Identity|n*Kc|NONCE_MT|Version List|Selected Version) */ - sha1_vector(5, addr, len, mk); - wpa_hexdump_key(MSG_DEBUG, "EAP-SIM: MK", mk, EAP_SIM_MK_LEN); -} - - -void eap_aka_derive_mk(const u8 *identity, size_t identity_len, - const u8 *ik, const u8 *ck, u8 *mk) -{ - const u8 *addr[3]; - size_t len[3]; - - addr[0] = identity; - len[0] = identity_len; - addr[1] = ik; - len[1] = EAP_AKA_IK_LEN; - addr[2] = ck; - len[2] = EAP_AKA_CK_LEN; - - /* MK = SHA1(Identity|IK|CK) */ - sha1_vector(3, addr, len, mk); - wpa_hexdump_key(MSG_DEBUG, "EAP-AKA: IK", ik, EAP_AKA_IK_LEN); - wpa_hexdump_key(MSG_DEBUG, "EAP-AKA: CK", ck, EAP_AKA_CK_LEN); - wpa_hexdump_key(MSG_DEBUG, "EAP-AKA: MK", mk, EAP_SIM_MK_LEN); -} - - -int eap_sim_derive_keys(const u8 *mk, u8 *k_encr, u8 *k_aut, u8 *msk, u8 *emsk) -{ - u8 buf[EAP_SIM_K_ENCR_LEN + EAP_SIM_K_AUT_LEN + - EAP_SIM_KEYING_DATA_LEN + EAP_EMSK_LEN], *pos; - if (eap_sim_prf(mk, buf, sizeof(buf)) < 0) { - wpa_printf(MSG_ERROR, "EAP-SIM: Failed to derive keys"); - return -1; - } - pos = buf; - os_memcpy(k_encr, pos, EAP_SIM_K_ENCR_LEN); - pos += EAP_SIM_K_ENCR_LEN; - os_memcpy(k_aut, pos, EAP_SIM_K_AUT_LEN); - pos += EAP_SIM_K_AUT_LEN; - os_memcpy(msk, pos, EAP_SIM_KEYING_DATA_LEN); - pos += EAP_SIM_KEYING_DATA_LEN; - os_memcpy(emsk, pos, EAP_EMSK_LEN); - - wpa_hexdump_key(MSG_DEBUG, "EAP-SIM: K_encr", - k_encr, EAP_SIM_K_ENCR_LEN); - wpa_hexdump_key(MSG_DEBUG, "EAP-SIM: K_aut", - k_aut, EAP_SIM_K_AUT_LEN); - wpa_hexdump_key(MSG_DEBUG, "EAP-SIM: keying material (MSK)", - msk, EAP_SIM_KEYING_DATA_LEN); - wpa_hexdump_key(MSG_DEBUG, "EAP-SIM: EMSK", emsk, EAP_EMSK_LEN); - os_memset(buf, 0, sizeof(buf)); - - return 0; -} - - -int eap_sim_derive_keys_reauth(u16 _counter, - const u8 *identity, size_t identity_len, - const u8 *nonce_s, const u8 *mk, u8 *msk, - u8 *emsk) -{ - u8 xkey[SHA1_MAC_LEN]; - u8 buf[EAP_SIM_KEYING_DATA_LEN + EAP_EMSK_LEN + 32]; - u8 counter[2]; - const u8 *addr[4]; - size_t len[4]; - - while (identity_len > 0 && identity[identity_len - 1] == 0) { - wpa_printf(MSG_DEBUG, "EAP-SIM: Workaround - drop null " - "character from the end of identity"); - identity_len--; - } - addr[0] = identity; - len[0] = identity_len; - addr[1] = counter; - len[1] = 2; - addr[2] = nonce_s; - len[2] = EAP_SIM_NONCE_S_LEN; - addr[3] = mk; - len[3] = EAP_SIM_MK_LEN; - - WPA_PUT_BE16(counter, _counter); - - wpa_printf(MSG_DEBUG, "EAP-SIM: Deriving keying data from reauth"); - wpa_hexdump_ascii(MSG_DEBUG, "EAP-SIM: Identity", - identity, identity_len); - wpa_hexdump(MSG_DEBUG, "EAP-SIM: counter", counter, 2); - wpa_hexdump(MSG_DEBUG, "EAP-SIM: NONCE_S", nonce_s, - EAP_SIM_NONCE_S_LEN); - wpa_hexdump_key(MSG_DEBUG, "EAP-SIM: MK", mk, EAP_SIM_MK_LEN); - - /* XKEY' = SHA1(Identity|counter|NONCE_S|MK) */ - sha1_vector(4, addr, len, xkey); - wpa_hexdump(MSG_DEBUG, "EAP-SIM: XKEY'", xkey, SHA1_MAC_LEN); - - if (eap_sim_prf(xkey, buf, sizeof(buf)) < 0) { - wpa_printf(MSG_ERROR, "EAP-SIM: Failed to derive keys"); - return -1; - } - if (msk) { - os_memcpy(msk, buf, EAP_SIM_KEYING_DATA_LEN); - wpa_hexdump(MSG_DEBUG, "EAP-SIM: keying material (MSK)", - msk, EAP_SIM_KEYING_DATA_LEN); - } - if (emsk) { - os_memcpy(emsk, buf + EAP_SIM_KEYING_DATA_LEN, EAP_EMSK_LEN); - wpa_hexdump(MSG_DEBUG, "EAP-SIM: EMSK", emsk, EAP_EMSK_LEN); - } - os_memset(buf, 0, sizeof(buf)); - - return 0; -} - - -int eap_sim_verify_mac(const u8 *k_aut, const struct wpabuf *req, - const u8 *mac, const u8 *extra, size_t extra_len) -{ - unsigned char hmac[SHA1_MAC_LEN]; - const u8 *addr[2]; - size_t len[2]; - u8 *tmp; - - if (mac == NULL || wpabuf_len(req) < EAP_SIM_MAC_LEN || - mac < wpabuf_head_u8(req) || - mac > wpabuf_head_u8(req) + wpabuf_len(req) - EAP_SIM_MAC_LEN) - return -1; - - tmp = os_malloc(wpabuf_len(req)); - if (tmp == NULL) - return -1; - - addr[0] = tmp; - len[0] = wpabuf_len(req); - addr[1] = extra; - len[1] = extra_len; - - /* HMAC-SHA1-128 */ - os_memcpy(tmp, wpabuf_head(req), wpabuf_len(req)); - os_memset(tmp + (mac - wpabuf_head_u8(req)), 0, EAP_SIM_MAC_LEN); - wpa_hexdump(MSG_MSGDUMP, "EAP-SIM: Verify MAC - msg", - tmp, wpabuf_len(req)); - wpa_hexdump(MSG_MSGDUMP, "EAP-SIM: Verify MAC - extra data", - extra, extra_len); - wpa_hexdump_key(MSG_MSGDUMP, "EAP-SIM: Verify MAC - K_aut", - k_aut, EAP_SIM_K_AUT_LEN); - hmac_sha1_vector(k_aut, EAP_SIM_K_AUT_LEN, 2, addr, len, hmac); - wpa_hexdump(MSG_MSGDUMP, "EAP-SIM: Verify MAC: MAC", - hmac, EAP_SIM_MAC_LEN); - os_free(tmp); - - return (os_memcmp(hmac, mac, EAP_SIM_MAC_LEN) == 0) ? 0 : 1; -} - - -void eap_sim_add_mac(const u8 *k_aut, const u8 *msg, size_t msg_len, u8 *mac, - const u8 *extra, size_t extra_len) -{ - unsigned char hmac[SHA1_MAC_LEN]; - const u8 *addr[2]; - size_t len[2]; - - addr[0] = msg; - len[0] = msg_len; - addr[1] = extra; - len[1] = extra_len; - - /* HMAC-SHA1-128 */ - os_memset(mac, 0, EAP_SIM_MAC_LEN); - wpa_hexdump(MSG_MSGDUMP, "EAP-SIM: Add MAC - msg", msg, msg_len); - wpa_hexdump(MSG_MSGDUMP, "EAP-SIM: Add MAC - extra data", - extra, extra_len); - wpa_hexdump_key(MSG_MSGDUMP, "EAP-SIM: Add MAC - K_aut", - k_aut, EAP_SIM_K_AUT_LEN); - hmac_sha1_vector(k_aut, EAP_SIM_K_AUT_LEN, 2, addr, len, hmac); - os_memcpy(mac, hmac, EAP_SIM_MAC_LEN); - wpa_hexdump(MSG_MSGDUMP, "EAP-SIM: Add MAC: MAC", - mac, EAP_SIM_MAC_LEN); -} - - -#if defined(EAP_AKA_PRIME) || defined(EAP_SERVER_AKA_PRIME) -static void prf_prime(const u8 *k, const char *seed1, - const u8 *seed2, size_t seed2_len, - const u8 *seed3, size_t seed3_len, - u8 *res, size_t res_len) -{ - const u8 *addr[5]; - size_t len[5]; - u8 hash[SHA256_MAC_LEN]; - u8 iter; - - /* - * PRF'(K,S) = T1 | T2 | T3 | T4 | ... - * T1 = HMAC-SHA-256 (K, S | 0x01) - * T2 = HMAC-SHA-256 (K, T1 | S | 0x02) - * T3 = HMAC-SHA-256 (K, T2 | S | 0x03) - * T4 = HMAC-SHA-256 (K, T3 | S | 0x04) - * ... - */ - - addr[0] = hash; - len[0] = 0; - addr[1] = (const u8 *) seed1; - len[1] = os_strlen(seed1); - addr[2] = seed2; - len[2] = seed2_len; - addr[3] = seed3; - len[3] = seed3_len; - addr[4] = &iter; - len[4] = 1; - - iter = 0; - while (res_len) { - size_t hlen; - iter++; - hmac_sha256_vector(k, 32, 5, addr, len, hash); - len[0] = SHA256_MAC_LEN; - hlen = res_len > SHA256_MAC_LEN ? SHA256_MAC_LEN : res_len; - os_memcpy(res, hash, hlen); - res += hlen; - res_len -= hlen; - } -} - - -void eap_aka_prime_derive_keys(const u8 *identity, size_t identity_len, - const u8 *ik, const u8 *ck, u8 *k_encr, - u8 *k_aut, u8 *k_re, u8 *msk, u8 *emsk) -{ - u8 key[EAP_AKA_IK_LEN + EAP_AKA_CK_LEN]; - u8 keys[EAP_SIM_K_ENCR_LEN + EAP_AKA_PRIME_K_AUT_LEN + - EAP_AKA_PRIME_K_RE_LEN + EAP_MSK_LEN + EAP_EMSK_LEN]; - u8 *pos; - - /* - * MK = PRF'(IK'|CK',"EAP-AKA'"|Identity) - * K_encr = MK[0..127] - * K_aut = MK[128..383] - * K_re = MK[384..639] - * MSK = MK[640..1151] - * EMSK = MK[1152..1663] - */ - - os_memcpy(key, ik, EAP_AKA_IK_LEN); - os_memcpy(key + EAP_AKA_IK_LEN, ck, EAP_AKA_CK_LEN); - - prf_prime(key, "EAP-AKA'", identity, identity_len, NULL, 0, - keys, sizeof(keys)); - - pos = keys; - os_memcpy(k_encr, pos, EAP_SIM_K_ENCR_LEN); - wpa_hexdump_key(MSG_DEBUG, "EAP-AKA': K_encr", - k_encr, EAP_SIM_K_ENCR_LEN); - pos += EAP_SIM_K_ENCR_LEN; - - os_memcpy(k_aut, pos, EAP_AKA_PRIME_K_AUT_LEN); - wpa_hexdump_key(MSG_DEBUG, "EAP-AKA': K_aut", - k_aut, EAP_AKA_PRIME_K_AUT_LEN); - pos += EAP_AKA_PRIME_K_AUT_LEN; - - os_memcpy(k_re, pos, EAP_AKA_PRIME_K_RE_LEN); - wpa_hexdump_key(MSG_DEBUG, "EAP-AKA': K_re", - k_re, EAP_AKA_PRIME_K_RE_LEN); - pos += EAP_AKA_PRIME_K_RE_LEN; - - os_memcpy(msk, pos, EAP_MSK_LEN); - wpa_hexdump_key(MSG_DEBUG, "EAP-AKA': MSK", msk, EAP_MSK_LEN); - pos += EAP_MSK_LEN; - - os_memcpy(emsk, pos, EAP_EMSK_LEN); - wpa_hexdump_key(MSG_DEBUG, "EAP-AKA': EMSK", emsk, EAP_EMSK_LEN); -} - - -int eap_aka_prime_derive_keys_reauth(const u8 *k_re, u16 counter, - const u8 *identity, size_t identity_len, - const u8 *nonce_s, u8 *msk, u8 *emsk) -{ - u8 seed3[2 + EAP_SIM_NONCE_S_LEN]; - u8 keys[EAP_MSK_LEN + EAP_EMSK_LEN]; - u8 *pos; - - /* - * MK = PRF'(K_re,"EAP-AKA' re-auth"|Identity|counter|NONCE_S) - * MSK = MK[0..511] - * EMSK = MK[512..1023] - */ - - WPA_PUT_BE16(seed3, counter); - os_memcpy(seed3 + 2, nonce_s, EAP_SIM_NONCE_S_LEN); - - prf_prime(k_re, "EAP-AKA' re-auth", identity, identity_len, - seed3, sizeof(seed3), - keys, sizeof(keys)); - - pos = keys; - os_memcpy(msk, pos, EAP_MSK_LEN); - wpa_hexdump_key(MSG_DEBUG, "EAP-AKA': MSK", msk, EAP_MSK_LEN); - pos += EAP_MSK_LEN; - - os_memcpy(emsk, pos, EAP_EMSK_LEN); - wpa_hexdump_key(MSG_DEBUG, "EAP-AKA': EMSK", emsk, EAP_EMSK_LEN); - - os_memset(keys, 0, sizeof(keys)); - - return 0; -} - - -int eap_sim_verify_mac_sha256(const u8 *k_aut, const struct wpabuf *req, - const u8 *mac, const u8 *extra, size_t extra_len) -{ - unsigned char hmac[SHA256_MAC_LEN]; - const u8 *addr[2]; - size_t len[2]; - u8 *tmp; - - if (mac == NULL || wpabuf_len(req) < EAP_SIM_MAC_LEN || - mac < wpabuf_head_u8(req) || - mac > wpabuf_head_u8(req) + wpabuf_len(req) - EAP_SIM_MAC_LEN) - return -1; - - tmp = os_malloc(wpabuf_len(req)); - if (tmp == NULL) - return -1; - - addr[0] = tmp; - len[0] = wpabuf_len(req); - addr[1] = extra; - len[1] = extra_len; - - /* HMAC-SHA-256-128 */ - os_memcpy(tmp, wpabuf_head(req), wpabuf_len(req)); - os_memset(tmp + (mac - wpabuf_head_u8(req)), 0, EAP_SIM_MAC_LEN); - wpa_hexdump(MSG_MSGDUMP, "EAP-AKA': Verify MAC - msg", - tmp, wpabuf_len(req)); - wpa_hexdump(MSG_MSGDUMP, "EAP-AKA': Verify MAC - extra data", - extra, extra_len); - wpa_hexdump_key(MSG_MSGDUMP, "EAP-AKA': Verify MAC - K_aut", - k_aut, EAP_AKA_PRIME_K_AUT_LEN); - hmac_sha256_vector(k_aut, EAP_AKA_PRIME_K_AUT_LEN, 2, addr, len, hmac); - wpa_hexdump(MSG_MSGDUMP, "EAP-AKA': Verify MAC: MAC", - hmac, EAP_SIM_MAC_LEN); - os_free(tmp); - - return (os_memcmp(hmac, mac, EAP_SIM_MAC_LEN) == 0) ? 0 : 1; -} - - -void eap_sim_add_mac_sha256(const u8 *k_aut, const u8 *msg, size_t msg_len, - u8 *mac, const u8 *extra, size_t extra_len) -{ - unsigned char hmac[SHA256_MAC_LEN]; - const u8 *addr[2]; - size_t len[2]; - - addr[0] = msg; - len[0] = msg_len; - addr[1] = extra; - len[1] = extra_len; - - /* HMAC-SHA-256-128 */ - os_memset(mac, 0, EAP_SIM_MAC_LEN); - wpa_hexdump(MSG_MSGDUMP, "EAP-AKA': Add MAC - msg", msg, msg_len); - wpa_hexdump(MSG_MSGDUMP, "EAP-AKA': Add MAC - extra data", - extra, extra_len); - wpa_hexdump_key(MSG_MSGDUMP, "EAP-AKA': Add MAC - K_aut", - k_aut, EAP_AKA_PRIME_K_AUT_LEN); - hmac_sha256_vector(k_aut, EAP_AKA_PRIME_K_AUT_LEN, 2, addr, len, hmac); - os_memcpy(mac, hmac, EAP_SIM_MAC_LEN); - wpa_hexdump(MSG_MSGDUMP, "EAP-AKA': Add MAC: MAC", - mac, EAP_SIM_MAC_LEN); -} - - -void eap_aka_prime_derive_ck_ik_prime(u8 *ck, u8 *ik, const u8 *sqn_ak, - const u8 *network_name, - size_t network_name_len) -{ - u8 key[EAP_AKA_CK_LEN + EAP_AKA_IK_LEN]; - u8 hash[SHA256_MAC_LEN]; - const u8 *addr[5]; - size_t len[5]; - u8 fc; - u8 l0[2], l1[2]; - - /* 3GPP TS 33.402 V8.0.0 - * (CK', IK') = F(CK, IK, ) - */ - /* TODO: CK', IK' generation should really be moved into the actual - * AKA procedure with network name passed in there and option to use - * AMF separation bit = 1 (3GPP TS 33.401). */ - - /* Change Request 33.402 CR 0033 to version 8.1.1 from - * 3GPP TSG-SA WG3 Meeting #53 in September 2008: - * - * CK' || IK' = HMAC-SHA-256(Key, S) - * S = FC || P0 || L0 || P1 || L1 || ... || Pn || Ln - * Key = CK || IK - * FC = 0x20 - * P0 = access network identity (3GPP TS 24.302) - * L0 = length of acceess network identity (2 octets, big endian) - * P1 = SQN xor AK (if AK is not used, AK is treaded as 000..0 - * L1 = 0x00 0x06 - */ - - fc = 0x20; - - wpa_printf(MSG_DEBUG, "EAP-AKA': Derive (CK',IK') from (CK,IK)"); - wpa_hexdump_key(MSG_DEBUG, "EAP-AKA': CK", ck, EAP_AKA_CK_LEN); - wpa_hexdump_key(MSG_DEBUG, "EAP-AKA': IK", ik, EAP_AKA_IK_LEN); - wpa_printf(MSG_DEBUG, "EAP-AKA': FC = 0x%x", fc); - wpa_hexdump_ascii(MSG_DEBUG, "EAP-AKA': P0 = Access network identity", - network_name, network_name_len); - wpa_hexdump(MSG_DEBUG, "EAP-AKA': P1 = SQN xor AK", sqn_ak, 6); - - os_memcpy(key, ck, EAP_AKA_CK_LEN); - os_memcpy(key + EAP_AKA_CK_LEN, ik, EAP_AKA_IK_LEN); - wpa_hexdump_key(MSG_DEBUG, "EAP-AKA': Key = CK || IK", - key, sizeof(key)); - - addr[0] = &fc; - len[0] = 1; - addr[1] = network_name; - len[1] = network_name_len; - WPA_PUT_BE16(l0, network_name_len); - addr[2] = l0; - len[2] = 2; - addr[3] = sqn_ak; - len[3] = 6; - WPA_PUT_BE16(l1, 6); - addr[4] = l1; - len[4] = 2; - - hmac_sha256_vector(key, sizeof(key), 5, addr, len, hash); - wpa_hexdump_key(MSG_DEBUG, "EAP-AKA': KDF output (CK' || IK')", - hash, sizeof(hash)); - - os_memcpy(ck, hash, EAP_AKA_CK_LEN); - os_memcpy(ik, hash + EAP_AKA_CK_LEN, EAP_AKA_IK_LEN); - wpa_hexdump_key(MSG_DEBUG, "EAP-AKA': CK'", ck, EAP_AKA_CK_LEN); - wpa_hexdump_key(MSG_DEBUG, "EAP-AKA': IK'", ik, EAP_AKA_IK_LEN); -} -#endif /* EAP_AKA_PRIME || EAP_SERVER_AKA_PRIME */ - - -int eap_sim_parse_attr(const u8 *start, const u8 *end, - struct eap_sim_attrs *attr, int aka, int encr) -{ - const u8 *pos = start, *apos; - size_t alen, plen, i, list_len; - - os_memset(attr, 0, sizeof(*attr)); - attr->id_req = NO_ID_REQ; - attr->notification = -1; - attr->counter = -1; - attr->selected_version = -1; - attr->client_error_code = -1; - - while (pos < end) { - if (pos + 2 > end) { - wpa_printf(MSG_INFO, "EAP-SIM: Attribute overflow(1)"); - return -1; - } - wpa_printf(MSG_MSGDUMP, "EAP-SIM: Attribute: Type=%d Len=%d", - pos[0], pos[1] * 4); - if (pos + pos[1] * 4 > end) { - wpa_printf(MSG_INFO, "EAP-SIM: Attribute overflow " - "(pos=%p len=%d end=%p)", - pos, pos[1] * 4, end); - return -1; - } - if (pos[1] == 0) { - wpa_printf(MSG_INFO, "EAP-SIM: Attribute underflow"); - return -1; - } - apos = pos + 2; - alen = pos[1] * 4 - 2; - wpa_hexdump(MSG_MSGDUMP, "EAP-SIM: Attribute data", - apos, alen); - - switch (pos[0]) { - case EAP_SIM_AT_RAND: - wpa_printf(MSG_DEBUG, "EAP-SIM: AT_RAND"); - apos += 2; - alen -= 2; - if ((!aka && (alen % GSM_RAND_LEN)) || - (aka && alen != EAP_AKA_RAND_LEN)) { - wpa_printf(MSG_INFO, "EAP-SIM: Invalid AT_RAND" - " (len %lu)", - (unsigned long) alen); - return -1; - } - attr->rand = apos; - attr->num_chal = alen / GSM_RAND_LEN; - break; - case EAP_SIM_AT_AUTN: - wpa_printf(MSG_DEBUG, "EAP-AKA: AT_AUTN"); - if (!aka) { - wpa_printf(MSG_DEBUG, "EAP-SIM: " - "Unexpected AT_AUTN"); - return -1; - } - apos += 2; - alen -= 2; - if (alen != EAP_AKA_AUTN_LEN) { - wpa_printf(MSG_INFO, "EAP-AKA: Invalid AT_AUTN" - " (len %lu)", - (unsigned long) alen); - return -1; - } - attr->autn = apos; - break; - case EAP_SIM_AT_PADDING: - if (!encr) { - wpa_printf(MSG_ERROR, "EAP-SIM: Unencrypted " - "AT_PADDING"); - return -1; - } - wpa_printf(MSG_DEBUG, "EAP-SIM: (encr) AT_PADDING"); - for (i = 2; i < alen; i++) { - if (apos[i] != 0) { - wpa_printf(MSG_INFO, "EAP-SIM: (encr) " - "AT_PADDING used a non-zero" - " padding byte"); - wpa_hexdump(MSG_DEBUG, "EAP-SIM: " - "(encr) padding bytes", - apos + 2, alen - 2); - return -1; - } - } - break; - case EAP_SIM_AT_NONCE_MT: - wpa_printf(MSG_DEBUG, "EAP-SIM: AT_NONCE_MT"); - if (alen != 2 + EAP_SIM_NONCE_MT_LEN) { - wpa_printf(MSG_INFO, "EAP-SIM: Invalid " - "AT_NONCE_MT length"); - return -1; - } - attr->nonce_mt = apos + 2; - break; - case EAP_SIM_AT_PERMANENT_ID_REQ: - wpa_printf(MSG_DEBUG, "EAP-SIM: AT_PERMANENT_ID_REQ"); - attr->id_req = PERMANENT_ID; - break; - case EAP_SIM_AT_MAC: - wpa_printf(MSG_DEBUG, "EAP-SIM: AT_MAC"); - if (alen != 2 + EAP_SIM_MAC_LEN) { - wpa_printf(MSG_INFO, "EAP-SIM: Invalid AT_MAC " - "length"); - return -1; - } - attr->mac = apos + 2; - break; - case EAP_SIM_AT_NOTIFICATION: - if (alen != 2) { - wpa_printf(MSG_INFO, "EAP-SIM: Invalid " - "AT_NOTIFICATION length %lu", - (unsigned long) alen); - return -1; - } - attr->notification = apos[0] * 256 + apos[1]; - wpa_printf(MSG_DEBUG, "EAP-SIM: AT_NOTIFICATION %d", - attr->notification); - break; - case EAP_SIM_AT_ANY_ID_REQ: - wpa_printf(MSG_DEBUG, "EAP-SIM: AT_ANY_ID_REQ"); - attr->id_req = ANY_ID; - break; - case EAP_SIM_AT_IDENTITY: - wpa_printf(MSG_DEBUG, "EAP-SIM: AT_IDENTITY"); - plen = WPA_GET_BE16(apos); - apos += 2; - alen -= 2; - if (plen > alen) { - wpa_printf(MSG_INFO, "EAP-SIM: Invalid " - "AT_IDENTITY (Actual Length %lu, " - "remaining length %lu)", - (unsigned long) plen, - (unsigned long) alen); - return -1; - } - - attr->identity = apos; - attr->identity_len = plen; - break; - case EAP_SIM_AT_VERSION_LIST: - if (aka) { - wpa_printf(MSG_DEBUG, "EAP-AKA: " - "Unexpected AT_VERSION_LIST"); - return -1; - } - list_len = apos[0] * 256 + apos[1]; - wpa_printf(MSG_DEBUG, "EAP-SIM: AT_VERSION_LIST"); - if (list_len < 2 || list_len > alen - 2) { - wpa_printf(MSG_WARNING, "EAP-SIM: Invalid " - "AT_VERSION_LIST (list_len=%lu " - "attr_len=%lu)", - (unsigned long) list_len, - (unsigned long) alen); - return -1; - } - attr->version_list = apos + 2; - attr->version_list_len = list_len; - break; - case EAP_SIM_AT_SELECTED_VERSION: - wpa_printf(MSG_DEBUG, "EAP-SIM: AT_SELECTED_VERSION"); - if (alen != 2) { - wpa_printf(MSG_INFO, "EAP-SIM: Invalid " - "AT_SELECTED_VERSION length %lu", - (unsigned long) alen); - return -1; - } - attr->selected_version = apos[0] * 256 + apos[1]; - wpa_printf(MSG_DEBUG, "EAP-SIM: AT_SELECTED_VERSION " - "%d", attr->selected_version); - break; - case EAP_SIM_AT_FULLAUTH_ID_REQ: - wpa_printf(MSG_DEBUG, "EAP-SIM: AT_FULLAUTH_ID_REQ"); - attr->id_req = FULLAUTH_ID; - break; - case EAP_SIM_AT_COUNTER: - if (!encr) { - wpa_printf(MSG_ERROR, "EAP-SIM: Unencrypted " - "AT_COUNTER"); - return -1; - } - if (alen != 2) { - wpa_printf(MSG_INFO, "EAP-SIM: (encr) Invalid " - "AT_COUNTER (alen=%lu)", - (unsigned long) alen); - return -1; - } - attr->counter = apos[0] * 256 + apos[1]; - wpa_printf(MSG_DEBUG, "EAP-SIM: (encr) AT_COUNTER %d", - attr->counter); - break; - case EAP_SIM_AT_COUNTER_TOO_SMALL: - if (!encr) { - wpa_printf(MSG_ERROR, "EAP-SIM: Unencrypted " - "AT_COUNTER_TOO_SMALL"); - return -1; - } - if (alen != 2) { - wpa_printf(MSG_INFO, "EAP-SIM: (encr) Invalid " - "AT_COUNTER_TOO_SMALL (alen=%lu)", - (unsigned long) alen); - return -1; - } - wpa_printf(MSG_DEBUG, "EAP-SIM: (encr) " - "AT_COUNTER_TOO_SMALL"); - attr->counter_too_small = 1; - break; - case EAP_SIM_AT_NONCE_S: - if (!encr) { - wpa_printf(MSG_ERROR, "EAP-SIM: Unencrypted " - "AT_NONCE_S"); - return -1; - } - wpa_printf(MSG_DEBUG, "EAP-SIM: (encr) " - "AT_NONCE_S"); - if (alen != 2 + EAP_SIM_NONCE_S_LEN) { - wpa_printf(MSG_INFO, "EAP-SIM: (encr) Invalid " - "AT_NONCE_S (alen=%lu)", - (unsigned long) alen); - return -1; - } - attr->nonce_s = apos + 2; - break; - case EAP_SIM_AT_CLIENT_ERROR_CODE: - if (alen != 2) { - wpa_printf(MSG_INFO, "EAP-SIM: Invalid " - "AT_CLIENT_ERROR_CODE length %lu", - (unsigned long) alen); - return -1; - } - attr->client_error_code = apos[0] * 256 + apos[1]; - wpa_printf(MSG_DEBUG, "EAP-SIM: AT_CLIENT_ERROR_CODE " - "%d", attr->client_error_code); - break; - case EAP_SIM_AT_IV: - wpa_printf(MSG_DEBUG, "EAP-SIM: AT_IV"); - if (alen != 2 + EAP_SIM_MAC_LEN) { - wpa_printf(MSG_INFO, "EAP-SIM: Invalid AT_IV " - "length %lu", (unsigned long) alen); - return -1; - } - attr->iv = apos + 2; - break; - case EAP_SIM_AT_ENCR_DATA: - wpa_printf(MSG_DEBUG, "EAP-SIM: AT_ENCR_DATA"); - attr->encr_data = apos + 2; - attr->encr_data_len = alen - 2; - if (attr->encr_data_len % 16) { - wpa_printf(MSG_INFO, "EAP-SIM: Invalid " - "AT_ENCR_DATA length %lu", - (unsigned long) - attr->encr_data_len); - return -1; - } - break; - case EAP_SIM_AT_NEXT_PSEUDONYM: - if (!encr) { - wpa_printf(MSG_ERROR, "EAP-SIM: Unencrypted " - "AT_NEXT_PSEUDONYM"); - return -1; - } - wpa_printf(MSG_DEBUG, "EAP-SIM: (encr) " - "AT_NEXT_PSEUDONYM"); - plen = apos[0] * 256 + apos[1]; - if (plen > alen - 2) { - wpa_printf(MSG_INFO, "EAP-SIM: (encr) Invalid" - " AT_NEXT_PSEUDONYM (actual" - " len %lu, attr len %lu)", - (unsigned long) plen, - (unsigned long) alen); - return -1; - } - attr->next_pseudonym = pos + 4; - attr->next_pseudonym_len = plen; - break; - case EAP_SIM_AT_NEXT_REAUTH_ID: - if (!encr) { - wpa_printf(MSG_ERROR, "EAP-SIM: Unencrypted " - "AT_NEXT_REAUTH_ID"); - return -1; - } - wpa_printf(MSG_DEBUG, "EAP-SIM: (encr) " - "AT_NEXT_REAUTH_ID"); - plen = apos[0] * 256 + apos[1]; - if (plen > alen - 2) { - wpa_printf(MSG_INFO, "EAP-SIM: (encr) Invalid" - " AT_NEXT_REAUTH_ID (actual" - " len %lu, attr len %lu)", - (unsigned long) plen, - (unsigned long) alen); - return -1; - } - attr->next_reauth_id = pos + 4; - attr->next_reauth_id_len = plen; - break; - case EAP_SIM_AT_RES: - wpa_printf(MSG_DEBUG, "EAP-SIM: AT_RES"); - attr->res_len_bits = WPA_GET_BE16(apos); - apos += 2; - alen -= 2; - if (!aka || alen < EAP_AKA_MIN_RES_LEN || - alen > EAP_AKA_MAX_RES_LEN) { - wpa_printf(MSG_INFO, "EAP-SIM: Invalid AT_RES " - "(len %lu)", - (unsigned long) alen); - return -1; - } - attr->res = apos; - attr->res_len = alen; - break; - case EAP_SIM_AT_AUTS: - wpa_printf(MSG_DEBUG, "EAP-AKA: AT_AUTS"); - if (!aka) { - wpa_printf(MSG_DEBUG, "EAP-SIM: " - "Unexpected AT_AUTS"); - return -1; - } - if (alen != EAP_AKA_AUTS_LEN) { - wpa_printf(MSG_INFO, "EAP-AKA: Invalid AT_AUTS" - " (len %lu)", - (unsigned long) alen); - return -1; - } - attr->auts = apos; - break; - case EAP_SIM_AT_CHECKCODE: - wpa_printf(MSG_DEBUG, "EAP-AKA: AT_CHECKCODE"); - if (!aka) { - wpa_printf(MSG_DEBUG, "EAP-SIM: " - "Unexpected AT_CHECKCODE"); - return -1; - } - apos += 2; - alen -= 2; - if (alen != 0 && alen != EAP_AKA_CHECKCODE_LEN && - alen != EAP_AKA_PRIME_CHECKCODE_LEN) { - wpa_printf(MSG_INFO, "EAP-AKA: Invalid " - "AT_CHECKCODE (len %lu)", - (unsigned long) alen); - return -1; - } - attr->checkcode = apos; - attr->checkcode_len = alen; - break; - case EAP_SIM_AT_RESULT_IND: - if (encr) { - wpa_printf(MSG_ERROR, "EAP-SIM: Encrypted " - "AT_RESULT_IND"); - return -1; - } - if (alen != 2) { - wpa_printf(MSG_INFO, "EAP-SIM: Invalid " - "AT_RESULT_IND (alen=%lu)", - (unsigned long) alen); - return -1; - } - wpa_printf(MSG_DEBUG, "EAP-SIM: AT_RESULT_IND"); - attr->result_ind = 1; - break; -#if defined(EAP_AKA_PRIME) || defined(EAP_SERVER_AKA_PRIME) - case EAP_SIM_AT_KDF_INPUT: - if (aka != 2) { - wpa_printf(MSG_INFO, "EAP-AKA: Unexpected " - "AT_KDF_INPUT"); - return -1; - } - - wpa_printf(MSG_DEBUG, "EAP-AKA: AT_KDF_INPUT"); - plen = WPA_GET_BE16(apos); - apos += 2; - alen -= 2; - if (plen > alen) { - wpa_printf(MSG_INFO, "EAP-AKA': Invalid " - "AT_KDF_INPUT (Actual Length %lu, " - "remaining length %lu)", - (unsigned long) plen, - (unsigned long) alen); - return -1; - } - attr->kdf_input = apos; - attr->kdf_input_len = plen; - break; - case EAP_SIM_AT_KDF: - if (aka != 2) { - wpa_printf(MSG_INFO, "EAP-AKA: Unexpected " - "AT_KDF"); - return -1; - } - - wpa_printf(MSG_DEBUG, "EAP-AKA: AT_KDF"); - if (alen != 2) { - wpa_printf(MSG_INFO, "EAP-AKA': Invalid " - "AT_KDF (len %lu)", - (unsigned long) alen); - return -1; - } - if (attr->kdf_count == EAP_AKA_PRIME_KDF_MAX) { - wpa_printf(MSG_DEBUG, "EAP-AKA': Too many " - "AT_KDF attributes - ignore this"); - continue; - } - attr->kdf[attr->kdf_count] = WPA_GET_BE16(apos); - attr->kdf_count++; - break; - case EAP_SIM_AT_BIDDING: - wpa_printf(MSG_DEBUG, "EAP-AKA: AT_BIDDING"); - if (alen != 2) { - wpa_printf(MSG_INFO, "EAP-AKA: Invalid " - "AT_BIDDING (len %lu)", - (unsigned long) alen); - return -1; - } - attr->bidding = apos; - break; -#endif /* EAP_AKA_PRIME || EAP_SERVER_AKA_PRIME */ - default: - if (pos[0] < 128) { - wpa_printf(MSG_INFO, "EAP-SIM: Unrecognized " - "non-skippable attribute %d", - pos[0]); - return -1; - } - - wpa_printf(MSG_DEBUG, "EAP-SIM: Unrecognized skippable" - " attribute %d ignored", pos[0]); - break; - } - - pos += pos[1] * 4; - } - - wpa_printf(MSG_DEBUG, "EAP-SIM: Attributes parsed successfully " - "(aka=%d encr=%d)", aka, encr); - - return 0; -} - - -u8 * eap_sim_parse_encr(const u8 *k_encr, const u8 *encr_data, - size_t encr_data_len, const u8 *iv, - struct eap_sim_attrs *attr, int aka) -{ - u8 *decrypted; - - if (!iv) { - wpa_printf(MSG_INFO, "EAP-SIM: Encrypted data, but no IV"); - return NULL; - } - - decrypted = os_malloc(encr_data_len); - if (decrypted == NULL) - return NULL; - os_memcpy(decrypted, encr_data, encr_data_len); - - if (aes_128_cbc_decrypt(k_encr, iv, decrypted, encr_data_len)) { - os_free(decrypted); - return NULL; - } - wpa_hexdump(MSG_MSGDUMP, "EAP-SIM: Decrypted AT_ENCR_DATA", - decrypted, encr_data_len); - - if (eap_sim_parse_attr(decrypted, decrypted + encr_data_len, attr, - aka, 1)) { - wpa_printf(MSG_INFO, "EAP-SIM: (encr) Failed to parse " - "decrypted AT_ENCR_DATA"); - os_free(decrypted); - return NULL; - } - - return decrypted; -} - - -#define EAP_SIM_INIT_LEN 128 - -struct eap_sim_msg { - struct wpabuf *buf; - size_t mac, iv, encr; /* index from buf */ - int type; -}; - - -struct eap_sim_msg * eap_sim_msg_init(int code, int id, int type, int subtype) -{ - struct eap_sim_msg *msg; - struct eap_hdr *eap; - u8 *pos; - - msg = os_zalloc(sizeof(*msg)); - if (msg == NULL) - return NULL; - - msg->type = type; - msg->buf = wpabuf_alloc(EAP_SIM_INIT_LEN); - if (msg->buf == NULL) { - os_free(msg); - return NULL; - } - eap = wpabuf_put(msg->buf, sizeof(*eap)); - eap->code = code; - eap->identifier = id; - - pos = wpabuf_put(msg->buf, 4); - *pos++ = type; - *pos++ = subtype; - *pos++ = 0; /* Reserved */ - *pos++ = 0; /* Reserved */ - - return msg; -} - - -struct wpabuf * eap_sim_msg_finish(struct eap_sim_msg *msg, const u8 *k_aut, - const u8 *extra, size_t extra_len) -{ - struct eap_hdr *eap; - struct wpabuf *buf; - - if (msg == NULL) - return NULL; - - eap = wpabuf_mhead(msg->buf); - eap->length = host_to_be16(wpabuf_len(msg->buf)); - -#if defined(EAP_AKA_PRIME) || defined(EAP_SERVER_AKA_PRIME) - if (k_aut && msg->mac && msg->type == EAP_TYPE_AKA_PRIME) { - eap_sim_add_mac_sha256(k_aut, (u8 *) wpabuf_head(msg->buf), - wpabuf_len(msg->buf), - (u8 *) wpabuf_mhead(msg->buf) + - msg->mac, extra, extra_len); - } else -#endif /* EAP_AKA_PRIME || EAP_SERVER_AKA_PRIME */ - if (k_aut && msg->mac) { - eap_sim_add_mac(k_aut, (u8 *) wpabuf_head(msg->buf), - wpabuf_len(msg->buf), - (u8 *) wpabuf_mhead(msg->buf) + msg->mac, - extra, extra_len); - } - - buf = msg->buf; - os_free(msg); - return buf; -} - - -void eap_sim_msg_free(struct eap_sim_msg *msg) -{ - if (msg) { - wpabuf_free(msg->buf); - os_free(msg); - } -} - - -u8 * eap_sim_msg_add_full(struct eap_sim_msg *msg, u8 attr, - const u8 *data, size_t len) -{ - int attr_len = 2 + len; - int pad_len; - u8 *start; - - if (msg == NULL) - return NULL; - - pad_len = (4 - attr_len % 4) % 4; - attr_len += pad_len; - if (wpabuf_resize(&msg->buf, attr_len)) - return NULL; - start = wpabuf_put(msg->buf, 0); - wpabuf_put_u8(msg->buf, attr); - wpabuf_put_u8(msg->buf, attr_len / 4); - wpabuf_put_data(msg->buf, data, len); - if (pad_len) - os_memset(wpabuf_put(msg->buf, pad_len), 0, pad_len); - return start; -} - - -u8 * eap_sim_msg_add(struct eap_sim_msg *msg, u8 attr, u16 value, - const u8 *data, size_t len) -{ - int attr_len = 4 + len; - int pad_len; - u8 *start; - - if (msg == NULL) - return NULL; - - pad_len = (4 - attr_len % 4) % 4; - attr_len += pad_len; - if (wpabuf_resize(&msg->buf, attr_len)) - return NULL; - start = wpabuf_put(msg->buf, 0); - wpabuf_put_u8(msg->buf, attr); - wpabuf_put_u8(msg->buf, attr_len / 4); - wpabuf_put_be16(msg->buf, value); - if (data) - wpabuf_put_data(msg->buf, data, len); - else - wpabuf_put(msg->buf, len); - if (pad_len) - os_memset(wpabuf_put(msg->buf, pad_len), 0, pad_len); - return start; -} - - -u8 * eap_sim_msg_add_mac(struct eap_sim_msg *msg, u8 attr) -{ - u8 *pos = eap_sim_msg_add(msg, attr, 0, NULL, EAP_SIM_MAC_LEN); - if (pos) - msg->mac = (pos - wpabuf_head_u8(msg->buf)) + 4; - return pos; -} - - -int eap_sim_msg_add_encr_start(struct eap_sim_msg *msg, u8 attr_iv, - u8 attr_encr) -{ - u8 *pos = eap_sim_msg_add(msg, attr_iv, 0, NULL, EAP_SIM_IV_LEN); - if (pos == NULL) - return -1; - msg->iv = (pos - wpabuf_head_u8(msg->buf)) + 4; - if (random_get_bytes(wpabuf_mhead_u8(msg->buf) + msg->iv, - EAP_SIM_IV_LEN)) { - msg->iv = 0; - return -1; - } - - pos = eap_sim_msg_add(msg, attr_encr, 0, NULL, 0); - if (pos == NULL) { - msg->iv = 0; - return -1; - } - msg->encr = pos - wpabuf_head_u8(msg->buf); - - return 0; -} - - -int eap_sim_msg_add_encr_end(struct eap_sim_msg *msg, u8 *k_encr, int attr_pad) -{ - size_t encr_len; - - if (msg == NULL || k_encr == NULL || msg->iv == 0 || msg->encr == 0) - return -1; - - encr_len = wpabuf_len(msg->buf) - msg->encr - 4; - if (encr_len % 16) { - u8 *pos; - int pad_len = 16 - (encr_len % 16); - if (pad_len < 4) { - wpa_printf(MSG_WARNING, "EAP-SIM: " - "eap_sim_msg_add_encr_end - invalid pad_len" - " %d", pad_len); - return -1; - } - wpa_printf(MSG_DEBUG, " *AT_PADDING"); - pos = eap_sim_msg_add(msg, attr_pad, 0, NULL, pad_len - 4); - if (pos == NULL) - return -1; - os_memset(pos + 4, 0, pad_len - 4); - encr_len += pad_len; - } - wpa_printf(MSG_DEBUG, " (AT_ENCR_DATA data len %lu)", - (unsigned long) encr_len); - wpabuf_mhead_u8(msg->buf)[msg->encr + 1] = encr_len / 4 + 1; - return aes_128_cbc_encrypt(k_encr, wpabuf_head_u8(msg->buf) + msg->iv, - wpabuf_mhead_u8(msg->buf) + msg->encr + 4, - encr_len); -} - - -void eap_sim_report_notification(void *msg_ctx, int notification, int aka) -{ -#ifndef CONFIG_NO_STDOUT_DEBUG - const char *type = aka ? "AKA" : "SIM"; -#endif /* CONFIG_NO_STDOUT_DEBUG */ - - switch (notification) { - case EAP_SIM_GENERAL_FAILURE_AFTER_AUTH: - wpa_printf(MSG_WARNING, "EAP-%s: General failure " - "notification (after authentication)", type); - break; - case EAP_SIM_TEMPORARILY_DENIED: - wpa_printf(MSG_WARNING, "EAP-%s: Failure notification: " - "User has been temporarily denied access to the " - "requested service", type); - break; - case EAP_SIM_NOT_SUBSCRIBED: - wpa_printf(MSG_WARNING, "EAP-%s: Failure notification: " - "User has not subscribed to the requested service", - type); - break; - case EAP_SIM_GENERAL_FAILURE_BEFORE_AUTH: - wpa_printf(MSG_WARNING, "EAP-%s: General failure " - "notification (before authentication)", type); - break; - case EAP_SIM_SUCCESS: - wpa_printf(MSG_INFO, "EAP-%s: Successful authentication " - "notification", type); - break; - default: - if (notification >= 32768) { - wpa_printf(MSG_INFO, "EAP-%s: Unrecognized " - "non-failure notification %d", - type, notification); - } else { - wpa_printf(MSG_WARNING, "EAP-%s: Unrecognized " - "failure notification %d", - type, notification); - } - } -} diff --git a/hostapd-0.8/src/eap_common/eap_sim_common.h b/hostapd-0.8/src/eap_common/eap_sim_common.h deleted file mode 100644 index 48c8eaa..0000000 --- a/hostapd-0.8/src/eap_common/eap_sim_common.h +++ /dev/null @@ -1,235 +0,0 @@ -/* - * EAP peer/server: EAP-SIM/AKA/AKA' shared routines - * Copyright (c) 2004-2008, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#ifndef EAP_SIM_COMMON_H -#define EAP_SIM_COMMON_H - -#define EAP_SIM_NONCE_S_LEN 16 -#define EAP_SIM_NONCE_MT_LEN 16 -#define EAP_SIM_MAC_LEN 16 -#define EAP_SIM_MK_LEN 20 -#define EAP_SIM_K_AUT_LEN 16 -#define EAP_SIM_K_ENCR_LEN 16 -#define EAP_SIM_KEYING_DATA_LEN 64 -#define EAP_SIM_IV_LEN 16 -#define EAP_SIM_KC_LEN 8 -#define EAP_SIM_SRES_LEN 4 - -#define GSM_RAND_LEN 16 - -#define EAP_SIM_VERSION 1 - -/* EAP-SIM Subtypes */ -#define EAP_SIM_SUBTYPE_START 10 -#define EAP_SIM_SUBTYPE_CHALLENGE 11 -#define EAP_SIM_SUBTYPE_NOTIFICATION 12 -#define EAP_SIM_SUBTYPE_REAUTHENTICATION 13 -#define EAP_SIM_SUBTYPE_CLIENT_ERROR 14 - -/* AT_CLIENT_ERROR_CODE error codes */ -#define EAP_SIM_UNABLE_TO_PROCESS_PACKET 0 -#define EAP_SIM_UNSUPPORTED_VERSION 1 -#define EAP_SIM_INSUFFICIENT_NUM_OF_CHAL 2 -#define EAP_SIM_RAND_NOT_FRESH 3 - -#define EAP_SIM_MAX_FAST_REAUTHS 1000 - -#define EAP_SIM_MAX_CHAL 3 - - -/* EAP-AKA Subtypes */ -#define EAP_AKA_SUBTYPE_CHALLENGE 1 -#define EAP_AKA_SUBTYPE_AUTHENTICATION_REJECT 2 -#define EAP_AKA_SUBTYPE_SYNCHRONIZATION_FAILURE 4 -#define EAP_AKA_SUBTYPE_IDENTITY 5 -#define EAP_AKA_SUBTYPE_NOTIFICATION 12 -#define EAP_AKA_SUBTYPE_REAUTHENTICATION 13 -#define EAP_AKA_SUBTYPE_CLIENT_ERROR 14 - -/* AT_CLIENT_ERROR_CODE error codes */ -#define EAP_AKA_UNABLE_TO_PROCESS_PACKET 0 - -#define EAP_AKA_RAND_LEN 16 -#define EAP_AKA_AUTN_LEN 16 -#define EAP_AKA_AUTS_LEN 14 -#define EAP_AKA_RES_MAX_LEN 16 -#define EAP_AKA_IK_LEN 16 -#define EAP_AKA_CK_LEN 16 -#define EAP_AKA_MAX_FAST_REAUTHS 1000 -#define EAP_AKA_MIN_RES_LEN 4 -#define EAP_AKA_MAX_RES_LEN 16 -#define EAP_AKA_CHECKCODE_LEN 20 - -#define EAP_AKA_PRIME_K_AUT_LEN 32 -#define EAP_AKA_PRIME_CHECKCODE_LEN 32 -#define EAP_AKA_PRIME_K_RE_LEN 32 - -struct wpabuf; - -void eap_sim_derive_mk(const u8 *identity, size_t identity_len, - const u8 *nonce_mt, u16 selected_version, - const u8 *ver_list, size_t ver_list_len, - int num_chal, const u8 *kc, u8 *mk); -void eap_aka_derive_mk(const u8 *identity, size_t identity_len, - const u8 *ik, const u8 *ck, u8 *mk); -int eap_sim_derive_keys(const u8 *mk, u8 *k_encr, u8 *k_aut, u8 *msk, - u8 *emsk); -int eap_sim_derive_keys_reauth(u16 _counter, - const u8 *identity, size_t identity_len, - const u8 *nonce_s, const u8 *mk, u8 *msk, - u8 *emsk); -int eap_sim_verify_mac(const u8 *k_aut, const struct wpabuf *req, - const u8 *mac, const u8 *extra, size_t extra_len); -void eap_sim_add_mac(const u8 *k_aut, const u8 *msg, size_t msg_len, u8 *mac, - const u8 *extra, size_t extra_len); - -#if defined(EAP_AKA_PRIME) || defined(EAP_SERVER_AKA_PRIME) -void eap_aka_prime_derive_keys(const u8 *identity, size_t identity_len, - const u8 *ik, const u8 *ck, u8 *k_encr, - u8 *k_aut, u8 *k_re, u8 *msk, u8 *emsk); -int eap_aka_prime_derive_keys_reauth(const u8 *k_re, u16 counter, - const u8 *identity, size_t identity_len, - const u8 *nonce_s, u8 *msk, u8 *emsk); -int eap_sim_verify_mac_sha256(const u8 *k_aut, const struct wpabuf *req, - const u8 *mac, const u8 *extra, - size_t extra_len); -void eap_sim_add_mac_sha256(const u8 *k_aut, const u8 *msg, size_t msg_len, - u8 *mac, const u8 *extra, size_t extra_len); - -void eap_aka_prime_derive_ck_ik_prime(u8 *ck, u8 *ik, const u8 *sqn_ak, - const u8 *network_name, - size_t network_name_len); -#else /* EAP_AKA_PRIME || EAP_SERVER_AKA_PRIME */ -static inline void eap_aka_prime_derive_keys(const u8 *identity, - size_t identity_len, - const u8 *ik, const u8 *ck, - u8 *k_encr, u8 *k_aut, u8 *k_re, - u8 *msk, u8 *emsk) -{ -} - -static inline int eap_aka_prime_derive_keys_reauth(const u8 *k_re, u16 counter, - const u8 *identity, - size_t identity_len, - const u8 *nonce_s, u8 *msk, - u8 *emsk) -{ - return -1; -} - -static inline int eap_sim_verify_mac_sha256(const u8 *k_aut, - const struct wpabuf *req, - const u8 *mac, const u8 *extra, - size_t extra_len) -{ - return -1; -} -#endif /* EAP_AKA_PRIME || EAP_SERVER_AKA_PRIME */ - - -/* EAP-SIM/AKA Attributes (0..127 non-skippable) */ -#define EAP_SIM_AT_RAND 1 -#define EAP_SIM_AT_AUTN 2 /* only AKA */ -#define EAP_SIM_AT_RES 3 /* only AKA, only peer->server */ -#define EAP_SIM_AT_AUTS 4 /* only AKA, only peer->server */ -#define EAP_SIM_AT_PADDING 6 /* only encrypted */ -#define EAP_SIM_AT_NONCE_MT 7 /* only SIM, only send */ -#define EAP_SIM_AT_PERMANENT_ID_REQ 10 -#define EAP_SIM_AT_MAC 11 -#define EAP_SIM_AT_NOTIFICATION 12 -#define EAP_SIM_AT_ANY_ID_REQ 13 -#define EAP_SIM_AT_IDENTITY 14 /* only send */ -#define EAP_SIM_AT_VERSION_LIST 15 /* only SIM */ -#define EAP_SIM_AT_SELECTED_VERSION 16 /* only SIM */ -#define EAP_SIM_AT_FULLAUTH_ID_REQ 17 -#define EAP_SIM_AT_COUNTER 19 /* only encrypted */ -#define EAP_SIM_AT_COUNTER_TOO_SMALL 20 /* only encrypted */ -#define EAP_SIM_AT_NONCE_S 21 /* only encrypted */ -#define EAP_SIM_AT_CLIENT_ERROR_CODE 22 /* only send */ -#define EAP_SIM_AT_KDF_INPUT 23 /* only AKA' */ -#define EAP_SIM_AT_KDF 24 /* only AKA' */ -#define EAP_SIM_AT_IV 129 -#define EAP_SIM_AT_ENCR_DATA 130 -#define EAP_SIM_AT_NEXT_PSEUDONYM 132 /* only encrypted */ -#define EAP_SIM_AT_NEXT_REAUTH_ID 133 /* only encrypted */ -#define EAP_SIM_AT_CHECKCODE 134 /* only AKA */ -#define EAP_SIM_AT_RESULT_IND 135 -#define EAP_SIM_AT_BIDDING 136 - -/* AT_NOTIFICATION notification code values */ -#define EAP_SIM_GENERAL_FAILURE_AFTER_AUTH 0 -#define EAP_SIM_TEMPORARILY_DENIED 1026 -#define EAP_SIM_NOT_SUBSCRIBED 1031 -#define EAP_SIM_GENERAL_FAILURE_BEFORE_AUTH 16384 -#define EAP_SIM_SUCCESS 32768 - -/* EAP-AKA' AT_KDF Key Derivation Function values */ -#define EAP_AKA_PRIME_KDF 1 - -/* AT_BIDDING flags */ -#define EAP_AKA_BIDDING_FLAG_D 0x8000 - - -enum eap_sim_id_req { - NO_ID_REQ, ANY_ID, FULLAUTH_ID, PERMANENT_ID -}; - - -struct eap_sim_attrs { - const u8 *rand, *autn, *mac, *iv, *encr_data, *version_list, *nonce_s; - const u8 *next_pseudonym, *next_reauth_id; - const u8 *nonce_mt, *identity, *res, *auts; - const u8 *checkcode; - const u8 *kdf_input; - const u8 *bidding; - size_t num_chal, version_list_len, encr_data_len; - size_t next_pseudonym_len, next_reauth_id_len, identity_len, res_len; - size_t res_len_bits; - size_t checkcode_len; - size_t kdf_input_len; - enum eap_sim_id_req id_req; - int notification, counter, selected_version, client_error_code; - int counter_too_small; - int result_ind; -#define EAP_AKA_PRIME_KDF_MAX 10 - u16 kdf[EAP_AKA_PRIME_KDF_MAX]; - size_t kdf_count; -}; - -int eap_sim_parse_attr(const u8 *start, const u8 *end, - struct eap_sim_attrs *attr, int aka, int encr); -u8 * eap_sim_parse_encr(const u8 *k_encr, const u8 *encr_data, - size_t encr_data_len, const u8 *iv, - struct eap_sim_attrs *attr, int aka); - - -struct eap_sim_msg; - -struct eap_sim_msg * eap_sim_msg_init(int code, int id, int type, int subtype); -struct wpabuf * eap_sim_msg_finish(struct eap_sim_msg *msg, const u8 *k_aut, - const u8 *extra, size_t extra_len); -void eap_sim_msg_free(struct eap_sim_msg *msg); -u8 * eap_sim_msg_add_full(struct eap_sim_msg *msg, u8 attr, - const u8 *data, size_t len); -u8 * eap_sim_msg_add(struct eap_sim_msg *msg, u8 attr, - u16 value, const u8 *data, size_t len); -u8 * eap_sim_msg_add_mac(struct eap_sim_msg *msg, u8 attr); -int eap_sim_msg_add_encr_start(struct eap_sim_msg *msg, u8 attr_iv, - u8 attr_encr); -int eap_sim_msg_add_encr_end(struct eap_sim_msg *msg, u8 *k_encr, - int attr_pad); - -void eap_sim_report_notification(void *msg_ctx, int notification, int aka); - -#endif /* EAP_SIM_COMMON_H */ diff --git a/hostapd-0.8/src/eap_common/eap_tlv_common.h b/hostapd-0.8/src/eap_common/eap_tlv_common.h deleted file mode 100644 index f86015d..0000000 --- a/hostapd-0.8/src/eap_common/eap_tlv_common.h +++ /dev/null @@ -1,118 +0,0 @@ -/* - * EAP-TLV definitions (draft-josefsson-pppext-eap-tls-eap-10.txt) - * Copyright (c) 2004-2008, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#ifndef EAP_TLV_COMMON_H -#define EAP_TLV_COMMON_H - -/* EAP-TLV TLVs (draft-josefsson-ppext-eap-tls-eap-10.txt) */ -#define EAP_TLV_RESULT_TLV 3 /* Acknowledged Result */ -#define EAP_TLV_NAK_TLV 4 -#define EAP_TLV_ERROR_CODE_TLV 5 -#define EAP_TLV_CONNECTION_BINDING_TLV 6 -#define EAP_TLV_VENDOR_SPECIFIC_TLV 7 -#define EAP_TLV_URI_TLV 8 -#define EAP_TLV_EAP_PAYLOAD_TLV 9 -#define EAP_TLV_INTERMEDIATE_RESULT_TLV 10 -#define EAP_TLV_PAC_TLV 11 /* RFC 5422, Section 4.2 */ -#define EAP_TLV_CRYPTO_BINDING_TLV 12 -#define EAP_TLV_CALLING_STATION_ID_TLV 13 -#define EAP_TLV_CALLED_STATION_ID_TLV 14 -#define EAP_TLV_NAS_PORT_TYPE_TLV 15 -#define EAP_TLV_SERVER_IDENTIFIER_TLV 16 -#define EAP_TLV_IDENTITY_TYPE_TLV 17 -#define EAP_TLV_SERVER_TRUSTED_ROOT_TLV 18 -#define EAP_TLV_REQUEST_ACTION_TLV 19 -#define EAP_TLV_PKCS7_TLV 20 - -#define EAP_TLV_RESULT_SUCCESS 1 -#define EAP_TLV_RESULT_FAILURE 2 - -#define EAP_TLV_TYPE_MANDATORY 0x8000 -#define EAP_TLV_TYPE_MASK 0x3fff - -#ifdef _MSC_VER -#pragma pack(push, 1) -#endif /* _MSC_VER */ - -struct eap_tlv_hdr { - be16 tlv_type; - be16 length; -} STRUCT_PACKED; - -struct eap_tlv_nak_tlv { - be16 tlv_type; - be16 length; - be32 vendor_id; - be16 nak_type; -} STRUCT_PACKED; - -struct eap_tlv_result_tlv { - be16 tlv_type; - be16 length; - be16 status; -} STRUCT_PACKED; - -/* RFC 4851, Section 4.2.7 - Intermediate-Result TLV */ -struct eap_tlv_intermediate_result_tlv { - be16 tlv_type; - be16 length; - be16 status; - /* Followed by optional TLVs */ -} STRUCT_PACKED; - -/* RFC 4851, Section 4.2.8 - Crypto-Binding TLV */ -struct eap_tlv_crypto_binding_tlv { - be16 tlv_type; - be16 length; - u8 reserved; - u8 version; - u8 received_version; - u8 subtype; - u8 nonce[32]; - u8 compound_mac[20]; -} STRUCT_PACKED; - -struct eap_tlv_pac_ack_tlv { - be16 tlv_type; - be16 length; - be16 pac_type; - be16 pac_len; - be16 result; -} STRUCT_PACKED; - -/* RFC 4851, Section 4.2.9 - Request-Action TLV */ -struct eap_tlv_request_action_tlv { - be16 tlv_type; - be16 length; - be16 action; -} STRUCT_PACKED; - -/* RFC 5422, Section 4.2.6 - PAC-Type TLV */ -struct eap_tlv_pac_type_tlv { - be16 tlv_type; /* PAC_TYPE_PAC_TYPE */ - be16 length; - be16 pac_type; -} STRUCT_PACKED; - -#ifdef _MSC_VER -#pragma pack(pop) -#endif /* _MSC_VER */ - -#define EAP_TLV_CRYPTO_BINDING_SUBTYPE_REQUEST 0 -#define EAP_TLV_CRYPTO_BINDING_SUBTYPE_RESPONSE 1 - -#define EAP_TLV_ACTION_PROCESS_TLV 1 -#define EAP_TLV_ACTION_NEGOTIATE_EAP 2 - -#endif /* EAP_TLV_COMMON_H */ diff --git a/hostapd-0.8/src/eap_common/eap_ttls.h b/hostapd-0.8/src/eap_common/eap_ttls.h deleted file mode 100644 index 797d084..0000000 --- a/hostapd-0.8/src/eap_common/eap_ttls.h +++ /dev/null @@ -1,71 +0,0 @@ -/* - * EAP server/peer: EAP-TTLS (RFC 5281) - * Copyright (c) 2004-2007, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#ifndef EAP_TTLS_H -#define EAP_TTLS_H - -struct ttls_avp { - be32 avp_code; - be32 avp_length; /* 8-bit flags, 24-bit length; - * length includes AVP header */ - /* optional 32-bit Vendor-ID */ - /* Data */ -}; - -struct ttls_avp_vendor { - be32 avp_code; - be32 avp_length; /* 8-bit flags, 24-bit length; - * length includes AVP header */ - be32 vendor_id; - /* Data */ -}; - -#define AVP_FLAGS_VENDOR 0x80 -#define AVP_FLAGS_MANDATORY 0x40 - -#define AVP_PAD(start, pos) \ -do { \ - int __pad; \ - __pad = (4 - (((pos) - (start)) & 3)) & 3; \ - os_memset((pos), 0, __pad); \ - pos += __pad; \ -} while (0) - - -/* RFC 2865 */ -#define RADIUS_ATTR_USER_NAME 1 -#define RADIUS_ATTR_USER_PASSWORD 2 -#define RADIUS_ATTR_CHAP_PASSWORD 3 -#define RADIUS_ATTR_REPLY_MESSAGE 18 -#define RADIUS_ATTR_CHAP_CHALLENGE 60 -#define RADIUS_ATTR_EAP_MESSAGE 79 - -/* RFC 2548 */ -#define RADIUS_VENDOR_ID_MICROSOFT 311 -#define RADIUS_ATTR_MS_CHAP_RESPONSE 1 -#define RADIUS_ATTR_MS_CHAP_ERROR 2 -#define RADIUS_ATTR_MS_CHAP_NT_ENC_PW 6 -#define RADIUS_ATTR_MS_CHAP_CHALLENGE 11 -#define RADIUS_ATTR_MS_CHAP2_RESPONSE 25 -#define RADIUS_ATTR_MS_CHAP2_SUCCESS 26 -#define RADIUS_ATTR_MS_CHAP2_CPW 27 - -#define EAP_TTLS_MSCHAPV2_CHALLENGE_LEN 16 -#define EAP_TTLS_MSCHAPV2_RESPONSE_LEN 50 -#define EAP_TTLS_MSCHAP_CHALLENGE_LEN 8 -#define EAP_TTLS_MSCHAP_RESPONSE_LEN 50 -#define EAP_TTLS_CHAP_CHALLENGE_LEN 16 -#define EAP_TTLS_CHAP_PASSWORD_LEN 16 - -#endif /* EAP_TTLS_H */ diff --git a/hostapd-0.8/src/eap_common/eap_wsc_common.c b/hostapd-0.8/src/eap_common/eap_wsc_common.c deleted file mode 100644 index 5d4e8cc..0000000 --- a/hostapd-0.8/src/eap_common/eap_wsc_common.c +++ /dev/null @@ -1,39 +0,0 @@ -/* - * EAP-WSC common routines for Wi-Fi Protected Setup - * Copyright (c) 2007, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#include "includes.h" - -#include "common.h" -#include "eap_defs.h" -#include "eap_common.h" -#include "wps/wps.h" -#include "eap_wsc_common.h" - -struct wpabuf * eap_wsc_build_frag_ack(u8 id, u8 code) -{ - struct wpabuf *msg; - - msg = eap_msg_alloc(EAP_VENDOR_WFA, EAP_VENDOR_TYPE_WSC, 2, code, id); - if (msg == NULL) { - wpa_printf(MSG_ERROR, "EAP-WSC: Failed to allocate memory for " - "FRAG_ACK"); - return NULL; - } - - wpa_printf(MSG_DEBUG, "EAP-WSC: Send WSC/FRAG_ACK"); - wpabuf_put_u8(msg, WSC_FRAG_ACK); /* Op-Code */ - wpabuf_put_u8(msg, 0); /* Flags */ - - return msg; -} diff --git a/hostapd-0.8/src/eap_common/eap_wsc_common.h b/hostapd-0.8/src/eap_common/eap_wsc_common.h deleted file mode 100644 index fdf61d3..0000000 --- a/hostapd-0.8/src/eap_common/eap_wsc_common.h +++ /dev/null @@ -1,33 +0,0 @@ -/* - * EAP-WSC definitions for Wi-Fi Protected Setup - * Copyright (c) 2007, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#ifndef EAP_WSC_COMMON_H -#define EAP_WSC_COMMON_H - -#define EAP_VENDOR_TYPE_WSC 1 - -#define WSC_FLAGS_MF 0x01 -#define WSC_FLAGS_LF 0x02 - -#define WSC_ID_REGISTRAR "WFA-SimpleConfig-Registrar-1-0" -#define WSC_ID_REGISTRAR_LEN 30 -#define WSC_ID_ENROLLEE "WFA-SimpleConfig-Enrollee-1-0" -#define WSC_ID_ENROLLEE_LEN 29 - -#define WSC_FRAGMENT_SIZE 1400 - - -struct wpabuf * eap_wsc_build_frag_ack(u8 id, u8 code); - -#endif /* EAP_WSC_COMMON_H */ diff --git a/hostapd-0.8/src/eap_common/ikev2_common.c b/hostapd-0.8/src/eap_common/ikev2_common.c deleted file mode 100644 index 003c288..0000000 --- a/hostapd-0.8/src/eap_common/ikev2_common.c +++ /dev/null @@ -1,797 +0,0 @@ -/* - * IKEv2 common routines for initiator and responder - * Copyright (c) 2007, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#include "includes.h" - -#include "common.h" -#include "crypto/crypto.h" -#include "crypto/md5.h" -#include "crypto/sha1.h" -#include "crypto/random.h" -#include "ikev2_common.h" - - -static struct ikev2_integ_alg ikev2_integ_algs[] = { - { AUTH_HMAC_SHA1_96, 20, 12 }, - { AUTH_HMAC_MD5_96, 16, 12 } -}; - -#define NUM_INTEG_ALGS (sizeof(ikev2_integ_algs) / sizeof(ikev2_integ_algs[0])) - - -static struct ikev2_prf_alg ikev2_prf_algs[] = { - { PRF_HMAC_SHA1, 20, 20 }, - { PRF_HMAC_MD5, 16, 16 } -}; - -#define NUM_PRF_ALGS (sizeof(ikev2_prf_algs) / sizeof(ikev2_prf_algs[0])) - - -static struct ikev2_encr_alg ikev2_encr_algs[] = { - { ENCR_AES_CBC, 16, 16 }, /* only 128-bit keys supported for now */ - { ENCR_3DES, 24, 8 } -}; - -#define NUM_ENCR_ALGS (sizeof(ikev2_encr_algs) / sizeof(ikev2_encr_algs[0])) - - -const struct ikev2_integ_alg * ikev2_get_integ(int id) -{ - size_t i; - - for (i = 0; i < NUM_INTEG_ALGS; i++) { - if (ikev2_integ_algs[i].id == id) - return &ikev2_integ_algs[i]; - } - - return NULL; -} - - -int ikev2_integ_hash(int alg, const u8 *key, size_t key_len, const u8 *data, - size_t data_len, u8 *hash) -{ - u8 tmphash[IKEV2_MAX_HASH_LEN]; - - switch (alg) { - case AUTH_HMAC_SHA1_96: - if (key_len != 20) - return -1; - hmac_sha1(key, key_len, data, data_len, tmphash); - os_memcpy(hash, tmphash, 12); - break; - case AUTH_HMAC_MD5_96: - if (key_len != 16) - return -1; - hmac_md5(key, key_len, data, data_len, tmphash); - os_memcpy(hash, tmphash, 12); - break; - default: - return -1; - } - - return 0; -} - - -const struct ikev2_prf_alg * ikev2_get_prf(int id) -{ - size_t i; - - for (i = 0; i < NUM_PRF_ALGS; i++) { - if (ikev2_prf_algs[i].id == id) - return &ikev2_prf_algs[i]; - } - - return NULL; -} - - -int ikev2_prf_hash(int alg, const u8 *key, size_t key_len, - size_t num_elem, const u8 *addr[], const size_t *len, - u8 *hash) -{ - switch (alg) { - case PRF_HMAC_SHA1: - hmac_sha1_vector(key, key_len, num_elem, addr, len, hash); - break; - case PRF_HMAC_MD5: - hmac_md5_vector(key, key_len, num_elem, addr, len, hash); - break; - default: - return -1; - } - - return 0; -} - - -int ikev2_prf_plus(int alg, const u8 *key, size_t key_len, - const u8 *data, size_t data_len, - u8 *out, size_t out_len) -{ - u8 hash[IKEV2_MAX_HASH_LEN]; - size_t hash_len; - u8 iter, *pos, *end; - const u8 *addr[3]; - size_t len[3]; - const struct ikev2_prf_alg *prf; - int res; - - prf = ikev2_get_prf(alg); - if (prf == NULL) - return -1; - hash_len = prf->hash_len; - - addr[0] = hash; - len[0] = hash_len; - addr[1] = data; - len[1] = data_len; - addr[2] = &iter; - len[2] = 1; - - pos = out; - end = out + out_len; - iter = 1; - while (pos < end) { - size_t clen; - if (iter == 1) - res = ikev2_prf_hash(alg, key, key_len, 2, &addr[1], - &len[1], hash); - else - res = ikev2_prf_hash(alg, key, key_len, 3, addr, len, - hash); - if (res < 0) - return -1; - clen = hash_len; - if ((int) clen > end - pos) - clen = end - pos; - os_memcpy(pos, hash, clen); - pos += clen; - iter++; - } - - return 0; -} - - -const struct ikev2_encr_alg * ikev2_get_encr(int id) -{ - size_t i; - - for (i = 0; i < NUM_ENCR_ALGS; i++) { - if (ikev2_encr_algs[i].id == id) - return &ikev2_encr_algs[i]; - } - - return NULL; -} - - -#ifdef CCNS_PL -/* from des.c */ -struct des3_key_s { - u32 ek[3][32]; - u32 dk[3][32]; -}; - -void des3_key_setup(const u8 *key, struct des3_key_s *dkey); -void des3_encrypt(const u8 *plain, const struct des3_key_s *key, u8 *crypt); -void des3_decrypt(const u8 *crypt, const struct des3_key_s *key, u8 *plain); -#endif /* CCNS_PL */ - - -int ikev2_encr_encrypt(int alg, const u8 *key, size_t key_len, const u8 *iv, - const u8 *plain, u8 *crypt, size_t len) -{ - struct crypto_cipher *cipher; - int encr_alg; - -#ifdef CCNS_PL - if (alg == ENCR_3DES) { - struct des3_key_s des3key; - size_t i, blocks; - u8 *pos; - - /* ECB mode is used incorrectly for 3DES!? */ - if (key_len != 24) { - wpa_printf(MSG_INFO, "IKEV2: Invalid encr key length"); - return -1; - } - des3_key_setup(key, &des3key); - - blocks = len / 8; - pos = crypt; - for (i = 0; i < blocks; i++) { - des3_encrypt(pos, &des3key, pos); - pos += 8; - } - } else { -#endif /* CCNS_PL */ - switch (alg) { - case ENCR_3DES: - encr_alg = CRYPTO_CIPHER_ALG_3DES; - break; - case ENCR_AES_CBC: - encr_alg = CRYPTO_CIPHER_ALG_AES; - break; - default: - wpa_printf(MSG_DEBUG, "IKEV2: Unsupported encr alg %d", alg); - return -1; - } - - cipher = crypto_cipher_init(encr_alg, iv, key, key_len); - if (cipher == NULL) { - wpa_printf(MSG_INFO, "IKEV2: Failed to initialize cipher"); - return -1; - } - - if (crypto_cipher_encrypt(cipher, plain, crypt, len) < 0) { - wpa_printf(MSG_INFO, "IKEV2: Encryption failed"); - crypto_cipher_deinit(cipher); - return -1; - } - crypto_cipher_deinit(cipher); -#ifdef CCNS_PL - } -#endif /* CCNS_PL */ - - return 0; -} - - -int ikev2_encr_decrypt(int alg, const u8 *key, size_t key_len, const u8 *iv, - const u8 *crypt, u8 *plain, size_t len) -{ - struct crypto_cipher *cipher; - int encr_alg; - -#ifdef CCNS_PL - if (alg == ENCR_3DES) { - struct des3_key_s des3key; - size_t i, blocks; - - /* ECB mode is used incorrectly for 3DES!? */ - if (key_len != 24) { - wpa_printf(MSG_INFO, "IKEV2: Invalid encr key length"); - return -1; - } - des3_key_setup(key, &des3key); - - if (len % 8) { - wpa_printf(MSG_INFO, "IKEV2: Invalid encrypted " - "length"); - return -1; - } - blocks = len / 8; - for (i = 0; i < blocks; i++) { - des3_decrypt(crypt, &des3key, plain); - plain += 8; - crypt += 8; - } - } else { -#endif /* CCNS_PL */ - switch (alg) { - case ENCR_3DES: - encr_alg = CRYPTO_CIPHER_ALG_3DES; - break; - case ENCR_AES_CBC: - encr_alg = CRYPTO_CIPHER_ALG_AES; - break; - default: - wpa_printf(MSG_DEBUG, "IKEV2: Unsupported encr alg %d", alg); - return -1; - } - - cipher = crypto_cipher_init(encr_alg, iv, key, key_len); - if (cipher == NULL) { - wpa_printf(MSG_INFO, "IKEV2: Failed to initialize cipher"); - return -1; - } - - if (crypto_cipher_decrypt(cipher, crypt, plain, len) < 0) { - wpa_printf(MSG_INFO, "IKEV2: Decryption failed"); - crypto_cipher_deinit(cipher); - return -1; - } - crypto_cipher_deinit(cipher); -#ifdef CCNS_PL - } -#endif /* CCNS_PL */ - - return 0; -} - - -int ikev2_parse_payloads(struct ikev2_payloads *payloads, - u8 next_payload, const u8 *pos, const u8 *end) -{ - const struct ikev2_payload_hdr *phdr; - - os_memset(payloads, 0, sizeof(*payloads)); - - while (next_payload != IKEV2_PAYLOAD_NO_NEXT_PAYLOAD) { - int plen, pdatalen; - const u8 *pdata; - wpa_printf(MSG_DEBUG, "IKEV2: Processing payload %u", - next_payload); - if (end - pos < (int) sizeof(*phdr)) { - wpa_printf(MSG_INFO, "IKEV2: Too short message for " - "payload header (left=%ld)", - (long) (end - pos)); - } - phdr = (const struct ikev2_payload_hdr *) pos; - plen = WPA_GET_BE16(phdr->payload_length); - if (plen < (int) sizeof(*phdr) || pos + plen > end) { - wpa_printf(MSG_INFO, "IKEV2: Invalid payload header " - "length %d", plen); - return -1; - } - - wpa_printf(MSG_DEBUG, "IKEV2: Next Payload: %u Flags: 0x%x" - " Payload Length: %d", - phdr->next_payload, phdr->flags, plen); - - pdata = (const u8 *) (phdr + 1); - pdatalen = plen - sizeof(*phdr); - - switch (next_payload) { - case IKEV2_PAYLOAD_SA: - wpa_printf(MSG_DEBUG, "IKEV2: Payload: Security " - "Association"); - payloads->sa = pdata; - payloads->sa_len = pdatalen; - break; - case IKEV2_PAYLOAD_KEY_EXCHANGE: - wpa_printf(MSG_DEBUG, "IKEV2: Payload: Key " - "Exchange"); - payloads->ke = pdata; - payloads->ke_len = pdatalen; - break; - case IKEV2_PAYLOAD_IDi: - wpa_printf(MSG_DEBUG, "IKEV2: Payload: IDi"); - payloads->idi = pdata; - payloads->idi_len = pdatalen; - break; - case IKEV2_PAYLOAD_IDr: - wpa_printf(MSG_DEBUG, "IKEV2: Payload: IDr"); - payloads->idr = pdata; - payloads->idr_len = pdatalen; - break; - case IKEV2_PAYLOAD_CERTIFICATE: - wpa_printf(MSG_DEBUG, "IKEV2: Payload: Certificate"); - payloads->cert = pdata; - payloads->cert_len = pdatalen; - break; - case IKEV2_PAYLOAD_AUTHENTICATION: - wpa_printf(MSG_DEBUG, "IKEV2: Payload: " - "Authentication"); - payloads->auth = pdata; - payloads->auth_len = pdatalen; - break; - case IKEV2_PAYLOAD_NONCE: - wpa_printf(MSG_DEBUG, "IKEV2: Payload: Nonce"); - payloads->nonce = pdata; - payloads->nonce_len = pdatalen; - break; - case IKEV2_PAYLOAD_ENCRYPTED: - wpa_printf(MSG_DEBUG, "IKEV2: Payload: Encrypted"); - payloads->encrypted = pdata; - payloads->encrypted_len = pdatalen; - break; - case IKEV2_PAYLOAD_NOTIFICATION: - wpa_printf(MSG_DEBUG, "IKEV2: Payload: " - "Notification"); - payloads->notification = pdata; - payloads->notification_len = pdatalen; - break; - default: - if (phdr->flags & IKEV2_PAYLOAD_FLAGS_CRITICAL) { - wpa_printf(MSG_INFO, "IKEV2: Unsupported " - "critical payload %u - reject the " - "entire message", next_payload); - return -1; - } else { - wpa_printf(MSG_DEBUG, "IKEV2: Skipped " - "unsupported payload %u", - next_payload); - } - } - - if (next_payload == IKEV2_PAYLOAD_ENCRYPTED && - pos + plen == end) { - /* - * Next Payload in the case of Encrypted Payload is - * actually the payload type for the first embedded - * payload. - */ - payloads->encr_next_payload = phdr->next_payload; - next_payload = IKEV2_PAYLOAD_NO_NEXT_PAYLOAD; - } else - next_payload = phdr->next_payload; - - pos += plen; - } - - if (pos != end) { - wpa_printf(MSG_INFO, "IKEV2: Unexpected extra data after " - "payloads"); - return -1; - } - - return 0; -} - - -int ikev2_derive_auth_data(int prf_alg, const struct wpabuf *sign_msg, - const u8 *ID, size_t ID_len, u8 ID_type, - struct ikev2_keys *keys, int initiator, - const u8 *shared_secret, size_t shared_secret_len, - const u8 *nonce, size_t nonce_len, - const u8 *key_pad, size_t key_pad_len, - u8 *auth_data) -{ - size_t sign_len, buf_len; - u8 *sign_data, *pos, *buf, hash[IKEV2_MAX_HASH_LEN]; - const struct ikev2_prf_alg *prf; - const u8 *SK_p = initiator ? keys->SK_pi : keys->SK_pr; - - prf = ikev2_get_prf(prf_alg); - if (sign_msg == NULL || ID == NULL || SK_p == NULL || - shared_secret == NULL || nonce == NULL || prf == NULL) - return -1; - - /* prf(SK_pi/r,IDi/r') */ - buf_len = 4 + ID_len; - buf = os_zalloc(buf_len); - if (buf == NULL) - return -1; - buf[0] = ID_type; - os_memcpy(buf + 4, ID, ID_len); - if (ikev2_prf_hash(prf->id, SK_p, keys->SK_prf_len, - 1, (const u8 **) &buf, &buf_len, hash) < 0) { - os_free(buf); - return -1; - } - os_free(buf); - - /* sign_data = msg | Nr/i | prf(SK_pi/r,IDi/r') */ - sign_len = wpabuf_len(sign_msg) + nonce_len + prf->hash_len; - sign_data = os_malloc(sign_len); - if (sign_data == NULL) - return -1; - pos = sign_data; - os_memcpy(pos, wpabuf_head(sign_msg), wpabuf_len(sign_msg)); - pos += wpabuf_len(sign_msg); - os_memcpy(pos, nonce, nonce_len); - pos += nonce_len; - os_memcpy(pos, hash, prf->hash_len); - - /* AUTH = prf(prf(Shared Secret, key pad, sign_data) */ - if (ikev2_prf_hash(prf->id, shared_secret, shared_secret_len, 1, - &key_pad, &key_pad_len, hash) < 0 || - ikev2_prf_hash(prf->id, hash, prf->hash_len, 1, - (const u8 **) &sign_data, &sign_len, auth_data) < 0) - { - os_free(sign_data); - return -1; - } - os_free(sign_data); - - return 0; -} - - -u8 * ikev2_decrypt_payload(int encr_id, int integ_id, - struct ikev2_keys *keys, int initiator, - const struct ikev2_hdr *hdr, - const u8 *encrypted, size_t encrypted_len, - size_t *res_len) -{ - size_t iv_len; - const u8 *pos, *end, *iv, *integ; - u8 hash[IKEV2_MAX_HASH_LEN], *decrypted; - size_t decrypted_len, pad_len; - const struct ikev2_integ_alg *integ_alg; - const struct ikev2_encr_alg *encr_alg; - const u8 *SK_e = initiator ? keys->SK_ei : keys->SK_er; - const u8 *SK_a = initiator ? keys->SK_ai : keys->SK_ar; - - if (encrypted == NULL) { - wpa_printf(MSG_INFO, "IKEV2: No Encrypted payload in SA_AUTH"); - return NULL; - } - - encr_alg = ikev2_get_encr(encr_id); - if (encr_alg == NULL) { - wpa_printf(MSG_INFO, "IKEV2: Unsupported encryption type"); - return NULL; - } - iv_len = encr_alg->block_size; - - integ_alg = ikev2_get_integ(integ_id); - if (integ_alg == NULL) { - wpa_printf(MSG_INFO, "IKEV2: Unsupported intergrity type"); - return NULL; - } - - if (encrypted_len < iv_len + 1 + integ_alg->hash_len) { - wpa_printf(MSG_INFO, "IKEV2: No room for IV or Integrity " - "Checksum"); - return NULL; - } - - iv = encrypted; - pos = iv + iv_len; - end = encrypted + encrypted_len; - integ = end - integ_alg->hash_len; - - if (SK_a == NULL) { - wpa_printf(MSG_INFO, "IKEV2: No SK_a available"); - return NULL; - } - if (ikev2_integ_hash(integ_id, SK_a, keys->SK_integ_len, - (const u8 *) hdr, - integ - (const u8 *) hdr, hash) < 0) { - wpa_printf(MSG_INFO, "IKEV2: Failed to calculate integrity " - "hash"); - return NULL; - } - if (os_memcmp(integ, hash, integ_alg->hash_len) != 0) { - wpa_printf(MSG_INFO, "IKEV2: Incorrect Integrity Checksum " - "Data"); - return NULL; - } - - if (SK_e == NULL) { - wpa_printf(MSG_INFO, "IKEV2: No SK_e available"); - return NULL; - } - - decrypted_len = integ - pos; - decrypted = os_malloc(decrypted_len); - if (decrypted == NULL) - return NULL; - - if (ikev2_encr_decrypt(encr_alg->id, SK_e, keys->SK_encr_len, iv, pos, - decrypted, decrypted_len) < 0) { - os_free(decrypted); - return NULL; - } - - pad_len = decrypted[decrypted_len - 1]; - if (decrypted_len < pad_len + 1) { - wpa_printf(MSG_INFO, "IKEV2: Invalid padding in encrypted " - "payload"); - os_free(decrypted); - return NULL; - } - - decrypted_len -= pad_len + 1; - - *res_len = decrypted_len; - return decrypted; -} - - -void ikev2_update_hdr(struct wpabuf *msg) -{ - struct ikev2_hdr *hdr; - - /* Update lenth field in HDR */ - hdr = wpabuf_mhead(msg); - WPA_PUT_BE32(hdr->length, wpabuf_len(msg)); -} - - -int ikev2_build_encrypted(int encr_id, int integ_id, struct ikev2_keys *keys, - int initiator, struct wpabuf *msg, - struct wpabuf *plain, u8 next_payload) -{ - struct ikev2_payload_hdr *phdr; - size_t plen; - size_t iv_len, pad_len; - u8 *icv, *iv; - const struct ikev2_integ_alg *integ_alg; - const struct ikev2_encr_alg *encr_alg; - const u8 *SK_e = initiator ? keys->SK_ei : keys->SK_er; - const u8 *SK_a = initiator ? keys->SK_ai : keys->SK_ar; - - wpa_printf(MSG_DEBUG, "IKEV2: Adding Encrypted payload"); - - /* Encr - RFC 4306, Sect. 3.14 */ - - encr_alg = ikev2_get_encr(encr_id); - if (encr_alg == NULL) { - wpa_printf(MSG_INFO, "IKEV2: Unsupported encryption type"); - return -1; - } - iv_len = encr_alg->block_size; - - integ_alg = ikev2_get_integ(integ_id); - if (integ_alg == NULL) { - wpa_printf(MSG_INFO, "IKEV2: Unsupported intergrity type"); - return -1; - } - - if (SK_e == NULL) { - wpa_printf(MSG_INFO, "IKEV2: No SK_e available"); - return -1; - } - - if (SK_a == NULL) { - wpa_printf(MSG_INFO, "IKEV2: No SK_a available"); - return -1; - } - - phdr = wpabuf_put(msg, sizeof(*phdr)); - phdr->next_payload = next_payload; - phdr->flags = 0; - - iv = wpabuf_put(msg, iv_len); - if (random_get_bytes(iv, iv_len)) { - wpa_printf(MSG_INFO, "IKEV2: Could not generate IV"); - return -1; - } - - pad_len = iv_len - (wpabuf_len(plain) + 1) % iv_len; - if (pad_len == iv_len) - pad_len = 0; - wpabuf_put(plain, pad_len); - wpabuf_put_u8(plain, pad_len); - - if (ikev2_encr_encrypt(encr_alg->id, SK_e, keys->SK_encr_len, iv, - wpabuf_head(plain), wpabuf_mhead(plain), - wpabuf_len(plain)) < 0) - return -1; - - wpabuf_put_buf(msg, plain); - - /* Need to update all headers (Length fields) prior to hash func */ - icv = wpabuf_put(msg, integ_alg->hash_len); - plen = (u8 *) wpabuf_put(msg, 0) - (u8 *) phdr; - WPA_PUT_BE16(phdr->payload_length, plen); - - ikev2_update_hdr(msg); - - return ikev2_integ_hash(integ_id, SK_a, keys->SK_integ_len, - wpabuf_head(msg), - wpabuf_len(msg) - integ_alg->hash_len, icv); - - return 0; -} - - -int ikev2_keys_set(struct ikev2_keys *keys) -{ - return keys->SK_d && keys->SK_ai && keys->SK_ar && keys->SK_ei && - keys->SK_er && keys->SK_pi && keys->SK_pr; -} - - -void ikev2_free_keys(struct ikev2_keys *keys) -{ - os_free(keys->SK_d); - os_free(keys->SK_ai); - os_free(keys->SK_ar); - os_free(keys->SK_ei); - os_free(keys->SK_er); - os_free(keys->SK_pi); - os_free(keys->SK_pr); - keys->SK_d = keys->SK_ai = keys->SK_ar = keys->SK_ei = keys->SK_er = - keys->SK_pi = keys->SK_pr = NULL; -} - - -int ikev2_derive_sk_keys(const struct ikev2_prf_alg *prf, - const struct ikev2_integ_alg *integ, - const struct ikev2_encr_alg *encr, - const u8 *skeyseed, const u8 *data, size_t data_len, - struct ikev2_keys *keys) -{ - u8 *keybuf, *pos; - size_t keybuf_len; - - /* - * {SK_d | SK_ai | SK_ar | SK_ei | SK_er | SK_pi | SK_pr } = - * prf+(SKEYSEED, Ni | Nr | SPIi | SPIr ) - */ - ikev2_free_keys(keys); - keys->SK_d_len = prf->key_len; - keys->SK_integ_len = integ->key_len; - keys->SK_encr_len = encr->key_len; - keys->SK_prf_len = prf->key_len; -#ifdef CCNS_PL - /* Uses encryption key length for SK_d; should be PRF length */ - keys->SK_d_len = keys->SK_encr_len; -#endif /* CCNS_PL */ - - keybuf_len = keys->SK_d_len + 2 * keys->SK_integ_len + - 2 * keys->SK_encr_len + 2 * keys->SK_prf_len; - keybuf = os_malloc(keybuf_len); - if (keybuf == NULL) - return -1; - - if (ikev2_prf_plus(prf->id, skeyseed, prf->hash_len, - data, data_len, keybuf, keybuf_len)) { - os_free(keybuf); - return -1; - } - - pos = keybuf; - - keys->SK_d = os_malloc(keys->SK_d_len); - if (keys->SK_d) { - os_memcpy(keys->SK_d, pos, keys->SK_d_len); - wpa_hexdump_key(MSG_DEBUG, "IKEV2: SK_d", - keys->SK_d, keys->SK_d_len); - } - pos += keys->SK_d_len; - - keys->SK_ai = os_malloc(keys->SK_integ_len); - if (keys->SK_ai) { - os_memcpy(keys->SK_ai, pos, keys->SK_integ_len); - wpa_hexdump_key(MSG_DEBUG, "IKEV2: SK_ai", - keys->SK_ai, keys->SK_integ_len); - } - pos += keys->SK_integ_len; - - keys->SK_ar = os_malloc(keys->SK_integ_len); - if (keys->SK_ar) { - os_memcpy(keys->SK_ar, pos, keys->SK_integ_len); - wpa_hexdump_key(MSG_DEBUG, "IKEV2: SK_ar", - keys->SK_ar, keys->SK_integ_len); - } - pos += keys->SK_integ_len; - - keys->SK_ei = os_malloc(keys->SK_encr_len); - if (keys->SK_ei) { - os_memcpy(keys->SK_ei, pos, keys->SK_encr_len); - wpa_hexdump_key(MSG_DEBUG, "IKEV2: SK_ei", - keys->SK_ei, keys->SK_encr_len); - } - pos += keys->SK_encr_len; - - keys->SK_er = os_malloc(keys->SK_encr_len); - if (keys->SK_er) { - os_memcpy(keys->SK_er, pos, keys->SK_encr_len); - wpa_hexdump_key(MSG_DEBUG, "IKEV2: SK_er", - keys->SK_er, keys->SK_encr_len); - } - pos += keys->SK_encr_len; - - keys->SK_pi = os_malloc(keys->SK_prf_len); - if (keys->SK_pi) { - os_memcpy(keys->SK_pi, pos, keys->SK_prf_len); - wpa_hexdump_key(MSG_DEBUG, "IKEV2: SK_pi", - keys->SK_pi, keys->SK_prf_len); - } - pos += keys->SK_prf_len; - - keys->SK_pr = os_malloc(keys->SK_prf_len); - if (keys->SK_pr) { - os_memcpy(keys->SK_pr, pos, keys->SK_prf_len); - wpa_hexdump_key(MSG_DEBUG, "IKEV2: SK_pr", - keys->SK_pr, keys->SK_prf_len); - } - - os_free(keybuf); - - if (!ikev2_keys_set(keys)) { - ikev2_free_keys(keys); - return -1; - } - - return 0; -} diff --git a/hostapd-0.8/src/eap_common/ikev2_common.h b/hostapd-0.8/src/eap_common/ikev2_common.h deleted file mode 100644 index c96a070..0000000 --- a/hostapd-0.8/src/eap_common/ikev2_common.h +++ /dev/null @@ -1,344 +0,0 @@ -/* - * IKEv2 definitions - * Copyright (c) 2007, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#ifndef IKEV2_COMMON_H -#define IKEV2_COMMON_H - -/* - * Nonce length must be at least 16 octets. It must also be at least half the - * key size of the negotiated PRF. - */ -#define IKEV2_NONCE_MIN_LEN 16 -#define IKEV2_NONCE_MAX_LEN 256 - -/* IKE Header - RFC 4306, Sect. 3.1 */ -#ifdef _MSC_VER -#pragma pack(push, 1) -#endif /* _MSC_VER */ - -#define IKEV2_SPI_LEN 8 - -struct ikev2_hdr { - u8 i_spi[IKEV2_SPI_LEN]; /* IKE_SA Initiator's SPI */ - u8 r_spi[IKEV2_SPI_LEN]; /* IKE_SA Responder's SPI */ - u8 next_payload; - u8 version; /* MjVer | MnVer */ - u8 exchange_type; - u8 flags; - u8 message_id[4]; - u8 length[4]; /* total length of HDR + payloads */ -} STRUCT_PACKED; - -struct ikev2_payload_hdr { - u8 next_payload; - u8 flags; - u8 payload_length[2]; /* this payload, including the payload header */ -} STRUCT_PACKED; - -struct ikev2_proposal { - u8 type; /* 0 (last) or 2 (more) */ - u8 reserved; - u8 proposal_length[2]; /* including all transform and attributes */ - u8 proposal_num; - u8 protocol_id; /* IKEV2_PROTOCOL_* */ - u8 spi_size; - u8 num_transforms; - /* SPI of spi_size octets */ - /* Transforms */ -} STRUCT_PACKED; - -struct ikev2_transform { - u8 type; /* 0 (last) or 3 (more) */ - u8 reserved; - u8 transform_length[2]; /* including Header and Attributes */ - u8 transform_type; - u8 reserved2; - u8 transform_id[2]; - /* Transform Attributes */ -} STRUCT_PACKED; - -#ifdef _MSC_VER -#pragma pack(pop) -#endif /* _MSC_VER */ - - -/* Current IKEv2 version from RFC 4306 */ -#define IKEV2_MjVer 2 -#define IKEV2_MnVer 0 -#ifdef CCNS_PL -#define IKEV2_VERSION ((IKEV2_MjVer) | ((IKEV2_MnVer) << 4)) -#else /* CCNS_PL */ -#define IKEV2_VERSION (((IKEV2_MjVer) << 4) | (IKEV2_MnVer)) -#endif /* CCNS_PL */ - -/* IKEv2 Exchange Types */ -enum { - /* 0-33 RESERVED */ - IKE_SA_INIT = 34, - IKE_SA_AUTH = 35, - CREATE_CHILD_SA = 36, - INFORMATION = 37 - /* 38-239 RESERVED TO IANA */ - /* 240-255 Reserved for private use */ -}; - -/* IKEv2 Flags */ -#define IKEV2_HDR_INITIATOR 0x08 -#define IKEV2_HDR_VERSION 0x10 -#define IKEV2_HDR_RESPONSE 0x20 - -/* Payload Header Flags */ -#define IKEV2_PAYLOAD_FLAGS_CRITICAL 0x01 - - -/* EAP-IKEv2 Payload Types (in Next Payload Type field) - * http://www.iana.org/assignments/eap-ikev2-payloads */ -enum { - IKEV2_PAYLOAD_NO_NEXT_PAYLOAD = 0, - IKEV2_PAYLOAD_SA = 33, - IKEV2_PAYLOAD_KEY_EXCHANGE = 34, - IKEV2_PAYLOAD_IDi = 35, - IKEV2_PAYLOAD_IDr = 36, - IKEV2_PAYLOAD_CERTIFICATE = 37, - IKEV2_PAYLOAD_CERT_REQ = 38, - IKEV2_PAYLOAD_AUTHENTICATION = 39, - IKEV2_PAYLOAD_NONCE = 40, - IKEV2_PAYLOAD_NOTIFICATION = 41, - IKEV2_PAYLOAD_VENDOD_ID = 43, - IKEV2_PAYLOAD_ENCRYPTED = 46, - IKEV2_PAYLOAD_NEXT_FAST_ID = 121 -}; - - -/* IKEv2 Proposal - Protocol ID */ -enum { - IKEV2_PROTOCOL_RESERVED = 0, - IKEV2_PROTOCOL_IKE = 1, /* IKE is the only one allowed for EAP-IKEv2 */ - IKEV2_PROTOCOL_AH = 2, - IKEV2_PROTOCOL_ESP = 3 -}; - - -/* IKEv2 Transform Types */ -enum { - IKEV2_TRANSFORM_ENCR = 1, - IKEV2_TRANSFORM_PRF = 2, - IKEV2_TRANSFORM_INTEG = 3, - IKEV2_TRANSFORM_DH = 4, - IKEV2_TRANSFORM_ESN = 5 -}; - -/* IKEv2 Tranform Type 1 (Encryption Algorithm) */ -enum { - ENCR_DES_IV64 = 1, - ENCR_DES = 2, - ENCR_3DES = 3, - ENCR_RC5 = 4, - ENCR_IDEA = 5, - ENCR_CAST = 6, - ENCR_BLOWFISH = 7, - ENCR_3IDEA = 8, - ENCR_DES_IV32 = 9, - ENCR_NULL = 11, - ENCR_AES_CBC = 12, - ENCR_AES_CTR = 13 -}; - -/* IKEv2 Transform Type 2 (Pseudo-random Function) */ -enum { - PRF_HMAC_MD5 = 1, - PRF_HMAC_SHA1 = 2, - PRF_HMAC_TIGER = 3, - PRF_AES128_XCBC = 4 -}; - -/* IKEv2 Transform Type 3 (Integrity Algorithm) */ -enum { - AUTH_HMAC_MD5_96 = 1, - AUTH_HMAC_SHA1_96 = 2, - AUTH_DES_MAC = 3, - AUTH_KPDK_MD5 = 4, - AUTH_AES_XCBC_96 = 5 -}; - -/* IKEv2 Transform Type 4 (Diffie-Hellman Group) */ -enum { - DH_GROUP1_768BIT_MODP = 1, /* RFC 4306 */ - DH_GROUP2_1024BIT_MODP = 2, /* RFC 4306 */ - DH_GROUP5_1536BIT_MODP = 5, /* RFC 3526 */ - DH_GROUP5_2048BIT_MODP = 14, /* RFC 3526 */ - DH_GROUP5_3072BIT_MODP = 15, /* RFC 3526 */ - DH_GROUP5_4096BIT_MODP = 16, /* RFC 3526 */ - DH_GROUP5_6144BIT_MODP = 17, /* RFC 3526 */ - DH_GROUP5_8192BIT_MODP = 18 /* RFC 3526 */ -}; - - -/* Identification Data Types (RFC 4306, Sect. 3.5) */ -enum { - ID_IPV4_ADDR = 1, - ID_FQDN = 2, - ID_RFC822_ADDR = 3, - ID_IPV6_ADDR = 5, - ID_DER_ASN1_DN = 9, - ID_DER_ASN1_GN= 10, - ID_KEY_ID = 11 -}; - - -/* Certificate Encoding (RFC 4306, Sect. 3.6) */ -enum { - CERT_ENCODING_PKCS7_X509 = 1, - CERT_ENCODING_PGP_CERT = 2, - CERT_ENCODING_DNS_SIGNED_KEY = 3, - /* X.509 Certificate - Signature: DER encoded X.509 certificate whose - * public key is used to validate the sender's AUTH payload */ - CERT_ENCODING_X509_CERT_SIGN = 4, - CERT_ENCODING_KERBEROS_TOKEN = 6, - /* DER encoded X.509 certificate revocation list */ - CERT_ENCODING_CRL = 7, - CERT_ENCODING_ARL = 8, - CERT_ENCODING_SPKI_CERT = 9, - CERT_ENCODING_X509_CERT_ATTR = 10, - /* PKCS #1 encoded RSA key */ - CERT_ENCODING_RAW_RSA_KEY = 11, - CERT_ENCODING_HASH_AND_URL_X509_CERT = 12, - CERT_ENCODING_HASH_AND_URL_X509_BUNDLE = 13 -}; - - -/* Authentication Method (RFC 4306, Sect. 3.8) */ -enum { - AUTH_RSA_SIGN = 1, - AUTH_SHARED_KEY_MIC = 2, - AUTH_DSS_SIGN = 3 -}; - - -/* Notify Message Types (RFC 4306, Sect. 3.10.1) */ -enum { - UNSUPPORTED_CRITICAL_PAYLOAD = 1, - INVALID_IKE_SPI = 4, - INVALID_MAJOR_VERSION = 5, - INVALID_SYNTAX = 7, - INVALID_MESSAGE_ID = 9, - INVALID_SPI = 11, - NO_PROPOSAL_CHOSEN = 14, - INVALID_KE_PAYLOAD = 17, - AUTHENTICATION_FAILED = 24, - SINGLE_PAIR_REQUIRED = 34, - NO_ADDITIONAL_SAS = 35, - INTERNAL_ADDRESS_FAILURE = 36, - FAILED_CP_REQUIRED = 37, - TS_UNACCEPTABLE = 38, - INVALID_SELECTORS = 39 -}; - - -struct ikev2_keys { - u8 *SK_d, *SK_ai, *SK_ar, *SK_ei, *SK_er, *SK_pi, *SK_pr; - size_t SK_d_len, SK_integ_len, SK_encr_len, SK_prf_len; -}; - - -int ikev2_keys_set(struct ikev2_keys *keys); -void ikev2_free_keys(struct ikev2_keys *keys); - - -/* Maximum hash length for supported hash algorithms */ -#define IKEV2_MAX_HASH_LEN 20 - -struct ikev2_integ_alg { - int id; - size_t key_len; - size_t hash_len; -}; - -struct ikev2_prf_alg { - int id; - size_t key_len; - size_t hash_len; -}; - -struct ikev2_encr_alg { - int id; - size_t key_len; - size_t block_size; -}; - -const struct ikev2_integ_alg * ikev2_get_integ(int id); -int ikev2_integ_hash(int alg, const u8 *key, size_t key_len, const u8 *data, - size_t data_len, u8 *hash); -const struct ikev2_prf_alg * ikev2_get_prf(int id); -int ikev2_prf_hash(int alg, const u8 *key, size_t key_len, - size_t num_elem, const u8 *addr[], const size_t *len, - u8 *hash); -int ikev2_prf_plus(int alg, const u8 *key, size_t key_len, - const u8 *data, size_t data_len, - u8 *out, size_t out_len); -const struct ikev2_encr_alg * ikev2_get_encr(int id); -int ikev2_encr_encrypt(int alg, const u8 *key, size_t key_len, const u8 *iv, - const u8 *plain, u8 *crypt, size_t len); -int ikev2_encr_decrypt(int alg, const u8 *key, size_t key_len, const u8 *iv, - const u8 *crypt, u8 *plain, size_t len); - -int ikev2_derive_auth_data(int prf_alg, const struct wpabuf *sign_msg, - const u8 *ID, size_t ID_len, u8 ID_type, - struct ikev2_keys *keys, int initiator, - const u8 *shared_secret, size_t shared_secret_len, - const u8 *nonce, size_t nonce_len, - const u8 *key_pad, size_t key_pad_len, - u8 *auth_data); - - -struct ikev2_payloads { - const u8 *sa; - size_t sa_len; - const u8 *ke; - size_t ke_len; - const u8 *idi; - size_t idi_len; - const u8 *idr; - size_t idr_len; - const u8 *cert; - size_t cert_len; - const u8 *auth; - size_t auth_len; - const u8 *nonce; - size_t nonce_len; - const u8 *encrypted; - size_t encrypted_len; - u8 encr_next_payload; - const u8 *notification; - size_t notification_len; -}; - -int ikev2_parse_payloads(struct ikev2_payloads *payloads, - u8 next_payload, const u8 *pos, const u8 *end); - -u8 * ikev2_decrypt_payload(int encr_id, int integ_id, struct ikev2_keys *keys, - int initiator, const struct ikev2_hdr *hdr, - const u8 *encrypted, size_t encrypted_len, - size_t *res_len); -void ikev2_update_hdr(struct wpabuf *msg); -int ikev2_build_encrypted(int encr_id, int integ_id, struct ikev2_keys *keys, - int initiator, struct wpabuf *msg, - struct wpabuf *plain, u8 next_payload); -int ikev2_derive_sk_keys(const struct ikev2_prf_alg *prf, - const struct ikev2_integ_alg *integ, - const struct ikev2_encr_alg *encr, - const u8 *skeyseed, const u8 *data, size_t data_len, - struct ikev2_keys *keys); - -#endif /* IKEV2_COMMON_H */ diff --git a/hostapd-0.8/src/eap_peer/Makefile b/hostapd-0.8/src/eap_peer/Makefile deleted file mode 100644 index 3651056..0000000 --- a/hostapd-0.8/src/eap_peer/Makefile +++ /dev/null @@ -1,11 +0,0 @@ -all: - @echo Nothing to be made. - -clean: - rm -f *~ *.o *.so *.d - -install: - if ls *.so >/dev/null 2>&1; then \ - install -d $(DESTDIR)$(LIBDIR)/wpa_supplicant && \ - cp *.so $(DESTDIR)$(LIBDIR)/wpa_supplicant \ - ; fi diff --git a/hostapd-0.8/src/eap_peer/eap.c b/hostapd-0.8/src/eap_peer/eap.c deleted file mode 100644 index 8a9826f..0000000 --- a/hostapd-0.8/src/eap_peer/eap.c +++ /dev/null @@ -1,2159 +0,0 @@ -/* - * EAP peer state machines (RFC 4137) - * Copyright (c) 2004-2010, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - * - * This file implements the Peer State Machine as defined in RFC 4137. The used - * states and state transitions match mostly with the RFC. However, there are - * couple of additional transitions for working around small issues noticed - * during testing. These exceptions are explained in comments within the - * functions in this file. The method functions, m.func(), are similar to the - * ones used in RFC 4137, but some small changes have used here to optimize - * operations and to add functionality needed for fast re-authentication - * (session resumption). - */ - -#include "includes.h" - -#include "common.h" -#include "pcsc_funcs.h" -#include "state_machine.h" -#include "crypto/crypto.h" -#include "crypto/tls.h" -#include "common/wpa_ctrl.h" -#include "eap_common/eap_wsc_common.h" -#include "eap_i.h" -#include "eap_config.h" - -#define STATE_MACHINE_DATA struct eap_sm -#define STATE_MACHINE_DEBUG_PREFIX "EAP" - -#define EAP_MAX_AUTH_ROUNDS 50 -#define EAP_CLIENT_TIMEOUT_DEFAULT 60 - - -static Boolean eap_sm_allowMethod(struct eap_sm *sm, int vendor, - EapType method); -static struct wpabuf * eap_sm_buildNak(struct eap_sm *sm, int id); -static void eap_sm_processIdentity(struct eap_sm *sm, - const struct wpabuf *req); -static void eap_sm_processNotify(struct eap_sm *sm, const struct wpabuf *req); -static struct wpabuf * eap_sm_buildNotify(int id); -static void eap_sm_parseEapReq(struct eap_sm *sm, const struct wpabuf *req); -#if defined(CONFIG_CTRL_IFACE) || !defined(CONFIG_NO_STDOUT_DEBUG) -static const char * eap_sm_method_state_txt(EapMethodState state); -static const char * eap_sm_decision_txt(EapDecision decision); -#endif /* CONFIG_CTRL_IFACE || !CONFIG_NO_STDOUT_DEBUG */ - - - -static Boolean eapol_get_bool(struct eap_sm *sm, enum eapol_bool_var var) -{ - return sm->eapol_cb->get_bool(sm->eapol_ctx, var); -} - - -static void eapol_set_bool(struct eap_sm *sm, enum eapol_bool_var var, - Boolean value) -{ - sm->eapol_cb->set_bool(sm->eapol_ctx, var, value); -} - - -static unsigned int eapol_get_int(struct eap_sm *sm, enum eapol_int_var var) -{ - return sm->eapol_cb->get_int(sm->eapol_ctx, var); -} - - -static void eapol_set_int(struct eap_sm *sm, enum eapol_int_var var, - unsigned int value) -{ - sm->eapol_cb->set_int(sm->eapol_ctx, var, value); -} - - -static struct wpabuf * eapol_get_eapReqData(struct eap_sm *sm) -{ - return sm->eapol_cb->get_eapReqData(sm->eapol_ctx); -} - - -static void eap_deinit_prev_method(struct eap_sm *sm, const char *txt) -{ - if (sm->m == NULL || sm->eap_method_priv == NULL) - return; - - wpa_printf(MSG_DEBUG, "EAP: deinitialize previously used EAP method " - "(%d, %s) at %s", sm->selectedMethod, sm->m->name, txt); - sm->m->deinit(sm, sm->eap_method_priv); - sm->eap_method_priv = NULL; - sm->m = NULL; -} - - -/** - * eap_allowed_method - Check whether EAP method is allowed - * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init() - * @vendor: Vendor-Id for expanded types or 0 = IETF for legacy types - * @method: EAP type - * Returns: 1 = allowed EAP method, 0 = not allowed - */ -int eap_allowed_method(struct eap_sm *sm, int vendor, u32 method) -{ - struct eap_peer_config *config = eap_get_config(sm); - int i; - struct eap_method_type *m; - - if (config == NULL || config->eap_methods == NULL) - return 1; - - m = config->eap_methods; - for (i = 0; m[i].vendor != EAP_VENDOR_IETF || - m[i].method != EAP_TYPE_NONE; i++) { - if (m[i].vendor == vendor && m[i].method == method) - return 1; - } - return 0; -} - - -/* - * This state initializes state machine variables when the machine is - * activated (portEnabled = TRUE). This is also used when re-starting - * authentication (eapRestart == TRUE). - */ -SM_STATE(EAP, INITIALIZE) -{ - SM_ENTRY(EAP, INITIALIZE); - if (sm->fast_reauth && sm->m && sm->m->has_reauth_data && - sm->m->has_reauth_data(sm, sm->eap_method_priv) && - !sm->prev_failure) { - wpa_printf(MSG_DEBUG, "EAP: maintaining EAP method data for " - "fast reauthentication"); - sm->m->deinit_for_reauth(sm, sm->eap_method_priv); - } else { - eap_deinit_prev_method(sm, "INITIALIZE"); - } - sm->selectedMethod = EAP_TYPE_NONE; - sm->methodState = METHOD_NONE; - sm->allowNotifications = TRUE; - sm->decision = DECISION_FAIL; - eapol_set_int(sm, EAPOL_idleWhile, sm->ClientTimeout); - eapol_set_bool(sm, EAPOL_eapSuccess, FALSE); - eapol_set_bool(sm, EAPOL_eapFail, FALSE); - os_free(sm->eapKeyData); - sm->eapKeyData = NULL; - sm->eapKeyAvailable = FALSE; - eapol_set_bool(sm, EAPOL_eapRestart, FALSE); - sm->lastId = -1; /* new session - make sure this does not match with - * the first EAP-Packet */ - /* - * RFC 4137 does not reset eapResp and eapNoResp here. However, this - * seemed to be able to trigger cases where both were set and if EAPOL - * state machine uses eapNoResp first, it may end up not sending a real - * reply correctly. This occurred when the workaround in FAIL state set - * eapNoResp = TRUE.. Maybe that workaround needs to be fixed to do - * something else(?) - */ - eapol_set_bool(sm, EAPOL_eapResp, FALSE); - eapol_set_bool(sm, EAPOL_eapNoResp, FALSE); - sm->num_rounds = 0; - sm->prev_failure = 0; -} - - -/* - * This state is reached whenever service from the lower layer is interrupted - * or unavailable (portEnabled == FALSE). Immediate transition to INITIALIZE - * occurs when the port becomes enabled. - */ -SM_STATE(EAP, DISABLED) -{ - SM_ENTRY(EAP, DISABLED); - sm->num_rounds = 0; -} - - -/* - * The state machine spends most of its time here, waiting for something to - * happen. This state is entered unconditionally from INITIALIZE, DISCARD, and - * SEND_RESPONSE states. - */ -SM_STATE(EAP, IDLE) -{ - SM_ENTRY(EAP, IDLE); -} - - -/* - * This state is entered when an EAP packet is received (eapReq == TRUE) to - * parse the packet header. - */ -SM_STATE(EAP, RECEIVED) -{ - const struct wpabuf *eapReqData; - - SM_ENTRY(EAP, RECEIVED); - eapReqData = eapol_get_eapReqData(sm); - /* parse rxReq, rxSuccess, rxFailure, reqId, reqMethod */ - eap_sm_parseEapReq(sm, eapReqData); - sm->num_rounds++; -} - - -/* - * This state is entered when a request for a new type comes in. Either the - * correct method is started, or a Nak response is built. - */ -SM_STATE(EAP, GET_METHOD) -{ - int reinit; - EapType method; - - SM_ENTRY(EAP, GET_METHOD); - - if (sm->reqMethod == EAP_TYPE_EXPANDED) - method = sm->reqVendorMethod; - else - method = sm->reqMethod; - - if (!eap_sm_allowMethod(sm, sm->reqVendor, method)) { - wpa_printf(MSG_DEBUG, "EAP: vendor %u method %u not allowed", - sm->reqVendor, method); - wpa_msg(sm->msg_ctx, MSG_INFO, WPA_EVENT_EAP_PROPOSED_METHOD - "vendor=%u method=%u -> NAK", - sm->reqVendor, method); - goto nak; - } - - wpa_msg(sm->msg_ctx, MSG_INFO, WPA_EVENT_EAP_PROPOSED_METHOD - "vendor=%u method=%u", sm->reqVendor, method); - - /* - * RFC 4137 does not define specific operation for fast - * re-authentication (session resumption). The design here is to allow - * the previously used method data to be maintained for - * re-authentication if the method support session resumption. - * Otherwise, the previously used method data is freed and a new method - * is allocated here. - */ - if (sm->fast_reauth && - sm->m && sm->m->vendor == sm->reqVendor && - sm->m->method == method && - sm->m->has_reauth_data && - sm->m->has_reauth_data(sm, sm->eap_method_priv)) { - wpa_printf(MSG_DEBUG, "EAP: Using previous method data" - " for fast re-authentication"); - reinit = 1; - } else { - eap_deinit_prev_method(sm, "GET_METHOD"); - reinit = 0; - } - - sm->selectedMethod = sm->reqMethod; - if (sm->m == NULL) - sm->m = eap_peer_get_eap_method(sm->reqVendor, method); - if (!sm->m) { - wpa_printf(MSG_DEBUG, "EAP: Could not find selected method: " - "vendor %d method %d", - sm->reqVendor, method); - goto nak; - } - - sm->ClientTimeout = EAP_CLIENT_TIMEOUT_DEFAULT; - - wpa_printf(MSG_DEBUG, "EAP: Initialize selected EAP method: " - "vendor %u method %u (%s)", - sm->reqVendor, method, sm->m->name); - if (reinit) - sm->eap_method_priv = sm->m->init_for_reauth( - sm, sm->eap_method_priv); - else - sm->eap_method_priv = sm->m->init(sm); - - if (sm->eap_method_priv == NULL) { - struct eap_peer_config *config = eap_get_config(sm); - wpa_msg(sm->msg_ctx, MSG_INFO, - "EAP: Failed to initialize EAP method: vendor %u " - "method %u (%s)", - sm->reqVendor, method, sm->m->name); - sm->m = NULL; - sm->methodState = METHOD_NONE; - sm->selectedMethod = EAP_TYPE_NONE; - if (sm->reqMethod == EAP_TYPE_TLS && config && - (config->pending_req_pin || - config->pending_req_passphrase)) { - /* - * Return without generating Nak in order to allow - * entering of PIN code or passphrase to retry the - * current EAP packet. - */ - wpa_printf(MSG_DEBUG, "EAP: Pending PIN/passphrase " - "request - skip Nak"); - return; - } - - goto nak; - } - - sm->methodState = METHOD_INIT; - wpa_msg(sm->msg_ctx, MSG_INFO, WPA_EVENT_EAP_METHOD - "EAP vendor %u method %u (%s) selected", - sm->reqVendor, method, sm->m->name); - return; - -nak: - wpabuf_free(sm->eapRespData); - sm->eapRespData = NULL; - sm->eapRespData = eap_sm_buildNak(sm, sm->reqId); -} - - -/* - * The method processing happens here. The request from the authenticator is - * processed, and an appropriate response packet is built. - */ -SM_STATE(EAP, METHOD) -{ - struct wpabuf *eapReqData; - struct eap_method_ret ret; - - SM_ENTRY(EAP, METHOD); - if (sm->m == NULL) { - wpa_printf(MSG_WARNING, "EAP::METHOD - method not selected"); - return; - } - - eapReqData = eapol_get_eapReqData(sm); - - /* - * Get ignore, methodState, decision, allowNotifications, and - * eapRespData. RFC 4137 uses three separate method procedure (check, - * process, and buildResp) in this state. These have been combined into - * a single function call to m->process() in order to optimize EAP - * method implementation interface a bit. These procedures are only - * used from within this METHOD state, so there is no need to keep - * these as separate C functions. - * - * The RFC 4137 procedures return values as follows: - * ignore = m.check(eapReqData) - * (methodState, decision, allowNotifications) = m.process(eapReqData) - * eapRespData = m.buildResp(reqId) - */ - os_memset(&ret, 0, sizeof(ret)); - ret.ignore = sm->ignore; - ret.methodState = sm->methodState; - ret.decision = sm->decision; - ret.allowNotifications = sm->allowNotifications; - wpabuf_free(sm->eapRespData); - sm->eapRespData = NULL; - sm->eapRespData = sm->m->process(sm, sm->eap_method_priv, &ret, - eapReqData); - wpa_printf(MSG_DEBUG, "EAP: method process -> ignore=%s " - "methodState=%s decision=%s", - ret.ignore ? "TRUE" : "FALSE", - eap_sm_method_state_txt(ret.methodState), - eap_sm_decision_txt(ret.decision)); - - sm->ignore = ret.ignore; - if (sm->ignore) - return; - sm->methodState = ret.methodState; - sm->decision = ret.decision; - sm->allowNotifications = ret.allowNotifications; - - if (sm->m->isKeyAvailable && sm->m->getKey && - sm->m->isKeyAvailable(sm, sm->eap_method_priv)) { - os_free(sm->eapKeyData); - sm->eapKeyData = sm->m->getKey(sm, sm->eap_method_priv, - &sm->eapKeyDataLen); - } -} - - -/* - * This state signals the lower layer that a response packet is ready to be - * sent. - */ -SM_STATE(EAP, SEND_RESPONSE) -{ - SM_ENTRY(EAP, SEND_RESPONSE); - wpabuf_free(sm->lastRespData); - if (sm->eapRespData) { - if (sm->workaround) - os_memcpy(sm->last_md5, sm->req_md5, 16); - sm->lastId = sm->reqId; - sm->lastRespData = wpabuf_dup(sm->eapRespData); - eapol_set_bool(sm, EAPOL_eapResp, TRUE); - } else - sm->lastRespData = NULL; - eapol_set_bool(sm, EAPOL_eapReq, FALSE); - eapol_set_int(sm, EAPOL_idleWhile, sm->ClientTimeout); -} - - -/* - * This state signals the lower layer that the request was discarded, and no - * response packet will be sent at this time. - */ -SM_STATE(EAP, DISCARD) -{ - SM_ENTRY(EAP, DISCARD); - eapol_set_bool(sm, EAPOL_eapReq, FALSE); - eapol_set_bool(sm, EAPOL_eapNoResp, TRUE); -} - - -/* - * Handles requests for Identity method and builds a response. - */ -SM_STATE(EAP, IDENTITY) -{ - const struct wpabuf *eapReqData; - - SM_ENTRY(EAP, IDENTITY); - eapReqData = eapol_get_eapReqData(sm); - eap_sm_processIdentity(sm, eapReqData); - wpabuf_free(sm->eapRespData); - sm->eapRespData = NULL; - sm->eapRespData = eap_sm_buildIdentity(sm, sm->reqId, 0); -} - - -/* - * Handles requests for Notification method and builds a response. - */ -SM_STATE(EAP, NOTIFICATION) -{ - const struct wpabuf *eapReqData; - - SM_ENTRY(EAP, NOTIFICATION); - eapReqData = eapol_get_eapReqData(sm); - eap_sm_processNotify(sm, eapReqData); - wpabuf_free(sm->eapRespData); - sm->eapRespData = NULL; - sm->eapRespData = eap_sm_buildNotify(sm->reqId); -} - - -/* - * This state retransmits the previous response packet. - */ -SM_STATE(EAP, RETRANSMIT) -{ - SM_ENTRY(EAP, RETRANSMIT); - wpabuf_free(sm->eapRespData); - if (sm->lastRespData) - sm->eapRespData = wpabuf_dup(sm->lastRespData); - else - sm->eapRespData = NULL; -} - - -/* - * This state is entered in case of a successful completion of authentication - * and state machine waits here until port is disabled or EAP authentication is - * restarted. - */ -SM_STATE(EAP, SUCCESS) -{ - SM_ENTRY(EAP, SUCCESS); - if (sm->eapKeyData != NULL) - sm->eapKeyAvailable = TRUE; - eapol_set_bool(sm, EAPOL_eapSuccess, TRUE); - - /* - * RFC 4137 does not clear eapReq here, but this seems to be required - * to avoid processing the same request twice when state machine is - * initialized. - */ - eapol_set_bool(sm, EAPOL_eapReq, FALSE); - - /* - * RFC 4137 does not set eapNoResp here, but this seems to be required - * to get EAPOL Supplicant backend state machine into SUCCESS state. In - * addition, either eapResp or eapNoResp is required to be set after - * processing the received EAP frame. - */ - eapol_set_bool(sm, EAPOL_eapNoResp, TRUE); - - wpa_msg(sm->msg_ctx, MSG_INFO, WPA_EVENT_EAP_SUCCESS - "EAP authentication completed successfully"); -} - - -/* - * This state is entered in case of a failure and state machine waits here - * until port is disabled or EAP authentication is restarted. - */ -SM_STATE(EAP, FAILURE) -{ - SM_ENTRY(EAP, FAILURE); - eapol_set_bool(sm, EAPOL_eapFail, TRUE); - - /* - * RFC 4137 does not clear eapReq here, but this seems to be required - * to avoid processing the same request twice when state machine is - * initialized. - */ - eapol_set_bool(sm, EAPOL_eapReq, FALSE); - - /* - * RFC 4137 does not set eapNoResp here. However, either eapResp or - * eapNoResp is required to be set after processing the received EAP - * frame. - */ - eapol_set_bool(sm, EAPOL_eapNoResp, TRUE); - - wpa_msg(sm->msg_ctx, MSG_INFO, WPA_EVENT_EAP_FAILURE - "EAP authentication failed"); - - sm->prev_failure = 1; -} - - -static int eap_success_workaround(struct eap_sm *sm, int reqId, int lastId) -{ - /* - * At least Microsoft IAS and Meetinghouse Aegis seem to be sending - * EAP-Success/Failure with lastId + 1 even though RFC 3748 and - * RFC 4137 require that reqId == lastId. In addition, it looks like - * Ringmaster v2.1.2.0 would be using lastId + 2 in EAP-Success. - * - * Accept this kind of Id if EAP workarounds are enabled. These are - * unauthenticated plaintext messages, so this should have minimal - * security implications (bit easier to fake EAP-Success/Failure). - */ - if (sm->workaround && (reqId == ((lastId + 1) & 0xff) || - reqId == ((lastId + 2) & 0xff))) { - wpa_printf(MSG_DEBUG, "EAP: Workaround for unexpected " - "identifier field in EAP Success: " - "reqId=%d lastId=%d (these are supposed to be " - "same)", reqId, lastId); - return 1; - } - wpa_printf(MSG_DEBUG, "EAP: EAP-Success Id mismatch - reqId=%d " - "lastId=%d", reqId, lastId); - return 0; -} - - -/* - * RFC 4137 - Appendix A.1: EAP Peer State Machine - State transitions - */ - -static void eap_peer_sm_step_idle(struct eap_sm *sm) -{ - /* - * The first three transitions are from RFC 4137. The last two are - * local additions to handle special cases with LEAP and PEAP server - * not sending EAP-Success in some cases. - */ - if (eapol_get_bool(sm, EAPOL_eapReq)) - SM_ENTER(EAP, RECEIVED); - else if ((eapol_get_bool(sm, EAPOL_altAccept) && - sm->decision != DECISION_FAIL) || - (eapol_get_int(sm, EAPOL_idleWhile) == 0 && - sm->decision == DECISION_UNCOND_SUCC)) - SM_ENTER(EAP, SUCCESS); - else if (eapol_get_bool(sm, EAPOL_altReject) || - (eapol_get_int(sm, EAPOL_idleWhile) == 0 && - sm->decision != DECISION_UNCOND_SUCC) || - (eapol_get_bool(sm, EAPOL_altAccept) && - sm->methodState != METHOD_CONT && - sm->decision == DECISION_FAIL)) - SM_ENTER(EAP, FAILURE); - else if (sm->selectedMethod == EAP_TYPE_LEAP && - sm->leap_done && sm->decision != DECISION_FAIL && - sm->methodState == METHOD_DONE) - SM_ENTER(EAP, SUCCESS); - else if (sm->selectedMethod == EAP_TYPE_PEAP && - sm->peap_done && sm->decision != DECISION_FAIL && - sm->methodState == METHOD_DONE) - SM_ENTER(EAP, SUCCESS); -} - - -static int eap_peer_req_is_duplicate(struct eap_sm *sm) -{ - int duplicate; - - duplicate = (sm->reqId == sm->lastId) && sm->rxReq; - if (sm->workaround && duplicate && - os_memcmp(sm->req_md5, sm->last_md5, 16) != 0) { - /* - * RFC 4137 uses (reqId == lastId) as the only verification for - * duplicate EAP requests. However, this misses cases where the - * AS is incorrectly using the same id again; and - * unfortunately, such implementations exist. Use MD5 hash as - * an extra verification for the packets being duplicate to - * workaround these issues. - */ - wpa_printf(MSG_DEBUG, "EAP: AS used the same Id again, but " - "EAP packets were not identical"); - wpa_printf(MSG_DEBUG, "EAP: workaround - assume this is not a " - "duplicate packet"); - duplicate = 0; - } - - return duplicate; -} - - -static void eap_peer_sm_step_received(struct eap_sm *sm) -{ - int duplicate = eap_peer_req_is_duplicate(sm); - - /* - * Two special cases below for LEAP are local additions to work around - * odd LEAP behavior (EAP-Success in the middle of authentication and - * then swapped roles). Other transitions are based on RFC 4137. - */ - if (sm->rxSuccess && sm->decision != DECISION_FAIL && - (sm->reqId == sm->lastId || - eap_success_workaround(sm, sm->reqId, sm->lastId))) - SM_ENTER(EAP, SUCCESS); - else if (sm->methodState != METHOD_CONT && - ((sm->rxFailure && - sm->decision != DECISION_UNCOND_SUCC) || - (sm->rxSuccess && sm->decision == DECISION_FAIL && - (sm->selectedMethod != EAP_TYPE_LEAP || - sm->methodState != METHOD_MAY_CONT))) && - (sm->reqId == sm->lastId || - eap_success_workaround(sm, sm->reqId, sm->lastId))) - SM_ENTER(EAP, FAILURE); - else if (sm->rxReq && duplicate) - SM_ENTER(EAP, RETRANSMIT); - else if (sm->rxReq && !duplicate && - sm->reqMethod == EAP_TYPE_NOTIFICATION && - sm->allowNotifications) - SM_ENTER(EAP, NOTIFICATION); - else if (sm->rxReq && !duplicate && - sm->selectedMethod == EAP_TYPE_NONE && - sm->reqMethod == EAP_TYPE_IDENTITY) - SM_ENTER(EAP, IDENTITY); - else if (sm->rxReq && !duplicate && - sm->selectedMethod == EAP_TYPE_NONE && - sm->reqMethod != EAP_TYPE_IDENTITY && - sm->reqMethod != EAP_TYPE_NOTIFICATION) - SM_ENTER(EAP, GET_METHOD); - else if (sm->rxReq && !duplicate && - sm->reqMethod == sm->selectedMethod && - sm->methodState != METHOD_DONE) - SM_ENTER(EAP, METHOD); - else if (sm->selectedMethod == EAP_TYPE_LEAP && - (sm->rxSuccess || sm->rxResp)) - SM_ENTER(EAP, METHOD); - else - SM_ENTER(EAP, DISCARD); -} - - -static void eap_peer_sm_step_local(struct eap_sm *sm) -{ - switch (sm->EAP_state) { - case EAP_INITIALIZE: - SM_ENTER(EAP, IDLE); - break; - case EAP_DISABLED: - if (eapol_get_bool(sm, EAPOL_portEnabled) && - !sm->force_disabled) - SM_ENTER(EAP, INITIALIZE); - break; - case EAP_IDLE: - eap_peer_sm_step_idle(sm); - break; - case EAP_RECEIVED: - eap_peer_sm_step_received(sm); - break; - case EAP_GET_METHOD: - if (sm->selectedMethod == sm->reqMethod) - SM_ENTER(EAP, METHOD); - else - SM_ENTER(EAP, SEND_RESPONSE); - break; - case EAP_METHOD: - if (sm->ignore) - SM_ENTER(EAP, DISCARD); - else - SM_ENTER(EAP, SEND_RESPONSE); - break; - case EAP_SEND_RESPONSE: - SM_ENTER(EAP, IDLE); - break; - case EAP_DISCARD: - SM_ENTER(EAP, IDLE); - break; - case EAP_IDENTITY: - SM_ENTER(EAP, SEND_RESPONSE); - break; - case EAP_NOTIFICATION: - SM_ENTER(EAP, SEND_RESPONSE); - break; - case EAP_RETRANSMIT: - SM_ENTER(EAP, SEND_RESPONSE); - break; - case EAP_SUCCESS: - break; - case EAP_FAILURE: - break; - } -} - - -SM_STEP(EAP) -{ - /* Global transitions */ - if (eapol_get_bool(sm, EAPOL_eapRestart) && - eapol_get_bool(sm, EAPOL_portEnabled)) - SM_ENTER_GLOBAL(EAP, INITIALIZE); - else if (!eapol_get_bool(sm, EAPOL_portEnabled) || sm->force_disabled) - SM_ENTER_GLOBAL(EAP, DISABLED); - else if (sm->num_rounds > EAP_MAX_AUTH_ROUNDS) { - /* RFC 4137 does not place any limit on number of EAP messages - * in an authentication session. However, some error cases have - * ended up in a state were EAP messages were sent between the - * peer and server in a loop (e.g., TLS ACK frame in both - * direction). Since this is quite undesired outcome, limit the - * total number of EAP round-trips and abort authentication if - * this limit is exceeded. - */ - if (sm->num_rounds == EAP_MAX_AUTH_ROUNDS + 1) { - wpa_msg(sm->msg_ctx, MSG_INFO, "EAP: more than %d " - "authentication rounds - abort", - EAP_MAX_AUTH_ROUNDS); - sm->num_rounds++; - SM_ENTER_GLOBAL(EAP, FAILURE); - } - } else { - /* Local transitions */ - eap_peer_sm_step_local(sm); - } -} - - -static Boolean eap_sm_allowMethod(struct eap_sm *sm, int vendor, - EapType method) -{ - if (!eap_allowed_method(sm, vendor, method)) { - wpa_printf(MSG_DEBUG, "EAP: configuration does not allow: " - "vendor %u method %u", vendor, method); - return FALSE; - } - if (eap_peer_get_eap_method(vendor, method)) - return TRUE; - wpa_printf(MSG_DEBUG, "EAP: not included in build: " - "vendor %u method %u", vendor, method); - return FALSE; -} - - -static struct wpabuf * eap_sm_build_expanded_nak( - struct eap_sm *sm, int id, const struct eap_method *methods, - size_t count) -{ - struct wpabuf *resp; - int found = 0; - const struct eap_method *m; - - wpa_printf(MSG_DEBUG, "EAP: Building expanded EAP-Nak"); - - /* RFC 3748 - 5.3.2: Expanded Nak */ - resp = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_EXPANDED, - 8 + 8 * (count + 1), EAP_CODE_RESPONSE, id); - if (resp == NULL) - return NULL; - - wpabuf_put_be24(resp, EAP_VENDOR_IETF); - wpabuf_put_be32(resp, EAP_TYPE_NAK); - - for (m = methods; m; m = m->next) { - if (sm->reqVendor == m->vendor && - sm->reqVendorMethod == m->method) - continue; /* do not allow the current method again */ - if (eap_allowed_method(sm, m->vendor, m->method)) { - wpa_printf(MSG_DEBUG, "EAP: allowed type: " - "vendor=%u method=%u", - m->vendor, m->method); - wpabuf_put_u8(resp, EAP_TYPE_EXPANDED); - wpabuf_put_be24(resp, m->vendor); - wpabuf_put_be32(resp, m->method); - - found++; - } - } - if (!found) { - wpa_printf(MSG_DEBUG, "EAP: no more allowed methods"); - wpabuf_put_u8(resp, EAP_TYPE_EXPANDED); - wpabuf_put_be24(resp, EAP_VENDOR_IETF); - wpabuf_put_be32(resp, EAP_TYPE_NONE); - } - - eap_update_len(resp); - - return resp; -} - - -static struct wpabuf * eap_sm_buildNak(struct eap_sm *sm, int id) -{ - struct wpabuf *resp; - u8 *start; - int found = 0, expanded_found = 0; - size_t count; - const struct eap_method *methods, *m; - - wpa_printf(MSG_DEBUG, "EAP: Building EAP-Nak (requested type %u " - "vendor=%u method=%u not allowed)", sm->reqMethod, - sm->reqVendor, sm->reqVendorMethod); - methods = eap_peer_get_methods(&count); - if (methods == NULL) - return NULL; - if (sm->reqMethod == EAP_TYPE_EXPANDED) - return eap_sm_build_expanded_nak(sm, id, methods, count); - - /* RFC 3748 - 5.3.1: Legacy Nak */ - resp = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_NAK, - sizeof(struct eap_hdr) + 1 + count + 1, - EAP_CODE_RESPONSE, id); - if (resp == NULL) - return NULL; - - start = wpabuf_put(resp, 0); - for (m = methods; m; m = m->next) { - if (m->vendor == EAP_VENDOR_IETF && m->method == sm->reqMethod) - continue; /* do not allow the current method again */ - if (eap_allowed_method(sm, m->vendor, m->method)) { - if (m->vendor != EAP_VENDOR_IETF) { - if (expanded_found) - continue; - expanded_found = 1; - wpabuf_put_u8(resp, EAP_TYPE_EXPANDED); - } else - wpabuf_put_u8(resp, m->method); - found++; - } - } - if (!found) - wpabuf_put_u8(resp, EAP_TYPE_NONE); - wpa_hexdump(MSG_DEBUG, "EAP: allowed methods", start, found); - - eap_update_len(resp); - - return resp; -} - - -static void eap_sm_processIdentity(struct eap_sm *sm, const struct wpabuf *req) -{ - const struct eap_hdr *hdr = wpabuf_head(req); - const u8 *pos = (const u8 *) (hdr + 1); - pos++; - - wpa_msg(sm->msg_ctx, MSG_INFO, WPA_EVENT_EAP_STARTED - "EAP authentication started"); - - /* - * RFC 3748 - 5.1: Identity - * Data field may contain a displayable message in UTF-8. If this - * includes NUL-character, only the data before that should be - * displayed. Some EAP implementasitons may piggy-back additional - * options after the NUL. - */ - /* TODO: could save displayable message so that it can be shown to the - * user in case of interaction is required */ - wpa_hexdump_ascii(MSG_DEBUG, "EAP: EAP-Request Identity data", - pos, be_to_host16(hdr->length) - 5); -} - - -#ifdef PCSC_FUNCS -static int eap_sm_imsi_identity(struct eap_sm *sm, - struct eap_peer_config *conf) -{ - int aka = 0; - char imsi[100]; - size_t imsi_len; - struct eap_method_type *m = conf->eap_methods; - int i; - - imsi_len = sizeof(imsi); - if (scard_get_imsi(sm->scard_ctx, imsi, &imsi_len)) { - wpa_printf(MSG_WARNING, "Failed to get IMSI from SIM"); - return -1; - } - - wpa_hexdump_ascii(MSG_DEBUG, "IMSI", (u8 *) imsi, imsi_len); - - for (i = 0; m && (m[i].vendor != EAP_VENDOR_IETF || - m[i].method != EAP_TYPE_NONE); i++) { - if (m[i].vendor == EAP_VENDOR_IETF && - m[i].method == EAP_TYPE_AKA) { - aka = 1; - break; - } - } - - os_free(conf->identity); - conf->identity = os_malloc(1 + imsi_len); - if (conf->identity == NULL) { - wpa_printf(MSG_WARNING, "Failed to allocate buffer for " - "IMSI-based identity"); - return -1; - } - - conf->identity[0] = aka ? '0' : '1'; - os_memcpy(conf->identity + 1, imsi, imsi_len); - conf->identity_len = 1 + imsi_len; - - return 0; -} -#endif /* PCSC_FUNCS */ - - -static int eap_sm_set_scard_pin(struct eap_sm *sm, - struct eap_peer_config *conf) -{ -#ifdef PCSC_FUNCS - if (scard_set_pin(sm->scard_ctx, conf->pin)) { - /* - * Make sure the same PIN is not tried again in order to avoid - * blocking SIM. - */ - os_free(conf->pin); - conf->pin = NULL; - - wpa_printf(MSG_WARNING, "PIN validation failed"); - eap_sm_request_pin(sm); - return -1; - } - return 0; -#else /* PCSC_FUNCS */ - return -1; -#endif /* PCSC_FUNCS */ -} - -static int eap_sm_get_scard_identity(struct eap_sm *sm, - struct eap_peer_config *conf) -{ -#ifdef PCSC_FUNCS - if (eap_sm_set_scard_pin(sm, conf)) - return -1; - - return eap_sm_imsi_identity(sm, conf); -#else /* PCSC_FUNCS */ - return -1; -#endif /* PCSC_FUNCS */ -} - - -/** - * eap_sm_buildIdentity - Build EAP-Identity/Response for the current network - * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init() - * @id: EAP identifier for the packet - * @encrypted: Whether the packet is for encrypted tunnel (EAP phase 2) - * Returns: Pointer to the allocated EAP-Identity/Response packet or %NULL on - * failure - * - * This function allocates and builds an EAP-Identity/Response packet for the - * current network. The caller is responsible for freeing the returned data. - */ -struct wpabuf * eap_sm_buildIdentity(struct eap_sm *sm, int id, int encrypted) -{ - struct eap_peer_config *config = eap_get_config(sm); - struct wpabuf *resp; - const u8 *identity; - size_t identity_len; - - if (config == NULL) { - wpa_printf(MSG_WARNING, "EAP: buildIdentity: configuration " - "was not available"); - return NULL; - } - - if (sm->m && sm->m->get_identity && - (identity = sm->m->get_identity(sm, sm->eap_method_priv, - &identity_len)) != NULL) { - wpa_hexdump_ascii(MSG_DEBUG, "EAP: using method re-auth " - "identity", identity, identity_len); - } else if (!encrypted && config->anonymous_identity) { - identity = config->anonymous_identity; - identity_len = config->anonymous_identity_len; - wpa_hexdump_ascii(MSG_DEBUG, "EAP: using anonymous identity", - identity, identity_len); - } else { - identity = config->identity; - identity_len = config->identity_len; - wpa_hexdump_ascii(MSG_DEBUG, "EAP: using real identity", - identity, identity_len); - } - - if (identity == NULL) { - wpa_printf(MSG_WARNING, "EAP: buildIdentity: identity " - "configuration was not available"); - if (config->pcsc) { - if (eap_sm_get_scard_identity(sm, config) < 0) - return NULL; - identity = config->identity; - identity_len = config->identity_len; - wpa_hexdump_ascii(MSG_DEBUG, "permanent identity from " - "IMSI", identity, identity_len); - } else { - eap_sm_request_identity(sm); - return NULL; - } - } else if (config->pcsc) { - if (eap_sm_set_scard_pin(sm, config) < 0) - return NULL; - } - - resp = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_IDENTITY, identity_len, - EAP_CODE_RESPONSE, id); - if (resp == NULL) - return NULL; - - wpabuf_put_data(resp, identity, identity_len); - - return resp; -} - - -static void eap_sm_processNotify(struct eap_sm *sm, const struct wpabuf *req) -{ - const u8 *pos; - char *msg; - size_t i, msg_len; - - pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_NOTIFICATION, req, - &msg_len); - if (pos == NULL) - return; - wpa_hexdump_ascii(MSG_DEBUG, "EAP: EAP-Request Notification data", - pos, msg_len); - - msg = os_malloc(msg_len + 1); - if (msg == NULL) - return; - for (i = 0; i < msg_len; i++) - msg[i] = isprint(pos[i]) ? (char) pos[i] : '_'; - msg[msg_len] = '\0'; - wpa_msg(sm->msg_ctx, MSG_INFO, "%s%s", - WPA_EVENT_EAP_NOTIFICATION, msg); - os_free(msg); -} - - -static struct wpabuf * eap_sm_buildNotify(int id) -{ - struct wpabuf *resp; - - wpa_printf(MSG_DEBUG, "EAP: Generating EAP-Response Notification"); - resp = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_NOTIFICATION, 0, - EAP_CODE_RESPONSE, id); - if (resp == NULL) - return NULL; - - return resp; -} - - -static void eap_sm_parseEapReq(struct eap_sm *sm, const struct wpabuf *req) -{ - const struct eap_hdr *hdr; - size_t plen; - const u8 *pos; - - sm->rxReq = sm->rxResp = sm->rxSuccess = sm->rxFailure = FALSE; - sm->reqId = 0; - sm->reqMethod = EAP_TYPE_NONE; - sm->reqVendor = EAP_VENDOR_IETF; - sm->reqVendorMethod = EAP_TYPE_NONE; - - if (req == NULL || wpabuf_len(req) < sizeof(*hdr)) - return; - - hdr = wpabuf_head(req); - plen = be_to_host16(hdr->length); - if (plen > wpabuf_len(req)) { - wpa_printf(MSG_DEBUG, "EAP: Ignored truncated EAP-Packet " - "(len=%lu plen=%lu)", - (unsigned long) wpabuf_len(req), - (unsigned long) plen); - return; - } - - sm->reqId = hdr->identifier; - - if (sm->workaround) { - const u8 *addr[1]; - addr[0] = wpabuf_head(req); - md5_vector(1, addr, &plen, sm->req_md5); - } - - switch (hdr->code) { - case EAP_CODE_REQUEST: - if (plen < sizeof(*hdr) + 1) { - wpa_printf(MSG_DEBUG, "EAP: Too short EAP-Request - " - "no Type field"); - return; - } - sm->rxReq = TRUE; - pos = (const u8 *) (hdr + 1); - sm->reqMethod = *pos++; - if (sm->reqMethod == EAP_TYPE_EXPANDED) { - if (plen < sizeof(*hdr) + 8) { - wpa_printf(MSG_DEBUG, "EAP: Ignored truncated " - "expanded EAP-Packet (plen=%lu)", - (unsigned long) plen); - return; - } - sm->reqVendor = WPA_GET_BE24(pos); - pos += 3; - sm->reqVendorMethod = WPA_GET_BE32(pos); - } - wpa_printf(MSG_DEBUG, "EAP: Received EAP-Request id=%d " - "method=%u vendor=%u vendorMethod=%u", - sm->reqId, sm->reqMethod, sm->reqVendor, - sm->reqVendorMethod); - break; - case EAP_CODE_RESPONSE: - if (sm->selectedMethod == EAP_TYPE_LEAP) { - /* - * LEAP differs from RFC 4137 by using reversed roles - * for mutual authentication and because of this, we - * need to accept EAP-Response frames if LEAP is used. - */ - if (plen < sizeof(*hdr) + 1) { - wpa_printf(MSG_DEBUG, "EAP: Too short " - "EAP-Response - no Type field"); - return; - } - sm->rxResp = TRUE; - pos = (const u8 *) (hdr + 1); - sm->reqMethod = *pos; - wpa_printf(MSG_DEBUG, "EAP: Received EAP-Response for " - "LEAP method=%d id=%d", - sm->reqMethod, sm->reqId); - break; - } - wpa_printf(MSG_DEBUG, "EAP: Ignored EAP-Response"); - break; - case EAP_CODE_SUCCESS: - wpa_printf(MSG_DEBUG, "EAP: Received EAP-Success"); - sm->rxSuccess = TRUE; - break; - case EAP_CODE_FAILURE: - wpa_printf(MSG_DEBUG, "EAP: Received EAP-Failure"); - sm->rxFailure = TRUE; - break; - default: - wpa_printf(MSG_DEBUG, "EAP: Ignored EAP-Packet with unknown " - "code %d", hdr->code); - break; - } -} - - -static void eap_peer_sm_tls_event(void *ctx, enum tls_event ev, - union tls_event_data *data) -{ - struct eap_sm *sm = ctx; - char *hash_hex = NULL; - char *cert_hex = NULL; - - switch (ev) { - case TLS_CERT_CHAIN_FAILURE: - wpa_msg(sm->msg_ctx, MSG_INFO, WPA_EVENT_EAP_TLS_CERT_ERROR - "reason=%d depth=%d subject='%s' err='%s'", - data->cert_fail.reason, - data->cert_fail.depth, - data->cert_fail.subject, - data->cert_fail.reason_txt); - break; - case TLS_PEER_CERTIFICATE: - if (data->peer_cert.hash) { - size_t len = data->peer_cert.hash_len * 2 + 1; - hash_hex = os_malloc(len); - if (hash_hex) { - wpa_snprintf_hex(hash_hex, len, - data->peer_cert.hash, - data->peer_cert.hash_len); - } - } - wpa_msg(sm->msg_ctx, MSG_INFO, WPA_EVENT_EAP_PEER_CERT - "depth=%d subject='%s'%s%s", - data->peer_cert.depth, data->peer_cert.subject, - hash_hex ? " hash=" : "", hash_hex ? hash_hex : ""); - - if (data->peer_cert.cert) { - size_t len = wpabuf_len(data->peer_cert.cert) * 2 + 1; - cert_hex = os_malloc(len); - if (cert_hex == NULL) - break; - wpa_snprintf_hex(cert_hex, len, - wpabuf_head(data->peer_cert.cert), - wpabuf_len(data->peer_cert.cert)); - wpa_msg_ctrl(sm->msg_ctx, MSG_INFO, - WPA_EVENT_EAP_PEER_CERT - "depth=%d subject='%s' cert=%s", - data->peer_cert.depth, - data->peer_cert.subject, - cert_hex); - } - break; - } - - os_free(hash_hex); - os_free(cert_hex); -} - - -/** - * eap_peer_sm_init - Allocate and initialize EAP peer state machine - * @eapol_ctx: Context data to be used with eapol_cb calls - * @eapol_cb: Pointer to EAPOL callback functions - * @msg_ctx: Context data for wpa_msg() calls - * @conf: EAP configuration - * Returns: Pointer to the allocated EAP state machine or %NULL on failure - * - * This function allocates and initializes an EAP state machine. In addition, - * this initializes TLS library for the new EAP state machine. eapol_cb pointer - * will be in use until eap_peer_sm_deinit() is used to deinitialize this EAP - * state machine. Consequently, the caller must make sure that this data - * structure remains alive while the EAP state machine is active. - */ -struct eap_sm * eap_peer_sm_init(void *eapol_ctx, - struct eapol_callbacks *eapol_cb, - void *msg_ctx, struct eap_config *conf) -{ - struct eap_sm *sm; - struct tls_config tlsconf; - - sm = os_zalloc(sizeof(*sm)); - if (sm == NULL) - return NULL; - sm->eapol_ctx = eapol_ctx; - sm->eapol_cb = eapol_cb; - sm->msg_ctx = msg_ctx; - sm->ClientTimeout = EAP_CLIENT_TIMEOUT_DEFAULT; - sm->wps = conf->wps; - - os_memset(&tlsconf, 0, sizeof(tlsconf)); - tlsconf.opensc_engine_path = conf->opensc_engine_path; - tlsconf.pkcs11_engine_path = conf->pkcs11_engine_path; - tlsconf.pkcs11_module_path = conf->pkcs11_module_path; -#ifdef CONFIG_FIPS - tlsconf.fips_mode = 1; -#endif /* CONFIG_FIPS */ - tlsconf.event_cb = eap_peer_sm_tls_event; - tlsconf.cb_ctx = sm; - sm->ssl_ctx = tls_init(&tlsconf); - if (sm->ssl_ctx == NULL) { - wpa_printf(MSG_WARNING, "SSL: Failed to initialize TLS " - "context."); - os_free(sm); - return NULL; - } - - return sm; -} - - -/** - * eap_peer_sm_deinit - Deinitialize and free an EAP peer state machine - * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init() - * - * This function deinitializes EAP state machine and frees all allocated - * resources. - */ -void eap_peer_sm_deinit(struct eap_sm *sm) -{ - if (sm == NULL) - return; - eap_deinit_prev_method(sm, "EAP deinit"); - eap_sm_abort(sm); - tls_deinit(sm->ssl_ctx); - os_free(sm); -} - - -/** - * eap_peer_sm_step - Step EAP peer state machine - * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init() - * Returns: 1 if EAP state was changed or 0 if not - * - * This function advances EAP state machine to a new state to match with the - * current variables. This should be called whenever variables used by the EAP - * state machine have changed. - */ -int eap_peer_sm_step(struct eap_sm *sm) -{ - int res = 0; - do { - sm->changed = FALSE; - SM_STEP_RUN(EAP); - if (sm->changed) - res = 1; - } while (sm->changed); - return res; -} - - -/** - * eap_sm_abort - Abort EAP authentication - * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init() - * - * Release system resources that have been allocated for the authentication - * session without fully deinitializing the EAP state machine. - */ -void eap_sm_abort(struct eap_sm *sm) -{ - wpabuf_free(sm->lastRespData); - sm->lastRespData = NULL; - wpabuf_free(sm->eapRespData); - sm->eapRespData = NULL; - os_free(sm->eapKeyData); - sm->eapKeyData = NULL; - - /* This is not clearly specified in the EAP statemachines draft, but - * it seems necessary to make sure that some of the EAPOL variables get - * cleared for the next authentication. */ - eapol_set_bool(sm, EAPOL_eapSuccess, FALSE); -} - - -#ifdef CONFIG_CTRL_IFACE -static const char * eap_sm_state_txt(int state) -{ - switch (state) { - case EAP_INITIALIZE: - return "INITIALIZE"; - case EAP_DISABLED: - return "DISABLED"; - case EAP_IDLE: - return "IDLE"; - case EAP_RECEIVED: - return "RECEIVED"; - case EAP_GET_METHOD: - return "GET_METHOD"; - case EAP_METHOD: - return "METHOD"; - case EAP_SEND_RESPONSE: - return "SEND_RESPONSE"; - case EAP_DISCARD: - return "DISCARD"; - case EAP_IDENTITY: - return "IDENTITY"; - case EAP_NOTIFICATION: - return "NOTIFICATION"; - case EAP_RETRANSMIT: - return "RETRANSMIT"; - case EAP_SUCCESS: - return "SUCCESS"; - case EAP_FAILURE: - return "FAILURE"; - default: - return "UNKNOWN"; - } -} -#endif /* CONFIG_CTRL_IFACE */ - - -#if defined(CONFIG_CTRL_IFACE) || !defined(CONFIG_NO_STDOUT_DEBUG) -static const char * eap_sm_method_state_txt(EapMethodState state) -{ - switch (state) { - case METHOD_NONE: - return "NONE"; - case METHOD_INIT: - return "INIT"; - case METHOD_CONT: - return "CONT"; - case METHOD_MAY_CONT: - return "MAY_CONT"; - case METHOD_DONE: - return "DONE"; - default: - return "UNKNOWN"; - } -} - - -static const char * eap_sm_decision_txt(EapDecision decision) -{ - switch (decision) { - case DECISION_FAIL: - return "FAIL"; - case DECISION_COND_SUCC: - return "COND_SUCC"; - case DECISION_UNCOND_SUCC: - return "UNCOND_SUCC"; - default: - return "UNKNOWN"; - } -} -#endif /* CONFIG_CTRL_IFACE || !CONFIG_NO_STDOUT_DEBUG */ - - -#ifdef CONFIG_CTRL_IFACE - -/** - * eap_sm_get_status - Get EAP state machine status - * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init() - * @buf: Buffer for status information - * @buflen: Maximum buffer length - * @verbose: Whether to include verbose status information - * Returns: Number of bytes written to buf. - * - * Query EAP state machine for status information. This function fills in a - * text area with current status information from the EAPOL state machine. If - * the buffer (buf) is not large enough, status information will be truncated - * to fit the buffer. - */ -int eap_sm_get_status(struct eap_sm *sm, char *buf, size_t buflen, int verbose) -{ - int len, ret; - - if (sm == NULL) - return 0; - - len = os_snprintf(buf, buflen, - "EAP state=%s\n", - eap_sm_state_txt(sm->EAP_state)); - if (len < 0 || (size_t) len >= buflen) - return 0; - - if (sm->selectedMethod != EAP_TYPE_NONE) { - const char *name; - if (sm->m) { - name = sm->m->name; - } else { - const struct eap_method *m = - eap_peer_get_eap_method(EAP_VENDOR_IETF, - sm->selectedMethod); - if (m) - name = m->name; - else - name = "?"; - } - ret = os_snprintf(buf + len, buflen - len, - "selectedMethod=%d (EAP-%s)\n", - sm->selectedMethod, name); - if (ret < 0 || (size_t) ret >= buflen - len) - return len; - len += ret; - - if (sm->m && sm->m->get_status) { - len += sm->m->get_status(sm, sm->eap_method_priv, - buf + len, buflen - len, - verbose); - } - } - - if (verbose) { - ret = os_snprintf(buf + len, buflen - len, - "reqMethod=%d\n" - "methodState=%s\n" - "decision=%s\n" - "ClientTimeout=%d\n", - sm->reqMethod, - eap_sm_method_state_txt(sm->methodState), - eap_sm_decision_txt(sm->decision), - sm->ClientTimeout); - if (ret < 0 || (size_t) ret >= buflen - len) - return len; - len += ret; - } - - return len; -} -#endif /* CONFIG_CTRL_IFACE */ - - -#if defined(CONFIG_CTRL_IFACE) || !defined(CONFIG_NO_STDOUT_DEBUG) -typedef enum { - TYPE_IDENTITY, TYPE_PASSWORD, TYPE_OTP, TYPE_PIN, TYPE_NEW_PASSWORD, - TYPE_PASSPHRASE -} eap_ctrl_req_type; - -static void eap_sm_request(struct eap_sm *sm, eap_ctrl_req_type type, - const char *msg, size_t msglen) -{ - struct eap_peer_config *config; - char *field, *txt, *tmp; - - if (sm == NULL) - return; - config = eap_get_config(sm); - if (config == NULL) - return; - - switch (type) { - case TYPE_IDENTITY: - field = "IDENTITY"; - txt = "Identity"; - config->pending_req_identity++; - break; - case TYPE_PASSWORD: - field = "PASSWORD"; - txt = "Password"; - config->pending_req_password++; - break; - case TYPE_NEW_PASSWORD: - field = "NEW_PASSWORD"; - txt = "New Password"; - config->pending_req_new_password++; - break; - case TYPE_PIN: - field = "PIN"; - txt = "PIN"; - config->pending_req_pin++; - break; - case TYPE_OTP: - field = "OTP"; - if (msg) { - tmp = os_malloc(msglen + 3); - if (tmp == NULL) - return; - tmp[0] = '['; - os_memcpy(tmp + 1, msg, msglen); - tmp[msglen + 1] = ']'; - tmp[msglen + 2] = '\0'; - txt = tmp; - os_free(config->pending_req_otp); - config->pending_req_otp = tmp; - config->pending_req_otp_len = msglen + 3; - } else { - if (config->pending_req_otp == NULL) - return; - txt = config->pending_req_otp; - } - break; - case TYPE_PASSPHRASE: - field = "PASSPHRASE"; - txt = "Private key passphrase"; - config->pending_req_passphrase++; - break; - default: - return; - } - - if (sm->eapol_cb->eap_param_needed) - sm->eapol_cb->eap_param_needed(sm->eapol_ctx, field, txt); -} -#else /* CONFIG_CTRL_IFACE || !CONFIG_NO_STDOUT_DEBUG */ -#define eap_sm_request(sm, type, msg, msglen) do { } while (0) -#endif /* CONFIG_CTRL_IFACE || !CONFIG_NO_STDOUT_DEBUG */ - -const char * eap_sm_get_method_name(struct eap_sm *sm) -{ - if (sm->m == NULL) - return "UNKNOWN"; - return sm->m->name; -} - - -/** - * eap_sm_request_identity - Request identity from user (ctrl_iface) - * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init() - * - * EAP methods can call this function to request identity information for the - * current network. This is normally called when the identity is not included - * in the network configuration. The request will be sent to monitor programs - * through the control interface. - */ -void eap_sm_request_identity(struct eap_sm *sm) -{ - eap_sm_request(sm, TYPE_IDENTITY, NULL, 0); -} - - -/** - * eap_sm_request_password - Request password from user (ctrl_iface) - * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init() - * - * EAP methods can call this function to request password information for the - * current network. This is normally called when the password is not included - * in the network configuration. The request will be sent to monitor programs - * through the control interface. - */ -void eap_sm_request_password(struct eap_sm *sm) -{ - eap_sm_request(sm, TYPE_PASSWORD, NULL, 0); -} - - -/** - * eap_sm_request_new_password - Request new password from user (ctrl_iface) - * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init() - * - * EAP methods can call this function to request new password information for - * the current network. This is normally called when the EAP method indicates - * that the current password has expired and password change is required. The - * request will be sent to monitor programs through the control interface. - */ -void eap_sm_request_new_password(struct eap_sm *sm) -{ - eap_sm_request(sm, TYPE_NEW_PASSWORD, NULL, 0); -} - - -/** - * eap_sm_request_pin - Request SIM or smart card PIN from user (ctrl_iface) - * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init() - * - * EAP methods can call this function to request SIM or smart card PIN - * information for the current network. This is normally called when the PIN is - * not included in the network configuration. The request will be sent to - * monitor programs through the control interface. - */ -void eap_sm_request_pin(struct eap_sm *sm) -{ - eap_sm_request(sm, TYPE_PIN, NULL, 0); -} - - -/** - * eap_sm_request_otp - Request one time password from user (ctrl_iface) - * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init() - * @msg: Message to be displayed to the user when asking for OTP - * @msg_len: Length of the user displayable message - * - * EAP methods can call this function to request open time password (OTP) for - * the current network. The request will be sent to monitor programs through - * the control interface. - */ -void eap_sm_request_otp(struct eap_sm *sm, const char *msg, size_t msg_len) -{ - eap_sm_request(sm, TYPE_OTP, msg, msg_len); -} - - -/** - * eap_sm_request_passphrase - Request passphrase from user (ctrl_iface) - * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init() - * - * EAP methods can call this function to request passphrase for a private key - * for the current network. This is normally called when the passphrase is not - * included in the network configuration. The request will be sent to monitor - * programs through the control interface. - */ -void eap_sm_request_passphrase(struct eap_sm *sm) -{ - eap_sm_request(sm, TYPE_PASSPHRASE, NULL, 0); -} - - -/** - * eap_sm_notify_ctrl_attached - Notification of attached monitor - * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init() - * - * Notify EAP state machines that a monitor was attached to the control - * interface to trigger re-sending of pending requests for user input. - */ -void eap_sm_notify_ctrl_attached(struct eap_sm *sm) -{ - struct eap_peer_config *config = eap_get_config(sm); - - if (config == NULL) - return; - - /* Re-send any pending requests for user data since a new control - * interface was added. This handles cases where the EAP authentication - * starts immediately after system startup when the user interface is - * not yet running. */ - if (config->pending_req_identity) - eap_sm_request_identity(sm); - if (config->pending_req_password) - eap_sm_request_password(sm); - if (config->pending_req_new_password) - eap_sm_request_new_password(sm); - if (config->pending_req_otp) - eap_sm_request_otp(sm, NULL, 0); - if (config->pending_req_pin) - eap_sm_request_pin(sm); - if (config->pending_req_passphrase) - eap_sm_request_passphrase(sm); -} - - -static int eap_allowed_phase2_type(int vendor, int type) -{ - if (vendor != EAP_VENDOR_IETF) - return 0; - return type != EAP_TYPE_PEAP && type != EAP_TYPE_TTLS && - type != EAP_TYPE_FAST; -} - - -/** - * eap_get_phase2_type - Get EAP type for the given EAP phase 2 method name - * @name: EAP method name, e.g., MD5 - * @vendor: Buffer for returning EAP Vendor-Id - * Returns: EAP method type or %EAP_TYPE_NONE if not found - * - * This function maps EAP type names into EAP type numbers that are allowed for - * Phase 2, i.e., for tunneled authentication. Phase 2 is used, e.g., with - * EAP-PEAP, EAP-TTLS, and EAP-FAST. - */ -u32 eap_get_phase2_type(const char *name, int *vendor) -{ - int v; - u8 type = eap_peer_get_type(name, &v); - if (eap_allowed_phase2_type(v, type)) { - *vendor = v; - return type; - } - *vendor = EAP_VENDOR_IETF; - return EAP_TYPE_NONE; -} - - -/** - * eap_get_phase2_types - Get list of allowed EAP phase 2 types - * @config: Pointer to a network configuration - * @count: Pointer to a variable to be filled with number of returned EAP types - * Returns: Pointer to allocated type list or %NULL on failure - * - * This function generates an array of allowed EAP phase 2 (tunneled) types for - * the given network configuration. - */ -struct eap_method_type * eap_get_phase2_types(struct eap_peer_config *config, - size_t *count) -{ - struct eap_method_type *buf; - u32 method; - int vendor; - size_t mcount; - const struct eap_method *methods, *m; - - methods = eap_peer_get_methods(&mcount); - if (methods == NULL) - return NULL; - *count = 0; - buf = os_malloc(mcount * sizeof(struct eap_method_type)); - if (buf == NULL) - return NULL; - - for (m = methods; m; m = m->next) { - vendor = m->vendor; - method = m->method; - if (eap_allowed_phase2_type(vendor, method)) { - if (vendor == EAP_VENDOR_IETF && - method == EAP_TYPE_TLS && config && - config->private_key2 == NULL) - continue; - buf[*count].vendor = vendor; - buf[*count].method = method; - (*count)++; - } - } - - return buf; -} - - -/** - * eap_set_fast_reauth - Update fast_reauth setting - * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init() - * @enabled: 1 = Fast reauthentication is enabled, 0 = Disabled - */ -void eap_set_fast_reauth(struct eap_sm *sm, int enabled) -{ - sm->fast_reauth = enabled; -} - - -/** - * eap_set_workaround - Update EAP workarounds setting - * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init() - * @workaround: 1 = Enable EAP workarounds, 0 = Disable EAP workarounds - */ -void eap_set_workaround(struct eap_sm *sm, unsigned int workaround) -{ - sm->workaround = workaround; -} - - -/** - * eap_get_config - Get current network configuration - * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init() - * Returns: Pointer to the current network configuration or %NULL if not found - * - * EAP peer methods should avoid using this function if they can use other - * access functions, like eap_get_config_identity() and - * eap_get_config_password(), that do not require direct access to - * struct eap_peer_config. - */ -struct eap_peer_config * eap_get_config(struct eap_sm *sm) -{ - return sm->eapol_cb->get_config(sm->eapol_ctx); -} - - -/** - * eap_get_config_identity - Get identity from the network configuration - * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init() - * @len: Buffer for the length of the identity - * Returns: Pointer to the identity or %NULL if not found - */ -const u8 * eap_get_config_identity(struct eap_sm *sm, size_t *len) -{ - struct eap_peer_config *config = eap_get_config(sm); - if (config == NULL) - return NULL; - *len = config->identity_len; - return config->identity; -} - - -/** - * eap_get_config_password - Get password from the network configuration - * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init() - * @len: Buffer for the length of the password - * Returns: Pointer to the password or %NULL if not found - */ -const u8 * eap_get_config_password(struct eap_sm *sm, size_t *len) -{ - struct eap_peer_config *config = eap_get_config(sm); - if (config == NULL) - return NULL; - *len = config->password_len; - return config->password; -} - - -/** - * eap_get_config_password2 - Get password from the network configuration - * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init() - * @len: Buffer for the length of the password - * @hash: Buffer for returning whether the password is stored as a - * NtPasswordHash instead of plaintext password; can be %NULL if this - * information is not needed - * Returns: Pointer to the password or %NULL if not found - */ -const u8 * eap_get_config_password2(struct eap_sm *sm, size_t *len, int *hash) -{ - struct eap_peer_config *config = eap_get_config(sm); - if (config == NULL) - return NULL; - *len = config->password_len; - if (hash) - *hash = !!(config->flags & EAP_CONFIG_FLAGS_PASSWORD_NTHASH); - return config->password; -} - - -/** - * eap_get_config_new_password - Get new password from network configuration - * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init() - * @len: Buffer for the length of the new password - * Returns: Pointer to the new password or %NULL if not found - */ -const u8 * eap_get_config_new_password(struct eap_sm *sm, size_t *len) -{ - struct eap_peer_config *config = eap_get_config(sm); - if (config == NULL) - return NULL; - *len = config->new_password_len; - return config->new_password; -} - - -/** - * eap_get_config_otp - Get one-time password from the network configuration - * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init() - * @len: Buffer for the length of the one-time password - * Returns: Pointer to the one-time password or %NULL if not found - */ -const u8 * eap_get_config_otp(struct eap_sm *sm, size_t *len) -{ - struct eap_peer_config *config = eap_get_config(sm); - if (config == NULL) - return NULL; - *len = config->otp_len; - return config->otp; -} - - -/** - * eap_clear_config_otp - Clear used one-time password - * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init() - * - * This function clears a used one-time password (OTP) from the current network - * configuration. This should be called when the OTP has been used and is not - * needed anymore. - */ -void eap_clear_config_otp(struct eap_sm *sm) -{ - struct eap_peer_config *config = eap_get_config(sm); - if (config == NULL) - return; - os_memset(config->otp, 0, config->otp_len); - os_free(config->otp); - config->otp = NULL; - config->otp_len = 0; -} - - -/** - * eap_get_config_phase1 - Get phase1 data from the network configuration - * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init() - * Returns: Pointer to the phase1 data or %NULL if not found - */ -const char * eap_get_config_phase1(struct eap_sm *sm) -{ - struct eap_peer_config *config = eap_get_config(sm); - if (config == NULL) - return NULL; - return config->phase1; -} - - -/** - * eap_get_config_phase2 - Get phase2 data from the network configuration - * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init() - * Returns: Pointer to the phase1 data or %NULL if not found - */ -const char * eap_get_config_phase2(struct eap_sm *sm) -{ - struct eap_peer_config *config = eap_get_config(sm); - if (config == NULL) - return NULL; - return config->phase2; -} - - -int eap_get_config_fragment_size(struct eap_sm *sm) -{ - struct eap_peer_config *config = eap_get_config(sm); - if (config == NULL) - return -1; - return config->fragment_size; -} - - -/** - * eap_key_available - Get key availability (eapKeyAvailable variable) - * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init() - * Returns: 1 if EAP keying material is available, 0 if not - */ -int eap_key_available(struct eap_sm *sm) -{ - return sm ? sm->eapKeyAvailable : 0; -} - - -/** - * eap_notify_success - Notify EAP state machine about external success trigger - * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init() - * - * This function is called when external event, e.g., successful completion of - * WPA-PSK key handshake, is indicating that EAP state machine should move to - * success state. This is mainly used with security modes that do not use EAP - * state machine (e.g., WPA-PSK). - */ -void eap_notify_success(struct eap_sm *sm) -{ - if (sm) { - sm->decision = DECISION_COND_SUCC; - sm->EAP_state = EAP_SUCCESS; - } -} - - -/** - * eap_notify_lower_layer_success - Notification of lower layer success - * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init() - * - * Notify EAP state machines that a lower layer has detected a successful - * authentication. This is used to recover from dropped EAP-Success messages. - */ -void eap_notify_lower_layer_success(struct eap_sm *sm) -{ - if (sm == NULL) - return; - - if (eapol_get_bool(sm, EAPOL_eapSuccess) || - sm->decision == DECISION_FAIL || - (sm->methodState != METHOD_MAY_CONT && - sm->methodState != METHOD_DONE)) - return; - - if (sm->eapKeyData != NULL) - sm->eapKeyAvailable = TRUE; - eapol_set_bool(sm, EAPOL_eapSuccess, TRUE); - wpa_msg(sm->msg_ctx, MSG_INFO, WPA_EVENT_EAP_SUCCESS - "EAP authentication completed successfully (based on lower " - "layer success)"); -} - - -/** - * eap_get_eapKeyData - Get master session key (MSK) from EAP state machine - * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init() - * @len: Pointer to variable that will be set to number of bytes in the key - * Returns: Pointer to the EAP keying data or %NULL on failure - * - * Fetch EAP keying material (MSK, eapKeyData) from the EAP state machine. The - * key is available only after a successful authentication. EAP state machine - * continues to manage the key data and the caller must not change or free the - * returned data. - */ -const u8 * eap_get_eapKeyData(struct eap_sm *sm, size_t *len) -{ - if (sm == NULL || sm->eapKeyData == NULL) { - *len = 0; - return NULL; - } - - *len = sm->eapKeyDataLen; - return sm->eapKeyData; -} - - -/** - * eap_get_eapKeyData - Get EAP response data - * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init() - * Returns: Pointer to the EAP response (eapRespData) or %NULL on failure - * - * Fetch EAP response (eapRespData) from the EAP state machine. This data is - * available when EAP state machine has processed an incoming EAP request. The - * EAP state machine does not maintain a reference to the response after this - * function is called and the caller is responsible for freeing the data. - */ -struct wpabuf * eap_get_eapRespData(struct eap_sm *sm) -{ - struct wpabuf *resp; - - if (sm == NULL || sm->eapRespData == NULL) - return NULL; - - resp = sm->eapRespData; - sm->eapRespData = NULL; - - return resp; -} - - -/** - * eap_sm_register_scard_ctx - Notification of smart card context - * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init() - * @ctx: Context data for smart card operations - * - * Notify EAP state machines of context data for smart card operations. This - * context data will be used as a parameter for scard_*() functions. - */ -void eap_register_scard_ctx(struct eap_sm *sm, void *ctx) -{ - if (sm) - sm->scard_ctx = ctx; -} - - -/** - * eap_set_config_blob - Set or add a named configuration blob - * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init() - * @blob: New value for the blob - * - * Adds a new configuration blob or replaces the current value of an existing - * blob. - */ -void eap_set_config_blob(struct eap_sm *sm, struct wpa_config_blob *blob) -{ -#ifndef CONFIG_NO_CONFIG_BLOBS - sm->eapol_cb->set_config_blob(sm->eapol_ctx, blob); -#endif /* CONFIG_NO_CONFIG_BLOBS */ -} - - -/** - * eap_get_config_blob - Get a named configuration blob - * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init() - * @name: Name of the blob - * Returns: Pointer to blob data or %NULL if not found - */ -const struct wpa_config_blob * eap_get_config_blob(struct eap_sm *sm, - const char *name) -{ -#ifndef CONFIG_NO_CONFIG_BLOBS - return sm->eapol_cb->get_config_blob(sm->eapol_ctx, name); -#else /* CONFIG_NO_CONFIG_BLOBS */ - return NULL; -#endif /* CONFIG_NO_CONFIG_BLOBS */ -} - - -/** - * eap_set_force_disabled - Set force_disabled flag - * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init() - * @disabled: 1 = EAP disabled, 0 = EAP enabled - * - * This function is used to force EAP state machine to be disabled when it is - * not in use (e.g., with WPA-PSK or plaintext connections). - */ -void eap_set_force_disabled(struct eap_sm *sm, int disabled) -{ - sm->force_disabled = disabled; -} - - - /** - * eap_notify_pending - Notify that EAP method is ready to re-process a request - * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init() - * - * An EAP method can perform a pending operation (e.g., to get a response from - * an external process). Once the response is available, this function can be - * used to request EAPOL state machine to retry delivering the previously - * received (and still unanswered) EAP request to EAP state machine. - */ -void eap_notify_pending(struct eap_sm *sm) -{ - sm->eapol_cb->notify_pending(sm->eapol_ctx); -} - - -/** - * eap_invalidate_cached_session - Mark cached session data invalid - * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init() - */ -void eap_invalidate_cached_session(struct eap_sm *sm) -{ - if (sm) - eap_deinit_prev_method(sm, "invalidate"); -} - - -int eap_is_wps_pbc_enrollee(struct eap_peer_config *conf) -{ - if (conf->identity_len != WSC_ID_ENROLLEE_LEN || - os_memcmp(conf->identity, WSC_ID_ENROLLEE, WSC_ID_ENROLLEE_LEN)) - return 0; /* Not a WPS Enrollee */ - - if (conf->phase1 == NULL || os_strstr(conf->phase1, "pbc=1") == NULL) - return 0; /* Not using PBC */ - - return 1; -} - - -int eap_is_wps_pin_enrollee(struct eap_peer_config *conf) -{ - if (conf->identity_len != WSC_ID_ENROLLEE_LEN || - os_memcmp(conf->identity, WSC_ID_ENROLLEE, WSC_ID_ENROLLEE_LEN)) - return 0; /* Not a WPS Enrollee */ - - if (conf->phase1 == NULL || os_strstr(conf->phase1, "pin=") == NULL) - return 0; /* Not using PIN */ - - return 1; -} diff --git a/hostapd-0.8/src/eap_peer/eap.h b/hostapd-0.8/src/eap_peer/eap.h deleted file mode 100644 index 3550909..0000000 --- a/hostapd-0.8/src/eap_peer/eap.h +++ /dev/null @@ -1,292 +0,0 @@ -/* - * EAP peer state machine functions (RFC 4137) - * Copyright (c) 2004-2007, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#ifndef EAP_H -#define EAP_H - -#include "common/defs.h" -#include "eap_common/eap_defs.h" -#include "eap_peer/eap_methods.h" - -struct eap_sm; -struct wpa_config_blob; -struct wpabuf; - -struct eap_method_type { - int vendor; - u32 method; -}; - -#ifdef IEEE8021X_EAPOL - -/** - * enum eapol_bool_var - EAPOL boolean state variables for EAP state machine - * - * These variables are used in the interface between EAP peer state machine and - * lower layer. These are defined in RFC 4137, Sect. 4.1. Lower layer code is - * expected to maintain these variables and register a callback functions for - * EAP state machine to get and set the variables. - */ -enum eapol_bool_var { - /** - * EAPOL_eapSuccess - EAP SUCCESS state reached - * - * EAP state machine reads and writes this value. - */ - EAPOL_eapSuccess, - - /** - * EAPOL_eapRestart - Lower layer request to restart authentication - * - * Set to TRUE in lower layer, FALSE in EAP state machine. - */ - EAPOL_eapRestart, - - /** - * EAPOL_eapFail - EAP FAILURE state reached - * - * EAP state machine writes this value. - */ - EAPOL_eapFail, - - /** - * EAPOL_eapResp - Response to send - * - * Set to TRUE in EAP state machine, FALSE in lower layer. - */ - EAPOL_eapResp, - - /** - * EAPOL_eapNoResp - Request has been process; no response to send - * - * Set to TRUE in EAP state machine, FALSE in lower layer. - */ - EAPOL_eapNoResp, - - /** - * EAPOL_eapReq - EAP request available from lower layer - * - * Set to TRUE in lower layer, FALSE in EAP state machine. - */ - EAPOL_eapReq, - - /** - * EAPOL_portEnabled - Lower layer is ready for communication - * - * EAP state machines reads this value. - */ - EAPOL_portEnabled, - - /** - * EAPOL_altAccept - Alternate indication of success (RFC3748) - * - * EAP state machines reads this value. - */ - EAPOL_altAccept, - - /** - * EAPOL_altReject - Alternate indication of failure (RFC3748) - * - * EAP state machines reads this value. - */ - EAPOL_altReject -}; - -/** - * enum eapol_int_var - EAPOL integer state variables for EAP state machine - * - * These variables are used in the interface between EAP peer state machine and - * lower layer. These are defined in RFC 4137, Sect. 4.1. Lower layer code is - * expected to maintain these variables and register a callback functions for - * EAP state machine to get and set the variables. - */ -enum eapol_int_var { - /** - * EAPOL_idleWhile - Outside time for EAP peer timeout - * - * This integer variable is used to provide an outside timer that the - * external (to EAP state machine) code must decrement by one every - * second until the value reaches zero. This is used in the same way as - * EAPOL state machine timers. EAP state machine reads and writes this - * value. - */ - EAPOL_idleWhile -}; - -/** - * struct eapol_callbacks - Callback functions from EAP to lower layer - * - * This structure defines the callback functions that EAP state machine - * requires from the lower layer (usually EAPOL state machine) for updating - * state variables and requesting information. eapol_ctx from - * eap_peer_sm_init() call will be used as the ctx parameter for these - * callback functions. - */ -struct eapol_callbacks { - /** - * get_config - Get pointer to the current network configuration - * @ctx: eapol_ctx from eap_peer_sm_init() call - */ - struct eap_peer_config * (*get_config)(void *ctx); - - /** - * get_bool - Get a boolean EAPOL state variable - * @variable: EAPOL boolean variable to get - * Returns: Value of the EAPOL variable - */ - Boolean (*get_bool)(void *ctx, enum eapol_bool_var variable); - - /** - * set_bool - Set a boolean EAPOL state variable - * @ctx: eapol_ctx from eap_peer_sm_init() call - * @variable: EAPOL boolean variable to set - * @value: Value for the EAPOL variable - */ - void (*set_bool)(void *ctx, enum eapol_bool_var variable, - Boolean value); - - /** - * get_int - Get an integer EAPOL state variable - * @ctx: eapol_ctx from eap_peer_sm_init() call - * @variable: EAPOL integer variable to get - * Returns: Value of the EAPOL variable - */ - unsigned int (*get_int)(void *ctx, enum eapol_int_var variable); - - /** - * set_int - Set an integer EAPOL state variable - * @ctx: eapol_ctx from eap_peer_sm_init() call - * @variable: EAPOL integer variable to set - * @value: Value for the EAPOL variable - */ - void (*set_int)(void *ctx, enum eapol_int_var variable, - unsigned int value); - - /** - * get_eapReqData - Get EAP-Request data - * @ctx: eapol_ctx from eap_peer_sm_init() call - * @len: Pointer to variable that will be set to eapReqDataLen - * Returns: Reference to eapReqData (EAP state machine will not free - * this) or %NULL if eapReqData not available. - */ - struct wpabuf * (*get_eapReqData)(void *ctx); - - /** - * set_config_blob - Set named configuration blob - * @ctx: eapol_ctx from eap_peer_sm_init() call - * @blob: New value for the blob - * - * Adds a new configuration blob or replaces the current value of an - * existing blob. - */ - void (*set_config_blob)(void *ctx, struct wpa_config_blob *blob); - - /** - * get_config_blob - Get a named configuration blob - * @ctx: eapol_ctx from eap_peer_sm_init() call - * @name: Name of the blob - * Returns: Pointer to blob data or %NULL if not found - */ - const struct wpa_config_blob * (*get_config_blob)(void *ctx, - const char *name); - - /** - * notify_pending - Notify that a pending request can be retried - * @ctx: eapol_ctx from eap_peer_sm_init() call - * - * An EAP method can perform a pending operation (e.g., to get a - * response from an external process). Once the response is available, - * this callback function can be used to request EAPOL state machine to - * retry delivering the previously received (and still unanswered) EAP - * request to EAP state machine. - */ - void (*notify_pending)(void *ctx); - - /** - * eap_param_needed - Notify that EAP parameter is needed - * @ctx: eapol_ctx from eap_peer_sm_init() call - * @field: Field name (e.g., "IDENTITY") - * @txt: User readable text describing the required parameter - */ - void (*eap_param_needed)(void *ctx, const char *field, - const char *txt); -}; - -/** - * struct eap_config - Configuration for EAP state machine - */ -struct eap_config { - /** - * opensc_engine_path - OpenSC engine for OpenSSL engine support - * - * Usually, path to engine_opensc.so. - */ - const char *opensc_engine_path; - /** - * pkcs11_engine_path - PKCS#11 engine for OpenSSL engine support - * - * Usually, path to engine_pkcs11.so. - */ - const char *pkcs11_engine_path; - /** - * pkcs11_module_path - OpenSC PKCS#11 module for OpenSSL engine - * - * Usually, path to opensc-pkcs11.so. - */ - const char *pkcs11_module_path; - /** - * wps - WPS context data - * - * This is only used by EAP-WSC and can be left %NULL if not available. - */ - struct wps_context *wps; -}; - -struct eap_sm * eap_peer_sm_init(void *eapol_ctx, - struct eapol_callbacks *eapol_cb, - void *msg_ctx, struct eap_config *conf); -void eap_peer_sm_deinit(struct eap_sm *sm); -int eap_peer_sm_step(struct eap_sm *sm); -void eap_sm_abort(struct eap_sm *sm); -int eap_sm_get_status(struct eap_sm *sm, char *buf, size_t buflen, - int verbose); -const char * eap_sm_get_method_name(struct eap_sm *sm); -struct wpabuf * eap_sm_buildIdentity(struct eap_sm *sm, int id, int encrypted); -void eap_sm_request_identity(struct eap_sm *sm); -void eap_sm_request_password(struct eap_sm *sm); -void eap_sm_request_new_password(struct eap_sm *sm); -void eap_sm_request_pin(struct eap_sm *sm); -void eap_sm_request_otp(struct eap_sm *sm, const char *msg, size_t msg_len); -void eap_sm_request_passphrase(struct eap_sm *sm); -void eap_sm_notify_ctrl_attached(struct eap_sm *sm); -u32 eap_get_phase2_type(const char *name, int *vendor); -struct eap_method_type * eap_get_phase2_types(struct eap_peer_config *config, - size_t *count); -void eap_set_fast_reauth(struct eap_sm *sm, int enabled); -void eap_set_workaround(struct eap_sm *sm, unsigned int workaround); -void eap_set_force_disabled(struct eap_sm *sm, int disabled); -int eap_key_available(struct eap_sm *sm); -void eap_notify_success(struct eap_sm *sm); -void eap_notify_lower_layer_success(struct eap_sm *sm); -const u8 * eap_get_eapKeyData(struct eap_sm *sm, size_t *len); -struct wpabuf * eap_get_eapRespData(struct eap_sm *sm); -void eap_register_scard_ctx(struct eap_sm *sm, void *ctx); -void eap_invalidate_cached_session(struct eap_sm *sm); - -int eap_is_wps_pbc_enrollee(struct eap_peer_config *conf); -int eap_is_wps_pin_enrollee(struct eap_peer_config *conf); - -#endif /* IEEE8021X_EAPOL */ - -#endif /* EAP_H */ diff --git a/hostapd-0.8/src/eap_peer/eap_aka.c b/hostapd-0.8/src/eap_peer/eap_aka.c deleted file mode 100644 index 182f01a..0000000 --- a/hostapd-0.8/src/eap_peer/eap_aka.c +++ /dev/null @@ -1,1389 +0,0 @@ -/* - * EAP peer method: EAP-AKA (RFC 4187) and EAP-AKA' (draft-arkko-eap-aka-kdf) - * Copyright (c) 2004-2008, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#include "includes.h" - -#include "common.h" -#include "pcsc_funcs.h" -#include "crypto/crypto.h" -#include "crypto/sha1.h" -#include "crypto/sha256.h" -#include "crypto/milenage.h" -#include "eap_common/eap_sim_common.h" -#include "eap_config.h" -#include "eap_i.h" - - -struct eap_aka_data { - u8 ik[EAP_AKA_IK_LEN], ck[EAP_AKA_CK_LEN], res[EAP_AKA_RES_MAX_LEN]; - size_t res_len; - u8 nonce_s[EAP_SIM_NONCE_S_LEN]; - u8 mk[EAP_SIM_MK_LEN]; - u8 k_aut[EAP_AKA_PRIME_K_AUT_LEN]; - u8 k_encr[EAP_SIM_K_ENCR_LEN]; - u8 k_re[EAP_AKA_PRIME_K_RE_LEN]; /* EAP-AKA' only */ - u8 msk[EAP_SIM_KEYING_DATA_LEN]; - u8 emsk[EAP_EMSK_LEN]; - u8 rand[EAP_AKA_RAND_LEN], autn[EAP_AKA_AUTN_LEN]; - u8 auts[EAP_AKA_AUTS_LEN]; - - int num_id_req, num_notification; - u8 *pseudonym; - size_t pseudonym_len; - u8 *reauth_id; - size_t reauth_id_len; - int reauth; - unsigned int counter, counter_too_small; - u8 *last_eap_identity; - size_t last_eap_identity_len; - enum { - CONTINUE, RESULT_SUCCESS, RESULT_FAILURE, SUCCESS, FAILURE - } state; - - struct wpabuf *id_msgs; - int prev_id; - int result_ind, use_result_ind; - u8 eap_method; - u8 *network_name; - size_t network_name_len; - u16 kdf; - int kdf_negotiation; -}; - - -#ifndef CONFIG_NO_STDOUT_DEBUG -static const char * eap_aka_state_txt(int state) -{ - switch (state) { - case CONTINUE: - return "CONTINUE"; - case RESULT_SUCCESS: - return "RESULT_SUCCESS"; - case RESULT_FAILURE: - return "RESULT_FAILURE"; - case SUCCESS: - return "SUCCESS"; - case FAILURE: - return "FAILURE"; - default: - return "?"; - } -} -#endif /* CONFIG_NO_STDOUT_DEBUG */ - - -static void eap_aka_state(struct eap_aka_data *data, int state) -{ - wpa_printf(MSG_DEBUG, "EAP-AKA: %s -> %s", - eap_aka_state_txt(data->state), - eap_aka_state_txt(state)); - data->state = state; -} - - -static void * eap_aka_init(struct eap_sm *sm) -{ - struct eap_aka_data *data; - const char *phase1 = eap_get_config_phase1(sm); - - data = os_zalloc(sizeof(*data)); - if (data == NULL) - return NULL; - - data->eap_method = EAP_TYPE_AKA; - - eap_aka_state(data, CONTINUE); - data->prev_id = -1; - - data->result_ind = phase1 && os_strstr(phase1, "result_ind=1") != NULL; - - return data; -} - - -#ifdef EAP_AKA_PRIME -static void * eap_aka_prime_init(struct eap_sm *sm) -{ - struct eap_aka_data *data = eap_aka_init(sm); - if (data == NULL) - return NULL; - data->eap_method = EAP_TYPE_AKA_PRIME; - return data; -} -#endif /* EAP_AKA_PRIME */ - - -static void eap_aka_deinit(struct eap_sm *sm, void *priv) -{ - struct eap_aka_data *data = priv; - if (data) { - os_free(data->pseudonym); - os_free(data->reauth_id); - os_free(data->last_eap_identity); - wpabuf_free(data->id_msgs); - os_free(data->network_name); - os_free(data); - } -} - - -static int eap_aka_umts_auth(struct eap_sm *sm, struct eap_aka_data *data) -{ - struct eap_peer_config *conf; - - wpa_printf(MSG_DEBUG, "EAP-AKA: UMTS authentication algorithm"); - - conf = eap_get_config(sm); - if (conf == NULL) - return -1; - if (conf->pcsc) { - return scard_umts_auth(sm->scard_ctx, data->rand, - data->autn, data->res, &data->res_len, - data->ik, data->ck, data->auts); - } - -#ifdef CONFIG_USIM_SIMULATOR - if (conf->password) { - u8 opc[16], k[16], sqn[6]; - const char *pos; - wpa_printf(MSG_DEBUG, "EAP-AKA: Use internal Milenage " - "implementation for UMTS authentication"); - if (conf->password_len < 78) { - wpa_printf(MSG_DEBUG, "EAP-AKA: invalid Milenage " - "password"); - return -1; - } - pos = (const char *) conf->password; - if (hexstr2bin(pos, k, 16)) - return -1; - pos += 32; - if (*pos != ':') - return -1; - pos++; - - if (hexstr2bin(pos, opc, 16)) - return -1; - pos += 32; - if (*pos != ':') - return -1; - pos++; - - if (hexstr2bin(pos, sqn, 6)) - return -1; - - return milenage_check(opc, k, sqn, data->rand, data->autn, - data->ik, data->ck, - data->res, &data->res_len, data->auts); - } -#endif /* CONFIG_USIM_SIMULATOR */ - -#ifdef CONFIG_USIM_HARDCODED - wpa_printf(MSG_DEBUG, "EAP-AKA: Use hardcoded Kc and SRES values for " - "testing"); - - /* These hardcoded Kc and SRES values are used for testing. - * Could consider making them configurable. */ - os_memset(data->res, '2', EAP_AKA_RES_MAX_LEN); - data->res_len = EAP_AKA_RES_MAX_LEN; - os_memset(data->ik, '3', EAP_AKA_IK_LEN); - os_memset(data->ck, '4', EAP_AKA_CK_LEN); - { - u8 autn[EAP_AKA_AUTN_LEN]; - os_memset(autn, '1', EAP_AKA_AUTN_LEN); - if (os_memcmp(autn, data->autn, EAP_AKA_AUTN_LEN) != 0) { - wpa_printf(MSG_WARNING, "EAP-AKA: AUTN did not match " - "with expected value"); - return -1; - } - } -#if 0 - { - static int test_resync = 1; - if (test_resync) { - /* Test Resynchronization */ - test_resync = 0; - return -2; - } - } -#endif - return 0; - -#else /* CONFIG_USIM_HARDCODED */ - - wpa_printf(MSG_DEBUG, "EAP-AKA: No UMTS authentication algorith " - "enabled"); - return -1; - -#endif /* CONFIG_USIM_HARDCODED */ -} - - -#define CLEAR_PSEUDONYM 0x01 -#define CLEAR_REAUTH_ID 0x02 -#define CLEAR_EAP_ID 0x04 - -static void eap_aka_clear_identities(struct eap_aka_data *data, int id) -{ - wpa_printf(MSG_DEBUG, "EAP-AKA: forgetting old%s%s%s", - id & CLEAR_PSEUDONYM ? " pseudonym" : "", - id & CLEAR_REAUTH_ID ? " reauth_id" : "", - id & CLEAR_EAP_ID ? " eap_id" : ""); - if (id & CLEAR_PSEUDONYM) { - os_free(data->pseudonym); - data->pseudonym = NULL; - data->pseudonym_len = 0; - } - if (id & CLEAR_REAUTH_ID) { - os_free(data->reauth_id); - data->reauth_id = NULL; - data->reauth_id_len = 0; - } - if (id & CLEAR_EAP_ID) { - os_free(data->last_eap_identity); - data->last_eap_identity = NULL; - data->last_eap_identity_len = 0; - } -} - - -static int eap_aka_learn_ids(struct eap_aka_data *data, - struct eap_sim_attrs *attr) -{ - if (attr->next_pseudonym) { - os_free(data->pseudonym); - data->pseudonym = os_malloc(attr->next_pseudonym_len); - if (data->pseudonym == NULL) { - wpa_printf(MSG_INFO, "EAP-AKA: (encr) No memory for " - "next pseudonym"); - return -1; - } - os_memcpy(data->pseudonym, attr->next_pseudonym, - attr->next_pseudonym_len); - data->pseudonym_len = attr->next_pseudonym_len; - wpa_hexdump_ascii(MSG_DEBUG, - "EAP-AKA: (encr) AT_NEXT_PSEUDONYM", - data->pseudonym, - data->pseudonym_len); - } - - if (attr->next_reauth_id) { - os_free(data->reauth_id); - data->reauth_id = os_malloc(attr->next_reauth_id_len); - if (data->reauth_id == NULL) { - wpa_printf(MSG_INFO, "EAP-AKA: (encr) No memory for " - "next reauth_id"); - return -1; - } - os_memcpy(data->reauth_id, attr->next_reauth_id, - attr->next_reauth_id_len); - data->reauth_id_len = attr->next_reauth_id_len; - wpa_hexdump_ascii(MSG_DEBUG, - "EAP-AKA: (encr) AT_NEXT_REAUTH_ID", - data->reauth_id, - data->reauth_id_len); - } - - return 0; -} - - -static int eap_aka_add_id_msg(struct eap_aka_data *data, - const struct wpabuf *msg) -{ - if (msg == NULL) - return -1; - - if (data->id_msgs == NULL) { - data->id_msgs = wpabuf_dup(msg); - return data->id_msgs == NULL ? -1 : 0; - } - - if (wpabuf_resize(&data->id_msgs, wpabuf_len(msg)) < 0) - return -1; - wpabuf_put_buf(data->id_msgs, msg); - - return 0; -} - - -static void eap_aka_add_checkcode(struct eap_aka_data *data, - struct eap_sim_msg *msg) -{ - const u8 *addr; - size_t len; - u8 hash[SHA256_MAC_LEN]; - - wpa_printf(MSG_DEBUG, " AT_CHECKCODE"); - - if (data->id_msgs == NULL) { - /* - * No EAP-AKA/Identity packets were exchanged - send empty - * checkcode. - */ - eap_sim_msg_add(msg, EAP_SIM_AT_CHECKCODE, 0, NULL, 0); - return; - } - - /* Checkcode is SHA1/SHA256 hash over all EAP-AKA/Identity packets. */ - addr = wpabuf_head(data->id_msgs); - len = wpabuf_len(data->id_msgs); - wpa_hexdump(MSG_MSGDUMP, "EAP-AKA: AT_CHECKCODE data", addr, len); -#ifdef EAP_AKA_PRIME - if (data->eap_method == EAP_TYPE_AKA_PRIME) - sha256_vector(1, &addr, &len, hash); - else -#endif /* EAP_AKA_PRIME */ - sha1_vector(1, &addr, &len, hash); - - eap_sim_msg_add(msg, EAP_SIM_AT_CHECKCODE, 0, hash, - data->eap_method == EAP_TYPE_AKA_PRIME ? - EAP_AKA_PRIME_CHECKCODE_LEN : EAP_AKA_CHECKCODE_LEN); -} - - -static int eap_aka_verify_checkcode(struct eap_aka_data *data, - const u8 *checkcode, size_t checkcode_len) -{ - const u8 *addr; - size_t len; - u8 hash[SHA256_MAC_LEN]; - size_t hash_len; - - if (checkcode == NULL) - return -1; - - if (data->id_msgs == NULL) { - if (checkcode_len != 0) { - wpa_printf(MSG_DEBUG, "EAP-AKA: Checkcode from server " - "indicates that AKA/Identity messages were " - "used, but they were not"); - return -1; - } - return 0; - } - - hash_len = data->eap_method == EAP_TYPE_AKA_PRIME ? - EAP_AKA_PRIME_CHECKCODE_LEN : EAP_AKA_CHECKCODE_LEN; - - if (checkcode_len != hash_len) { - wpa_printf(MSG_DEBUG, "EAP-AKA: Checkcode from server " - "indicates that AKA/Identity message were not " - "used, but they were"); - return -1; - } - - /* Checkcode is SHA1/SHA256 hash over all EAP-AKA/Identity packets. */ - addr = wpabuf_head(data->id_msgs); - len = wpabuf_len(data->id_msgs); -#ifdef EAP_AKA_PRIME - if (data->eap_method == EAP_TYPE_AKA_PRIME) - sha256_vector(1, &addr, &len, hash); - else -#endif /* EAP_AKA_PRIME */ - sha1_vector(1, &addr, &len, hash); - - if (os_memcmp(hash, checkcode, hash_len) != 0) { - wpa_printf(MSG_DEBUG, "EAP-AKA: Mismatch in AT_CHECKCODE"); - return -1; - } - - return 0; -} - - -static struct wpabuf * eap_aka_client_error(struct eap_aka_data *data, u8 id, - int err) -{ - struct eap_sim_msg *msg; - - eap_aka_state(data, FAILURE); - data->num_id_req = 0; - data->num_notification = 0; - - msg = eap_sim_msg_init(EAP_CODE_RESPONSE, id, data->eap_method, - EAP_AKA_SUBTYPE_CLIENT_ERROR); - eap_sim_msg_add(msg, EAP_SIM_AT_CLIENT_ERROR_CODE, err, NULL, 0); - return eap_sim_msg_finish(msg, NULL, NULL, 0); -} - - -static struct wpabuf * eap_aka_authentication_reject(struct eap_aka_data *data, - u8 id) -{ - struct eap_sim_msg *msg; - - eap_aka_state(data, FAILURE); - data->num_id_req = 0; - data->num_notification = 0; - - wpa_printf(MSG_DEBUG, "Generating EAP-AKA Authentication-Reject " - "(id=%d)", id); - msg = eap_sim_msg_init(EAP_CODE_RESPONSE, id, data->eap_method, - EAP_AKA_SUBTYPE_AUTHENTICATION_REJECT); - return eap_sim_msg_finish(msg, NULL, NULL, 0); -} - - -static struct wpabuf * eap_aka_synchronization_failure( - struct eap_aka_data *data, u8 id) -{ - struct eap_sim_msg *msg; - - data->num_id_req = 0; - data->num_notification = 0; - - wpa_printf(MSG_DEBUG, "Generating EAP-AKA Synchronization-Failure " - "(id=%d)", id); - msg = eap_sim_msg_init(EAP_CODE_RESPONSE, id, data->eap_method, - EAP_AKA_SUBTYPE_SYNCHRONIZATION_FAILURE); - wpa_printf(MSG_DEBUG, " AT_AUTS"); - eap_sim_msg_add_full(msg, EAP_SIM_AT_AUTS, data->auts, - EAP_AKA_AUTS_LEN); - return eap_sim_msg_finish(msg, NULL, NULL, 0); -} - - -static struct wpabuf * eap_aka_response_identity(struct eap_sm *sm, - struct eap_aka_data *data, - u8 id, - enum eap_sim_id_req id_req) -{ - const u8 *identity = NULL; - size_t identity_len = 0; - struct eap_sim_msg *msg; - - data->reauth = 0; - if (id_req == ANY_ID && data->reauth_id) { - identity = data->reauth_id; - identity_len = data->reauth_id_len; - data->reauth = 1; - } else if ((id_req == ANY_ID || id_req == FULLAUTH_ID) && - data->pseudonym) { - identity = data->pseudonym; - identity_len = data->pseudonym_len; - eap_aka_clear_identities(data, CLEAR_REAUTH_ID); - } else if (id_req != NO_ID_REQ) { - identity = eap_get_config_identity(sm, &identity_len); - if (identity) { - eap_aka_clear_identities(data, CLEAR_PSEUDONYM | - CLEAR_REAUTH_ID); - } - } - if (id_req != NO_ID_REQ) - eap_aka_clear_identities(data, CLEAR_EAP_ID); - - wpa_printf(MSG_DEBUG, "Generating EAP-AKA Identity (id=%d)", id); - msg = eap_sim_msg_init(EAP_CODE_RESPONSE, id, data->eap_method, - EAP_AKA_SUBTYPE_IDENTITY); - - if (identity) { - wpa_hexdump_ascii(MSG_DEBUG, " AT_IDENTITY", - identity, identity_len); - eap_sim_msg_add(msg, EAP_SIM_AT_IDENTITY, identity_len, - identity, identity_len); - } - - return eap_sim_msg_finish(msg, NULL, NULL, 0); -} - - -static struct wpabuf * eap_aka_response_challenge(struct eap_aka_data *data, - u8 id) -{ - struct eap_sim_msg *msg; - - wpa_printf(MSG_DEBUG, "Generating EAP-AKA Challenge (id=%d)", id); - msg = eap_sim_msg_init(EAP_CODE_RESPONSE, id, data->eap_method, - EAP_AKA_SUBTYPE_CHALLENGE); - wpa_printf(MSG_DEBUG, " AT_RES"); - eap_sim_msg_add(msg, EAP_SIM_AT_RES, data->res_len * 8, - data->res, data->res_len); - eap_aka_add_checkcode(data, msg); - if (data->use_result_ind) { - wpa_printf(MSG_DEBUG, " AT_RESULT_IND"); - eap_sim_msg_add(msg, EAP_SIM_AT_RESULT_IND, 0, NULL, 0); - } - wpa_printf(MSG_DEBUG, " AT_MAC"); - eap_sim_msg_add_mac(msg, EAP_SIM_AT_MAC); - return eap_sim_msg_finish(msg, data->k_aut, (u8 *) "", 0); -} - - -static struct wpabuf * eap_aka_response_reauth(struct eap_aka_data *data, - u8 id, int counter_too_small, - const u8 *nonce_s) -{ - struct eap_sim_msg *msg; - unsigned int counter; - - wpa_printf(MSG_DEBUG, "Generating EAP-AKA Reauthentication (id=%d)", - id); - msg = eap_sim_msg_init(EAP_CODE_RESPONSE, id, data->eap_method, - EAP_AKA_SUBTYPE_REAUTHENTICATION); - wpa_printf(MSG_DEBUG, " AT_IV"); - wpa_printf(MSG_DEBUG, " AT_ENCR_DATA"); - eap_sim_msg_add_encr_start(msg, EAP_SIM_AT_IV, EAP_SIM_AT_ENCR_DATA); - - if (counter_too_small) { - wpa_printf(MSG_DEBUG, " *AT_COUNTER_TOO_SMALL"); - eap_sim_msg_add(msg, EAP_SIM_AT_COUNTER_TOO_SMALL, 0, NULL, 0); - counter = data->counter_too_small; - } else - counter = data->counter; - - wpa_printf(MSG_DEBUG, " *AT_COUNTER %d", counter); - eap_sim_msg_add(msg, EAP_SIM_AT_COUNTER, counter, NULL, 0); - - if (eap_sim_msg_add_encr_end(msg, data->k_encr, EAP_SIM_AT_PADDING)) { - wpa_printf(MSG_WARNING, "EAP-AKA: Failed to encrypt " - "AT_ENCR_DATA"); - eap_sim_msg_free(msg); - return NULL; - } - eap_aka_add_checkcode(data, msg); - if (data->use_result_ind) { - wpa_printf(MSG_DEBUG, " AT_RESULT_IND"); - eap_sim_msg_add(msg, EAP_SIM_AT_RESULT_IND, 0, NULL, 0); - } - wpa_printf(MSG_DEBUG, " AT_MAC"); - eap_sim_msg_add_mac(msg, EAP_SIM_AT_MAC); - return eap_sim_msg_finish(msg, data->k_aut, nonce_s, - EAP_SIM_NONCE_S_LEN); -} - - -static struct wpabuf * eap_aka_response_notification(struct eap_aka_data *data, - u8 id, u16 notification) -{ - struct eap_sim_msg *msg; - u8 *k_aut = (notification & 0x4000) == 0 ? data->k_aut : NULL; - - wpa_printf(MSG_DEBUG, "Generating EAP-AKA Notification (id=%d)", id); - msg = eap_sim_msg_init(EAP_CODE_RESPONSE, id, data->eap_method, - EAP_AKA_SUBTYPE_NOTIFICATION); - if (k_aut && data->reauth) { - wpa_printf(MSG_DEBUG, " AT_IV"); - wpa_printf(MSG_DEBUG, " AT_ENCR_DATA"); - eap_sim_msg_add_encr_start(msg, EAP_SIM_AT_IV, - EAP_SIM_AT_ENCR_DATA); - wpa_printf(MSG_DEBUG, " *AT_COUNTER %d", data->counter); - eap_sim_msg_add(msg, EAP_SIM_AT_COUNTER, data->counter, - NULL, 0); - if (eap_sim_msg_add_encr_end(msg, data->k_encr, - EAP_SIM_AT_PADDING)) { - wpa_printf(MSG_WARNING, "EAP-AKA: Failed to encrypt " - "AT_ENCR_DATA"); - eap_sim_msg_free(msg); - return NULL; - } - } - if (k_aut) { - wpa_printf(MSG_DEBUG, " AT_MAC"); - eap_sim_msg_add_mac(msg, EAP_SIM_AT_MAC); - } - return eap_sim_msg_finish(msg, k_aut, (u8 *) "", 0); -} - - -static struct wpabuf * eap_aka_process_identity(struct eap_sm *sm, - struct eap_aka_data *data, - u8 id, - const struct wpabuf *reqData, - struct eap_sim_attrs *attr) -{ - int id_error; - struct wpabuf *buf; - - wpa_printf(MSG_DEBUG, "EAP-AKA: subtype Identity"); - - id_error = 0; - switch (attr->id_req) { - case NO_ID_REQ: - break; - case ANY_ID: - if (data->num_id_req > 0) - id_error++; - data->num_id_req++; - break; - case FULLAUTH_ID: - if (data->num_id_req > 1) - id_error++; - data->num_id_req++; - break; - case PERMANENT_ID: - if (data->num_id_req > 2) - id_error++; - data->num_id_req++; - break; - } - if (id_error) { - wpa_printf(MSG_INFO, "EAP-AKA: Too many ID requests " - "used within one authentication"); - return eap_aka_client_error(data, id, - EAP_AKA_UNABLE_TO_PROCESS_PACKET); - } - - buf = eap_aka_response_identity(sm, data, id, attr->id_req); - - if (data->prev_id != id) { - eap_aka_add_id_msg(data, reqData); - eap_aka_add_id_msg(data, buf); - data->prev_id = id; - } - - return buf; -} - - -static int eap_aka_verify_mac(struct eap_aka_data *data, - const struct wpabuf *req, - const u8 *mac, const u8 *extra, - size_t extra_len) -{ - if (data->eap_method == EAP_TYPE_AKA_PRIME) - return eap_sim_verify_mac_sha256(data->k_aut, req, mac, extra, - extra_len); - return eap_sim_verify_mac(data->k_aut, req, mac, extra, extra_len); -} - - -#ifdef EAP_AKA_PRIME -static struct wpabuf * eap_aka_prime_kdf_select(struct eap_aka_data *data, - u8 id, u16 kdf) -{ - struct eap_sim_msg *msg; - - data->kdf_negotiation = 1; - data->kdf = kdf; - wpa_printf(MSG_DEBUG, "Generating EAP-AKA Challenge (id=%d) (KDF " - "select)", id); - msg = eap_sim_msg_init(EAP_CODE_RESPONSE, id, data->eap_method, - EAP_AKA_SUBTYPE_CHALLENGE); - wpa_printf(MSG_DEBUG, " AT_KDF"); - eap_sim_msg_add(msg, EAP_SIM_AT_KDF, kdf, NULL, 0); - return eap_sim_msg_finish(msg, NULL, NULL, 0); -} - - -static struct wpabuf * eap_aka_prime_kdf_neg(struct eap_aka_data *data, - u8 id, struct eap_sim_attrs *attr) -{ - size_t i; - - for (i = 0; i < attr->kdf_count; i++) { - if (attr->kdf[i] == EAP_AKA_PRIME_KDF) - return eap_aka_prime_kdf_select(data, id, - EAP_AKA_PRIME_KDF); - } - - /* No matching KDF found - fail authentication as if AUTN had been - * incorrect */ - return eap_aka_authentication_reject(data, id); -} - - -static int eap_aka_prime_kdf_valid(struct eap_aka_data *data, - struct eap_sim_attrs *attr) -{ - size_t i, j; - - if (attr->kdf_count == 0) - return 0; - - /* The only allowed (and required) duplication of a KDF is the addition - * of the selected KDF into the beginning of the list. */ - - if (data->kdf_negotiation) { - if (attr->kdf[0] != data->kdf) { - wpa_printf(MSG_WARNING, "EAP-AKA': The server did not " - "accept the selected KDF"); - return 0; - } - - for (i = 1; i < attr->kdf_count; i++) { - if (attr->kdf[i] == data->kdf) - break; - } - if (i == attr->kdf_count && - attr->kdf_count < EAP_AKA_PRIME_KDF_MAX) { - wpa_printf(MSG_WARNING, "EAP-AKA': The server did not " - "duplicate the selected KDF"); - return 0; - } - - /* TODO: should check that the list is identical to the one - * used in the previous Challenge message apart from the added - * entry in the beginning. */ - } - - for (i = data->kdf ? 1 : 0; i < attr->kdf_count; i++) { - for (j = i + 1; j < attr->kdf_count; j++) { - if (attr->kdf[i] == attr->kdf[j]) { - wpa_printf(MSG_WARNING, "EAP-AKA': The server " - "included a duplicated KDF"); - return 0; - } - } - } - - return 1; -} -#endif /* EAP_AKA_PRIME */ - - -static struct wpabuf * eap_aka_process_challenge(struct eap_sm *sm, - struct eap_aka_data *data, - u8 id, - const struct wpabuf *reqData, - struct eap_sim_attrs *attr) -{ - const u8 *identity; - size_t identity_len; - int res; - struct eap_sim_attrs eattr; - - wpa_printf(MSG_DEBUG, "EAP-AKA: subtype Challenge"); - - if (attr->checkcode && - eap_aka_verify_checkcode(data, attr->checkcode, - attr->checkcode_len)) { - wpa_printf(MSG_WARNING, "EAP-AKA: Invalid AT_CHECKCODE in the " - "message"); - return eap_aka_client_error(data, id, - EAP_AKA_UNABLE_TO_PROCESS_PACKET); - } - -#ifdef EAP_AKA_PRIME - if (data->eap_method == EAP_TYPE_AKA_PRIME) { - if (!attr->kdf_input || attr->kdf_input_len == 0) { - wpa_printf(MSG_WARNING, "EAP-AKA': Challenge message " - "did not include non-empty AT_KDF_INPUT"); - /* Fail authentication as if AUTN had been incorrect */ - return eap_aka_authentication_reject(data, id); - } - os_free(data->network_name); - data->network_name = os_malloc(attr->kdf_input_len); - if (data->network_name == NULL) { - wpa_printf(MSG_WARNING, "EAP-AKA': No memory for " - "storing Network Name"); - return eap_aka_authentication_reject(data, id); - } - os_memcpy(data->network_name, attr->kdf_input, - attr->kdf_input_len); - data->network_name_len = attr->kdf_input_len; - wpa_hexdump_ascii(MSG_DEBUG, "EAP-AKA': Network Name " - "(AT_KDF_INPUT)", - data->network_name, data->network_name_len); - /* TODO: check Network Name per 3GPP.33.402 */ - - if (!eap_aka_prime_kdf_valid(data, attr)) - return eap_aka_authentication_reject(data, id); - - if (attr->kdf[0] != EAP_AKA_PRIME_KDF) - return eap_aka_prime_kdf_neg(data, id, attr); - - data->kdf = EAP_AKA_PRIME_KDF; - wpa_printf(MSG_DEBUG, "EAP-AKA': KDF %d selected", data->kdf); - } - - if (data->eap_method == EAP_TYPE_AKA && attr->bidding) { - u16 flags = WPA_GET_BE16(attr->bidding); - if ((flags & EAP_AKA_BIDDING_FLAG_D) && - eap_allowed_method(sm, EAP_VENDOR_IETF, - EAP_TYPE_AKA_PRIME)) { - wpa_printf(MSG_WARNING, "EAP-AKA: Bidding down from " - "AKA' to AKA detected"); - /* Fail authentication as if AUTN had been incorrect */ - return eap_aka_authentication_reject(data, id); - } - } -#endif /* EAP_AKA_PRIME */ - - data->reauth = 0; - if (!attr->mac || !attr->rand || !attr->autn) { - wpa_printf(MSG_WARNING, "EAP-AKA: Challenge message " - "did not include%s%s%s", - !attr->mac ? " AT_MAC" : "", - !attr->rand ? " AT_RAND" : "", - !attr->autn ? " AT_AUTN" : ""); - return eap_aka_client_error(data, id, - EAP_AKA_UNABLE_TO_PROCESS_PACKET); - } - os_memcpy(data->rand, attr->rand, EAP_AKA_RAND_LEN); - os_memcpy(data->autn, attr->autn, EAP_AKA_AUTN_LEN); - - res = eap_aka_umts_auth(sm, data); - if (res == -1) { - wpa_printf(MSG_WARNING, "EAP-AKA: UMTS authentication " - "failed (AUTN)"); - return eap_aka_authentication_reject(data, id); - } else if (res == -2) { - wpa_printf(MSG_WARNING, "EAP-AKA: UMTS authentication " - "failed (AUTN seq# -> AUTS)"); - return eap_aka_synchronization_failure(data, id); - } else if (res) { - wpa_printf(MSG_WARNING, "EAP-AKA: UMTS authentication failed"); - return eap_aka_client_error(data, id, - EAP_AKA_UNABLE_TO_PROCESS_PACKET); - } -#ifdef EAP_AKA_PRIME - if (data->eap_method == EAP_TYPE_AKA_PRIME) { - /* Note: AUTN = (SQN ^ AK) || AMF || MAC which gives us the - * needed 6-octet SQN ^ AK for CK',IK' derivation */ - u16 amf = WPA_GET_BE16(data->autn + 6); - if (!(amf & 0x8000)) { - wpa_printf(MSG_WARNING, "EAP-AKA': AMF separation bit " - "not set (AMF=0x%4x)", amf); - return eap_aka_authentication_reject(data, id); - } - eap_aka_prime_derive_ck_ik_prime(data->ck, data->ik, - data->autn, - data->network_name, - data->network_name_len); - } -#endif /* EAP_AKA_PRIME */ - if (data->last_eap_identity) { - identity = data->last_eap_identity; - identity_len = data->last_eap_identity_len; - } else if (data->pseudonym) { - identity = data->pseudonym; - identity_len = data->pseudonym_len; - } else - identity = eap_get_config_identity(sm, &identity_len); - wpa_hexdump_ascii(MSG_DEBUG, "EAP-AKA: Selected identity for MK " - "derivation", identity, identity_len); - if (data->eap_method == EAP_TYPE_AKA_PRIME) { - eap_aka_prime_derive_keys(identity, identity_len, data->ik, - data->ck, data->k_encr, data->k_aut, - data->k_re, data->msk, data->emsk); - } else { - eap_aka_derive_mk(identity, identity_len, data->ik, data->ck, - data->mk); - eap_sim_derive_keys(data->mk, data->k_encr, data->k_aut, - data->msk, data->emsk); - } - if (eap_aka_verify_mac(data, reqData, attr->mac, (u8 *) "", 0)) { - wpa_printf(MSG_WARNING, "EAP-AKA: Challenge message " - "used invalid AT_MAC"); - return eap_aka_client_error(data, id, - EAP_AKA_UNABLE_TO_PROCESS_PACKET); - } - - /* Old reauthentication and pseudonym identities must not be used - * anymore. In other words, if no new identities are received, full - * authentication will be used on next reauthentication. */ - eap_aka_clear_identities(data, CLEAR_PSEUDONYM | CLEAR_REAUTH_ID | - CLEAR_EAP_ID); - - if (attr->encr_data) { - u8 *decrypted; - decrypted = eap_sim_parse_encr(data->k_encr, attr->encr_data, - attr->encr_data_len, attr->iv, - &eattr, 0); - if (decrypted == NULL) { - return eap_aka_client_error( - data, id, EAP_AKA_UNABLE_TO_PROCESS_PACKET); - } - eap_aka_learn_ids(data, &eattr); - os_free(decrypted); - } - - if (data->result_ind && attr->result_ind) - data->use_result_ind = 1; - - if (data->state != FAILURE && data->state != RESULT_FAILURE) { - eap_aka_state(data, data->use_result_ind ? - RESULT_SUCCESS : SUCCESS); - } - - data->num_id_req = 0; - data->num_notification = 0; - /* RFC 4187 specifies that counter is initialized to one after - * fullauth, but initializing it to zero makes it easier to implement - * reauth verification. */ - data->counter = 0; - return eap_aka_response_challenge(data, id); -} - - -static int eap_aka_process_notification_reauth(struct eap_aka_data *data, - struct eap_sim_attrs *attr) -{ - struct eap_sim_attrs eattr; - u8 *decrypted; - - if (attr->encr_data == NULL || attr->iv == NULL) { - wpa_printf(MSG_WARNING, "EAP-AKA: Notification message after " - "reauth did not include encrypted data"); - return -1; - } - - decrypted = eap_sim_parse_encr(data->k_encr, attr->encr_data, - attr->encr_data_len, attr->iv, &eattr, - 0); - if (decrypted == NULL) { - wpa_printf(MSG_WARNING, "EAP-AKA: Failed to parse encrypted " - "data from notification message"); - return -1; - } - - if (eattr.counter < 0 || (size_t) eattr.counter != data->counter) { - wpa_printf(MSG_WARNING, "EAP-AKA: Counter in notification " - "message does not match with counter in reauth " - "message"); - os_free(decrypted); - return -1; - } - - os_free(decrypted); - return 0; -} - - -static int eap_aka_process_notification_auth(struct eap_aka_data *data, - const struct wpabuf *reqData, - struct eap_sim_attrs *attr) -{ - if (attr->mac == NULL) { - wpa_printf(MSG_INFO, "EAP-AKA: no AT_MAC in after_auth " - "Notification message"); - return -1; - } - - if (eap_aka_verify_mac(data, reqData, attr->mac, (u8 *) "", 0)) { - wpa_printf(MSG_WARNING, "EAP-AKA: Notification message " - "used invalid AT_MAC"); - return -1; - } - - if (data->reauth && - eap_aka_process_notification_reauth(data, attr)) { - wpa_printf(MSG_WARNING, "EAP-AKA: Invalid notification " - "message after reauth"); - return -1; - } - - return 0; -} - - -static struct wpabuf * eap_aka_process_notification( - struct eap_sm *sm, struct eap_aka_data *data, u8 id, - const struct wpabuf *reqData, struct eap_sim_attrs *attr) -{ - wpa_printf(MSG_DEBUG, "EAP-AKA: subtype Notification"); - if (data->num_notification > 0) { - wpa_printf(MSG_INFO, "EAP-AKA: too many notification " - "rounds (only one allowed)"); - return eap_aka_client_error(data, id, - EAP_AKA_UNABLE_TO_PROCESS_PACKET); - } - data->num_notification++; - if (attr->notification == -1) { - wpa_printf(MSG_INFO, "EAP-AKA: no AT_NOTIFICATION in " - "Notification message"); - return eap_aka_client_error(data, id, - EAP_AKA_UNABLE_TO_PROCESS_PACKET); - } - - if ((attr->notification & 0x4000) == 0 && - eap_aka_process_notification_auth(data, reqData, attr)) { - return eap_aka_client_error(data, id, - EAP_AKA_UNABLE_TO_PROCESS_PACKET); - } - - eap_sim_report_notification(sm->msg_ctx, attr->notification, 1); - if (attr->notification >= 0 && attr->notification < 32768) { - eap_aka_state(data, FAILURE); - } else if (attr->notification == EAP_SIM_SUCCESS && - data->state == RESULT_SUCCESS) - eap_aka_state(data, SUCCESS); - return eap_aka_response_notification(data, id, attr->notification); -} - - -static struct wpabuf * eap_aka_process_reauthentication( - struct eap_sm *sm, struct eap_aka_data *data, u8 id, - const struct wpabuf *reqData, struct eap_sim_attrs *attr) -{ - struct eap_sim_attrs eattr; - u8 *decrypted; - - wpa_printf(MSG_DEBUG, "EAP-AKA: subtype Reauthentication"); - - if (attr->checkcode && - eap_aka_verify_checkcode(data, attr->checkcode, - attr->checkcode_len)) { - wpa_printf(MSG_WARNING, "EAP-AKA: Invalid AT_CHECKCODE in the " - "message"); - return eap_aka_client_error(data, id, - EAP_AKA_UNABLE_TO_PROCESS_PACKET); - } - - if (data->reauth_id == NULL) { - wpa_printf(MSG_WARNING, "EAP-AKA: Server is trying " - "reauthentication, but no reauth_id available"); - return eap_aka_client_error(data, id, - EAP_AKA_UNABLE_TO_PROCESS_PACKET); - } - - data->reauth = 1; - if (eap_aka_verify_mac(data, reqData, attr->mac, (u8 *) "", 0)) { - wpa_printf(MSG_WARNING, "EAP-AKA: Reauthentication " - "did not have valid AT_MAC"); - return eap_aka_client_error(data, id, - EAP_AKA_UNABLE_TO_PROCESS_PACKET); - } - - if (attr->encr_data == NULL || attr->iv == NULL) { - wpa_printf(MSG_WARNING, "EAP-AKA: Reauthentication " - "message did not include encrypted data"); - return eap_aka_client_error(data, id, - EAP_AKA_UNABLE_TO_PROCESS_PACKET); - } - - decrypted = eap_sim_parse_encr(data->k_encr, attr->encr_data, - attr->encr_data_len, attr->iv, &eattr, - 0); - if (decrypted == NULL) { - wpa_printf(MSG_WARNING, "EAP-AKA: Failed to parse encrypted " - "data from reauthentication message"); - return eap_aka_client_error(data, id, - EAP_AKA_UNABLE_TO_PROCESS_PACKET); - } - - if (eattr.nonce_s == NULL || eattr.counter < 0) { - wpa_printf(MSG_INFO, "EAP-AKA: (encr) No%s%s in reauth packet", - !eattr.nonce_s ? " AT_NONCE_S" : "", - eattr.counter < 0 ? " AT_COUNTER" : ""); - os_free(decrypted); - return eap_aka_client_error(data, id, - EAP_AKA_UNABLE_TO_PROCESS_PACKET); - } - - if (eattr.counter < 0 || (size_t) eattr.counter <= data->counter) { - struct wpabuf *res; - wpa_printf(MSG_INFO, "EAP-AKA: (encr) Invalid counter " - "(%d <= %d)", eattr.counter, data->counter); - data->counter_too_small = eattr.counter; - - /* Reply using Re-auth w/ AT_COUNTER_TOO_SMALL. The current - * reauth_id must not be used to start a new reauthentication. - * However, since it was used in the last EAP-Response-Identity - * packet, it has to saved for the following fullauth to be - * used in MK derivation. */ - os_free(data->last_eap_identity); - data->last_eap_identity = data->reauth_id; - data->last_eap_identity_len = data->reauth_id_len; - data->reauth_id = NULL; - data->reauth_id_len = 0; - - res = eap_aka_response_reauth(data, id, 1, eattr.nonce_s); - os_free(decrypted); - - return res; - } - data->counter = eattr.counter; - - os_memcpy(data->nonce_s, eattr.nonce_s, EAP_SIM_NONCE_S_LEN); - wpa_hexdump(MSG_DEBUG, "EAP-AKA: (encr) AT_NONCE_S", - data->nonce_s, EAP_SIM_NONCE_S_LEN); - - if (data->eap_method == EAP_TYPE_AKA_PRIME) { - eap_aka_prime_derive_keys_reauth(data->k_re, data->counter, - data->reauth_id, - data->reauth_id_len, - data->nonce_s, - data->msk, data->emsk); - } else { - eap_sim_derive_keys_reauth(data->counter, data->reauth_id, - data->reauth_id_len, - data->nonce_s, data->mk, - data->msk, data->emsk); - } - eap_aka_clear_identities(data, CLEAR_REAUTH_ID | CLEAR_EAP_ID); - eap_aka_learn_ids(data, &eattr); - - if (data->result_ind && attr->result_ind) - data->use_result_ind = 1; - - if (data->state != FAILURE && data->state != RESULT_FAILURE) { - eap_aka_state(data, data->use_result_ind ? - RESULT_SUCCESS : SUCCESS); - } - - data->num_id_req = 0; - data->num_notification = 0; - if (data->counter > EAP_AKA_MAX_FAST_REAUTHS) { - wpa_printf(MSG_DEBUG, "EAP-AKA: Maximum number of " - "fast reauths performed - force fullauth"); - eap_aka_clear_identities(data, CLEAR_REAUTH_ID | CLEAR_EAP_ID); - } - os_free(decrypted); - return eap_aka_response_reauth(data, id, 0, data->nonce_s); -} - - -static struct wpabuf * eap_aka_process(struct eap_sm *sm, void *priv, - struct eap_method_ret *ret, - const struct wpabuf *reqData) -{ - struct eap_aka_data *data = priv; - const struct eap_hdr *req; - u8 subtype, id; - struct wpabuf *res; - const u8 *pos; - struct eap_sim_attrs attr; - size_t len; - - wpa_hexdump_buf(MSG_DEBUG, "EAP-AKA: EAP data", reqData); - if (eap_get_config_identity(sm, &len) == NULL) { - wpa_printf(MSG_INFO, "EAP-AKA: Identity not configured"); - eap_sm_request_identity(sm); - ret->ignore = TRUE; - return NULL; - } - - pos = eap_hdr_validate(EAP_VENDOR_IETF, data->eap_method, reqData, - &len); - if (pos == NULL || len < 1) { - ret->ignore = TRUE; - return NULL; - } - req = wpabuf_head(reqData); - id = req->identifier; - len = be_to_host16(req->length); - - ret->ignore = FALSE; - ret->methodState = METHOD_MAY_CONT; - ret->decision = DECISION_FAIL; - ret->allowNotifications = TRUE; - - subtype = *pos++; - wpa_printf(MSG_DEBUG, "EAP-AKA: Subtype=%d", subtype); - pos += 2; /* Reserved */ - - if (eap_sim_parse_attr(pos, wpabuf_head_u8(reqData) + len, &attr, - data->eap_method == EAP_TYPE_AKA_PRIME ? 2 : 1, - 0)) { - res = eap_aka_client_error(data, id, - EAP_AKA_UNABLE_TO_PROCESS_PACKET); - goto done; - } - - switch (subtype) { - case EAP_AKA_SUBTYPE_IDENTITY: - res = eap_aka_process_identity(sm, data, id, reqData, &attr); - break; - case EAP_AKA_SUBTYPE_CHALLENGE: - res = eap_aka_process_challenge(sm, data, id, reqData, &attr); - break; - case EAP_AKA_SUBTYPE_NOTIFICATION: - res = eap_aka_process_notification(sm, data, id, reqData, - &attr); - break; - case EAP_AKA_SUBTYPE_REAUTHENTICATION: - res = eap_aka_process_reauthentication(sm, data, id, reqData, - &attr); - break; - case EAP_AKA_SUBTYPE_CLIENT_ERROR: - wpa_printf(MSG_DEBUG, "EAP-AKA: subtype Client-Error"); - res = eap_aka_client_error(data, id, - EAP_AKA_UNABLE_TO_PROCESS_PACKET); - break; - default: - wpa_printf(MSG_DEBUG, "EAP-AKA: Unknown subtype=%d", subtype); - res = eap_aka_client_error(data, id, - EAP_AKA_UNABLE_TO_PROCESS_PACKET); - break; - } - -done: - if (data->state == FAILURE) { - ret->decision = DECISION_FAIL; - ret->methodState = METHOD_DONE; - } else if (data->state == SUCCESS) { - ret->decision = data->use_result_ind ? - DECISION_UNCOND_SUCC : DECISION_COND_SUCC; - /* - * It is possible for the server to reply with AKA - * Notification, so we must allow the method to continue and - * not only accept EAP-Success at this point. - */ - ret->methodState = data->use_result_ind ? - METHOD_DONE : METHOD_MAY_CONT; - } else if (data->state == RESULT_FAILURE) - ret->methodState = METHOD_CONT; - else if (data->state == RESULT_SUCCESS) - ret->methodState = METHOD_CONT; - - if (ret->methodState == METHOD_DONE) { - ret->allowNotifications = FALSE; - } - - return res; -} - - -static Boolean eap_aka_has_reauth_data(struct eap_sm *sm, void *priv) -{ - struct eap_aka_data *data = priv; - return data->pseudonym || data->reauth_id; -} - - -static void eap_aka_deinit_for_reauth(struct eap_sm *sm, void *priv) -{ - struct eap_aka_data *data = priv; - eap_aka_clear_identities(data, CLEAR_EAP_ID); - data->prev_id = -1; - wpabuf_free(data->id_msgs); - data->id_msgs = NULL; - data->use_result_ind = 0; - data->kdf_negotiation = 0; -} - - -static void * eap_aka_init_for_reauth(struct eap_sm *sm, void *priv) -{ - struct eap_aka_data *data = priv; - data->num_id_req = 0; - data->num_notification = 0; - eap_aka_state(data, CONTINUE); - return priv; -} - - -static const u8 * eap_aka_get_identity(struct eap_sm *sm, void *priv, - size_t *len) -{ - struct eap_aka_data *data = priv; - - if (data->reauth_id) { - *len = data->reauth_id_len; - return data->reauth_id; - } - - if (data->pseudonym) { - *len = data->pseudonym_len; - return data->pseudonym; - } - - return NULL; -} - - -static Boolean eap_aka_isKeyAvailable(struct eap_sm *sm, void *priv) -{ - struct eap_aka_data *data = priv; - return data->state == SUCCESS; -} - - -static u8 * eap_aka_getKey(struct eap_sm *sm, void *priv, size_t *len) -{ - struct eap_aka_data *data = priv; - u8 *key; - - if (data->state != SUCCESS) - return NULL; - - key = os_malloc(EAP_SIM_KEYING_DATA_LEN); - if (key == NULL) - return NULL; - - *len = EAP_SIM_KEYING_DATA_LEN; - os_memcpy(key, data->msk, EAP_SIM_KEYING_DATA_LEN); - - return key; -} - - -static u8 * eap_aka_get_emsk(struct eap_sm *sm, void *priv, size_t *len) -{ - struct eap_aka_data *data = priv; - u8 *key; - - if (data->state != SUCCESS) - return NULL; - - key = os_malloc(EAP_EMSK_LEN); - if (key == NULL) - return NULL; - - *len = EAP_EMSK_LEN; - os_memcpy(key, data->emsk, EAP_EMSK_LEN); - - return key; -} - - -int eap_peer_aka_register(void) -{ - struct eap_method *eap; - int ret; - - eap = eap_peer_method_alloc(EAP_PEER_METHOD_INTERFACE_VERSION, - EAP_VENDOR_IETF, EAP_TYPE_AKA, "AKA"); - if (eap == NULL) - return -1; - - eap->init = eap_aka_init; - eap->deinit = eap_aka_deinit; - eap->process = eap_aka_process; - eap->isKeyAvailable = eap_aka_isKeyAvailable; - eap->getKey = eap_aka_getKey; - eap->has_reauth_data = eap_aka_has_reauth_data; - eap->deinit_for_reauth = eap_aka_deinit_for_reauth; - eap->init_for_reauth = eap_aka_init_for_reauth; - eap->get_identity = eap_aka_get_identity; - eap->get_emsk = eap_aka_get_emsk; - - ret = eap_peer_method_register(eap); - if (ret) - eap_peer_method_free(eap); - return ret; -} - - -#ifdef EAP_AKA_PRIME -int eap_peer_aka_prime_register(void) -{ - struct eap_method *eap; - int ret; - - eap = eap_peer_method_alloc(EAP_PEER_METHOD_INTERFACE_VERSION, - EAP_VENDOR_IETF, EAP_TYPE_AKA_PRIME, - "AKA'"); - if (eap == NULL) - return -1; - - eap->init = eap_aka_prime_init; - eap->deinit = eap_aka_deinit; - eap->process = eap_aka_process; - eap->isKeyAvailable = eap_aka_isKeyAvailable; - eap->getKey = eap_aka_getKey; - eap->has_reauth_data = eap_aka_has_reauth_data; - eap->deinit_for_reauth = eap_aka_deinit_for_reauth; - eap->init_for_reauth = eap_aka_init_for_reauth; - eap->get_identity = eap_aka_get_identity; - eap->get_emsk = eap_aka_get_emsk; - - ret = eap_peer_method_register(eap); - if (ret) - eap_peer_method_free(eap); - - return ret; -} -#endif /* EAP_AKA_PRIME */ diff --git a/hostapd-0.8/src/eap_peer/eap_config.h b/hostapd-0.8/src/eap_peer/eap_config.h deleted file mode 100644 index b64b68f..0000000 --- a/hostapd-0.8/src/eap_peer/eap_config.h +++ /dev/null @@ -1,669 +0,0 @@ -/* - * EAP peer configuration data - * Copyright (c) 2003-2008, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#ifndef EAP_CONFIG_H -#define EAP_CONFIG_H - -/** - * struct eap_peer_config - EAP peer configuration/credentials - */ -struct eap_peer_config { - /** - * identity - EAP Identity - * - * This field is used to set the real user identity or NAI (for - * EAP-PSK/PAX/SAKE/GPSK). - */ - u8 *identity; - - /** - * identity_len - EAP Identity length - */ - size_t identity_len; - - /** - * anonymous_identity - Anonymous EAP Identity - * - * This field is used for unencrypted use with EAP types that support - * different tunnelled identity, e.g., EAP-TTLS, in order to reveal the - * real identity (identity field) only to the authentication server. - * - * If not set, the identity field will be used for both unencrypted and - * protected fields. - */ - u8 *anonymous_identity; - - /** - * anonymous_identity_len - Length of anonymous_identity - */ - size_t anonymous_identity_len; - - /** - * password - Password string for EAP - * - * This field can include either the plaintext password (default - * option) or a NtPasswordHash (16-byte MD4 hash of the unicode - * presentation of the password) if flags field has - * EAP_CONFIG_FLAGS_PASSWORD_NTHASH bit set to 1. NtPasswordHash can - * only be used with authentication mechanism that use this hash as the - * starting point for operation: MSCHAP and MSCHAPv2 (EAP-MSCHAPv2, - * EAP-TTLS/MSCHAPv2, EAP-TTLS/MSCHAP, LEAP). - * - * In addition, this field is used to configure a pre-shared key for - * EAP-PSK/PAX/SAKE/GPSK. The length of the PSK must be 16 for EAP-PSK - * and EAP-PAX and 32 for EAP-SAKE. EAP-GPSK can use a variable length - * PSK. - */ - u8 *password; - - /** - * password_len - Length of password field - */ - size_t password_len; - - /** - * ca_cert - File path to CA certificate file (PEM/DER) - * - * This file can have one or more trusted CA certificates. If ca_cert - * and ca_path are not included, server certificate will not be - * verified. This is insecure and a trusted CA certificate should - * always be configured when using EAP-TLS/TTLS/PEAP. Full path to the - * file should be used since working directory may change when - * wpa_supplicant is run in the background. - * - * Alternatively, a named configuration blob can be used by setting - * this to blob://blob_name. - * - * Alternatively, this can be used to only perform matching of the - * server certificate (SHA-256 hash of the DER encoded X.509 - * certificate). In this case, the possible CA certificates in the - * server certificate chain are ignored and only the server certificate - * is verified. This is configured with the following format: - * hash:://server/sha256/cert_hash_in_hex - * For example: "hash://server/sha256/ - * 5a1bc1296205e6fdbe3979728efe3920798885c1c4590b5f90f43222d239ca6a" - * - * On Windows, trusted CA certificates can be loaded from the system - * certificate store by setting this to cert_store://name, e.g., - * ca_cert="cert_store://CA" or ca_cert="cert_store://ROOT". - * Note that when running wpa_supplicant as an application, the user - * certificate store (My user account) is used, whereas computer store - * (Computer account) is used when running wpasvc as a service. - */ - u8 *ca_cert; - - /** - * ca_path - Directory path for CA certificate files (PEM) - * - * This path may contain multiple CA certificates in OpenSSL format. - * Common use for this is to point to system trusted CA list which is - * often installed into directory like /etc/ssl/certs. If configured, - * these certificates are added to the list of trusted CAs. ca_cert - * may also be included in that case, but it is not required. - */ - u8 *ca_path; - - /** - * client_cert - File path to client certificate file (PEM/DER) - * - * This field is used with EAP method that use TLS authentication. - * Usually, this is only configured for EAP-TLS, even though this could - * in theory be used with EAP-TTLS and EAP-PEAP, too. Full path to the - * file should be used since working directory may change when - * wpa_supplicant is run in the background. - * - * Alternatively, a named configuration blob can be used by setting - * this to blob://blob_name. - */ - u8 *client_cert; - - /** - * private_key - File path to client private key file (PEM/DER/PFX) - * - * When PKCS#12/PFX file (.p12/.pfx) is used, client_cert should be - * commented out. Both the private key and certificate will be read - * from the PKCS#12 file in this case. Full path to the file should be - * used since working directory may change when wpa_supplicant is run - * in the background. - * - * Windows certificate store can be used by leaving client_cert out and - * configuring private_key in one of the following formats: - * - * cert://substring_to_match - * - * hash://certificate_thumbprint_in_hex - * - * For example: private_key="hash://63093aa9c47f56ae88334c7b65a4" - * - * Note that when running wpa_supplicant as an application, the user - * certificate store (My user account) is used, whereas computer store - * (Computer account) is used when running wpasvc as a service. - * - * Alternatively, a named configuration blob can be used by setting - * this to blob://blob_name. - */ - u8 *private_key; - - /** - * private_key_passwd - Password for private key file - * - * If left out, this will be asked through control interface. - */ - u8 *private_key_passwd; - - /** - * dh_file - File path to DH/DSA parameters file (in PEM format) - * - * This is an optional configuration file for setting parameters for an - * ephemeral DH key exchange. In most cases, the default RSA - * authentication does not use this configuration. However, it is - * possible setup RSA to use ephemeral DH key exchange. In addition, - * ciphers with DSA keys always use ephemeral DH keys. This can be used - * to achieve forward secrecy. If the file is in DSA parameters format, - * it will be automatically converted into DH params. Full path to the - * file should be used since working directory may change when - * wpa_supplicant is run in the background. - * - * Alternatively, a named configuration blob can be used by setting - * this to blob://blob_name. - */ - u8 *dh_file; - - /** - * subject_match - Constraint for server certificate subject - * - * This substring is matched against the subject of the authentication - * server certificate. If this string is set, the server sertificate is - * only accepted if it contains this string in the subject. The subject - * string is in following format: - * - * /C=US/ST=CA/L=San Francisco/CN=Test AS/emailAddress=as@n.example.com - */ - u8 *subject_match; - - /** - * altsubject_match - Constraint for server certificate alt. subject - * - * Semicolon separated string of entries to be matched against the - * alternative subject name of the authentication server certificate. - * If this string is set, the server sertificate is only accepted if it - * contains one of the entries in an alternative subject name - * extension. - * - * altSubjectName string is in following format: TYPE:VALUE - * - * Example: EMAIL:server@example.com - * Example: DNS:server.example.com;DNS:server2.example.com - * - * Following types are supported: EMAIL, DNS, URI - */ - u8 *altsubject_match; - - /** - * ca_cert2 - File path to CA certificate file (PEM/DER) (Phase 2) - * - * This file can have one or more trusted CA certificates. If ca_cert2 - * and ca_path2 are not included, server certificate will not be - * verified. This is insecure and a trusted CA certificate should - * always be configured. Full path to the file should be used since - * working directory may change when wpa_supplicant is run in the - * background. - * - * This field is like ca_cert, but used for phase 2 (inside - * EAP-TTLS/PEAP/FAST tunnel) authentication. - * - * Alternatively, a named configuration blob can be used by setting - * this to blob://blob_name. - */ - u8 *ca_cert2; - - /** - * ca_path2 - Directory path for CA certificate files (PEM) (Phase 2) - * - * This path may contain multiple CA certificates in OpenSSL format. - * Common use for this is to point to system trusted CA list which is - * often installed into directory like /etc/ssl/certs. If configured, - * these certificates are added to the list of trusted CAs. ca_cert - * may also be included in that case, but it is not required. - * - * This field is like ca_path, but used for phase 2 (inside - * EAP-TTLS/PEAP/FAST tunnel) authentication. - */ - u8 *ca_path2; - - /** - * client_cert2 - File path to client certificate file - * - * This field is like client_cert, but used for phase 2 (inside - * EAP-TTLS/PEAP/FAST tunnel) authentication. Full path to the - * file should be used since working directory may change when - * wpa_supplicant is run in the background. - * - * Alternatively, a named configuration blob can be used by setting - * this to blob://blob_name. - */ - u8 *client_cert2; - - /** - * private_key2 - File path to client private key file - * - * This field is like private_key, but used for phase 2 (inside - * EAP-TTLS/PEAP/FAST tunnel) authentication. Full path to the - * file should be used since working directory may change when - * wpa_supplicant is run in the background. - * - * Alternatively, a named configuration blob can be used by setting - * this to blob://blob_name. - */ - u8 *private_key2; - - /** - * private_key2_passwd - Password for private key file - * - * This field is like private_key_passwd, but used for phase 2 (inside - * EAP-TTLS/PEAP/FAST tunnel) authentication. - */ - u8 *private_key2_passwd; - - /** - * dh_file2 - File path to DH/DSA parameters file (in PEM format) - * - * This field is like dh_file, but used for phase 2 (inside - * EAP-TTLS/PEAP/FAST tunnel) authentication. Full path to the - * file should be used since working directory may change when - * wpa_supplicant is run in the background. - * - * Alternatively, a named configuration blob can be used by setting - * this to blob://blob_name. - */ - u8 *dh_file2; - - /** - * subject_match2 - Constraint for server certificate subject - * - * This field is like subject_match, but used for phase 2 (inside - * EAP-TTLS/PEAP/FAST tunnel) authentication. - */ - u8 *subject_match2; - - /** - * altsubject_match2 - Constraint for server certificate alt. subject - * - * This field is like altsubject_match, but used for phase 2 (inside - * EAP-TTLS/PEAP/FAST tunnel) authentication. - */ - u8 *altsubject_match2; - - /** - * eap_methods - Allowed EAP methods - * - * (vendor=EAP_VENDOR_IETF,method=EAP_TYPE_NONE) terminated list of - * allowed EAP methods or %NULL if all methods are accepted. - */ - struct eap_method_type *eap_methods; - - /** - * phase1 - Phase 1 (outer authentication) parameters - * - * String with field-value pairs, e.g., "peapver=0" or - * "peapver=1 peaplabel=1". - * - * 'peapver' can be used to force which PEAP version (0 or 1) is used. - * - * 'peaplabel=1' can be used to force new label, "client PEAP - * encryption", to be used during key derivation when PEAPv1 or newer. - * - * Most existing PEAPv1 implementation seem to be using the old label, - * "client EAP encryption", and wpa_supplicant is now using that as the - * default value. - * - * Some servers, e.g., Radiator, may require peaplabel=1 configuration - * to interoperate with PEAPv1; see eap_testing.txt for more details. - * - * 'peap_outer_success=0' can be used to terminate PEAP authentication - * on tunneled EAP-Success. This is required with some RADIUS servers - * that implement draft-josefsson-pppext-eap-tls-eap-05.txt (e.g., - * Lucent NavisRadius v4.4.0 with PEAP in "IETF Draft 5" mode). - * - * include_tls_length=1 can be used to force wpa_supplicant to include - * TLS Message Length field in all TLS messages even if they are not - * fragmented. - * - * sim_min_num_chal=3 can be used to configure EAP-SIM to require three - * challenges (by default, it accepts 2 or 3). - * - * result_ind=1 can be used to enable EAP-SIM and EAP-AKA to use - * protected result indication. - * - * fast_provisioning option can be used to enable in-line provisioning - * of EAP-FAST credentials (PAC): - * 0 = disabled, - * 1 = allow unauthenticated provisioning, - * 2 = allow authenticated provisioning, - * 3 = allow both unauthenticated and authenticated provisioning - * - * fast_max_pac_list_len=num option can be used to set the maximum - * number of PAC entries to store in a PAC list (default: 10). - * - * fast_pac_format=binary option can be used to select binary format - * for storing PAC entries in order to save some space (the default - * text format uses about 2.5 times the size of minimal binary format). - * - * crypto_binding option can be used to control PEAPv0 cryptobinding - * behavior: - * 0 = do not use cryptobinding (default) - * 1 = use cryptobinding if server supports it - * 2 = require cryptobinding - * - * EAP-WSC (WPS) uses following options: pin=Device_Password and - * uuid=Device_UUID - */ - char *phase1; - - /** - * phase2 - Phase2 (inner authentication with TLS tunnel) parameters - * - * String with field-value pairs, e.g., "auth=MSCHAPV2" for EAP-PEAP or - * "autheap=MSCHAPV2 autheap=MD5" for EAP-TTLS. - */ - char *phase2; - - /** - * pcsc - Parameters for PC/SC smartcard interface for USIM and GSM SIM - * - * This field is used to configure PC/SC smartcard interface. - * Currently, the only configuration is whether this field is %NULL (do - * not use PC/SC) or non-NULL (e.g., "") to enable PC/SC. - * - * This field is used for EAP-SIM and EAP-AKA. - */ - char *pcsc; - - /** - * pin - PIN for USIM, GSM SIM, and smartcards - * - * This field is used to configure PIN for SIM and smartcards for - * EAP-SIM and EAP-AKA. In addition, this is used with EAP-TLS if a - * smartcard is used for private key operations. - * - * If left out, this will be asked through control interface. - */ - char *pin; - - /** - * engine - Enable OpenSSL engine (e.g., for smartcard access) - * - * This is used if private key operations for EAP-TLS are performed - * using a smartcard. - */ - int engine; - - /** - * engine_id - Engine ID for OpenSSL engine - * - * "opensc" to select OpenSC engine or "pkcs11" to select PKCS#11 - * engine. - * - * This is used if private key operations for EAP-TLS are performed - * using a smartcard. - */ - char *engine_id; - - /** - * engine2 - Enable OpenSSL engine (e.g., for smartcard) (Phase 2) - * - * This is used if private key operations for EAP-TLS are performed - * using a smartcard. - * - * This field is like engine, but used for phase 2 (inside - * EAP-TTLS/PEAP/FAST tunnel) authentication. - */ - int engine2; - - - /** - * pin2 - PIN for USIM, GSM SIM, and smartcards (Phase 2) - * - * This field is used to configure PIN for SIM and smartcards for - * EAP-SIM and EAP-AKA. In addition, this is used with EAP-TLS if a - * smartcard is used for private key operations. - * - * This field is like pin2, but used for phase 2 (inside - * EAP-TTLS/PEAP/FAST tunnel) authentication. - * - * If left out, this will be asked through control interface. - */ - char *pin2; - - /** - * engine2_id - Engine ID for OpenSSL engine (Phase 2) - * - * "opensc" to select OpenSC engine or "pkcs11" to select PKCS#11 - * engine. - * - * This is used if private key operations for EAP-TLS are performed - * using a smartcard. - * - * This field is like engine_id, but used for phase 2 (inside - * EAP-TTLS/PEAP/FAST tunnel) authentication. - */ - char *engine2_id; - - - /** - * key_id - Key ID for OpenSSL engine - * - * This is used if private key operations for EAP-TLS are performed - * using a smartcard. - */ - char *key_id; - - /** - * cert_id - Cert ID for OpenSSL engine - * - * This is used if the certificate operations for EAP-TLS are performed - * using a smartcard. - */ - char *cert_id; - - /** - * ca_cert_id - CA Cert ID for OpenSSL engine - * - * This is used if the CA certificate for EAP-TLS is on a smartcard. - */ - char *ca_cert_id; - - /** - * key2_id - Key ID for OpenSSL engine (phase2) - * - * This is used if private key operations for EAP-TLS are performed - * using a smartcard. - */ - char *key2_id; - - /** - * cert2_id - Cert ID for OpenSSL engine (phase2) - * - * This is used if the certificate operations for EAP-TLS are performed - * using a smartcard. - */ - char *cert2_id; - - /** - * ca_cert2_id - CA Cert ID for OpenSSL engine (phase2) - * - * This is used if the CA certificate for EAP-TLS is on a smartcard. - */ - char *ca_cert2_id; - - /** - * otp - One-time-password - * - * This field should not be set in configuration step. It is only used - * internally when OTP is entered through the control interface. - */ - u8 *otp; - - /** - * otp_len - Length of the otp field - */ - size_t otp_len; - - /** - * pending_req_identity - Whether there is a pending identity request - * - * This field should not be set in configuration step. It is only used - * internally when control interface is used to request needed - * information. - */ - int pending_req_identity; - - /** - * pending_req_password - Whether there is a pending password request - * - * This field should not be set in configuration step. It is only used - * internally when control interface is used to request needed - * information. - */ - int pending_req_password; - - /** - * pending_req_pin - Whether there is a pending PIN request - * - * This field should not be set in configuration step. It is only used - * internally when control interface is used to request needed - * information. - */ - int pending_req_pin; - - /** - * pending_req_new_password - Pending password update request - * - * This field should not be set in configuration step. It is only used - * internally when control interface is used to request needed - * information. - */ - int pending_req_new_password; - - /** - * pending_req_passphrase - Pending passphrase request - * - * This field should not be set in configuration step. It is only used - * internally when control interface is used to request needed - * information. - */ - int pending_req_passphrase; - - /** - * pending_req_otp - Whether there is a pending OTP request - * - * This field should not be set in configuration step. It is only used - * internally when control interface is used to request needed - * information. - */ - char *pending_req_otp; - - /** - * pending_req_otp_len - Length of the pending OTP request - */ - size_t pending_req_otp_len; - - /** - * pac_file - File path or blob name for the PAC entries (EAP-FAST) - * - * wpa_supplicant will need to be able to create this file and write - * updates to it when PAC is being provisioned or refreshed. Full path - * to the file should be used since working directory may change when - * wpa_supplicant is run in the background. - * Alternatively, a named configuration blob can be used by setting - * this to blob://blob_name. - */ - char *pac_file; - - /** - * mschapv2_retry - MSCHAPv2 retry in progress - * - * This field is used internally by EAP-MSCHAPv2 and should not be set - * as part of configuration. - */ - int mschapv2_retry; - - /** - * new_password - New password for password update - * - * This field is used during MSCHAPv2 password update. This is normally - * requested from the user through the control interface and not set - * from configuration. - */ - u8 *new_password; - - /** - * new_password_len - Length of new_password field - */ - size_t new_password_len; - - /** - * fragment_size - Maximum EAP fragment size in bytes (default 1398) - * - * This value limits the fragment size for EAP methods that support - * fragmentation (e.g., EAP-TLS and EAP-PEAP). This value should be set - * small enough to make the EAP messages fit in MTU of the network - * interface used for EAPOL. The default value is suitable for most - * cases. - */ - int fragment_size; - -#define EAP_CONFIG_FLAGS_PASSWORD_NTHASH BIT(0) - /** - * flags - Network configuration flags (bitfield) - * - * This variable is used for internal flags to describe further details - * for the network parameters. - * bit 0 = password is represented as a 16-byte NtPasswordHash value - * instead of plaintext password - */ - u32 flags; -}; - - -/** - * struct wpa_config_blob - Named configuration blob - * - * This data structure is used to provide storage for binary objects to store - * abstract information like certificates and private keys inlined with the - * configuration data. - */ -struct wpa_config_blob { - /** - * name - Blob name - */ - char *name; - - /** - * data - Pointer to binary data - */ - u8 *data; - - /** - * len - Length of binary data - */ - size_t len; - - /** - * next - Pointer to next blob in the configuration - */ - struct wpa_config_blob *next; -}; - -#endif /* EAP_CONFIG_H */ diff --git a/hostapd-0.8/src/eap_peer/eap_fast.c b/hostapd-0.8/src/eap_peer/eap_fast.c deleted file mode 100644 index 5d3e69d..0000000 --- a/hostapd-0.8/src/eap_peer/eap_fast.c +++ /dev/null @@ -1,1712 +0,0 @@ -/* - * EAP peer method: EAP-FAST (RFC 4851) - * Copyright (c) 2004-2008, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#include "includes.h" - -#include "common.h" -#include "crypto/tls.h" -#include "crypto/sha1.h" -#include "eap_common/eap_tlv_common.h" -#include "eap_i.h" -#include "eap_tls_common.h" -#include "eap_config.h" -#include "eap_fast_pac.h" - -#ifdef EAP_FAST_DYNAMIC -#include "eap_fast_pac.c" -#endif /* EAP_FAST_DYNAMIC */ - -/* TODO: - * - test session resumption and enable it if it interoperates - * - password change (pending mschapv2 packet; replay decrypted packet) - */ - - -static void eap_fast_deinit(struct eap_sm *sm, void *priv); - - -struct eap_fast_data { - struct eap_ssl_data ssl; - - int fast_version; - - const struct eap_method *phase2_method; - void *phase2_priv; - int phase2_success; - - struct eap_method_type phase2_type; - struct eap_method_type *phase2_types; - size_t num_phase2_types; - int resuming; /* starting a resumed session */ - struct eap_fast_key_block_provisioning *key_block_p; -#define EAP_FAST_PROV_UNAUTH 1 -#define EAP_FAST_PROV_AUTH 2 - int provisioning_allowed; /* Allowed PAC provisioning modes */ - int provisioning; /* doing PAC provisioning (not the normal auth) */ - int anon_provisioning; /* doing anonymous (unauthenticated) - * provisioning */ - int session_ticket_used; - - u8 key_data[EAP_FAST_KEY_LEN]; - u8 emsk[EAP_EMSK_LEN]; - int success; - - struct eap_fast_pac *pac; - struct eap_fast_pac *current_pac; - size_t max_pac_list_len; - int use_pac_binary_format; - - u8 simck[EAP_FAST_SIMCK_LEN]; - int simck_idx; - - struct wpabuf *pending_phase2_req; -}; - - -static int eap_fast_session_ticket_cb(void *ctx, const u8 *ticket, size_t len, - const u8 *client_random, - const u8 *server_random, - u8 *master_secret) -{ - struct eap_fast_data *data = ctx; - - wpa_printf(MSG_DEBUG, "EAP-FAST: SessionTicket callback"); - - if (client_random == NULL || server_random == NULL || - master_secret == NULL) { - wpa_printf(MSG_DEBUG, "EAP-FAST: SessionTicket failed - fall " - "back to full TLS handshake"); - data->session_ticket_used = 0; - if (data->provisioning_allowed) { - wpa_printf(MSG_DEBUG, "EAP-FAST: Try to provision a " - "new PAC-Key"); - data->provisioning = 1; - data->current_pac = NULL; - } - return 0; - } - - wpa_hexdump(MSG_DEBUG, "EAP-FAST: SessionTicket", ticket, len); - - if (data->current_pac == NULL) { - wpa_printf(MSG_DEBUG, "EAP-FAST: No PAC-Key available for " - "using SessionTicket"); - data->session_ticket_used = 0; - return 0; - } - - eap_fast_derive_master_secret(data->current_pac->pac_key, - server_random, client_random, - master_secret); - - data->session_ticket_used = 1; - - return 1; -} - - -static int eap_fast_parse_phase1(struct eap_fast_data *data, - const char *phase1) -{ - const char *pos; - - pos = os_strstr(phase1, "fast_provisioning="); - if (pos) { - data->provisioning_allowed = atoi(pos + 18); - wpa_printf(MSG_DEBUG, "EAP-FAST: Automatic PAC provisioning " - "mode: %d", data->provisioning_allowed); - } - - pos = os_strstr(phase1, "fast_max_pac_list_len="); - if (pos) { - data->max_pac_list_len = atoi(pos + 22); - if (data->max_pac_list_len == 0) - data->max_pac_list_len = 1; - wpa_printf(MSG_DEBUG, "EAP-FAST: Maximum PAC list length: %lu", - (unsigned long) data->max_pac_list_len); - } - - pos = os_strstr(phase1, "fast_pac_format=binary"); - if (pos) { - data->use_pac_binary_format = 1; - wpa_printf(MSG_DEBUG, "EAP-FAST: Using binary format for PAC " - "list"); - } - - return 0; -} - - -static void * eap_fast_init(struct eap_sm *sm) -{ - struct eap_fast_data *data; - struct eap_peer_config *config = eap_get_config(sm); - - data = os_zalloc(sizeof(*data)); - if (data == NULL) - return NULL; - data->fast_version = EAP_FAST_VERSION; - data->max_pac_list_len = 10; - - if (config && config->phase1 && - eap_fast_parse_phase1(data, config->phase1) < 0) { - eap_fast_deinit(sm, data); - return NULL; - } - - if (eap_peer_select_phase2_methods(config, "auth=", - &data->phase2_types, - &data->num_phase2_types) < 0) { - eap_fast_deinit(sm, data); - return NULL; - } - - data->phase2_type.vendor = EAP_VENDOR_IETF; - data->phase2_type.method = EAP_TYPE_NONE; - - if (eap_peer_tls_ssl_init(sm, &data->ssl, config)) { - wpa_printf(MSG_INFO, "EAP-FAST: Failed to initialize SSL."); - eap_fast_deinit(sm, data); - return NULL; - } - - if (tls_connection_set_session_ticket_cb(sm->ssl_ctx, data->ssl.conn, - eap_fast_session_ticket_cb, - data) < 0) { - wpa_printf(MSG_INFO, "EAP-FAST: Failed to set SessionTicket " - "callback"); - eap_fast_deinit(sm, data); - return NULL; - } - - /* - * The local RADIUS server in a Cisco AP does not seem to like empty - * fragments before data, so disable that workaround for CBC. - * TODO: consider making this configurable - */ - if (tls_connection_enable_workaround(sm->ssl_ctx, data->ssl.conn)) { - wpa_printf(MSG_DEBUG, "EAP-FAST: Failed to enable TLS " - "workarounds"); - } - - if (data->use_pac_binary_format && - eap_fast_load_pac_bin(sm, &data->pac, config->pac_file) < 0) { - eap_fast_deinit(sm, data); - return NULL; - } - - if (!data->use_pac_binary_format && - eap_fast_load_pac(sm, &data->pac, config->pac_file) < 0) { - eap_fast_deinit(sm, data); - return NULL; - } - eap_fast_pac_list_truncate(data->pac, data->max_pac_list_len); - - if (data->pac == NULL && !data->provisioning_allowed) { - wpa_printf(MSG_INFO, "EAP-FAST: No PAC configured and " - "provisioning disabled"); - eap_fast_deinit(sm, data); - return NULL; - } - - return data; -} - - -static void eap_fast_deinit(struct eap_sm *sm, void *priv) -{ - struct eap_fast_data *data = priv; - struct eap_fast_pac *pac, *prev; - - if (data == NULL) - return; - if (data->phase2_priv && data->phase2_method) - data->phase2_method->deinit(sm, data->phase2_priv); - os_free(data->phase2_types); - os_free(data->key_block_p); - eap_peer_tls_ssl_deinit(sm, &data->ssl); - - pac = data->pac; - prev = NULL; - while (pac) { - prev = pac; - pac = pac->next; - eap_fast_free_pac(prev); - } - wpabuf_free(data->pending_phase2_req); - os_free(data); -} - - -static int eap_fast_derive_msk(struct eap_fast_data *data) -{ - eap_fast_derive_eap_msk(data->simck, data->key_data); - eap_fast_derive_eap_emsk(data->simck, data->emsk); - data->success = 1; - return 0; -} - - -static void eap_fast_derive_key_auth(struct eap_sm *sm, - struct eap_fast_data *data) -{ - u8 *sks; - - /* RFC 4851, Section 5.1: - * Extra key material after TLS key_block: session_key_seed[40] - */ - - sks = eap_fast_derive_key(sm->ssl_ctx, data->ssl.conn, "key expansion", - EAP_FAST_SKS_LEN); - if (sks == NULL) { - wpa_printf(MSG_DEBUG, "EAP-FAST: Failed to derive " - "session_key_seed"); - return; - } - - /* - * RFC 4851, Section 5.2: - * S-IMCK[0] = session_key_seed - */ - wpa_hexdump_key(MSG_DEBUG, - "EAP-FAST: session_key_seed (SKS = S-IMCK[0])", - sks, EAP_FAST_SKS_LEN); - data->simck_idx = 0; - os_memcpy(data->simck, sks, EAP_FAST_SIMCK_LEN); - os_free(sks); -} - - -static void eap_fast_derive_key_provisioning(struct eap_sm *sm, - struct eap_fast_data *data) -{ - os_free(data->key_block_p); - data->key_block_p = (struct eap_fast_key_block_provisioning *) - eap_fast_derive_key(sm->ssl_ctx, data->ssl.conn, - "key expansion", - sizeof(*data->key_block_p)); - if (data->key_block_p == NULL) { - wpa_printf(MSG_DEBUG, "EAP-FAST: Failed to derive key block"); - return; - } - /* - * RFC 4851, Section 5.2: - * S-IMCK[0] = session_key_seed - */ - wpa_hexdump_key(MSG_DEBUG, - "EAP-FAST: session_key_seed (SKS = S-IMCK[0])", - data->key_block_p->session_key_seed, - sizeof(data->key_block_p->session_key_seed)); - data->simck_idx = 0; - os_memcpy(data->simck, data->key_block_p->session_key_seed, - EAP_FAST_SIMCK_LEN); - wpa_hexdump_key(MSG_DEBUG, "EAP-FAST: server_challenge", - data->key_block_p->server_challenge, - sizeof(data->key_block_p->server_challenge)); - wpa_hexdump_key(MSG_DEBUG, "EAP-FAST: client_challenge", - data->key_block_p->client_challenge, - sizeof(data->key_block_p->client_challenge)); -} - - -static void eap_fast_derive_keys(struct eap_sm *sm, struct eap_fast_data *data) -{ - if (data->anon_provisioning) - eap_fast_derive_key_provisioning(sm, data); - else - eap_fast_derive_key_auth(sm, data); -} - - -static int eap_fast_init_phase2_method(struct eap_sm *sm, - struct eap_fast_data *data) -{ - data->phase2_method = - eap_peer_get_eap_method(data->phase2_type.vendor, - data->phase2_type.method); - if (data->phase2_method == NULL) - return -1; - - if (data->key_block_p) { - sm->auth_challenge = data->key_block_p->server_challenge; - sm->peer_challenge = data->key_block_p->client_challenge; - } - sm->init_phase2 = 1; - data->phase2_priv = data->phase2_method->init(sm); - sm->init_phase2 = 0; - sm->auth_challenge = NULL; - sm->peer_challenge = NULL; - - return data->phase2_priv == NULL ? -1 : 0; -} - - -static int eap_fast_select_phase2_method(struct eap_fast_data *data, u8 type) -{ - size_t i; - - /* TODO: TNC with anonymous provisioning; need to require both - * completed MSCHAPv2 and TNC */ - - if (data->anon_provisioning && type != EAP_TYPE_MSCHAPV2) { - wpa_printf(MSG_INFO, "EAP-FAST: Only EAP-MSCHAPv2 is allowed " - "during unauthenticated provisioning; reject phase2" - " type %d", type); - return -1; - } - -#ifdef EAP_TNC - if (type == EAP_TYPE_TNC) { - data->phase2_type.vendor = EAP_VENDOR_IETF; - data->phase2_type.method = EAP_TYPE_TNC; - wpa_printf(MSG_DEBUG, "EAP-FAST: Selected Phase 2 EAP " - "vendor %d method %d for TNC", - data->phase2_type.vendor, - data->phase2_type.method); - return 0; - } -#endif /* EAP_TNC */ - - for (i = 0; i < data->num_phase2_types; i++) { - if (data->phase2_types[i].vendor != EAP_VENDOR_IETF || - data->phase2_types[i].method != type) - continue; - - data->phase2_type.vendor = data->phase2_types[i].vendor; - data->phase2_type.method = data->phase2_types[i].method; - wpa_printf(MSG_DEBUG, "EAP-FAST: Selected Phase 2 EAP " - "vendor %d method %d", - data->phase2_type.vendor, - data->phase2_type.method); - break; - } - - if (type != data->phase2_type.method || type == EAP_TYPE_NONE) - return -1; - - return 0; -} - - -static int eap_fast_phase2_request(struct eap_sm *sm, - struct eap_fast_data *data, - struct eap_method_ret *ret, - struct eap_hdr *hdr, - struct wpabuf **resp) -{ - size_t len = be_to_host16(hdr->length); - u8 *pos; - struct eap_method_ret iret; - struct eap_peer_config *config = eap_get_config(sm); - struct wpabuf msg; - - if (len <= sizeof(struct eap_hdr)) { - wpa_printf(MSG_INFO, "EAP-FAST: too short " - "Phase 2 request (len=%lu)", (unsigned long) len); - return -1; - } - pos = (u8 *) (hdr + 1); - wpa_printf(MSG_DEBUG, "EAP-FAST: Phase 2 Request: type=%d", *pos); - if (*pos == EAP_TYPE_IDENTITY) { - *resp = eap_sm_buildIdentity(sm, hdr->identifier, 1); - return 0; - } - - if (data->phase2_priv && data->phase2_method && - *pos != data->phase2_type.method) { - wpa_printf(MSG_DEBUG, "EAP-FAST: Phase 2 EAP sequence - " - "deinitialize previous method"); - data->phase2_method->deinit(sm, data->phase2_priv); - data->phase2_method = NULL; - data->phase2_priv = NULL; - data->phase2_type.vendor = EAP_VENDOR_IETF; - data->phase2_type.method = EAP_TYPE_NONE; - } - - if (data->phase2_type.vendor == EAP_VENDOR_IETF && - data->phase2_type.method == EAP_TYPE_NONE && - eap_fast_select_phase2_method(data, *pos) < 0) { - if (eap_peer_tls_phase2_nak(data->phase2_types, - data->num_phase2_types, - hdr, resp)) - return -1; - return 0; - } - - if (data->phase2_priv == NULL && - eap_fast_init_phase2_method(sm, data) < 0) { - wpa_printf(MSG_INFO, "EAP-FAST: Failed to initialize " - "Phase 2 EAP method %d", *pos); - ret->methodState = METHOD_DONE; - ret->decision = DECISION_FAIL; - return -1; - } - - os_memset(&iret, 0, sizeof(iret)); - wpabuf_set(&msg, hdr, len); - *resp = data->phase2_method->process(sm, data->phase2_priv, &iret, - &msg); - if (*resp == NULL || - (iret.methodState == METHOD_DONE && - iret.decision == DECISION_FAIL)) { - ret->methodState = METHOD_DONE; - ret->decision = DECISION_FAIL; - } else if ((iret.methodState == METHOD_DONE || - iret.methodState == METHOD_MAY_CONT) && - (iret.decision == DECISION_UNCOND_SUCC || - iret.decision == DECISION_COND_SUCC)) { - data->phase2_success = 1; - } - - if (*resp == NULL && config && - (config->pending_req_identity || config->pending_req_password || - config->pending_req_otp || config->pending_req_new_password)) { - wpabuf_free(data->pending_phase2_req); - data->pending_phase2_req = wpabuf_alloc_copy(hdr, len); - } else if (*resp == NULL) - return -1; - - return 0; -} - - -static struct wpabuf * eap_fast_tlv_nak(int vendor_id, int tlv_type) -{ - struct wpabuf *buf; - struct eap_tlv_nak_tlv *nak; - buf = wpabuf_alloc(sizeof(*nak)); - if (buf == NULL) - return NULL; - nak = wpabuf_put(buf, sizeof(*nak)); - nak->tlv_type = host_to_be16(EAP_TLV_TYPE_MANDATORY | EAP_TLV_NAK_TLV); - nak->length = host_to_be16(6); - nak->vendor_id = host_to_be32(vendor_id); - nak->nak_type = host_to_be16(tlv_type); - return buf; -} - - -static struct wpabuf * eap_fast_tlv_result(int status, int intermediate) -{ - struct wpabuf *buf; - struct eap_tlv_intermediate_result_tlv *result; - buf = wpabuf_alloc(sizeof(*result)); - if (buf == NULL) - return NULL; - wpa_printf(MSG_DEBUG, "EAP-FAST: Add %sResult TLV(status=%d)", - intermediate ? "Intermediate " : "", status); - result = wpabuf_put(buf, sizeof(*result)); - result->tlv_type = host_to_be16(EAP_TLV_TYPE_MANDATORY | - (intermediate ? - EAP_TLV_INTERMEDIATE_RESULT_TLV : - EAP_TLV_RESULT_TLV)); - result->length = host_to_be16(2); - result->status = host_to_be16(status); - return buf; -} - - -static struct wpabuf * eap_fast_tlv_pac_ack(void) -{ - struct wpabuf *buf; - struct eap_tlv_result_tlv *res; - struct eap_tlv_pac_ack_tlv *ack; - - buf = wpabuf_alloc(sizeof(*res) + sizeof(*ack)); - if (buf == NULL) - return NULL; - - wpa_printf(MSG_DEBUG, "EAP-FAST: Add PAC TLV (ack)"); - ack = wpabuf_put(buf, sizeof(*ack)); - ack->tlv_type = host_to_be16(EAP_TLV_PAC_TLV | - EAP_TLV_TYPE_MANDATORY); - ack->length = host_to_be16(sizeof(*ack) - sizeof(struct eap_tlv_hdr)); - ack->pac_type = host_to_be16(PAC_TYPE_PAC_ACKNOWLEDGEMENT); - ack->pac_len = host_to_be16(2); - ack->result = host_to_be16(EAP_TLV_RESULT_SUCCESS); - - return buf; -} - - -static struct wpabuf * eap_fast_process_eap_payload_tlv( - struct eap_sm *sm, struct eap_fast_data *data, - struct eap_method_ret *ret, const struct eap_hdr *req, - u8 *eap_payload_tlv, size_t eap_payload_tlv_len) -{ - struct eap_hdr *hdr; - struct wpabuf *resp = NULL; - - if (eap_payload_tlv_len < sizeof(*hdr)) { - wpa_printf(MSG_DEBUG, "EAP-FAST: too short EAP " - "Payload TLV (len=%lu)", - (unsigned long) eap_payload_tlv_len); - return NULL; - } - - hdr = (struct eap_hdr *) eap_payload_tlv; - if (be_to_host16(hdr->length) > eap_payload_tlv_len) { - wpa_printf(MSG_DEBUG, "EAP-FAST: EAP packet overflow in " - "EAP Payload TLV"); - return NULL; - } - - if (hdr->code != EAP_CODE_REQUEST) { - wpa_printf(MSG_INFO, "EAP-FAST: Unexpected code=%d in " - "Phase 2 EAP header", hdr->code); - return NULL; - } - - if (eap_fast_phase2_request(sm, data, ret, hdr, &resp)) { - wpa_printf(MSG_INFO, "EAP-FAST: Phase2 Request processing " - "failed"); - return NULL; - } - - return eap_fast_tlv_eap_payload(resp); -} - - -static int eap_fast_validate_crypto_binding( - struct eap_tlv_crypto_binding_tlv *_bind) -{ - wpa_printf(MSG_DEBUG, "EAP-FAST: Crypto-Binding TLV: Version %d " - "Received Version %d SubType %d", - _bind->version, _bind->received_version, _bind->subtype); - wpa_hexdump(MSG_MSGDUMP, "EAP-FAST: NONCE", - _bind->nonce, sizeof(_bind->nonce)); - wpa_hexdump(MSG_MSGDUMP, "EAP-FAST: Compound MAC", - _bind->compound_mac, sizeof(_bind->compound_mac)); - - if (_bind->version != EAP_FAST_VERSION || - _bind->received_version != EAP_FAST_VERSION || - _bind->subtype != EAP_TLV_CRYPTO_BINDING_SUBTYPE_REQUEST) { - wpa_printf(MSG_INFO, "EAP-FAST: Invalid version/subtype in " - "Crypto-Binding TLV: Version %d " - "Received Version %d SubType %d", - _bind->version, _bind->received_version, - _bind->subtype); - return -1; - } - - return 0; -} - - -static void eap_fast_write_crypto_binding( - struct eap_tlv_crypto_binding_tlv *rbind, - struct eap_tlv_crypto_binding_tlv *_bind, const u8 *cmk) -{ - rbind->tlv_type = host_to_be16(EAP_TLV_TYPE_MANDATORY | - EAP_TLV_CRYPTO_BINDING_TLV); - rbind->length = host_to_be16(sizeof(*rbind) - - sizeof(struct eap_tlv_hdr)); - rbind->version = EAP_FAST_VERSION; - rbind->received_version = _bind->version; - rbind->subtype = EAP_TLV_CRYPTO_BINDING_SUBTYPE_RESPONSE; - os_memcpy(rbind->nonce, _bind->nonce, sizeof(_bind->nonce)); - inc_byte_array(rbind->nonce, sizeof(rbind->nonce)); - hmac_sha1(cmk, EAP_FAST_CMK_LEN, (u8 *) rbind, sizeof(*rbind), - rbind->compound_mac); - - wpa_printf(MSG_DEBUG, "EAP-FAST: Reply Crypto-Binding TLV: Version %d " - "Received Version %d SubType %d", - rbind->version, rbind->received_version, rbind->subtype); - wpa_hexdump(MSG_MSGDUMP, "EAP-FAST: NONCE", - rbind->nonce, sizeof(rbind->nonce)); - wpa_hexdump(MSG_MSGDUMP, "EAP-FAST: Compound MAC", - rbind->compound_mac, sizeof(rbind->compound_mac)); -} - - -static int eap_fast_get_phase2_key(struct eap_sm *sm, - struct eap_fast_data *data, - u8 *isk, size_t isk_len) -{ - u8 *key; - size_t key_len; - - os_memset(isk, 0, isk_len); - - if (data->phase2_method == NULL || data->phase2_priv == NULL) { - wpa_printf(MSG_DEBUG, "EAP-FAST: Phase 2 method not " - "available"); - return -1; - } - - if (data->phase2_method->isKeyAvailable == NULL || - data->phase2_method->getKey == NULL) - return 0; - - if (!data->phase2_method->isKeyAvailable(sm, data->phase2_priv) || - (key = data->phase2_method->getKey(sm, data->phase2_priv, - &key_len)) == NULL) { - wpa_printf(MSG_DEBUG, "EAP-FAST: Could not get key material " - "from Phase 2"); - return -1; - } - - if (key_len > isk_len) - key_len = isk_len; - if (key_len == 32 && - data->phase2_method->vendor == EAP_VENDOR_IETF && - data->phase2_method->method == EAP_TYPE_MSCHAPV2) { - /* - * EAP-FAST uses reverse order for MS-MPPE keys when deriving - * MSK from EAP-MSCHAPv2. Swap the keys here to get the correct - * ISK for EAP-FAST cryptobinding. - */ - os_memcpy(isk, key + 16, 16); - os_memcpy(isk + 16, key, 16); - } else - os_memcpy(isk, key, key_len); - os_free(key); - - return 0; -} - - -static int eap_fast_get_cmk(struct eap_sm *sm, struct eap_fast_data *data, - u8 *cmk) -{ - u8 isk[32], imck[60]; - - wpa_printf(MSG_DEBUG, "EAP-FAST: Determining CMK[%d] for Compound MIC " - "calculation", data->simck_idx + 1); - - /* - * RFC 4851, Section 5.2: - * IMCK[j] = T-PRF(S-IMCK[j-1], "Inner Methods Compound Keys", - * MSK[j], 60) - * S-IMCK[j] = first 40 octets of IMCK[j] - * CMK[j] = last 20 octets of IMCK[j] - */ - - if (eap_fast_get_phase2_key(sm, data, isk, sizeof(isk)) < 0) - return -1; - wpa_hexdump_key(MSG_MSGDUMP, "EAP-FAST: ISK[j]", isk, sizeof(isk)); - sha1_t_prf(data->simck, EAP_FAST_SIMCK_LEN, - "Inner Methods Compound Keys", - isk, sizeof(isk), imck, sizeof(imck)); - data->simck_idx++; - os_memcpy(data->simck, imck, EAP_FAST_SIMCK_LEN); - wpa_hexdump_key(MSG_MSGDUMP, "EAP-FAST: S-IMCK[j]", - data->simck, EAP_FAST_SIMCK_LEN); - os_memcpy(cmk, imck + EAP_FAST_SIMCK_LEN, EAP_FAST_CMK_LEN); - wpa_hexdump_key(MSG_MSGDUMP, "EAP-FAST: CMK[j]", - cmk, EAP_FAST_CMK_LEN); - - return 0; -} - - -static u8 * eap_fast_write_pac_request(u8 *pos, u16 pac_type) -{ - struct eap_tlv_hdr *pac; - struct eap_tlv_request_action_tlv *act; - struct eap_tlv_pac_type_tlv *type; - - act = (struct eap_tlv_request_action_tlv *) pos; - act->tlv_type = host_to_be16(EAP_TLV_REQUEST_ACTION_TLV); - act->length = host_to_be16(2); - act->action = host_to_be16(EAP_TLV_ACTION_PROCESS_TLV); - - pac = (struct eap_tlv_hdr *) (act + 1); - pac->tlv_type = host_to_be16(EAP_TLV_PAC_TLV); - pac->length = host_to_be16(sizeof(*type)); - - type = (struct eap_tlv_pac_type_tlv *) (pac + 1); - type->tlv_type = host_to_be16(PAC_TYPE_PAC_TYPE); - type->length = host_to_be16(2); - type->pac_type = host_to_be16(pac_type); - - return (u8 *) (type + 1); -} - - -static struct wpabuf * eap_fast_process_crypto_binding( - struct eap_sm *sm, struct eap_fast_data *data, - struct eap_method_ret *ret, - struct eap_tlv_crypto_binding_tlv *_bind, size_t bind_len) -{ - struct wpabuf *resp; - u8 *pos; - u8 cmk[EAP_FAST_CMK_LEN], cmac[SHA1_MAC_LEN]; - int res; - size_t len; - - if (eap_fast_validate_crypto_binding(_bind) < 0) - return NULL; - - if (eap_fast_get_cmk(sm, data, cmk) < 0) - return NULL; - - /* Validate received Compound MAC */ - os_memcpy(cmac, _bind->compound_mac, sizeof(cmac)); - os_memset(_bind->compound_mac, 0, sizeof(cmac)); - wpa_hexdump(MSG_MSGDUMP, "EAP-FAST: Crypto-Binding TLV for Compound " - "MAC calculation", (u8 *) _bind, bind_len); - hmac_sha1(cmk, EAP_FAST_CMK_LEN, (u8 *) _bind, bind_len, - _bind->compound_mac); - res = os_memcmp(cmac, _bind->compound_mac, sizeof(cmac)); - wpa_hexdump(MSG_MSGDUMP, "EAP-FAST: Received Compound MAC", - cmac, sizeof(cmac)); - wpa_hexdump(MSG_MSGDUMP, "EAP-FAST: Calculated Compound MAC", - _bind->compound_mac, sizeof(cmac)); - if (res != 0) { - wpa_printf(MSG_INFO, "EAP-FAST: Compound MAC did not match"); - os_memcpy(_bind->compound_mac, cmac, sizeof(cmac)); - return NULL; - } - - /* - * Compound MAC was valid, so authentication succeeded. Reply with - * crypto binding to allow server to complete authentication. - */ - - len = sizeof(struct eap_tlv_crypto_binding_tlv); - resp = wpabuf_alloc(len); - if (resp == NULL) - return NULL; - - if (!data->anon_provisioning && data->phase2_success && - eap_fast_derive_msk(data) < 0) { - wpa_printf(MSG_INFO, "EAP-FAST: Failed to generate MSK"); - ret->methodState = METHOD_DONE; - ret->decision = DECISION_FAIL; - data->phase2_success = 0; - wpabuf_free(resp); - return NULL; - } - - pos = wpabuf_put(resp, sizeof(struct eap_tlv_crypto_binding_tlv)); - eap_fast_write_crypto_binding((struct eap_tlv_crypto_binding_tlv *) - pos, _bind, cmk); - - return resp; -} - - -static void eap_fast_parse_pac_tlv(struct eap_fast_pac *entry, int type, - u8 *pos, size_t len, int *pac_key_found) -{ - switch (type & 0x7fff) { - case PAC_TYPE_PAC_KEY: - wpa_hexdump_key(MSG_DEBUG, "EAP-FAST: PAC-Key", pos, len); - if (len != EAP_FAST_PAC_KEY_LEN) { - wpa_printf(MSG_DEBUG, "EAP-FAST: Invalid PAC-Key " - "length %lu", (unsigned long) len); - break; - } - *pac_key_found = 1; - os_memcpy(entry->pac_key, pos, len); - break; - case PAC_TYPE_PAC_OPAQUE: - wpa_hexdump(MSG_DEBUG, "EAP-FAST: PAC-Opaque", pos, len); - entry->pac_opaque = pos; - entry->pac_opaque_len = len; - break; - case PAC_TYPE_PAC_INFO: - wpa_hexdump(MSG_DEBUG, "EAP-FAST: PAC-Info", pos, len); - entry->pac_info = pos; - entry->pac_info_len = len; - break; - default: - wpa_printf(MSG_DEBUG, "EAP-FAST: Ignored unknown PAC type %d", - type); - break; - } -} - - -static int eap_fast_process_pac_tlv(struct eap_fast_pac *entry, - u8 *pac, size_t pac_len) -{ - struct pac_tlv_hdr *hdr; - u8 *pos; - size_t left, len; - int type, pac_key_found = 0; - - pos = pac; - left = pac_len; - - while (left > sizeof(*hdr)) { - hdr = (struct pac_tlv_hdr *) pos; - type = be_to_host16(hdr->type); - len = be_to_host16(hdr->len); - pos += sizeof(*hdr); - left -= sizeof(*hdr); - if (len > left) { - wpa_printf(MSG_DEBUG, "EAP-FAST: PAC TLV overrun " - "(type=%d len=%lu left=%lu)", - type, (unsigned long) len, - (unsigned long) left); - return -1; - } - - eap_fast_parse_pac_tlv(entry, type, pos, len, &pac_key_found); - - pos += len; - left -= len; - } - - if (!pac_key_found || !entry->pac_opaque || !entry->pac_info) { - wpa_printf(MSG_DEBUG, "EAP-FAST: PAC TLV does not include " - "all the required fields"); - return -1; - } - - return 0; -} - - -static int eap_fast_parse_pac_info(struct eap_fast_pac *entry, int type, - u8 *pos, size_t len) -{ - u16 pac_type; - u32 lifetime; - struct os_time now; - - switch (type & 0x7fff) { - case PAC_TYPE_CRED_LIFETIME: - if (len != 4) { - wpa_hexdump(MSG_DEBUG, "EAP-FAST: PAC-Info - " - "Invalid CRED_LIFETIME length - ignored", - pos, len); - return 0; - } - - /* - * This is not currently saved separately in PAC files since - * the server can automatically initiate PAC update when - * needed. Anyway, the information is available from PAC-Info - * dump if it is needed for something in the future. - */ - lifetime = WPA_GET_BE32(pos); - os_get_time(&now); - wpa_printf(MSG_DEBUG, "EAP-FAST: PAC-Info - CRED_LIFETIME %d " - "(%d days)", - lifetime, (lifetime - (u32) now.sec) / 86400); - break; - case PAC_TYPE_A_ID: - wpa_hexdump_ascii(MSG_DEBUG, "EAP-FAST: PAC-Info - A-ID", - pos, len); - entry->a_id = pos; - entry->a_id_len = len; - break; - case PAC_TYPE_I_ID: - wpa_hexdump_ascii(MSG_DEBUG, "EAP-FAST: PAC-Info - I-ID", - pos, len); - entry->i_id = pos; - entry->i_id_len = len; - break; - case PAC_TYPE_A_ID_INFO: - wpa_hexdump_ascii(MSG_DEBUG, "EAP-FAST: PAC-Info - A-ID-Info", - pos, len); - entry->a_id_info = pos; - entry->a_id_info_len = len; - break; - case PAC_TYPE_PAC_TYPE: - /* RFC 5422, Section 4.2.6 - PAC-Type TLV */ - if (len != 2) { - wpa_printf(MSG_INFO, "EAP-FAST: Invalid PAC-Type " - "length %lu (expected 2)", - (unsigned long) len); - wpa_hexdump_ascii(MSG_DEBUG, - "EAP-FAST: PAC-Info - PAC-Type", - pos, len); - return -1; - } - pac_type = WPA_GET_BE16(pos); - if (pac_type != PAC_TYPE_TUNNEL_PAC && - pac_type != PAC_TYPE_USER_AUTHORIZATION && - pac_type != PAC_TYPE_MACHINE_AUTHENTICATION) { - wpa_printf(MSG_INFO, "EAP-FAST: Unsupported PAC Type " - "%d", pac_type); - return -1; - } - - wpa_printf(MSG_DEBUG, "EAP-FAST: PAC-Info - PAC-Type %d", - pac_type); - entry->pac_type = pac_type; - break; - default: - wpa_printf(MSG_DEBUG, "EAP-FAST: Ignored unknown PAC-Info " - "type %d", type); - break; - } - - return 0; -} - - -static int eap_fast_process_pac_info(struct eap_fast_pac *entry) -{ - struct pac_tlv_hdr *hdr; - u8 *pos; - size_t left, len; - int type; - - /* RFC 5422, Section 4.2.4 */ - - /* PAC-Type defaults to Tunnel PAC (Type 1) */ - entry->pac_type = PAC_TYPE_TUNNEL_PAC; - - pos = entry->pac_info; - left = entry->pac_info_len; - while (left > sizeof(*hdr)) { - hdr = (struct pac_tlv_hdr *) pos; - type = be_to_host16(hdr->type); - len = be_to_host16(hdr->len); - pos += sizeof(*hdr); - left -= sizeof(*hdr); - if (len > left) { - wpa_printf(MSG_DEBUG, "EAP-FAST: PAC-Info overrun " - "(type=%d len=%lu left=%lu)", - type, (unsigned long) len, - (unsigned long) left); - return -1; - } - - if (eap_fast_parse_pac_info(entry, type, pos, len) < 0) - return -1; - - pos += len; - left -= len; - } - - if (entry->a_id == NULL || entry->a_id_info == NULL) { - wpa_printf(MSG_DEBUG, "EAP-FAST: PAC-Info does not include " - "all the required fields"); - return -1; - } - - return 0; -} - - -static struct wpabuf * eap_fast_process_pac(struct eap_sm *sm, - struct eap_fast_data *data, - struct eap_method_ret *ret, - u8 *pac, size_t pac_len) -{ - struct eap_peer_config *config = eap_get_config(sm); - struct eap_fast_pac entry; - - os_memset(&entry, 0, sizeof(entry)); - if (eap_fast_process_pac_tlv(&entry, pac, pac_len) || - eap_fast_process_pac_info(&entry)) - return NULL; - - eap_fast_add_pac(&data->pac, &data->current_pac, &entry); - eap_fast_pac_list_truncate(data->pac, data->max_pac_list_len); - if (data->use_pac_binary_format) - eap_fast_save_pac_bin(sm, data->pac, config->pac_file); - else - eap_fast_save_pac(sm, data->pac, config->pac_file); - - if (data->provisioning) { - if (data->anon_provisioning) { - /* - * Unauthenticated provisioning does not provide keying - * material and must end with an EAP-Failure. - * Authentication will be done separately after this. - */ - data->success = 0; - ret->decision = DECISION_FAIL; - } else { - /* - * Server may or may not allow authenticated - * provisioning also for key generation. - */ - ret->decision = DECISION_COND_SUCC; - } - wpa_printf(MSG_DEBUG, "EAP-FAST: Send PAC-Acknowledgement TLV " - "- Provisioning completed successfully"); - } else { - /* - * This is PAC refreshing, i.e., normal authentication that is - * expected to be completed with an EAP-Success. - */ - wpa_printf(MSG_DEBUG, "EAP-FAST: Send PAC-Acknowledgement TLV " - "- PAC refreshing completed successfully"); - ret->decision = DECISION_UNCOND_SUCC; - } - ret->methodState = METHOD_DONE; - return eap_fast_tlv_pac_ack(); -} - - -static int eap_fast_parse_decrypted(struct wpabuf *decrypted, - struct eap_fast_tlv_parse *tlv, - struct wpabuf **resp) -{ - int mandatory, tlv_type, len, res; - u8 *pos, *end; - - os_memset(tlv, 0, sizeof(*tlv)); - - /* Parse TLVs from the decrypted Phase 2 data */ - pos = wpabuf_mhead(decrypted); - end = pos + wpabuf_len(decrypted); - while (pos + 4 < end) { - mandatory = pos[0] & 0x80; - tlv_type = WPA_GET_BE16(pos) & 0x3fff; - pos += 2; - len = WPA_GET_BE16(pos); - pos += 2; - if (pos + len > end) { - wpa_printf(MSG_INFO, "EAP-FAST: TLV overflow"); - return -1; - } - wpa_printf(MSG_DEBUG, "EAP-FAST: Received Phase 2: " - "TLV type %d length %d%s", - tlv_type, len, mandatory ? " (mandatory)" : ""); - - res = eap_fast_parse_tlv(tlv, tlv_type, pos, len); - if (res == -2) - break; - if (res < 0) { - if (mandatory) { - wpa_printf(MSG_DEBUG, "EAP-FAST: Nak unknown " - "mandatory TLV type %d", tlv_type); - *resp = eap_fast_tlv_nak(0, tlv_type); - break; - } else { - wpa_printf(MSG_DEBUG, "EAP-FAST: ignored " - "unknown optional TLV type %d", - tlv_type); - } - } - - pos += len; - } - - return 0; -} - - -static int eap_fast_encrypt_response(struct eap_sm *sm, - struct eap_fast_data *data, - struct wpabuf *resp, - u8 identifier, struct wpabuf **out_data) -{ - if (resp == NULL) - return 0; - - wpa_hexdump_buf(MSG_DEBUG, "EAP-FAST: Encrypting Phase 2 data", - resp); - if (eap_peer_tls_encrypt(sm, &data->ssl, EAP_TYPE_FAST, - data->fast_version, identifier, - resp, out_data)) { - wpa_printf(MSG_INFO, "EAP-FAST: Failed to encrypt a Phase 2 " - "frame"); - } - wpabuf_free(resp); - - return 0; -} - - -static struct wpabuf * eap_fast_pac_request(void) -{ - struct wpabuf *tmp; - u8 *pos, *pos2; - - tmp = wpabuf_alloc(sizeof(struct eap_tlv_hdr) + - sizeof(struct eap_tlv_request_action_tlv) + - sizeof(struct eap_tlv_pac_type_tlv)); - if (tmp == NULL) - return NULL; - - pos = wpabuf_put(tmp, 0); - pos2 = eap_fast_write_pac_request(pos, PAC_TYPE_TUNNEL_PAC); - wpabuf_put(tmp, pos2 - pos); - return tmp; -} - - -static int eap_fast_process_decrypted(struct eap_sm *sm, - struct eap_fast_data *data, - struct eap_method_ret *ret, - const struct eap_hdr *req, - struct wpabuf *decrypted, - struct wpabuf **out_data) -{ - struct wpabuf *resp = NULL, *tmp; - struct eap_fast_tlv_parse tlv; - int failed = 0; - - if (eap_fast_parse_decrypted(decrypted, &tlv, &resp) < 0) - return 0; - if (resp) - return eap_fast_encrypt_response(sm, data, resp, - req->identifier, out_data); - - if (tlv.result == EAP_TLV_RESULT_FAILURE) { - resp = eap_fast_tlv_result(EAP_TLV_RESULT_FAILURE, 0); - return eap_fast_encrypt_response(sm, data, resp, - req->identifier, out_data); - } - - if (tlv.iresult == EAP_TLV_RESULT_FAILURE) { - resp = eap_fast_tlv_result(EAP_TLV_RESULT_FAILURE, 1); - return eap_fast_encrypt_response(sm, data, resp, - req->identifier, out_data); - } - - if (tlv.crypto_binding) { - tmp = eap_fast_process_crypto_binding(sm, data, ret, - tlv.crypto_binding, - tlv.crypto_binding_len); - if (tmp == NULL) - failed = 1; - else - resp = wpabuf_concat(resp, tmp); - } - - if (tlv.iresult == EAP_TLV_RESULT_SUCCESS) { - tmp = eap_fast_tlv_result(failed ? EAP_TLV_RESULT_FAILURE : - EAP_TLV_RESULT_SUCCESS, 1); - resp = wpabuf_concat(resp, tmp); - } - - if (tlv.eap_payload_tlv) { - tmp = eap_fast_process_eap_payload_tlv( - sm, data, ret, req, tlv.eap_payload_tlv, - tlv.eap_payload_tlv_len); - resp = wpabuf_concat(resp, tmp); - } - - if (tlv.pac && tlv.result != EAP_TLV_RESULT_SUCCESS) { - wpa_printf(MSG_DEBUG, "EAP-FAST: PAC TLV without Result TLV " - "acknowledging success"); - failed = 1; - } else if (tlv.pac && tlv.result == EAP_TLV_RESULT_SUCCESS) { - tmp = eap_fast_process_pac(sm, data, ret, tlv.pac, - tlv.pac_len); - resp = wpabuf_concat(resp, tmp); - } - - if (data->current_pac == NULL && data->provisioning && - !data->anon_provisioning && !tlv.pac && - (tlv.iresult == EAP_TLV_RESULT_SUCCESS || - tlv.result == EAP_TLV_RESULT_SUCCESS)) { - /* - * Need to request Tunnel PAC when using authenticated - * provisioning. - */ - wpa_printf(MSG_DEBUG, "EAP-FAST: Request Tunnel PAC"); - tmp = eap_fast_pac_request(); - resp = wpabuf_concat(resp, tmp); - } - - if (tlv.result == EAP_TLV_RESULT_SUCCESS && !failed) { - tmp = eap_fast_tlv_result(EAP_TLV_RESULT_SUCCESS, 0); - resp = wpabuf_concat(tmp, resp); - } else if (failed) { - tmp = eap_fast_tlv_result(EAP_TLV_RESULT_FAILURE, 0); - resp = wpabuf_concat(tmp, resp); - } - - if (resp && tlv.result == EAP_TLV_RESULT_SUCCESS && !failed && - tlv.crypto_binding && data->phase2_success) { - if (data->anon_provisioning) { - wpa_printf(MSG_DEBUG, "EAP-FAST: Unauthenticated " - "provisioning completed successfully."); - ret->methodState = METHOD_DONE; - ret->decision = DECISION_FAIL; - } else { - wpa_printf(MSG_DEBUG, "EAP-FAST: Authentication " - "completed successfully."); - if (data->provisioning) - ret->methodState = METHOD_MAY_CONT; - else - ret->methodState = METHOD_DONE; - ret->decision = DECISION_UNCOND_SUCC; - } - } - - if (resp == NULL) { - wpa_printf(MSG_DEBUG, "EAP-FAST: No recognized TLVs - send " - "empty response packet"); - resp = wpabuf_alloc(1); - } - - return eap_fast_encrypt_response(sm, data, resp, req->identifier, - out_data); -} - - -static int eap_fast_decrypt(struct eap_sm *sm, struct eap_fast_data *data, - struct eap_method_ret *ret, - const struct eap_hdr *req, - const struct wpabuf *in_data, - struct wpabuf **out_data) -{ - struct wpabuf *in_decrypted; - int res; - - wpa_printf(MSG_DEBUG, "EAP-FAST: Received %lu bytes encrypted data for" - " Phase 2", (unsigned long) wpabuf_len(in_data)); - - if (data->pending_phase2_req) { - wpa_printf(MSG_DEBUG, "EAP-FAST: Pending Phase 2 request - " - "skip decryption and use old data"); - /* Clear TLS reassembly state. */ - eap_peer_tls_reset_input(&data->ssl); - - in_decrypted = data->pending_phase2_req; - data->pending_phase2_req = NULL; - goto continue_req; - } - - if (wpabuf_len(in_data) == 0) { - /* Received TLS ACK - requesting more fragments */ - return eap_peer_tls_encrypt(sm, &data->ssl, EAP_TYPE_FAST, - data->fast_version, - req->identifier, NULL, out_data); - } - - res = eap_peer_tls_decrypt(sm, &data->ssl, in_data, &in_decrypted); - if (res) - return res; - -continue_req: - wpa_hexdump_buf(MSG_MSGDUMP, "EAP-FAST: Decrypted Phase 2 TLV(s)", - in_decrypted); - - if (wpabuf_len(in_decrypted) < 4) { - wpa_printf(MSG_INFO, "EAP-FAST: Too short Phase 2 " - "TLV frame (len=%lu)", - (unsigned long) wpabuf_len(in_decrypted)); - wpabuf_free(in_decrypted); - return -1; - } - - res = eap_fast_process_decrypted(sm, data, ret, req, - in_decrypted, out_data); - - wpabuf_free(in_decrypted); - - return res; -} - - -static const u8 * eap_fast_get_a_id(const u8 *buf, size_t len, size_t *id_len) -{ - const u8 *a_id; - struct pac_tlv_hdr *hdr; - - /* - * Parse authority identity (A-ID) from the EAP-FAST/Start. This - * supports both raw A-ID and one inside an A-ID TLV. - */ - a_id = buf; - *id_len = len; - if (len > sizeof(*hdr)) { - int tlen; - hdr = (struct pac_tlv_hdr *) buf; - tlen = be_to_host16(hdr->len); - if (be_to_host16(hdr->type) == PAC_TYPE_A_ID && - sizeof(*hdr) + tlen <= len) { - wpa_printf(MSG_DEBUG, "EAP-FAST: A-ID was in TLV " - "(Start)"); - a_id = (u8 *) (hdr + 1); - *id_len = tlen; - } - } - wpa_hexdump_ascii(MSG_DEBUG, "EAP-FAST: A-ID", a_id, *id_len); - - return a_id; -} - - -static void eap_fast_select_pac(struct eap_fast_data *data, - const u8 *a_id, size_t a_id_len) -{ - data->current_pac = eap_fast_get_pac(data->pac, a_id, a_id_len, - PAC_TYPE_TUNNEL_PAC); - if (data->current_pac == NULL) { - /* - * Tunnel PAC was not available for this A-ID. Try to use - * Machine Authentication PAC, if one is available. - */ - data->current_pac = eap_fast_get_pac( - data->pac, a_id, a_id_len, - PAC_TYPE_MACHINE_AUTHENTICATION); - } - - if (data->current_pac) { - wpa_printf(MSG_DEBUG, "EAP-FAST: PAC found for this A-ID " - "(PAC-Type %d)", data->current_pac->pac_type); - wpa_hexdump_ascii(MSG_MSGDUMP, "EAP-FAST: A-ID-Info", - data->current_pac->a_id_info, - data->current_pac->a_id_info_len); - } -} - - -static int eap_fast_use_pac_opaque(struct eap_sm *sm, - struct eap_fast_data *data, - struct eap_fast_pac *pac) -{ - u8 *tlv; - size_t tlv_len, olen; - struct eap_tlv_hdr *ehdr; - - olen = pac->pac_opaque_len; - tlv_len = sizeof(*ehdr) + olen; - tlv = os_malloc(tlv_len); - if (tlv) { - ehdr = (struct eap_tlv_hdr *) tlv; - ehdr->tlv_type = host_to_be16(PAC_TYPE_PAC_OPAQUE); - ehdr->length = host_to_be16(olen); - os_memcpy(ehdr + 1, pac->pac_opaque, olen); - } - if (tlv == NULL || - tls_connection_client_hello_ext(sm->ssl_ctx, data->ssl.conn, - TLS_EXT_PAC_OPAQUE, - tlv, tlv_len) < 0) { - wpa_printf(MSG_DEBUG, "EAP-FAST: Failed to add PAC-Opaque TLS " - "extension"); - os_free(tlv); - return -1; - } - os_free(tlv); - - return 0; -} - - -static int eap_fast_clear_pac_opaque_ext(struct eap_sm *sm, - struct eap_fast_data *data) -{ - if (tls_connection_client_hello_ext(sm->ssl_ctx, data->ssl.conn, - TLS_EXT_PAC_OPAQUE, NULL, 0) < 0) { - wpa_printf(MSG_DEBUG, "EAP-FAST: Failed to remove PAC-Opaque " - "TLS extension"); - return -1; - } - return 0; -} - - -static int eap_fast_set_provisioning_ciphers(struct eap_sm *sm, - struct eap_fast_data *data) -{ - u8 ciphers[5]; - int count = 0; - - if (data->provisioning_allowed & EAP_FAST_PROV_UNAUTH) { - wpa_printf(MSG_DEBUG, "EAP-FAST: Enabling unauthenticated " - "provisioning TLS cipher suites"); - ciphers[count++] = TLS_CIPHER_ANON_DH_AES128_SHA; - } - - if (data->provisioning_allowed & EAP_FAST_PROV_AUTH) { - wpa_printf(MSG_DEBUG, "EAP-FAST: Enabling authenticated " - "provisioning TLS cipher suites"); - ciphers[count++] = TLS_CIPHER_RSA_DHE_AES128_SHA; - ciphers[count++] = TLS_CIPHER_AES128_SHA; - ciphers[count++] = TLS_CIPHER_RC4_SHA; - } - - ciphers[count++] = TLS_CIPHER_NONE; - - if (tls_connection_set_cipher_list(sm->ssl_ctx, data->ssl.conn, - ciphers)) { - wpa_printf(MSG_INFO, "EAP-FAST: Could not configure TLS " - "cipher suites for provisioning"); - return -1; - } - - return 0; -} - - -static int eap_fast_process_start(struct eap_sm *sm, - struct eap_fast_data *data, u8 flags, - const u8 *pos, size_t left) -{ - const u8 *a_id; - size_t a_id_len; - - /* EAP-FAST Version negotiation (section 3.1) */ - wpa_printf(MSG_DEBUG, "EAP-FAST: Start (server ver=%d, own ver=%d)", - flags & EAP_TLS_VERSION_MASK, data->fast_version); - if ((flags & EAP_TLS_VERSION_MASK) < data->fast_version) - data->fast_version = flags & EAP_TLS_VERSION_MASK; - wpa_printf(MSG_DEBUG, "EAP-FAST: Using FAST version %d", - data->fast_version); - - a_id = eap_fast_get_a_id(pos, left, &a_id_len); - eap_fast_select_pac(data, a_id, a_id_len); - - if (data->resuming && data->current_pac) { - wpa_printf(MSG_DEBUG, "EAP-FAST: Trying to resume session - " - "do not add PAC-Opaque to TLS ClientHello"); - if (eap_fast_clear_pac_opaque_ext(sm, data) < 0) - return -1; - } else if (data->current_pac) { - /* - * PAC found for the A-ID and we are not resuming an old - * session, so add PAC-Opaque extension to ClientHello. - */ - if (eap_fast_use_pac_opaque(sm, data, data->current_pac) < 0) - return -1; - } else { - /* No PAC found, so we must provision one. */ - if (!data->provisioning_allowed) { - wpa_printf(MSG_DEBUG, "EAP-FAST: No PAC found and " - "provisioning disabled"); - return -1; - } - wpa_printf(MSG_DEBUG, "EAP-FAST: No PAC found - " - "starting provisioning"); - if (eap_fast_set_provisioning_ciphers(sm, data) < 0 || - eap_fast_clear_pac_opaque_ext(sm, data) < 0) - return -1; - data->provisioning = 1; - } - - return 0; -} - - -static struct wpabuf * eap_fast_process(struct eap_sm *sm, void *priv, - struct eap_method_ret *ret, - const struct wpabuf *reqData) -{ - const struct eap_hdr *req; - size_t left; - int res; - u8 flags, id; - struct wpabuf *resp; - const u8 *pos; - struct eap_fast_data *data = priv; - - pos = eap_peer_tls_process_init(sm, &data->ssl, EAP_TYPE_FAST, ret, - reqData, &left, &flags); - if (pos == NULL) - return NULL; - - req = wpabuf_head(reqData); - id = req->identifier; - - if (flags & EAP_TLS_FLAGS_START) { - if (eap_fast_process_start(sm, data, flags, pos, left) < 0) - return NULL; - - left = 0; /* A-ID is not used in further packet processing */ - } - - resp = NULL; - if (tls_connection_established(sm->ssl_ctx, data->ssl.conn) && - !data->resuming) { - /* Process tunneled (encrypted) phase 2 data. */ - struct wpabuf msg; - wpabuf_set(&msg, pos, left); - res = eap_fast_decrypt(sm, data, ret, req, &msg, &resp); - if (res < 0) { - ret->methodState = METHOD_DONE; - ret->decision = DECISION_FAIL; - /* - * Ack possible Alert that may have caused failure in - * decryption. - */ - res = 1; - } - } else { - /* Continue processing TLS handshake (phase 1). */ - res = eap_peer_tls_process_helper(sm, &data->ssl, - EAP_TYPE_FAST, - data->fast_version, id, pos, - left, &resp); - - if (tls_connection_established(sm->ssl_ctx, data->ssl.conn)) { - char cipher[80]; - wpa_printf(MSG_DEBUG, - "EAP-FAST: TLS done, proceed to Phase 2"); - if (data->provisioning && - (!(data->provisioning_allowed & - EAP_FAST_PROV_AUTH) || - tls_get_cipher(sm->ssl_ctx, data->ssl.conn, - cipher, sizeof(cipher)) < 0 || - os_strstr(cipher, "ADH-") || - os_strstr(cipher, "anon"))) { - wpa_printf(MSG_DEBUG, "EAP-FAST: Using " - "anonymous (unauthenticated) " - "provisioning"); - data->anon_provisioning = 1; - } else - data->anon_provisioning = 0; - data->resuming = 0; - eap_fast_derive_keys(sm, data); - } - - if (res == 2) { - struct wpabuf msg; - /* - * Application data included in the handshake message. - */ - wpabuf_free(data->pending_phase2_req); - data->pending_phase2_req = resp; - resp = NULL; - wpabuf_set(&msg, pos, left); - res = eap_fast_decrypt(sm, data, ret, req, &msg, - &resp); - } - } - - if (res == 1) { - wpabuf_free(resp); - return eap_peer_tls_build_ack(id, EAP_TYPE_FAST, - data->fast_version); - } - - return resp; -} - - -#if 0 /* FIX */ -static Boolean eap_fast_has_reauth_data(struct eap_sm *sm, void *priv) -{ - struct eap_fast_data *data = priv; - return tls_connection_established(sm->ssl_ctx, data->ssl.conn); -} - - -static void eap_fast_deinit_for_reauth(struct eap_sm *sm, void *priv) -{ - struct eap_fast_data *data = priv; - os_free(data->key_block_p); - data->key_block_p = NULL; - wpabuf_free(data->pending_phase2_req); - data->pending_phase2_req = NULL; -} - - -static void * eap_fast_init_for_reauth(struct eap_sm *sm, void *priv) -{ - struct eap_fast_data *data = priv; - if (eap_peer_tls_reauth_init(sm, &data->ssl)) { - os_free(data); - return NULL; - } - if (data->phase2_priv && data->phase2_method && - data->phase2_method->init_for_reauth) - data->phase2_method->init_for_reauth(sm, data->phase2_priv); - data->phase2_success = 0; - data->resuming = 1; - data->provisioning = 0; - data->anon_provisioning = 0; - data->simck_idx = 0; - return priv; -} -#endif - - -static int eap_fast_get_status(struct eap_sm *sm, void *priv, char *buf, - size_t buflen, int verbose) -{ - struct eap_fast_data *data = priv; - int len, ret; - - len = eap_peer_tls_status(sm, &data->ssl, buf, buflen, verbose); - if (data->phase2_method) { - ret = os_snprintf(buf + len, buflen - len, - "EAP-FAST Phase2 method=%s\n", - data->phase2_method->name); - if (ret < 0 || (size_t) ret >= buflen - len) - return len; - len += ret; - } - return len; -} - - -static Boolean eap_fast_isKeyAvailable(struct eap_sm *sm, void *priv) -{ - struct eap_fast_data *data = priv; - return data->success; -} - - -static u8 * eap_fast_getKey(struct eap_sm *sm, void *priv, size_t *len) -{ - struct eap_fast_data *data = priv; - u8 *key; - - if (!data->success) - return NULL; - - key = os_malloc(EAP_FAST_KEY_LEN); - if (key == NULL) - return NULL; - - *len = EAP_FAST_KEY_LEN; - os_memcpy(key, data->key_data, EAP_FAST_KEY_LEN); - - return key; -} - - -static u8 * eap_fast_get_emsk(struct eap_sm *sm, void *priv, size_t *len) -{ - struct eap_fast_data *data = priv; - u8 *key; - - if (!data->success) - return NULL; - - key = os_malloc(EAP_EMSK_LEN); - if (key == NULL) - return NULL; - - *len = EAP_EMSK_LEN; - os_memcpy(key, data->emsk, EAP_EMSK_LEN); - - return key; -} - - -int eap_peer_fast_register(void) -{ - struct eap_method *eap; - int ret; - - eap = eap_peer_method_alloc(EAP_PEER_METHOD_INTERFACE_VERSION, - EAP_VENDOR_IETF, EAP_TYPE_FAST, "FAST"); - if (eap == NULL) - return -1; - - eap->init = eap_fast_init; - eap->deinit = eap_fast_deinit; - eap->process = eap_fast_process; - eap->isKeyAvailable = eap_fast_isKeyAvailable; - eap->getKey = eap_fast_getKey; - eap->get_status = eap_fast_get_status; -#if 0 - eap->has_reauth_data = eap_fast_has_reauth_data; - eap->deinit_for_reauth = eap_fast_deinit_for_reauth; - eap->init_for_reauth = eap_fast_init_for_reauth; -#endif - eap->get_emsk = eap_fast_get_emsk; - - ret = eap_peer_method_register(eap); - if (ret) - eap_peer_method_free(eap); - return ret; -} diff --git a/hostapd-0.8/src/eap_peer/eap_fast_pac.c b/hostapd-0.8/src/eap_peer/eap_fast_pac.c deleted file mode 100644 index 4037288..0000000 --- a/hostapd-0.8/src/eap_peer/eap_fast_pac.c +++ /dev/null @@ -1,923 +0,0 @@ -/* - * EAP peer method: EAP-FAST PAC file processing - * Copyright (c) 2004-2006, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#include "includes.h" - -#include "common.h" -#include "eap_config.h" -#include "eap_i.h" -#include "eap_fast_pac.h" - -/* TODO: encrypt PAC-Key in the PAC file */ - - -/* Text data format */ -static const char *pac_file_hdr = - "wpa_supplicant EAP-FAST PAC file - version 1"; - -/* - * Binary data format - * 4-octet magic value: 6A E4 92 0C - * 2-octet version (big endian) - * - * - * version=0: - * Sequence of PAC entries: - * 2-octet PAC-Type (big endian) - * 32-octet PAC-Key - * 2-octet PAC-Opaque length (big endian) - * PAC-Opaque data (length bytes) - * 2-octet PAC-Info length (big endian) - * PAC-Info data (length bytes) - */ - -#define EAP_FAST_PAC_BINARY_MAGIC 0x6ae4920c -#define EAP_FAST_PAC_BINARY_FORMAT_VERSION 0 - - -/** - * eap_fast_free_pac - Free PAC data - * @pac: Pointer to the PAC entry - * - * Note that the PAC entry must not be in a list since this function does not - * remove the list links. - */ -void eap_fast_free_pac(struct eap_fast_pac *pac) -{ - os_free(pac->pac_opaque); - os_free(pac->pac_info); - os_free(pac->a_id); - os_free(pac->i_id); - os_free(pac->a_id_info); - os_free(pac); -} - - -/** - * eap_fast_get_pac - Get a PAC entry based on A-ID - * @pac_root: Pointer to root of the PAC list - * @a_id: A-ID to search for - * @a_id_len: Length of A-ID - * @pac_type: PAC-Type to search for - * Returns: Pointer to the PAC entry, or %NULL if A-ID not found - */ -struct eap_fast_pac * eap_fast_get_pac(struct eap_fast_pac *pac_root, - const u8 *a_id, size_t a_id_len, - u16 pac_type) -{ - struct eap_fast_pac *pac = pac_root; - - while (pac) { - if (pac->pac_type == pac_type && pac->a_id_len == a_id_len && - os_memcmp(pac->a_id, a_id, a_id_len) == 0) { - return pac; - } - pac = pac->next; - } - return NULL; -} - - -static void eap_fast_remove_pac(struct eap_fast_pac **pac_root, - struct eap_fast_pac **pac_current, - const u8 *a_id, size_t a_id_len, u16 pac_type) -{ - struct eap_fast_pac *pac, *prev; - - pac = *pac_root; - prev = NULL; - - while (pac) { - if (pac->pac_type == pac_type && pac->a_id_len == a_id_len && - os_memcmp(pac->a_id, a_id, a_id_len) == 0) { - if (prev == NULL) - *pac_root = pac->next; - else - prev->next = pac->next; - if (*pac_current == pac) - *pac_current = NULL; - eap_fast_free_pac(pac); - break; - } - prev = pac; - pac = pac->next; - } -} - - -static int eap_fast_copy_buf(u8 **dst, size_t *dst_len, - const u8 *src, size_t src_len) -{ - if (src) { - *dst = os_malloc(src_len); - if (*dst == NULL) - return -1; - os_memcpy(*dst, src, src_len); - *dst_len = src_len; - } - return 0; -} - - -/** - * eap_fast_add_pac - Add a copy of a PAC entry to a list - * @pac_root: Pointer to PAC list root pointer - * @pac_current: Pointer to the current PAC pointer - * @entry: New entry to clone and add to the list - * Returns: 0 on success, -1 on failure - * - * This function makes a clone of the given PAC entry and adds this copied - * entry to the list (pac_root). If an old entry for the same A-ID is found, - * it will be removed from the PAC list and in this case, pac_current entry - * is set to %NULL if it was the removed entry. - */ -int eap_fast_add_pac(struct eap_fast_pac **pac_root, - struct eap_fast_pac **pac_current, - struct eap_fast_pac *entry) -{ - struct eap_fast_pac *pac; - - if (entry == NULL || entry->a_id == NULL) - return -1; - - /* Remove a possible old entry for the matching A-ID. */ - eap_fast_remove_pac(pac_root, pac_current, - entry->a_id, entry->a_id_len, entry->pac_type); - - /* Allocate a new entry and add it to the list of PACs. */ - pac = os_zalloc(sizeof(*pac)); - if (pac == NULL) - return -1; - - pac->pac_type = entry->pac_type; - os_memcpy(pac->pac_key, entry->pac_key, EAP_FAST_PAC_KEY_LEN); - if (eap_fast_copy_buf(&pac->pac_opaque, &pac->pac_opaque_len, - entry->pac_opaque, entry->pac_opaque_len) < 0 || - eap_fast_copy_buf(&pac->pac_info, &pac->pac_info_len, - entry->pac_info, entry->pac_info_len) < 0 || - eap_fast_copy_buf(&pac->a_id, &pac->a_id_len, - entry->a_id, entry->a_id_len) < 0 || - eap_fast_copy_buf(&pac->i_id, &pac->i_id_len, - entry->i_id, entry->i_id_len) < 0 || - eap_fast_copy_buf(&pac->a_id_info, &pac->a_id_info_len, - entry->a_id_info, entry->a_id_info_len) < 0) { - eap_fast_free_pac(pac); - return -1; - } - - pac->next = *pac_root; - *pac_root = pac; - - return 0; -} - - -struct eap_fast_read_ctx { - FILE *f; - const char *pos; - const char *end; - int line; - char *buf; - size_t buf_len; -}; - -static int eap_fast_read_line(struct eap_fast_read_ctx *rc, char **value) -{ - char *pos; - - rc->line++; - if (rc->f) { - if (fgets(rc->buf, rc->buf_len, rc->f) == NULL) - return -1; - } else { - const char *l_end; - size_t len; - if (rc->pos >= rc->end) - return -1; - l_end = rc->pos; - while (l_end < rc->end && *l_end != '\n') - l_end++; - len = l_end - rc->pos; - if (len >= rc->buf_len) - len = rc->buf_len - 1; - os_memcpy(rc->buf, rc->pos, len); - rc->buf[len] = '\0'; - rc->pos = l_end + 1; - } - - rc->buf[rc->buf_len - 1] = '\0'; - pos = rc->buf; - while (*pos != '\0') { - if (*pos == '\n' || *pos == '\r') { - *pos = '\0'; - break; - } - pos++; - } - - pos = os_strchr(rc->buf, '='); - if (pos) - *pos++ = '\0'; - *value = pos; - - return 0; -} - - -static u8 * eap_fast_parse_hex(const char *value, size_t *len) -{ - int hlen; - u8 *buf; - - if (value == NULL) - return NULL; - hlen = os_strlen(value); - if (hlen & 1) - return NULL; - *len = hlen / 2; - buf = os_malloc(*len); - if (buf == NULL) - return NULL; - if (hexstr2bin(value, buf, *len)) { - os_free(buf); - return NULL; - } - return buf; -} - - -static int eap_fast_init_pac_data(struct eap_sm *sm, const char *pac_file, - struct eap_fast_read_ctx *rc) -{ - os_memset(rc, 0, sizeof(*rc)); - - rc->buf_len = 2048; - rc->buf = os_malloc(rc->buf_len); - if (rc->buf == NULL) - return -1; - - if (os_strncmp(pac_file, "blob://", 7) == 0) { - const struct wpa_config_blob *blob; - blob = eap_get_config_blob(sm, pac_file + 7); - if (blob == NULL) { - wpa_printf(MSG_INFO, "EAP-FAST: No PAC blob '%s' - " - "assume no PAC entries have been " - "provisioned", pac_file + 7); - os_free(rc->buf); - return -1; - } - rc->pos = (char *) blob->data; - rc->end = (char *) blob->data + blob->len; - } else { - rc->f = fopen(pac_file, "rb"); - if (rc->f == NULL) { - wpa_printf(MSG_INFO, "EAP-FAST: No PAC file '%s' - " - "assume no PAC entries have been " - "provisioned", pac_file); - os_free(rc->buf); - return -1; - } - } - - return 0; -} - - -static void eap_fast_deinit_pac_data(struct eap_fast_read_ctx *rc) -{ - os_free(rc->buf); - if (rc->f) - fclose(rc->f); -} - - -static const char * eap_fast_parse_start(struct eap_fast_pac **pac) -{ - if (*pac) - return "START line without END"; - - *pac = os_zalloc(sizeof(struct eap_fast_pac)); - if (*pac == NULL) - return "No memory for PAC entry"; - (*pac)->pac_type = PAC_TYPE_TUNNEL_PAC; - return NULL; -} - - -static const char * eap_fast_parse_end(struct eap_fast_pac **pac_root, - struct eap_fast_pac **pac) -{ - if (*pac == NULL) - return "END line without START"; - if (*pac_root) { - struct eap_fast_pac *end = *pac_root; - while (end->next) - end = end->next; - end->next = *pac; - } else - *pac_root = *pac; - - *pac = NULL; - return NULL; -} - - -static const char * eap_fast_parse_pac_type(struct eap_fast_pac *pac, - char *pos) -{ - pac->pac_type = atoi(pos); - if (pac->pac_type != PAC_TYPE_TUNNEL_PAC && - pac->pac_type != PAC_TYPE_USER_AUTHORIZATION && - pac->pac_type != PAC_TYPE_MACHINE_AUTHENTICATION) - return "Unrecognized PAC-Type"; - - return NULL; -} - - -static const char * eap_fast_parse_pac_key(struct eap_fast_pac *pac, char *pos) -{ - u8 *key; - size_t key_len; - - key = eap_fast_parse_hex(pos, &key_len); - if (key == NULL || key_len != EAP_FAST_PAC_KEY_LEN) { - os_free(key); - return "Invalid PAC-Key"; - } - - os_memcpy(pac->pac_key, key, EAP_FAST_PAC_KEY_LEN); - os_free(key); - - return NULL; -} - - -static const char * eap_fast_parse_pac_opaque(struct eap_fast_pac *pac, - char *pos) -{ - os_free(pac->pac_opaque); - pac->pac_opaque = eap_fast_parse_hex(pos, &pac->pac_opaque_len); - if (pac->pac_opaque == NULL) - return "Invalid PAC-Opaque"; - return NULL; -} - - -static const char * eap_fast_parse_a_id(struct eap_fast_pac *pac, char *pos) -{ - os_free(pac->a_id); - pac->a_id = eap_fast_parse_hex(pos, &pac->a_id_len); - if (pac->a_id == NULL) - return "Invalid A-ID"; - return NULL; -} - - -static const char * eap_fast_parse_i_id(struct eap_fast_pac *pac, char *pos) -{ - os_free(pac->i_id); - pac->i_id = eap_fast_parse_hex(pos, &pac->i_id_len); - if (pac->i_id == NULL) - return "Invalid I-ID"; - return NULL; -} - - -static const char * eap_fast_parse_a_id_info(struct eap_fast_pac *pac, - char *pos) -{ - os_free(pac->a_id_info); - pac->a_id_info = eap_fast_parse_hex(pos, &pac->a_id_info_len); - if (pac->a_id_info == NULL) - return "Invalid A-ID-Info"; - return NULL; -} - - -/** - * eap_fast_load_pac - Load PAC entries (text format) - * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init() - * @pac_root: Pointer to root of the PAC list (to be filled) - * @pac_file: Name of the PAC file/blob to load - * Returns: 0 on success, -1 on failure - */ -int eap_fast_load_pac(struct eap_sm *sm, struct eap_fast_pac **pac_root, - const char *pac_file) -{ - struct eap_fast_read_ctx rc; - struct eap_fast_pac *pac = NULL; - int count = 0; - char *pos; - const char *err = NULL; - - if (pac_file == NULL) - return -1; - - if (eap_fast_init_pac_data(sm, pac_file, &rc) < 0) - return 0; - - if (eap_fast_read_line(&rc, &pos) < 0 || - os_strcmp(pac_file_hdr, rc.buf) != 0) - err = "Unrecognized header line"; - - while (!err && eap_fast_read_line(&rc, &pos) == 0) { - if (os_strcmp(rc.buf, "START") == 0) - err = eap_fast_parse_start(&pac); - else if (os_strcmp(rc.buf, "END") == 0) { - err = eap_fast_parse_end(pac_root, &pac); - count++; - } else if (!pac) - err = "Unexpected line outside START/END block"; - else if (os_strcmp(rc.buf, "PAC-Type") == 0) - err = eap_fast_parse_pac_type(pac, pos); - else if (os_strcmp(rc.buf, "PAC-Key") == 0) - err = eap_fast_parse_pac_key(pac, pos); - else if (os_strcmp(rc.buf, "PAC-Opaque") == 0) - err = eap_fast_parse_pac_opaque(pac, pos); - else if (os_strcmp(rc.buf, "A-ID") == 0) - err = eap_fast_parse_a_id(pac, pos); - else if (os_strcmp(rc.buf, "I-ID") == 0) - err = eap_fast_parse_i_id(pac, pos); - else if (os_strcmp(rc.buf, "A-ID-Info") == 0) - err = eap_fast_parse_a_id_info(pac, pos); - } - - if (pac) { - err = "PAC block not terminated with END"; - eap_fast_free_pac(pac); - } - - eap_fast_deinit_pac_data(&rc); - - if (err) { - wpa_printf(MSG_INFO, "EAP-FAST: %s in '%s:%d'", - err, pac_file, rc.line); - return -1; - } - - wpa_printf(MSG_DEBUG, "EAP-FAST: Read %d PAC entries from '%s'", - count, pac_file); - - return 0; -} - - -static void eap_fast_write(char **buf, char **pos, size_t *buf_len, - const char *field, const u8 *data, - size_t len, int txt) -{ - size_t i, need; - int ret; - char *end; - - if (data == NULL || buf == NULL || *buf == NULL || - pos == NULL || *pos == NULL || *pos < *buf) - return; - - need = os_strlen(field) + len * 2 + 30; - if (txt) - need += os_strlen(field) + len + 20; - - if (*pos - *buf + need > *buf_len) { - char *nbuf = os_realloc(*buf, *buf_len + need); - if (nbuf == NULL) { - os_free(*buf); - *buf = NULL; - return; - } - *pos = nbuf + (*pos - *buf); - *buf = nbuf; - *buf_len += need; - } - end = *buf + *buf_len; - - ret = os_snprintf(*pos, end - *pos, "%s=", field); - if (ret < 0 || ret >= end - *pos) - return; - *pos += ret; - *pos += wpa_snprintf_hex(*pos, end - *pos, data, len); - ret = os_snprintf(*pos, end - *pos, "\n"); - if (ret < 0 || ret >= end - *pos) - return; - *pos += ret; - - if (txt) { - ret = os_snprintf(*pos, end - *pos, "%s-txt=", field); - if (ret < 0 || ret >= end - *pos) - return; - *pos += ret; - for (i = 0; i < len; i++) { - ret = os_snprintf(*pos, end - *pos, "%c", data[i]); - if (ret < 0 || ret >= end - *pos) - return; - *pos += ret; - } - ret = os_snprintf(*pos, end - *pos, "\n"); - if (ret < 0 || ret >= end - *pos) - return; - *pos += ret; - } -} - - -static int eap_fast_write_pac(struct eap_sm *sm, const char *pac_file, - char *buf, size_t len) -{ - if (os_strncmp(pac_file, "blob://", 7) == 0) { - struct wpa_config_blob *blob; - blob = os_zalloc(sizeof(*blob)); - if (blob == NULL) - return -1; - blob->data = (u8 *) buf; - blob->len = len; - buf = NULL; - blob->name = os_strdup(pac_file + 7); - if (blob->name == NULL) { - os_free(blob); - return -1; - } - eap_set_config_blob(sm, blob); - } else { - FILE *f; - f = fopen(pac_file, "wb"); - if (f == NULL) { - wpa_printf(MSG_INFO, "EAP-FAST: Failed to open PAC " - "file '%s' for writing", pac_file); - return -1; - } - if (fwrite(buf, 1, len, f) != len) { - wpa_printf(MSG_INFO, "EAP-FAST: Failed to write all " - "PACs into '%s'", pac_file); - fclose(f); - return -1; - } - os_free(buf); - fclose(f); - } - - return 0; -} - - -static int eap_fast_add_pac_data(struct eap_fast_pac *pac, char **buf, - char **pos, size_t *buf_len) -{ - int ret; - - ret = os_snprintf(*pos, *buf + *buf_len - *pos, - "START\nPAC-Type=%d\n", pac->pac_type); - if (ret < 0 || ret >= *buf + *buf_len - *pos) - return -1; - - *pos += ret; - eap_fast_write(buf, pos, buf_len, "PAC-Key", - pac->pac_key, EAP_FAST_PAC_KEY_LEN, 0); - eap_fast_write(buf, pos, buf_len, "PAC-Opaque", - pac->pac_opaque, pac->pac_opaque_len, 0); - eap_fast_write(buf, pos, buf_len, "PAC-Info", - pac->pac_info, pac->pac_info_len, 0); - eap_fast_write(buf, pos, buf_len, "A-ID", - pac->a_id, pac->a_id_len, 0); - eap_fast_write(buf, pos, buf_len, "I-ID", - pac->i_id, pac->i_id_len, 1); - eap_fast_write(buf, pos, buf_len, "A-ID-Info", - pac->a_id_info, pac->a_id_info_len, 1); - if (*buf == NULL) { - wpa_printf(MSG_DEBUG, "EAP-FAST: No memory for PAC " - "data"); - return -1; - } - ret = os_snprintf(*pos, *buf + *buf_len - *pos, "END\n"); - if (ret < 0 || ret >= *buf + *buf_len - *pos) - return -1; - *pos += ret; - - return 0; -} - - -/** - * eap_fast_save_pac - Save PAC entries (text format) - * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init() - * @pac_root: Root of the PAC list - * @pac_file: Name of the PAC file/blob - * Returns: 0 on success, -1 on failure - */ -int eap_fast_save_pac(struct eap_sm *sm, struct eap_fast_pac *pac_root, - const char *pac_file) -{ - struct eap_fast_pac *pac; - int ret, count = 0; - char *buf, *pos; - size_t buf_len; - - if (pac_file == NULL) - return -1; - - buf_len = 1024; - pos = buf = os_malloc(buf_len); - if (buf == NULL) - return -1; - - ret = os_snprintf(pos, buf + buf_len - pos, "%s\n", pac_file_hdr); - if (ret < 0 || ret >= buf + buf_len - pos) { - os_free(buf); - return -1; - } - pos += ret; - - pac = pac_root; - while (pac) { - if (eap_fast_add_pac_data(pac, &buf, &pos, &buf_len)) { - os_free(buf); - return -1; - } - count++; - pac = pac->next; - } - - if (eap_fast_write_pac(sm, pac_file, buf, pos - buf)) { - os_free(buf); - return -1; - } - - wpa_printf(MSG_DEBUG, "EAP-FAST: Wrote %d PAC entries into '%s'", - count, pac_file); - - return 0; -} - - -/** - * eap_fast_pac_list_truncate - Truncate a PAC list to the given length - * @pac_root: Root of the PAC list - * @max_len: Maximum length of the list (>= 1) - * Returns: Number of PAC entries removed - */ -size_t eap_fast_pac_list_truncate(struct eap_fast_pac *pac_root, - size_t max_len) -{ - struct eap_fast_pac *pac, *prev; - size_t count; - - pac = pac_root; - prev = NULL; - count = 0; - - while (pac) { - count++; - if (count > max_len) - break; - prev = pac; - pac = pac->next; - } - - if (count <= max_len || prev == NULL) - return 0; - - count = 0; - prev->next = NULL; - - while (pac) { - prev = pac; - pac = pac->next; - eap_fast_free_pac(prev); - count++; - } - - return count; -} - - -static void eap_fast_pac_get_a_id(struct eap_fast_pac *pac) -{ - u8 *pos, *end; - u16 type, len; - - pos = pac->pac_info; - end = pos + pac->pac_info_len; - - while (pos + 4 < end) { - type = WPA_GET_BE16(pos); - pos += 2; - len = WPA_GET_BE16(pos); - pos += 2; - if (pos + len > end) - break; - - if (type == PAC_TYPE_A_ID) { - os_free(pac->a_id); - pac->a_id = os_malloc(len); - if (pac->a_id == NULL) - break; - os_memcpy(pac->a_id, pos, len); - pac->a_id_len = len; - } - - if (type == PAC_TYPE_A_ID_INFO) { - os_free(pac->a_id_info); - pac->a_id_info = os_malloc(len); - if (pac->a_id_info == NULL) - break; - os_memcpy(pac->a_id_info, pos, len); - pac->a_id_info_len = len; - } - - pos += len; - } -} - - -/** - * eap_fast_load_pac_bin - Load PAC entries (binary format) - * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init() - * @pac_root: Pointer to root of the PAC list (to be filled) - * @pac_file: Name of the PAC file/blob to load - * Returns: 0 on success, -1 on failure - */ -int eap_fast_load_pac_bin(struct eap_sm *sm, struct eap_fast_pac **pac_root, - const char *pac_file) -{ - const struct wpa_config_blob *blob = NULL; - u8 *buf, *end, *pos; - size_t len, count = 0; - struct eap_fast_pac *pac, *prev; - - *pac_root = NULL; - - if (pac_file == NULL) - return -1; - - if (os_strncmp(pac_file, "blob://", 7) == 0) { - blob = eap_get_config_blob(sm, pac_file + 7); - if (blob == NULL) { - wpa_printf(MSG_INFO, "EAP-FAST: No PAC blob '%s' - " - "assume no PAC entries have been " - "provisioned", pac_file + 7); - return 0; - } - buf = blob->data; - len = blob->len; - } else { - buf = (u8 *) os_readfile(pac_file, &len); - if (buf == NULL) { - wpa_printf(MSG_INFO, "EAP-FAST: No PAC file '%s' - " - "assume no PAC entries have been " - "provisioned", pac_file); - return 0; - } - } - - if (len == 0) { - if (blob == NULL) - os_free(buf); - return 0; - } - - if (len < 6 || WPA_GET_BE32(buf) != EAP_FAST_PAC_BINARY_MAGIC || - WPA_GET_BE16(buf + 4) != EAP_FAST_PAC_BINARY_FORMAT_VERSION) { - wpa_printf(MSG_INFO, "EAP-FAST: Invalid PAC file '%s' (bin)", - pac_file); - if (blob == NULL) - os_free(buf); - return -1; - } - - pac = prev = NULL; - pos = buf + 6; - end = buf + len; - while (pos < end) { - if (end - pos < 2 + 32 + 2 + 2) - goto parse_fail; - - pac = os_zalloc(sizeof(*pac)); - if (pac == NULL) - goto parse_fail; - - pac->pac_type = WPA_GET_BE16(pos); - pos += 2; - os_memcpy(pac->pac_key, pos, EAP_FAST_PAC_KEY_LEN); - pos += EAP_FAST_PAC_KEY_LEN; - pac->pac_opaque_len = WPA_GET_BE16(pos); - pos += 2; - if (pos + pac->pac_opaque_len + 2 > end) - goto parse_fail; - pac->pac_opaque = os_malloc(pac->pac_opaque_len); - if (pac->pac_opaque == NULL) - goto parse_fail; - os_memcpy(pac->pac_opaque, pos, pac->pac_opaque_len); - pos += pac->pac_opaque_len; - pac->pac_info_len = WPA_GET_BE16(pos); - pos += 2; - if (pos + pac->pac_info_len > end) - goto parse_fail; - pac->pac_info = os_malloc(pac->pac_info_len); - if (pac->pac_info == NULL) - goto parse_fail; - os_memcpy(pac->pac_info, pos, pac->pac_info_len); - pos += pac->pac_info_len; - eap_fast_pac_get_a_id(pac); - - count++; - if (prev) - prev->next = pac; - else - *pac_root = pac; - prev = pac; - } - - if (blob == NULL) - os_free(buf); - - wpa_printf(MSG_DEBUG, "EAP-FAST: Read %lu PAC entries from '%s' (bin)", - (unsigned long) count, pac_file); - - return 0; - -parse_fail: - wpa_printf(MSG_INFO, "EAP-FAST: Failed to parse PAC file '%s' (bin)", - pac_file); - if (blob == NULL) - os_free(buf); - if (pac) - eap_fast_free_pac(pac); - return -1; -} - - -/** - * eap_fast_save_pac_bin - Save PAC entries (binary format) - * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init() - * @pac_root: Root of the PAC list - * @pac_file: Name of the PAC file/blob - * Returns: 0 on success, -1 on failure - */ -int eap_fast_save_pac_bin(struct eap_sm *sm, struct eap_fast_pac *pac_root, - const char *pac_file) -{ - size_t len, count = 0; - struct eap_fast_pac *pac; - u8 *buf, *pos; - - len = 6; - pac = pac_root; - while (pac) { - if (pac->pac_opaque_len > 65535 || - pac->pac_info_len > 65535) - return -1; - len += 2 + EAP_FAST_PAC_KEY_LEN + 2 + pac->pac_opaque_len + - 2 + pac->pac_info_len; - pac = pac->next; - } - - buf = os_malloc(len); - if (buf == NULL) - return -1; - - pos = buf; - WPA_PUT_BE32(pos, EAP_FAST_PAC_BINARY_MAGIC); - pos += 4; - WPA_PUT_BE16(pos, EAP_FAST_PAC_BINARY_FORMAT_VERSION); - pos += 2; - - pac = pac_root; - while (pac) { - WPA_PUT_BE16(pos, pac->pac_type); - pos += 2; - os_memcpy(pos, pac->pac_key, EAP_FAST_PAC_KEY_LEN); - pos += EAP_FAST_PAC_KEY_LEN; - WPA_PUT_BE16(pos, pac->pac_opaque_len); - pos += 2; - os_memcpy(pos, pac->pac_opaque, pac->pac_opaque_len); - pos += pac->pac_opaque_len; - WPA_PUT_BE16(pos, pac->pac_info_len); - pos += 2; - os_memcpy(pos, pac->pac_info, pac->pac_info_len); - pos += pac->pac_info_len; - - pac = pac->next; - count++; - } - - if (eap_fast_write_pac(sm, pac_file, (char *) buf, len)) { - os_free(buf); - return -1; - } - - wpa_printf(MSG_DEBUG, "EAP-FAST: Wrote %lu PAC entries into '%s' " - "(bin)", (unsigned long) count, pac_file); - - return 0; -} diff --git a/hostapd-0.8/src/eap_peer/eap_fast_pac.h b/hostapd-0.8/src/eap_peer/eap_fast_pac.h deleted file mode 100644 index 9483f96..0000000 --- a/hostapd-0.8/src/eap_peer/eap_fast_pac.h +++ /dev/null @@ -1,56 +0,0 @@ -/* - * EAP peer method: EAP-FAST PAC file processing - * Copyright (c) 2004-2007, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#ifndef EAP_FAST_PAC_H -#define EAP_FAST_PAC_H - -#include "eap_common/eap_fast_common.h" - -struct eap_fast_pac { - struct eap_fast_pac *next; - - u8 pac_key[EAP_FAST_PAC_KEY_LEN]; - u8 *pac_opaque; - size_t pac_opaque_len; - u8 *pac_info; - size_t pac_info_len; - u8 *a_id; - size_t a_id_len; - u8 *i_id; - size_t i_id_len; - u8 *a_id_info; - size_t a_id_info_len; - u16 pac_type; -}; - - -void eap_fast_free_pac(struct eap_fast_pac *pac); -struct eap_fast_pac * eap_fast_get_pac(struct eap_fast_pac *pac_root, - const u8 *a_id, size_t a_id_len, - u16 pac_type); -int eap_fast_add_pac(struct eap_fast_pac **pac_root, - struct eap_fast_pac **pac_current, - struct eap_fast_pac *entry); -int eap_fast_load_pac(struct eap_sm *sm, struct eap_fast_pac **pac_root, - const char *pac_file); -int eap_fast_save_pac(struct eap_sm *sm, struct eap_fast_pac *pac_root, - const char *pac_file); -size_t eap_fast_pac_list_truncate(struct eap_fast_pac *pac_root, - size_t max_len); -int eap_fast_load_pac_bin(struct eap_sm *sm, struct eap_fast_pac **pac_root, - const char *pac_file); -int eap_fast_save_pac_bin(struct eap_sm *sm, struct eap_fast_pac *pac_root, - const char *pac_file); - -#endif /* EAP_FAST_PAC_H */ diff --git a/hostapd-0.8/src/eap_peer/eap_gpsk.c b/hostapd-0.8/src/eap_peer/eap_gpsk.c deleted file mode 100644 index 5037c60..0000000 --- a/hostapd-0.8/src/eap_peer/eap_gpsk.c +++ /dev/null @@ -1,738 +0,0 @@ -/* - * EAP peer method: EAP-GPSK (RFC 5433) - * Copyright (c) 2006-2008, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#include "includes.h" - -#include "common.h" -#include "crypto/random.h" -#include "eap_peer/eap_i.h" -#include "eap_common/eap_gpsk_common.h" - -struct eap_gpsk_data { - enum { GPSK_1, GPSK_3, SUCCESS, FAILURE } state; - u8 rand_server[EAP_GPSK_RAND_LEN]; - u8 rand_peer[EAP_GPSK_RAND_LEN]; - u8 msk[EAP_MSK_LEN]; - u8 emsk[EAP_EMSK_LEN]; - u8 sk[EAP_GPSK_MAX_SK_LEN]; - size_t sk_len; - u8 pk[EAP_GPSK_MAX_PK_LEN]; - size_t pk_len; - u8 session_id; - int session_id_set; - u8 *id_peer; - size_t id_peer_len; - u8 *id_server; - size_t id_server_len; - int vendor; /* CSuite/Specifier */ - int specifier; /* CSuite/Specifier */ - u8 *psk; - size_t psk_len; -}; - - -static struct wpabuf * eap_gpsk_send_gpsk_2(struct eap_gpsk_data *data, - u8 identifier, - const u8 *csuite_list, - size_t csuite_list_len); -static struct wpabuf * eap_gpsk_send_gpsk_4(struct eap_gpsk_data *data, - u8 identifier); - - -#ifndef CONFIG_NO_STDOUT_DEBUG -static const char * eap_gpsk_state_txt(int state) -{ - switch (state) { - case GPSK_1: - return "GPSK-1"; - case GPSK_3: - return "GPSK-3"; - case SUCCESS: - return "SUCCESS"; - case FAILURE: - return "FAILURE"; - default: - return "?"; - } -} -#endif /* CONFIG_NO_STDOUT_DEBUG */ - - -static void eap_gpsk_state(struct eap_gpsk_data *data, int state) -{ - wpa_printf(MSG_DEBUG, "EAP-GPSK: %s -> %s", - eap_gpsk_state_txt(data->state), - eap_gpsk_state_txt(state)); - data->state = state; -} - - -static void eap_gpsk_deinit(struct eap_sm *sm, void *priv); - - -static void * eap_gpsk_init(struct eap_sm *sm) -{ - struct eap_gpsk_data *data; - const u8 *identity, *password; - size_t identity_len, password_len; - - password = eap_get_config_password(sm, &password_len); - if (password == NULL) { - wpa_printf(MSG_INFO, "EAP-GPSK: No key (password) configured"); - return NULL; - } - - data = os_zalloc(sizeof(*data)); - if (data == NULL) - return NULL; - data->state = GPSK_1; - - identity = eap_get_config_identity(sm, &identity_len); - if (identity) { - data->id_peer = os_malloc(identity_len); - if (data->id_peer == NULL) { - eap_gpsk_deinit(sm, data); - return NULL; - } - os_memcpy(data->id_peer, identity, identity_len); - data->id_peer_len = identity_len; - } - - data->psk = os_malloc(password_len); - if (data->psk == NULL) { - eap_gpsk_deinit(sm, data); - return NULL; - } - os_memcpy(data->psk, password, password_len); - data->psk_len = password_len; - - return data; -} - - -static void eap_gpsk_deinit(struct eap_sm *sm, void *priv) -{ - struct eap_gpsk_data *data = priv; - os_free(data->id_server); - os_free(data->id_peer); - os_free(data->psk); - os_free(data); -} - - -static const u8 * eap_gpsk_process_id_server(struct eap_gpsk_data *data, - const u8 *pos, const u8 *end) -{ - u16 alen; - - if (end - pos < 2) { - wpa_printf(MSG_DEBUG, "EAP-GPSK: Too short GPSK-1 packet"); - return NULL; - } - alen = WPA_GET_BE16(pos); - pos += 2; - if (end - pos < alen) { - wpa_printf(MSG_DEBUG, "EAP-GPSK: ID_Server overflow"); - return NULL; - } - os_free(data->id_server); - data->id_server = os_malloc(alen); - if (data->id_server == NULL) { - wpa_printf(MSG_DEBUG, "EAP-GPSK: No memory for ID_Server"); - return NULL; - } - os_memcpy(data->id_server, pos, alen); - data->id_server_len = alen; - wpa_hexdump_ascii(MSG_DEBUG, "EAP-GPSK: ID_Server", - data->id_server, data->id_server_len); - pos += alen; - - return pos; -} - - -static const u8 * eap_gpsk_process_rand_server(struct eap_gpsk_data *data, - const u8 *pos, const u8 *end) -{ - if (pos == NULL) - return NULL; - - if (end - pos < EAP_GPSK_RAND_LEN) { - wpa_printf(MSG_DEBUG, "EAP-GPSK: RAND_Server overflow"); - return NULL; - } - os_memcpy(data->rand_server, pos, EAP_GPSK_RAND_LEN); - wpa_hexdump(MSG_DEBUG, "EAP-GPSK: RAND_Server", - data->rand_server, EAP_GPSK_RAND_LEN); - pos += EAP_GPSK_RAND_LEN; - - return pos; -} - - -static int eap_gpsk_select_csuite(struct eap_sm *sm, - struct eap_gpsk_data *data, - const u8 *csuite_list, - size_t csuite_list_len) -{ - struct eap_gpsk_csuite *csuite; - int i, count; - - count = csuite_list_len / sizeof(struct eap_gpsk_csuite); - data->vendor = EAP_GPSK_VENDOR_IETF; - data->specifier = EAP_GPSK_CIPHER_RESERVED; - csuite = (struct eap_gpsk_csuite *) csuite_list; - for (i = 0; i < count; i++) { - int vendor, specifier; - vendor = WPA_GET_BE32(csuite->vendor); - specifier = WPA_GET_BE16(csuite->specifier); - wpa_printf(MSG_DEBUG, "EAP-GPSK: CSuite[%d]: %d:%d", - i, vendor, specifier); - if (data->vendor == EAP_GPSK_VENDOR_IETF && - data->specifier == EAP_GPSK_CIPHER_RESERVED && - eap_gpsk_supported_ciphersuite(vendor, specifier)) { - data->vendor = vendor; - data->specifier = specifier; - } - csuite++; - } - if (data->vendor == EAP_GPSK_VENDOR_IETF && - data->specifier == EAP_GPSK_CIPHER_RESERVED) { - wpa_msg(sm->msg_ctx, MSG_INFO, "EAP-GPSK: No supported " - "ciphersuite found"); - return -1; - } - wpa_printf(MSG_DEBUG, "EAP-GPSK: Selected ciphersuite %d:%d", - data->vendor, data->specifier); - - return 0; -} - - -static const u8 * eap_gpsk_process_csuite_list(struct eap_sm *sm, - struct eap_gpsk_data *data, - const u8 **list, - size_t *list_len, - const u8 *pos, const u8 *end) -{ - if (pos == NULL) - return NULL; - - if (end - pos < 2) { - wpa_printf(MSG_DEBUG, "EAP-GPSK: Too short GPSK-1 packet"); - return NULL; - } - *list_len = WPA_GET_BE16(pos); - pos += 2; - if (end - pos < (int) *list_len) { - wpa_printf(MSG_DEBUG, "EAP-GPSK: CSuite_List overflow"); - return NULL; - } - if (*list_len == 0 || (*list_len % sizeof(struct eap_gpsk_csuite))) { - wpa_printf(MSG_DEBUG, "EAP-GPSK: Invalid CSuite_List len %lu", - (unsigned long) *list_len); - return NULL; - } - *list = pos; - pos += *list_len; - - if (eap_gpsk_select_csuite(sm, data, *list, *list_len) < 0) - return NULL; - - return pos; -} - - -static struct wpabuf * eap_gpsk_process_gpsk_1(struct eap_sm *sm, - struct eap_gpsk_data *data, - struct eap_method_ret *ret, - const struct wpabuf *reqData, - const u8 *payload, - size_t payload_len) -{ - size_t csuite_list_len; - const u8 *csuite_list, *pos, *end; - struct wpabuf *resp; - - if (data->state != GPSK_1) { - ret->ignore = TRUE; - return NULL; - } - - wpa_printf(MSG_DEBUG, "EAP-GPSK: Received Request/GPSK-1"); - - end = payload + payload_len; - - pos = eap_gpsk_process_id_server(data, payload, end); - pos = eap_gpsk_process_rand_server(data, pos, end); - pos = eap_gpsk_process_csuite_list(sm, data, &csuite_list, - &csuite_list_len, pos, end); - if (pos == NULL) { - eap_gpsk_state(data, FAILURE); - return NULL; - } - - resp = eap_gpsk_send_gpsk_2(data, eap_get_id(reqData), - csuite_list, csuite_list_len); - if (resp == NULL) - return NULL; - - eap_gpsk_state(data, GPSK_3); - - return resp; -} - - -static struct wpabuf * eap_gpsk_send_gpsk_2(struct eap_gpsk_data *data, - u8 identifier, - const u8 *csuite_list, - size_t csuite_list_len) -{ - struct wpabuf *resp; - size_t len, miclen; - u8 *rpos, *start; - struct eap_gpsk_csuite *csuite; - - wpa_printf(MSG_DEBUG, "EAP-GPSK: Sending Response/GPSK-2"); - - miclen = eap_gpsk_mic_len(data->vendor, data->specifier); - len = 1 + 2 + data->id_peer_len + 2 + data->id_server_len + - 2 * EAP_GPSK_RAND_LEN + 2 + csuite_list_len + - sizeof(struct eap_gpsk_csuite) + 2 + miclen; - - resp = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_GPSK, len, - EAP_CODE_RESPONSE, identifier); - if (resp == NULL) - return NULL; - - wpabuf_put_u8(resp, EAP_GPSK_OPCODE_GPSK_2); - start = wpabuf_put(resp, 0); - - wpa_hexdump_ascii(MSG_DEBUG, "EAP-GPSK: ID_Peer", - data->id_peer, data->id_peer_len); - wpabuf_put_be16(resp, data->id_peer_len); - wpabuf_put_data(resp, data->id_peer, data->id_peer_len); - - wpabuf_put_be16(resp, data->id_server_len); - wpabuf_put_data(resp, data->id_server, data->id_server_len); - - if (random_get_bytes(data->rand_peer, EAP_GPSK_RAND_LEN)) { - wpa_printf(MSG_DEBUG, "EAP-GPSK: Failed to get random data " - "for RAND_Peer"); - eap_gpsk_state(data, FAILURE); - wpabuf_free(resp); - return NULL; - } - wpa_hexdump(MSG_DEBUG, "EAP-GPSK: RAND_Peer", - data->rand_peer, EAP_GPSK_RAND_LEN); - wpabuf_put_data(resp, data->rand_peer, EAP_GPSK_RAND_LEN); - wpabuf_put_data(resp, data->rand_server, EAP_GPSK_RAND_LEN); - - wpabuf_put_be16(resp, csuite_list_len); - wpabuf_put_data(resp, csuite_list, csuite_list_len); - - csuite = wpabuf_put(resp, sizeof(*csuite)); - WPA_PUT_BE32(csuite->vendor, data->vendor); - WPA_PUT_BE16(csuite->specifier, data->specifier); - - if (eap_gpsk_derive_keys(data->psk, data->psk_len, - data->vendor, data->specifier, - data->rand_peer, data->rand_server, - data->id_peer, data->id_peer_len, - data->id_server, data->id_server_len, - data->msk, data->emsk, - data->sk, &data->sk_len, - data->pk, &data->pk_len) < 0) { - wpa_printf(MSG_DEBUG, "EAP-GPSK: Failed to derive keys"); - eap_gpsk_state(data, FAILURE); - wpabuf_free(resp); - return NULL; - } - - /* No PD_Payload_1 */ - wpabuf_put_be16(resp, 0); - - rpos = wpabuf_put(resp, miclen); - if (eap_gpsk_compute_mic(data->sk, data->sk_len, data->vendor, - data->specifier, start, rpos - start, rpos) < - 0) { - eap_gpsk_state(data, FAILURE); - wpabuf_free(resp); - return NULL; - } - - return resp; -} - - -static const u8 * eap_gpsk_validate_rand(struct eap_gpsk_data *data, - const u8 *pos, const u8 *end) -{ - if (end - pos < EAP_GPSK_RAND_LEN) { - wpa_printf(MSG_DEBUG, "EAP-GPSK: Message too short for " - "RAND_Peer"); - return NULL; - } - if (os_memcmp(pos, data->rand_peer, EAP_GPSK_RAND_LEN) != 0) { - wpa_printf(MSG_DEBUG, "EAP-GPSK: RAND_Peer in GPSK-2 and " - "GPSK-3 did not match"); - wpa_hexdump(MSG_DEBUG, "EAP-GPSK: RAND_Peer in GPSK-2", - data->rand_peer, EAP_GPSK_RAND_LEN); - wpa_hexdump(MSG_DEBUG, "EAP-GPSK: RAND_Peer in GPSK-3", - pos, EAP_GPSK_RAND_LEN); - return NULL; - } - pos += EAP_GPSK_RAND_LEN; - - if (end - pos < EAP_GPSK_RAND_LEN) { - wpa_printf(MSG_DEBUG, "EAP-GPSK: Message too short for " - "RAND_Server"); - return NULL; - } - if (os_memcmp(pos, data->rand_server, EAP_GPSK_RAND_LEN) != 0) { - wpa_printf(MSG_DEBUG, "EAP-GPSK: RAND_Server in GPSK-1 and " - "GPSK-3 did not match"); - wpa_hexdump(MSG_DEBUG, "EAP-GPSK: RAND_Server in GPSK-1", - data->rand_server, EAP_GPSK_RAND_LEN); - wpa_hexdump(MSG_DEBUG, "EAP-GPSK: RAND_Server in GPSK-3", - pos, EAP_GPSK_RAND_LEN); - return NULL; - } - pos += EAP_GPSK_RAND_LEN; - - return pos; -} - - -static const u8 * eap_gpsk_validate_id_server(struct eap_gpsk_data *data, - const u8 *pos, const u8 *end) -{ - size_t len; - - if (pos == NULL) - return NULL; - - if (end - pos < (int) 2) { - wpa_printf(MSG_DEBUG, "EAP-GPSK: Message too short for " - "length(ID_Server)"); - return NULL; - } - - len = WPA_GET_BE16(pos); - pos += 2; - - if (end - pos < (int) len) { - wpa_printf(MSG_DEBUG, "EAP-GPSK: Message too short for " - "ID_Server"); - return NULL; - } - - if (len != data->id_server_len || - os_memcmp(pos, data->id_server, len) != 0) { - wpa_printf(MSG_INFO, "EAP-GPSK: ID_Server did not match with " - "the one used in GPSK-1"); - wpa_hexdump_ascii(MSG_DEBUG, "EAP-GPSK: ID_Server in GPSK-1", - data->id_server, data->id_server_len); - wpa_hexdump_ascii(MSG_DEBUG, "EAP-GPSK: ID_Server in GPSK-3", - pos, len); - return NULL; - } - - pos += len; - - return pos; -} - - -static const u8 * eap_gpsk_validate_csuite(struct eap_gpsk_data *data, - const u8 *pos, const u8 *end) -{ - int vendor, specifier; - const struct eap_gpsk_csuite *csuite; - - if (pos == NULL) - return NULL; - - if (end - pos < (int) sizeof(*csuite)) { - wpa_printf(MSG_DEBUG, "EAP-GPSK: Message too short for " - "CSuite_Sel"); - return NULL; - } - csuite = (const struct eap_gpsk_csuite *) pos; - vendor = WPA_GET_BE32(csuite->vendor); - specifier = WPA_GET_BE16(csuite->specifier); - pos += sizeof(*csuite); - if (vendor != data->vendor || specifier != data->specifier) { - wpa_printf(MSG_DEBUG, "EAP-GPSK: CSuite_Sel (%d:%d) does not " - "match with the one sent in GPSK-2 (%d:%d)", - vendor, specifier, data->vendor, data->specifier); - return NULL; - } - - return pos; -} - - -static const u8 * eap_gpsk_validate_pd_payload_2(struct eap_gpsk_data *data, - const u8 *pos, const u8 *end) -{ - u16 alen; - - if (pos == NULL) - return NULL; - - if (end - pos < 2) { - wpa_printf(MSG_DEBUG, "EAP-GPSK: Message too short for " - "PD_Payload_2 length"); - return NULL; - } - alen = WPA_GET_BE16(pos); - pos += 2; - if (end - pos < alen) { - wpa_printf(MSG_DEBUG, "EAP-GPSK: Message too short for " - "%d-octet PD_Payload_2", alen); - return NULL; - } - wpa_hexdump(MSG_DEBUG, "EAP-GPSK: PD_Payload_2", pos, alen); - pos += alen; - - return pos; -} - - -static const u8 * eap_gpsk_validate_gpsk_3_mic(struct eap_gpsk_data *data, - const u8 *payload, - const u8 *pos, const u8 *end) -{ - size_t miclen; - u8 mic[EAP_GPSK_MAX_MIC_LEN]; - - if (pos == NULL) - return NULL; - - miclen = eap_gpsk_mic_len(data->vendor, data->specifier); - if (end - pos < (int) miclen) { - wpa_printf(MSG_DEBUG, "EAP-GPSK: Message too short for MIC " - "(left=%lu miclen=%lu)", - (unsigned long) (end - pos), - (unsigned long) miclen); - return NULL; - } - if (eap_gpsk_compute_mic(data->sk, data->sk_len, data->vendor, - data->specifier, payload, pos - payload, mic) - < 0) { - wpa_printf(MSG_DEBUG, "EAP-GPSK: Failed to compute MIC"); - return NULL; - } - if (os_memcmp(mic, pos, miclen) != 0) { - wpa_printf(MSG_INFO, "EAP-GPSK: Incorrect MIC in GPSK-3"); - wpa_hexdump(MSG_DEBUG, "EAP-GPSK: Received MIC", pos, miclen); - wpa_hexdump(MSG_DEBUG, "EAP-GPSK: Computed MIC", mic, miclen); - return NULL; - } - pos += miclen; - - return pos; -} - - -static struct wpabuf * eap_gpsk_process_gpsk_3(struct eap_sm *sm, - struct eap_gpsk_data *data, - struct eap_method_ret *ret, - const struct wpabuf *reqData, - const u8 *payload, - size_t payload_len) -{ - struct wpabuf *resp; - const u8 *pos, *end; - - if (data->state != GPSK_3) { - ret->ignore = TRUE; - return NULL; - } - - wpa_printf(MSG_DEBUG, "EAP-GPSK: Received Request/GPSK-3"); - - end = payload + payload_len; - - pos = eap_gpsk_validate_rand(data, payload, end); - pos = eap_gpsk_validate_id_server(data, pos, end); - pos = eap_gpsk_validate_csuite(data, pos, end); - pos = eap_gpsk_validate_pd_payload_2(data, pos, end); - pos = eap_gpsk_validate_gpsk_3_mic(data, payload, pos, end); - - if (pos == NULL) { - eap_gpsk_state(data, FAILURE); - return NULL; - } - if (pos != end) { - wpa_printf(MSG_DEBUG, "EAP-GPSK: Ignored %lu bytes of extra " - "data in the end of GPSK-2", - (unsigned long) (end - pos)); - } - - resp = eap_gpsk_send_gpsk_4(data, eap_get_id(reqData)); - if (resp == NULL) - return NULL; - - eap_gpsk_state(data, SUCCESS); - ret->methodState = METHOD_DONE; - ret->decision = DECISION_UNCOND_SUCC; - - return resp; -} - - -static struct wpabuf * eap_gpsk_send_gpsk_4(struct eap_gpsk_data *data, - u8 identifier) -{ - struct wpabuf *resp; - u8 *rpos, *start; - size_t mlen; - - wpa_printf(MSG_DEBUG, "EAP-GPSK: Sending Response/GPSK-4"); - - mlen = eap_gpsk_mic_len(data->vendor, data->specifier); - - resp = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_GPSK, 1 + 2 + mlen, - EAP_CODE_RESPONSE, identifier); - if (resp == NULL) - return NULL; - - wpabuf_put_u8(resp, EAP_GPSK_OPCODE_GPSK_4); - start = wpabuf_put(resp, 0); - - /* No PD_Payload_3 */ - wpabuf_put_be16(resp, 0); - - rpos = wpabuf_put(resp, mlen); - if (eap_gpsk_compute_mic(data->sk, data->sk_len, data->vendor, - data->specifier, start, rpos - start, rpos) < - 0) { - eap_gpsk_state(data, FAILURE); - wpabuf_free(resp); - return NULL; - } - - return resp; -} - - -static struct wpabuf * eap_gpsk_process(struct eap_sm *sm, void *priv, - struct eap_method_ret *ret, - const struct wpabuf *reqData) -{ - struct eap_gpsk_data *data = priv; - struct wpabuf *resp; - const u8 *pos; - size_t len; - - pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_GPSK, reqData, &len); - if (pos == NULL || len < 1) { - ret->ignore = TRUE; - return NULL; - } - - wpa_printf(MSG_DEBUG, "EAP-GPSK: Received frame: opcode %d", *pos); - - ret->ignore = FALSE; - ret->methodState = METHOD_MAY_CONT; - ret->decision = DECISION_FAIL; - ret->allowNotifications = FALSE; - - switch (*pos) { - case EAP_GPSK_OPCODE_GPSK_1: - resp = eap_gpsk_process_gpsk_1(sm, data, ret, reqData, - pos + 1, len - 1); - break; - case EAP_GPSK_OPCODE_GPSK_3: - resp = eap_gpsk_process_gpsk_3(sm, data, ret, reqData, - pos + 1, len - 1); - break; - default: - wpa_printf(MSG_DEBUG, "EAP-GPSK: Ignoring message with " - "unknown opcode %d", *pos); - ret->ignore = TRUE; - return NULL; - } - - return resp; -} - - -static Boolean eap_gpsk_isKeyAvailable(struct eap_sm *sm, void *priv) -{ - struct eap_gpsk_data *data = priv; - return data->state == SUCCESS; -} - - -static u8 * eap_gpsk_getKey(struct eap_sm *sm, void *priv, size_t *len) -{ - struct eap_gpsk_data *data = priv; - u8 *key; - - if (data->state != SUCCESS) - return NULL; - - key = os_malloc(EAP_MSK_LEN); - if (key == NULL) - return NULL; - os_memcpy(key, data->msk, EAP_MSK_LEN); - *len = EAP_MSK_LEN; - - return key; -} - - -static u8 * eap_gpsk_get_emsk(struct eap_sm *sm, void *priv, size_t *len) -{ - struct eap_gpsk_data *data = priv; - u8 *key; - - if (data->state != SUCCESS) - return NULL; - - key = os_malloc(EAP_EMSK_LEN); - if (key == NULL) - return NULL; - os_memcpy(key, data->emsk, EAP_EMSK_LEN); - *len = EAP_EMSK_LEN; - - return key; -} - - -int eap_peer_gpsk_register(void) -{ - struct eap_method *eap; - int ret; - - eap = eap_peer_method_alloc(EAP_PEER_METHOD_INTERFACE_VERSION, - EAP_VENDOR_IETF, EAP_TYPE_GPSK, "GPSK"); - if (eap == NULL) - return -1; - - eap->init = eap_gpsk_init; - eap->deinit = eap_gpsk_deinit; - eap->process = eap_gpsk_process; - eap->isKeyAvailable = eap_gpsk_isKeyAvailable; - eap->getKey = eap_gpsk_getKey; - eap->get_emsk = eap_gpsk_get_emsk; - - ret = eap_peer_method_register(eap); - if (ret) - eap_peer_method_free(eap); - return ret; -} diff --git a/hostapd-0.8/src/eap_peer/eap_gtc.c b/hostapd-0.8/src/eap_peer/eap_gtc.c deleted file mode 100644 index b2b554b..0000000 --- a/hostapd-0.8/src/eap_peer/eap_gtc.c +++ /dev/null @@ -1,151 +0,0 @@ -/* - * EAP peer method: EAP-GTC (RFC 3748) - * Copyright (c) 2004-2006, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#include "includes.h" - -#include "common.h" -#include "eap_i.h" - - -struct eap_gtc_data { - int prefix; -}; - - -static void * eap_gtc_init(struct eap_sm *sm) -{ - struct eap_gtc_data *data; - data = os_zalloc(sizeof(*data)); - if (data == NULL) - return NULL; - - if (sm->m && sm->m->vendor == EAP_VENDOR_IETF && - sm->m->method == EAP_TYPE_FAST) { - wpa_printf(MSG_DEBUG, "EAP-GTC: EAP-FAST tunnel - use prefix " - "with challenge/response"); - data->prefix = 1; - } - return data; -} - - -static void eap_gtc_deinit(struct eap_sm *sm, void *priv) -{ - struct eap_gtc_data *data = priv; - os_free(data); -} - - -static struct wpabuf * eap_gtc_process(struct eap_sm *sm, void *priv, - struct eap_method_ret *ret, - const struct wpabuf *reqData) -{ - struct eap_gtc_data *data = priv; - struct wpabuf *resp; - const u8 *pos, *password, *identity; - size_t password_len, identity_len, len, plen; - int otp; - u8 id; - - pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_GTC, reqData, &len); - if (pos == NULL) { - ret->ignore = TRUE; - return NULL; - } - id = eap_get_id(reqData); - - wpa_hexdump_ascii(MSG_MSGDUMP, "EAP-GTC: Request message", pos, len); - if (data->prefix && - (len < 10 || os_memcmp(pos, "CHALLENGE=", 10) != 0)) { - wpa_printf(MSG_DEBUG, "EAP-GTC: Challenge did not start with " - "expected prefix"); - - /* Send an empty response in order to allow tunneled - * acknowledgement of the failure. This will also cover the - * error case which seems to use EAP-MSCHAPv2 like error - * reporting with EAP-GTC inside EAP-FAST tunnel. */ - resp = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_GTC, - 0, EAP_CODE_RESPONSE, id); - return resp; - } - - password = eap_get_config_otp(sm, &password_len); - if (password) - otp = 1; - else { - password = eap_get_config_password(sm, &password_len); - otp = 0; - } - - if (password == NULL) { - wpa_printf(MSG_INFO, "EAP-GTC: Password not configured"); - eap_sm_request_otp(sm, (const char *) pos, len); - ret->ignore = TRUE; - return NULL; - } - - ret->ignore = FALSE; - - ret->methodState = data->prefix ? METHOD_MAY_CONT : METHOD_DONE; - ret->decision = DECISION_COND_SUCC; - ret->allowNotifications = FALSE; - - plen = password_len; - identity = eap_get_config_identity(sm, &identity_len); - if (identity == NULL) - return NULL; - if (data->prefix) - plen += 9 + identity_len + 1; - resp = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_GTC, plen, - EAP_CODE_RESPONSE, id); - if (resp == NULL) - return NULL; - if (data->prefix) { - wpabuf_put_data(resp, "RESPONSE=", 9); - wpabuf_put_data(resp, identity, identity_len); - wpabuf_put_u8(resp, '\0'); - } - wpabuf_put_data(resp, password, password_len); - wpa_hexdump_ascii_key(MSG_MSGDUMP, "EAP-GTC: Response", - wpabuf_head_u8(resp) + sizeof(struct eap_hdr) + - 1, plen); - - if (otp) { - wpa_printf(MSG_DEBUG, "EAP-GTC: Forgetting used password"); - eap_clear_config_otp(sm); - } - - return resp; -} - - -int eap_peer_gtc_register(void) -{ - struct eap_method *eap; - int ret; - - eap = eap_peer_method_alloc(EAP_PEER_METHOD_INTERFACE_VERSION, - EAP_VENDOR_IETF, EAP_TYPE_GTC, "GTC"); - if (eap == NULL) - return -1; - - eap->init = eap_gtc_init; - eap->deinit = eap_gtc_deinit; - eap->process = eap_gtc_process; - - ret = eap_peer_method_register(eap); - if (ret) - eap_peer_method_free(eap); - return ret; -} diff --git a/hostapd-0.8/src/eap_peer/eap_i.h b/hostapd-0.8/src/eap_peer/eap_i.h deleted file mode 100644 index afca611..0000000 --- a/hostapd-0.8/src/eap_peer/eap_i.h +++ /dev/null @@ -1,356 +0,0 @@ -/* - * EAP peer state machines internal structures (RFC 4137) - * Copyright (c) 2004-2007, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#ifndef EAP_I_H -#define EAP_I_H - -#include "wpabuf.h" -#include "eap_peer/eap.h" -#include "eap_common/eap_common.h" - -/* RFC 4137 - EAP Peer state machine */ - -typedef enum { - DECISION_FAIL, DECISION_COND_SUCC, DECISION_UNCOND_SUCC -} EapDecision; - -typedef enum { - METHOD_NONE, METHOD_INIT, METHOD_CONT, METHOD_MAY_CONT, METHOD_DONE -} EapMethodState; - -/** - * struct eap_method_ret - EAP return values from struct eap_method::process() - * - * These structure contains OUT variables for the interface between peer state - * machine and methods (RFC 4137, Sect. 4.2). eapRespData will be returned as - * the return value of struct eap_method::process() so it is not included in - * this structure. - */ -struct eap_method_ret { - /** - * ignore - Whether method decided to drop the current packed (OUT) - */ - Boolean ignore; - - /** - * methodState - Method-specific state (IN/OUT) - */ - EapMethodState methodState; - - /** - * decision - Authentication decision (OUT) - */ - EapDecision decision; - - /** - * allowNotifications - Whether method allows notifications (OUT) - */ - Boolean allowNotifications; -}; - - -/** - * struct eap_method - EAP method interface - * This structure defines the EAP method interface. Each method will need to - * register its own EAP type, EAP name, and set of function pointers for method - * specific operations. This interface is based on section 4.4 of RFC 4137. - */ -struct eap_method { - /** - * vendor - EAP Vendor-ID (EAP_VENDOR_*) (0 = IETF) - */ - int vendor; - - /** - * method - EAP type number (EAP_TYPE_*) - */ - EapType method; - - /** - * name - Name of the method (e.g., "TLS") - */ - const char *name; - - /** - * init - Initialize an EAP method - * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init() - * Returns: Pointer to allocated private data, or %NULL on failure - * - * This function is used to initialize the EAP method explicitly - * instead of using METHOD_INIT state as specific in RFC 4137. The - * method is expected to initialize it method-specific state and return - * a pointer that will be used as the priv argument to other calls. - */ - void * (*init)(struct eap_sm *sm); - - /** - * deinit - Deinitialize an EAP method - * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init() - * @priv: Pointer to private EAP method data from eap_method::init() - * - * Deinitialize the EAP method and free any allocated private data. - */ - void (*deinit)(struct eap_sm *sm, void *priv); - - /** - * process - Process an EAP request - * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init() - * @priv: Pointer to private EAP method data from eap_method::init() - * @ret: Return values from EAP request validation and processing - * @reqData: EAP request to be processed (eapReqData) - * Returns: Pointer to allocated EAP response packet (eapRespData) - * - * This function is a combination of m.check(), m.process(), and - * m.buildResp() procedures defined in section 4.4 of RFC 4137 In other - * words, this function validates the incoming request, processes it, - * and build a response packet. m.check() and m.process() return values - * are returned through struct eap_method_ret *ret variable. Caller is - * responsible for freeing the returned EAP response packet. - */ - struct wpabuf * (*process)(struct eap_sm *sm, void *priv, - struct eap_method_ret *ret, - const struct wpabuf *reqData); - - /** - * isKeyAvailable - Find out whether EAP method has keying material - * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init() - * @priv: Pointer to private EAP method data from eap_method::init() - * Returns: %TRUE if key material (eapKeyData) is available - */ - Boolean (*isKeyAvailable)(struct eap_sm *sm, void *priv); - - /** - * getKey - Get EAP method specific keying material (eapKeyData) - * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init() - * @priv: Pointer to private EAP method data from eap_method::init() - * @len: Pointer to variable to store key length (eapKeyDataLen) - * Returns: Keying material (eapKeyData) or %NULL if not available - * - * This function can be used to get the keying material from the EAP - * method. The key may already be stored in the method-specific private - * data or this function may derive the key. - */ - u8 * (*getKey)(struct eap_sm *sm, void *priv, size_t *len); - - /** - * get_status - Get EAP method status - * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init() - * @priv: Pointer to private EAP method data from eap_method::init() - * @buf: Buffer for status information - * @buflen: Maximum buffer length - * @verbose: Whether to include verbose status information - * Returns: Number of bytes written to buf - * - * Query EAP method for status information. This function fills in a - * text area with current status information from the EAP method. If - * the buffer (buf) is not large enough, status information will be - * truncated to fit the buffer. - */ - int (*get_status)(struct eap_sm *sm, void *priv, char *buf, - size_t buflen, int verbose); - - /** - * has_reauth_data - Whether method is ready for fast reauthentication - * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init() - * @priv: Pointer to private EAP method data from eap_method::init() - * Returns: %TRUE or %FALSE based on whether fast reauthentication is - * possible - * - * This function is an optional handler that only EAP methods - * supporting fast re-authentication need to implement. - */ - Boolean (*has_reauth_data)(struct eap_sm *sm, void *priv); - - /** - * deinit_for_reauth - Release data that is not needed for fast re-auth - * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init() - * @priv: Pointer to private EAP method data from eap_method::init() - * - * This function is an optional handler that only EAP methods - * supporting fast re-authentication need to implement. This is called - * when authentication has been completed and EAP state machine is - * requesting that enough state information is maintained for fast - * re-authentication - */ - void (*deinit_for_reauth)(struct eap_sm *sm, void *priv); - - /** - * init_for_reauth - Prepare for start of fast re-authentication - * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init() - * @priv: Pointer to private EAP method data from eap_method::init() - * - * This function is an optional handler that only EAP methods - * supporting fast re-authentication need to implement. This is called - * when EAP authentication is started and EAP state machine is - * requesting fast re-authentication to be used. - */ - void * (*init_for_reauth)(struct eap_sm *sm, void *priv); - - /** - * get_identity - Get method specific identity for re-authentication - * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init() - * @priv: Pointer to private EAP method data from eap_method::init() - * @len: Length of the returned identity - * Returns: Pointer to the method specific identity or %NULL if default - * identity is to be used - * - * This function is an optional handler that only EAP methods - * that use method specific identity need to implement. - */ - const u8 * (*get_identity)(struct eap_sm *sm, void *priv, size_t *len); - - /** - * free - Free EAP method data - * @method: Pointer to the method data registered with - * eap_peer_method_register(). - * - * This function will be called when the EAP method is being - * unregistered. If the EAP method allocated resources during - * registration (e.g., allocated struct eap_method), they should be - * freed in this function. No other method functions will be called - * after this call. If this function is not defined (i.e., function - * pointer is %NULL), a default handler is used to release the method - * data with free(method). This is suitable for most cases. - */ - void (*free)(struct eap_method *method); - -#define EAP_PEER_METHOD_INTERFACE_VERSION 1 - /** - * version - Version of the EAP peer method interface - * - * The EAP peer method implementation should set this variable to - * EAP_PEER_METHOD_INTERFACE_VERSION. This is used to verify that the - * EAP method is using supported API version when using dynamically - * loadable EAP methods. - */ - int version; - - /** - * next - Pointer to the next EAP method - * - * This variable is used internally in the EAP method registration code - * to create a linked list of registered EAP methods. - */ - struct eap_method *next; - -#ifdef CONFIG_DYNAMIC_EAP_METHODS - /** - * dl_handle - Handle for the dynamic library - * - * This variable is used internally in the EAP method registration code - * to store a handle for the dynamic library. If the method is linked - * in statically, this is %NULL. - */ - void *dl_handle; -#endif /* CONFIG_DYNAMIC_EAP_METHODS */ - - /** - * get_emsk - Get EAP method specific keying extended material (EMSK) - * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init() - * @priv: Pointer to private EAP method data from eap_method::init() - * @len: Pointer to a variable to store EMSK length - * Returns: EMSK or %NULL if not available - * - * This function can be used to get the extended keying material from - * the EAP method. The key may already be stored in the method-specific - * private data or this function may derive the key. - */ - u8 * (*get_emsk)(struct eap_sm *sm, void *priv, size_t *len); -}; - - -/** - * struct eap_sm - EAP state machine data - */ -struct eap_sm { - enum { - EAP_INITIALIZE, EAP_DISABLED, EAP_IDLE, EAP_RECEIVED, - EAP_GET_METHOD, EAP_METHOD, EAP_SEND_RESPONSE, EAP_DISCARD, - EAP_IDENTITY, EAP_NOTIFICATION, EAP_RETRANSMIT, EAP_SUCCESS, - EAP_FAILURE - } EAP_state; - /* Long-term local variables */ - EapType selectedMethod; - EapMethodState methodState; - int lastId; - struct wpabuf *lastRespData; - EapDecision decision; - /* Short-term local variables */ - Boolean rxReq; - Boolean rxSuccess; - Boolean rxFailure; - int reqId; - EapType reqMethod; - int reqVendor; - u32 reqVendorMethod; - Boolean ignore; - /* Constants */ - int ClientTimeout; - - /* Miscellaneous variables */ - Boolean allowNotifications; /* peer state machine <-> methods */ - struct wpabuf *eapRespData; /* peer to lower layer */ - Boolean eapKeyAvailable; /* peer to lower layer */ - u8 *eapKeyData; /* peer to lower layer */ - size_t eapKeyDataLen; /* peer to lower layer */ - const struct eap_method *m; /* selected EAP method */ - /* not defined in RFC 4137 */ - Boolean changed; - void *eapol_ctx; - struct eapol_callbacks *eapol_cb; - void *eap_method_priv; - int init_phase2; - int fast_reauth; - - Boolean rxResp /* LEAP only */; - Boolean leap_done; - Boolean peap_done; - u8 req_md5[16]; /* MD5() of the current EAP packet */ - u8 last_md5[16]; /* MD5() of the previously received EAP packet; used - * in duplicate request detection. */ - - void *msg_ctx; - void *scard_ctx; - void *ssl_ctx; - - unsigned int workaround; - - /* Optional challenges generated in Phase 1 (EAP-FAST) */ - u8 *peer_challenge, *auth_challenge; - - int num_rounds; - int force_disabled; - - struct wps_context *wps; - - int prev_failure; -}; - -const u8 * eap_get_config_identity(struct eap_sm *sm, size_t *len); -const u8 * eap_get_config_password(struct eap_sm *sm, size_t *len); -const u8 * eap_get_config_password2(struct eap_sm *sm, size_t *len, int *hash); -const u8 * eap_get_config_new_password(struct eap_sm *sm, size_t *len); -const u8 * eap_get_config_otp(struct eap_sm *sm, size_t *len); -void eap_clear_config_otp(struct eap_sm *sm); -const char * eap_get_config_phase1(struct eap_sm *sm); -const char * eap_get_config_phase2(struct eap_sm *sm); -int eap_get_config_fragment_size(struct eap_sm *sm); -struct eap_peer_config * eap_get_config(struct eap_sm *sm); -void eap_set_config_blob(struct eap_sm *sm, struct wpa_config_blob *blob); -const struct wpa_config_blob * -eap_get_config_blob(struct eap_sm *sm, const char *name); -void eap_notify_pending(struct eap_sm *sm); -int eap_allowed_method(struct eap_sm *sm, int vendor, u32 method); - -#endif /* EAP_I_H */ diff --git a/hostapd-0.8/src/eap_peer/eap_ikev2.c b/hostapd-0.8/src/eap_peer/eap_ikev2.c deleted file mode 100644 index bb49a66..0000000 --- a/hostapd-0.8/src/eap_peer/eap_ikev2.c +++ /dev/null @@ -1,506 +0,0 @@ -/* - * EAP-IKEv2 peer (RFC 5106) - * Copyright (c) 2007, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#include "includes.h" - -#include "common.h" -#include "eap_i.h" -#include "eap_common/eap_ikev2_common.h" -#include "ikev2.h" - - -struct eap_ikev2_data { - struct ikev2_responder_data ikev2; - enum { WAIT_START, PROC_MSG, WAIT_FRAG_ACK, DONE, FAIL } state; - struct wpabuf *in_buf; - struct wpabuf *out_buf; - size_t out_used; - size_t fragment_size; - int keys_ready; - u8 keymat[EAP_MSK_LEN + EAP_EMSK_LEN]; - int keymat_ok; -}; - - -static const char * eap_ikev2_state_txt(int state) -{ - switch (state) { - case WAIT_START: - return "WAIT_START"; - case PROC_MSG: - return "PROC_MSG"; - case WAIT_FRAG_ACK: - return "WAIT_FRAG_ACK"; - case DONE: - return "DONE"; - case FAIL: - return "FAIL"; - default: - return "?"; - } -} - - -static void eap_ikev2_state(struct eap_ikev2_data *data, int state) -{ - wpa_printf(MSG_DEBUG, "EAP-IKEV2: %s -> %s", - eap_ikev2_state_txt(data->state), - eap_ikev2_state_txt(state)); - data->state = state; -} - - -static void * eap_ikev2_init(struct eap_sm *sm) -{ - struct eap_ikev2_data *data; - const u8 *identity, *password; - size_t identity_len, password_len; - - identity = eap_get_config_identity(sm, &identity_len); - if (identity == NULL) { - wpa_printf(MSG_INFO, "EAP-IKEV2: No identity available"); - return NULL; - } - - data = os_zalloc(sizeof(*data)); - if (data == NULL) - return NULL; - data->state = WAIT_START; - data->fragment_size = IKEV2_FRAGMENT_SIZE; - data->ikev2.state = SA_INIT; - data->ikev2.peer_auth = PEER_AUTH_SECRET; - data->ikev2.key_pad = (u8 *) os_strdup("Key Pad for EAP-IKEv2"); - if (data->ikev2.key_pad == NULL) - goto failed; - data->ikev2.key_pad_len = 21; - data->ikev2.IDr = os_malloc(identity_len); - if (data->ikev2.IDr == NULL) - goto failed; - os_memcpy(data->ikev2.IDr, identity, identity_len); - data->ikev2.IDr_len = identity_len; - - password = eap_get_config_password(sm, &password_len); - if (password) { - data->ikev2.shared_secret = os_malloc(password_len); - if (data->ikev2.shared_secret == NULL) - goto failed; - os_memcpy(data->ikev2.shared_secret, password, password_len); - data->ikev2.shared_secret_len = password_len; - } - - return data; - -failed: - ikev2_responder_deinit(&data->ikev2); - os_free(data); - return NULL; -} - - -static void eap_ikev2_deinit(struct eap_sm *sm, void *priv) -{ - struct eap_ikev2_data *data = priv; - wpabuf_free(data->in_buf); - wpabuf_free(data->out_buf); - ikev2_responder_deinit(&data->ikev2); - os_free(data); -} - - -static int eap_ikev2_peer_keymat(struct eap_ikev2_data *data) -{ - if (eap_ikev2_derive_keymat( - data->ikev2.proposal.prf, &data->ikev2.keys, - data->ikev2.i_nonce, data->ikev2.i_nonce_len, - data->ikev2.r_nonce, data->ikev2.r_nonce_len, - data->keymat) < 0) { - wpa_printf(MSG_DEBUG, "EAP-IKEV2: Failed to " - "derive key material"); - return -1; - } - data->keymat_ok = 1; - return 0; -} - - -static struct wpabuf * eap_ikev2_build_msg(struct eap_ikev2_data *data, - struct eap_method_ret *ret, u8 id) -{ - struct wpabuf *resp; - u8 flags; - size_t send_len, plen, icv_len = 0; - - ret->ignore = FALSE; - wpa_printf(MSG_DEBUG, "EAP-IKEV2: Generating Response"); - ret->allowNotifications = TRUE; - - flags = 0; - send_len = wpabuf_len(data->out_buf) - data->out_used; - if (1 + send_len > data->fragment_size) { - send_len = data->fragment_size - 1; - flags |= IKEV2_FLAGS_MORE_FRAGMENTS; - if (data->out_used == 0) { - flags |= IKEV2_FLAGS_LENGTH_INCLUDED; - send_len -= 4; - } - } -#ifdef CCNS_PL - /* Some issues figuring out the length of the message if Message Length - * field not included?! */ - if (!(flags & IKEV2_FLAGS_LENGTH_INCLUDED)) - flags |= IKEV2_FLAGS_LENGTH_INCLUDED; -#endif /* CCNS_PL */ - - plen = 1 + send_len; - if (flags & IKEV2_FLAGS_LENGTH_INCLUDED) - plen += 4; - if (data->keys_ready) { - const struct ikev2_integ_alg *integ; - wpa_printf(MSG_DEBUG, "EAP-IKEV2: Add Integrity Checksum " - "Data"); - flags |= IKEV2_FLAGS_ICV_INCLUDED; - integ = ikev2_get_integ(data->ikev2.proposal.integ); - if (integ == NULL) { - wpa_printf(MSG_DEBUG, "EAP-IKEV2: Unknown INTEG " - "transform / cannot generate ICV"); - return NULL; - } - icv_len = integ->hash_len; - - plen += icv_len; - } - resp = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_IKEV2, plen, - EAP_CODE_RESPONSE, id); - if (resp == NULL) - return NULL; - - wpabuf_put_u8(resp, flags); /* Flags */ - if (flags & IKEV2_FLAGS_LENGTH_INCLUDED) - wpabuf_put_be32(resp, wpabuf_len(data->out_buf)); - - wpabuf_put_data(resp, wpabuf_head_u8(data->out_buf) + data->out_used, - send_len); - data->out_used += send_len; - - if (flags & IKEV2_FLAGS_ICV_INCLUDED) { - const u8 *msg = wpabuf_head(resp); - size_t len = wpabuf_len(resp); - ikev2_integ_hash(data->ikev2.proposal.integ, - data->ikev2.keys.SK_ar, - data->ikev2.keys.SK_integ_len, - msg, len, wpabuf_put(resp, icv_len)); - } - - ret->methodState = METHOD_MAY_CONT; - ret->decision = DECISION_FAIL; - - if (data->out_used == wpabuf_len(data->out_buf)) { - wpa_printf(MSG_DEBUG, "EAP-IKEV2: Sending out %lu bytes " - "(message sent completely)", - (unsigned long) send_len); - wpabuf_free(data->out_buf); - data->out_buf = NULL; - data->out_used = 0; - switch (data->ikev2.state) { - case SA_AUTH: - /* SA_INIT was sent out, so message have to be - * integrity protected from now on. */ - data->keys_ready = 1; - break; - case IKEV2_DONE: - ret->methodState = METHOD_DONE; - if (data->state == FAIL) - break; - ret->decision = DECISION_COND_SUCC; - wpa_printf(MSG_DEBUG, "EAP-IKEV2: Authentication " - "completed successfully"); - if (eap_ikev2_peer_keymat(data)) - break; - eap_ikev2_state(data, DONE); - break; - case IKEV2_FAILED: - wpa_printf(MSG_DEBUG, "EAP-IKEV2: Authentication " - "failed"); - ret->methodState = METHOD_DONE; - ret->decision = DECISION_FAIL; - break; - default: - break; - } - } else { - wpa_printf(MSG_DEBUG, "EAP-IKEV2: Sending out %lu bytes " - "(%lu more to send)", (unsigned long) send_len, - (unsigned long) wpabuf_len(data->out_buf) - - data->out_used); - eap_ikev2_state(data, WAIT_FRAG_ACK); - } - - return resp; -} - - -static int eap_ikev2_process_icv(struct eap_ikev2_data *data, - const struct wpabuf *reqData, - u8 flags, const u8 *pos, const u8 **end) -{ - if (flags & IKEV2_FLAGS_ICV_INCLUDED) { - int icv_len = eap_ikev2_validate_icv( - data->ikev2.proposal.integ, &data->ikev2.keys, 1, - reqData, pos, *end); - if (icv_len < 0) - return -1; - /* Hide Integrity Checksum Data from further processing */ - *end -= icv_len; - } else if (data->keys_ready) { - wpa_printf(MSG_INFO, "EAP-IKEV2: The message should have " - "included integrity checksum"); - return -1; - } - - return 0; -} - - -static int eap_ikev2_process_cont(struct eap_ikev2_data *data, - const u8 *buf, size_t len) -{ - /* Process continuation of a pending message */ - if (len > wpabuf_tailroom(data->in_buf)) { - wpa_printf(MSG_DEBUG, "EAP-IKEV2: Fragment overflow"); - eap_ikev2_state(data, FAIL); - return -1; - } - - wpabuf_put_data(data->in_buf, buf, len); - wpa_printf(MSG_DEBUG, "EAP-IKEV2: Received %lu bytes, waiting " - "for %lu bytes more", (unsigned long) len, - (unsigned long) wpabuf_tailroom(data->in_buf)); - - return 0; -} - - -static struct wpabuf * eap_ikev2_process_fragment(struct eap_ikev2_data *data, - struct eap_method_ret *ret, - u8 id, u8 flags, - u32 message_length, - const u8 *buf, size_t len) -{ - /* Process a fragment that is not the last one of the message */ - if (data->in_buf == NULL && !(flags & IKEV2_FLAGS_LENGTH_INCLUDED)) { - wpa_printf(MSG_DEBUG, "EAP-IKEV2: No Message Length field in " - "a fragmented packet"); - ret->ignore = TRUE; - return NULL; - } - - if (data->in_buf == NULL) { - /* First fragment of the message */ - data->in_buf = wpabuf_alloc(message_length); - if (data->in_buf == NULL) { - wpa_printf(MSG_DEBUG, "EAP-IKEV2: No memory for " - "message"); - ret->ignore = TRUE; - return NULL; - } - wpabuf_put_data(data->in_buf, buf, len); - wpa_printf(MSG_DEBUG, "EAP-IKEV2: Received %lu bytes in first " - "fragment, waiting for %lu bytes more", - (unsigned long) len, - (unsigned long) wpabuf_tailroom(data->in_buf)); - } - - return eap_ikev2_build_frag_ack(id, EAP_CODE_RESPONSE); -} - - -static struct wpabuf * eap_ikev2_process(struct eap_sm *sm, void *priv, - struct eap_method_ret *ret, - const struct wpabuf *reqData) -{ - struct eap_ikev2_data *data = priv; - const u8 *start, *pos, *end; - size_t len; - u8 flags, id; - u32 message_length = 0; - struct wpabuf tmpbuf; - - pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_IKEV2, reqData, &len); - if (pos == NULL) { - ret->ignore = TRUE; - return NULL; - } - - id = eap_get_id(reqData); - - start = pos; - end = start + len; - - if (len == 0) - flags = 0; /* fragment ack */ - else - flags = *pos++; - - if (eap_ikev2_process_icv(data, reqData, flags, pos, &end) < 0) { - ret->ignore = TRUE; - return NULL; - } - - if (flags & IKEV2_FLAGS_LENGTH_INCLUDED) { - if (end - pos < 4) { - wpa_printf(MSG_DEBUG, "EAP-IKEV2: Message underflow"); - ret->ignore = TRUE; - return NULL; - } - message_length = WPA_GET_BE32(pos); - pos += 4; - - if (message_length < (u32) (end - pos)) { - wpa_printf(MSG_DEBUG, "EAP-IKEV2: Invalid Message " - "Length (%d; %ld remaining in this msg)", - message_length, (long) (end - pos)); - ret->ignore = TRUE; - return NULL; - } - } - - wpa_printf(MSG_DEBUG, "EAP-IKEV2: Received packet: Flags 0x%x " - "Message Length %u", flags, message_length); - - if (data->state == WAIT_FRAG_ACK) { -#ifdef CCNS_PL - if (len > 1) /* Empty Flags field included in ACK */ -#else /* CCNS_PL */ - if (len != 0) -#endif /* CCNS_PL */ - { - wpa_printf(MSG_DEBUG, "EAP-IKEV2: Unexpected payload " - "in WAIT_FRAG_ACK state"); - ret->ignore = TRUE; - return NULL; - } - wpa_printf(MSG_DEBUG, "EAP-IKEV2: Fragment acknowledged"); - eap_ikev2_state(data, PROC_MSG); - return eap_ikev2_build_msg(data, ret, id); - } - - if (data->in_buf && eap_ikev2_process_cont(data, pos, end - pos) < 0) { - ret->ignore = TRUE; - return NULL; - } - - if (flags & IKEV2_FLAGS_MORE_FRAGMENTS) { - return eap_ikev2_process_fragment(data, ret, id, flags, - message_length, pos, - end - pos); - } - - if (data->in_buf == NULL) { - /* Wrap unfragmented messages as wpabuf without extra copy */ - wpabuf_set(&tmpbuf, pos, end - pos); - data->in_buf = &tmpbuf; - } - - if (ikev2_responder_process(&data->ikev2, data->in_buf) < 0) { - if (data->in_buf == &tmpbuf) - data->in_buf = NULL; - eap_ikev2_state(data, FAIL); - return NULL; - } - - if (data->in_buf != &tmpbuf) - wpabuf_free(data->in_buf); - data->in_buf = NULL; - - if (data->out_buf == NULL) { - data->out_buf = ikev2_responder_build(&data->ikev2); - if (data->out_buf == NULL) { - wpa_printf(MSG_DEBUG, "EAP-IKEV2: Failed to generate " - "IKEv2 message"); - return NULL; - } - data->out_used = 0; - } - - eap_ikev2_state(data, PROC_MSG); - return eap_ikev2_build_msg(data, ret, id); -} - - -static Boolean eap_ikev2_isKeyAvailable(struct eap_sm *sm, void *priv) -{ - struct eap_ikev2_data *data = priv; - return data->state == DONE && data->keymat_ok; -} - - -static u8 * eap_ikev2_getKey(struct eap_sm *sm, void *priv, size_t *len) -{ - struct eap_ikev2_data *data = priv; - u8 *key; - - if (data->state != DONE || !data->keymat_ok) - return NULL; - - key = os_malloc(EAP_MSK_LEN); - if (key) { - os_memcpy(key, data->keymat, EAP_MSK_LEN); - *len = EAP_MSK_LEN; - } - - return key; -} - - -static u8 * eap_ikev2_get_emsk(struct eap_sm *sm, void *priv, size_t *len) -{ - struct eap_ikev2_data *data = priv; - u8 *key; - - if (data->state != DONE || !data->keymat_ok) - return NULL; - - key = os_malloc(EAP_EMSK_LEN); - if (key) { - os_memcpy(key, data->keymat + EAP_MSK_LEN, EAP_EMSK_LEN); - *len = EAP_EMSK_LEN; - } - - return key; -} - - -int eap_peer_ikev2_register(void) -{ - struct eap_method *eap; - int ret; - - eap = eap_peer_method_alloc(EAP_PEER_METHOD_INTERFACE_VERSION, - EAP_VENDOR_IETF, EAP_TYPE_IKEV2, - "IKEV2"); - if (eap == NULL) - return -1; - - eap->init = eap_ikev2_init; - eap->deinit = eap_ikev2_deinit; - eap->process = eap_ikev2_process; - eap->isKeyAvailable = eap_ikev2_isKeyAvailable; - eap->getKey = eap_ikev2_getKey; - eap->get_emsk = eap_ikev2_get_emsk; - - ret = eap_peer_method_register(eap); - if (ret) - eap_peer_method_free(eap); - return ret; -} diff --git a/hostapd-0.8/src/eap_peer/eap_leap.c b/hostapd-0.8/src/eap_peer/eap_leap.c deleted file mode 100644 index 6a8efcd..0000000 --- a/hostapd-0.8/src/eap_peer/eap_leap.c +++ /dev/null @@ -1,416 +0,0 @@ -/* - * EAP peer method: LEAP - * Copyright (c) 2004-2007, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#include "includes.h" - -#include "common.h" -#include "crypto/ms_funcs.h" -#include "crypto/crypto.h" -#include "crypto/random.h" -#include "eap_i.h" - -#define LEAP_VERSION 1 -#define LEAP_CHALLENGE_LEN 8 -#define LEAP_RESPONSE_LEN 24 -#define LEAP_KEY_LEN 16 - - -struct eap_leap_data { - enum { - LEAP_WAIT_CHALLENGE, - LEAP_WAIT_SUCCESS, - LEAP_WAIT_RESPONSE, - LEAP_DONE - } state; - - u8 peer_challenge[LEAP_CHALLENGE_LEN]; - u8 peer_response[LEAP_RESPONSE_LEN]; - - u8 ap_challenge[LEAP_CHALLENGE_LEN]; - u8 ap_response[LEAP_RESPONSE_LEN]; -}; - - -static void * eap_leap_init(struct eap_sm *sm) -{ - struct eap_leap_data *data; - - data = os_zalloc(sizeof(*data)); - if (data == NULL) - return NULL; - data->state = LEAP_WAIT_CHALLENGE; - - sm->leap_done = FALSE; - return data; -} - - -static void eap_leap_deinit(struct eap_sm *sm, void *priv) -{ - os_free(priv); -} - - -static struct wpabuf * eap_leap_process_request(struct eap_sm *sm, void *priv, - struct eap_method_ret *ret, - const struct wpabuf *reqData) -{ - struct eap_leap_data *data = priv; - struct wpabuf *resp; - const u8 *pos, *challenge, *identity, *password; - u8 challenge_len, *rpos; - size_t identity_len, password_len, len; - int pwhash; - - wpa_printf(MSG_DEBUG, "EAP-LEAP: Processing EAP-Request"); - - identity = eap_get_config_identity(sm, &identity_len); - password = eap_get_config_password2(sm, &password_len, &pwhash); - if (identity == NULL || password == NULL) - return NULL; - - pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_LEAP, reqData, &len); - if (pos == NULL || len < 3) { - wpa_printf(MSG_INFO, "EAP-LEAP: Invalid EAP-Request frame"); - ret->ignore = TRUE; - return NULL; - } - - if (*pos != LEAP_VERSION) { - wpa_printf(MSG_WARNING, "EAP-LEAP: Unsupported LEAP version " - "%d", *pos); - ret->ignore = TRUE; - return NULL; - } - pos++; - - pos++; /* skip unused byte */ - - challenge_len = *pos++; - if (challenge_len != LEAP_CHALLENGE_LEN || challenge_len > len - 3) { - wpa_printf(MSG_INFO, "EAP-LEAP: Invalid challenge " - "(challenge_len=%d reqDataLen=%lu)", - challenge_len, (unsigned long) wpabuf_len(reqData)); - ret->ignore = TRUE; - return NULL; - } - challenge = pos; - os_memcpy(data->peer_challenge, challenge, LEAP_CHALLENGE_LEN); - wpa_hexdump(MSG_MSGDUMP, "EAP-LEAP: Challenge from AP", - challenge, LEAP_CHALLENGE_LEN); - - wpa_printf(MSG_DEBUG, "EAP-LEAP: Generating Challenge Response"); - - resp = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_LEAP, - 3 + LEAP_RESPONSE_LEN + identity_len, - EAP_CODE_RESPONSE, eap_get_id(reqData)); - if (resp == NULL) - return NULL; - wpabuf_put_u8(resp, LEAP_VERSION); - wpabuf_put_u8(resp, 0); /* unused */ - wpabuf_put_u8(resp, LEAP_RESPONSE_LEN); - rpos = wpabuf_put(resp, LEAP_RESPONSE_LEN); - if (pwhash) - challenge_response(challenge, password, rpos); - else - nt_challenge_response(challenge, password, password_len, rpos); - os_memcpy(data->peer_response, rpos, LEAP_RESPONSE_LEN); - wpa_hexdump(MSG_MSGDUMP, "EAP-LEAP: Response", - rpos, LEAP_RESPONSE_LEN); - wpabuf_put_data(resp, identity, identity_len); - - data->state = LEAP_WAIT_SUCCESS; - - return resp; -} - - -static struct wpabuf * eap_leap_process_success(struct eap_sm *sm, void *priv, - struct eap_method_ret *ret, - const struct wpabuf *reqData) -{ - struct eap_leap_data *data = priv; - struct wpabuf *resp; - u8 *pos; - const u8 *identity; - size_t identity_len; - - wpa_printf(MSG_DEBUG, "EAP-LEAP: Processing EAP-Success"); - - identity = eap_get_config_identity(sm, &identity_len); - if (identity == NULL) - return NULL; - - if (data->state != LEAP_WAIT_SUCCESS) { - wpa_printf(MSG_INFO, "EAP-LEAP: EAP-Success received in " - "unexpected state (%d) - ignored", data->state); - ret->ignore = TRUE; - return NULL; - } - - resp = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_LEAP, - 3 + LEAP_CHALLENGE_LEN + identity_len, - EAP_CODE_REQUEST, eap_get_id(reqData)); - if (resp == NULL) - return NULL; - wpabuf_put_u8(resp, LEAP_VERSION); - wpabuf_put_u8(resp, 0); /* unused */ - wpabuf_put_u8(resp, LEAP_CHALLENGE_LEN); - pos = wpabuf_put(resp, LEAP_CHALLENGE_LEN); - if (random_get_bytes(pos, LEAP_CHALLENGE_LEN)) { - wpa_printf(MSG_WARNING, "EAP-LEAP: Failed to read random data " - "for challenge"); - wpabuf_free(resp); - ret->ignore = TRUE; - return NULL; - } - os_memcpy(data->ap_challenge, pos, LEAP_CHALLENGE_LEN); - wpa_hexdump(MSG_MSGDUMP, "EAP-LEAP: Challenge to AP/AS", pos, - LEAP_CHALLENGE_LEN); - wpabuf_put_data(resp, identity, identity_len); - - data->state = LEAP_WAIT_RESPONSE; - - return resp; -} - - -static struct wpabuf * eap_leap_process_response(struct eap_sm *sm, void *priv, - struct eap_method_ret *ret, - const struct wpabuf *reqData) -{ - struct eap_leap_data *data = priv; - const u8 *pos, *password; - u8 response_len, pw_hash[16], pw_hash_hash[16], - expected[LEAP_RESPONSE_LEN]; - size_t password_len, len; - int pwhash; - - wpa_printf(MSG_DEBUG, "EAP-LEAP: Processing EAP-Response"); - - password = eap_get_config_password2(sm, &password_len, &pwhash); - if (password == NULL) - return NULL; - - pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_LEAP, reqData, &len); - if (pos == NULL || len < 3) { - wpa_printf(MSG_INFO, "EAP-LEAP: Invalid EAP-Response frame"); - ret->ignore = TRUE; - return NULL; - } - - if (*pos != LEAP_VERSION) { - wpa_printf(MSG_WARNING, "EAP-LEAP: Unsupported LEAP version " - "%d", *pos); - ret->ignore = TRUE; - return NULL; - } - pos++; - - pos++; /* skip unused byte */ - - response_len = *pos++; - if (response_len != LEAP_RESPONSE_LEN || response_len > len - 3) { - wpa_printf(MSG_INFO, "EAP-LEAP: Invalid response " - "(response_len=%d reqDataLen=%lu)", - response_len, (unsigned long) wpabuf_len(reqData)); - ret->ignore = TRUE; - return NULL; - } - - wpa_hexdump(MSG_DEBUG, "EAP-LEAP: Response from AP", - pos, LEAP_RESPONSE_LEN); - os_memcpy(data->ap_response, pos, LEAP_RESPONSE_LEN); - - if (pwhash) { - if (hash_nt_password_hash(password, pw_hash_hash)) { - ret->ignore = TRUE; - return NULL; - } - } else { - if (nt_password_hash(password, password_len, pw_hash) || - hash_nt_password_hash(pw_hash, pw_hash_hash)) { - ret->ignore = TRUE; - return NULL; - } - } - challenge_response(data->ap_challenge, pw_hash_hash, expected); - - ret->methodState = METHOD_DONE; - ret->allowNotifications = FALSE; - - if (os_memcmp(pos, expected, LEAP_RESPONSE_LEN) != 0) { - wpa_printf(MSG_WARNING, "EAP-LEAP: AP sent an invalid " - "response - authentication failed"); - wpa_hexdump(MSG_DEBUG, "EAP-LEAP: Expected response from AP", - expected, LEAP_RESPONSE_LEN); - ret->decision = DECISION_FAIL; - return NULL; - } - - ret->decision = DECISION_UNCOND_SUCC; - - /* LEAP is somewhat odd method since it sends EAP-Success in the middle - * of the authentication. Use special variable to transit EAP state - * machine to SUCCESS state. */ - sm->leap_done = TRUE; - data->state = LEAP_DONE; - - /* No more authentication messages expected; AP will send EAPOL-Key - * frames if encryption is enabled. */ - return NULL; -} - - -static struct wpabuf * eap_leap_process(struct eap_sm *sm, void *priv, - struct eap_method_ret *ret, - const struct wpabuf *reqData) -{ - const struct eap_hdr *eap; - size_t password_len; - const u8 *password; - - password = eap_get_config_password(sm, &password_len); - if (password == NULL) { - wpa_printf(MSG_INFO, "EAP-LEAP: Password not configured"); - eap_sm_request_password(sm); - ret->ignore = TRUE; - return NULL; - } - - /* - * LEAP needs to be able to handle EAP-Success frame which does not - * include Type field. Consequently, eap_hdr_validate() cannot be used - * here. This validation will be done separately for EAP-Request and - * EAP-Response frames. - */ - eap = wpabuf_head(reqData); - if (wpabuf_len(reqData) < sizeof(*eap) || - be_to_host16(eap->length) > wpabuf_len(reqData)) { - wpa_printf(MSG_INFO, "EAP-LEAP: Invalid frame"); - ret->ignore = TRUE; - return NULL; - } - - ret->ignore = FALSE; - ret->allowNotifications = TRUE; - ret->methodState = METHOD_MAY_CONT; - ret->decision = DECISION_FAIL; - - sm->leap_done = FALSE; - - switch (eap->code) { - case EAP_CODE_REQUEST: - return eap_leap_process_request(sm, priv, ret, reqData); - case EAP_CODE_SUCCESS: - return eap_leap_process_success(sm, priv, ret, reqData); - case EAP_CODE_RESPONSE: - return eap_leap_process_response(sm, priv, ret, reqData); - default: - wpa_printf(MSG_INFO, "EAP-LEAP: Unexpected EAP code (%d) - " - "ignored", eap->code); - ret->ignore = TRUE; - return NULL; - } -} - - -static Boolean eap_leap_isKeyAvailable(struct eap_sm *sm, void *priv) -{ - struct eap_leap_data *data = priv; - return data->state == LEAP_DONE; -} - - -static u8 * eap_leap_getKey(struct eap_sm *sm, void *priv, size_t *len) -{ - struct eap_leap_data *data = priv; - u8 *key, pw_hash_hash[16], pw_hash[16]; - const u8 *addr[5], *password; - size_t elen[5], password_len; - int pwhash; - - if (data->state != LEAP_DONE) - return NULL; - - password = eap_get_config_password2(sm, &password_len, &pwhash); - if (password == NULL) - return NULL; - - key = os_malloc(LEAP_KEY_LEN); - if (key == NULL) - return NULL; - - if (pwhash) { - if (hash_nt_password_hash(password, pw_hash_hash)) { - os_free(key); - return NULL; - } - } else { - if (nt_password_hash(password, password_len, pw_hash) || - hash_nt_password_hash(pw_hash, pw_hash_hash)) { - os_free(key); - return NULL; - } - } - wpa_hexdump_key(MSG_DEBUG, "EAP-LEAP: pw_hash_hash", - pw_hash_hash, 16); - wpa_hexdump(MSG_DEBUG, "EAP-LEAP: peer_challenge", - data->peer_challenge, LEAP_CHALLENGE_LEN); - wpa_hexdump(MSG_DEBUG, "EAP-LEAP: peer_response", - data->peer_response, LEAP_RESPONSE_LEN); - wpa_hexdump(MSG_DEBUG, "EAP-LEAP: ap_challenge", - data->ap_challenge, LEAP_CHALLENGE_LEN); - wpa_hexdump(MSG_DEBUG, "EAP-LEAP: ap_response", - data->ap_response, LEAP_RESPONSE_LEN); - - addr[0] = pw_hash_hash; - elen[0] = 16; - addr[1] = data->ap_challenge; - elen[1] = LEAP_CHALLENGE_LEN; - addr[2] = data->ap_response; - elen[2] = LEAP_RESPONSE_LEN; - addr[3] = data->peer_challenge; - elen[3] = LEAP_CHALLENGE_LEN; - addr[4] = data->peer_response; - elen[4] = LEAP_RESPONSE_LEN; - md5_vector(5, addr, elen, key); - wpa_hexdump_key(MSG_DEBUG, "EAP-LEAP: master key", key, LEAP_KEY_LEN); - *len = LEAP_KEY_LEN; - - return key; -} - - -int eap_peer_leap_register(void) -{ - struct eap_method *eap; - int ret; - - eap = eap_peer_method_alloc(EAP_PEER_METHOD_INTERFACE_VERSION, - EAP_VENDOR_IETF, EAP_TYPE_LEAP, "LEAP"); - if (eap == NULL) - return -1; - - eap->init = eap_leap_init; - eap->deinit = eap_leap_deinit; - eap->process = eap_leap_process; - eap->isKeyAvailable = eap_leap_isKeyAvailable; - eap->getKey = eap_leap_getKey; - - ret = eap_peer_method_register(eap); - if (ret) - eap_peer_method_free(eap); - return ret; -} diff --git a/hostapd-0.8/src/eap_peer/eap_md5.c b/hostapd-0.8/src/eap_peer/eap_md5.c deleted file mode 100644 index 0edbae8..0000000 --- a/hostapd-0.8/src/eap_peer/eap_md5.c +++ /dev/null @@ -1,120 +0,0 @@ -/* - * EAP peer method: EAP-MD5 (RFC 3748 and RFC 1994) - * Copyright (c) 2004-2006, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#include "includes.h" - -#include "common.h" -#include "eap_i.h" -#include "eap_common/chap.h" - - -static void * eap_md5_init(struct eap_sm *sm) -{ - /* No need for private data. However, must return non-NULL to indicate - * success. */ - return (void *) 1; -} - - -static void eap_md5_deinit(struct eap_sm *sm, void *priv) -{ -} - - -static struct wpabuf * eap_md5_process(struct eap_sm *sm, void *priv, - struct eap_method_ret *ret, - const struct wpabuf *reqData) -{ - struct wpabuf *resp; - const u8 *pos, *challenge, *password; - u8 *rpos, id; - size_t len, challenge_len, password_len; - - password = eap_get_config_password(sm, &password_len); - if (password == NULL) { - wpa_printf(MSG_INFO, "EAP-MD5: Password not configured"); - eap_sm_request_password(sm); - ret->ignore = TRUE; - return NULL; - } - - pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_MD5, reqData, &len); - if (pos == NULL || len == 0) { - wpa_printf(MSG_INFO, "EAP-MD5: Invalid frame (pos=%p len=%lu)", - pos, (unsigned long) len); - ret->ignore = TRUE; - return NULL; - } - - /* - * CHAP Challenge: - * Value-Size (1 octet) | Value(Challenge) | Name(optional) - */ - challenge_len = *pos++; - if (challenge_len == 0 || challenge_len > len - 1) { - wpa_printf(MSG_INFO, "EAP-MD5: Invalid challenge " - "(challenge_len=%lu len=%lu)", - (unsigned long) challenge_len, (unsigned long) len); - ret->ignore = TRUE; - return NULL; - } - ret->ignore = FALSE; - challenge = pos; - wpa_hexdump(MSG_MSGDUMP, "EAP-MD5: Challenge", - challenge, challenge_len); - - wpa_printf(MSG_DEBUG, "EAP-MD5: Generating Challenge Response"); - ret->methodState = METHOD_DONE; - ret->decision = DECISION_COND_SUCC; - ret->allowNotifications = TRUE; - - resp = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_MD5, 1 + CHAP_MD5_LEN, - EAP_CODE_RESPONSE, eap_get_id(reqData)); - if (resp == NULL) - return NULL; - - /* - * CHAP Response: - * Value-Size (1 octet) | Value(Response) | Name(optional) - */ - wpabuf_put_u8(resp, CHAP_MD5_LEN); - - id = eap_get_id(resp); - rpos = wpabuf_put(resp, CHAP_MD5_LEN); - chap_md5(id, password, password_len, challenge, challenge_len, rpos); - wpa_hexdump(MSG_MSGDUMP, "EAP-MD5: Response", rpos, CHAP_MD5_LEN); - - return resp; -} - - -int eap_peer_md5_register(void) -{ - struct eap_method *eap; - int ret; - - eap = eap_peer_method_alloc(EAP_PEER_METHOD_INTERFACE_VERSION, - EAP_VENDOR_IETF, EAP_TYPE_MD5, "MD5"); - if (eap == NULL) - return -1; - - eap->init = eap_md5_init; - eap->deinit = eap_md5_deinit; - eap->process = eap_md5_process; - - ret = eap_peer_method_register(eap); - if (ret) - eap_peer_method_free(eap); - return ret; -} diff --git a/hostapd-0.8/src/eap_peer/eap_methods.c b/hostapd-0.8/src/eap_peer/eap_methods.c deleted file mode 100644 index 3b0af05..0000000 --- a/hostapd-0.8/src/eap_peer/eap_methods.c +++ /dev/null @@ -1,373 +0,0 @@ -/* - * EAP peer: Method registration - * Copyright (c) 2004-2007, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#include "includes.h" -#ifdef CONFIG_DYNAMIC_EAP_METHODS -#include -#endif /* CONFIG_DYNAMIC_EAP_METHODS */ - -#include "common.h" -#include "eap_i.h" -#include "eap_methods.h" - - -static struct eap_method *eap_methods = NULL; - - -/** - * eap_peer_get_eap_method - Get EAP method based on type number - * @vendor: EAP Vendor-Id (0 = IETF) - * @method: EAP type number - * Returns: Pointer to EAP method or %NULL if not found - */ -const struct eap_method * eap_peer_get_eap_method(int vendor, EapType method) -{ - struct eap_method *m; - for (m = eap_methods; m; m = m->next) { - if (m->vendor == vendor && m->method == method) - return m; - } - return NULL; -} - - -/** - * eap_peer_get_type - Get EAP type for the given EAP method name - * @name: EAP method name, e.g., TLS - * @vendor: Buffer for returning EAP Vendor-Id - * Returns: EAP method type or %EAP_TYPE_NONE if not found - * - * This function maps EAP type names into EAP type numbers based on the list of - * EAP methods included in the build. - */ -EapType eap_peer_get_type(const char *name, int *vendor) -{ - struct eap_method *m; - for (m = eap_methods; m; m = m->next) { - if (os_strcmp(m->name, name) == 0) { - *vendor = m->vendor; - return m->method; - } - } - *vendor = EAP_VENDOR_IETF; - return EAP_TYPE_NONE; -} - - -/** - * eap_get_name - Get EAP method name for the given EAP type - * @vendor: EAP Vendor-Id (0 = IETF) - * @type: EAP method type - * Returns: EAP method name, e.g., TLS, or %NULL if not found - * - * This function maps EAP type numbers into EAP type names based on the list of - * EAP methods included in the build. - */ -const char * eap_get_name(int vendor, EapType type) -{ - struct eap_method *m; - for (m = eap_methods; m; m = m->next) { - if (m->vendor == vendor && m->method == type) - return m->name; - } - return NULL; -} - - -/** - * eap_get_names - Get space separated list of names for supported EAP methods - * @buf: Buffer for names - * @buflen: Buffer length - * Returns: Number of characters written into buf (not including nul - * termination) - */ -size_t eap_get_names(char *buf, size_t buflen) -{ - char *pos, *end; - struct eap_method *m; - int ret; - - if (buflen == 0) - return 0; - - pos = buf; - end = pos + buflen; - - for (m = eap_methods; m; m = m->next) { - ret = os_snprintf(pos, end - pos, "%s%s", - m == eap_methods ? "" : " ", m->name); - if (ret < 0 || ret >= end - pos) - break; - pos += ret; - } - buf[buflen - 1] = '\0'; - - return pos - buf; -} - - -/** - * eap_get_names_as_string_array - Get supported EAP methods as string array - * @num: Buffer for returning the number of items in array, not including %NULL - * terminator. This parameter can be %NULL if the length is not needed. - * Returns: A %NULL-terminated array of strings, or %NULL on error. - * - * This function returns the list of names for all supported EAP methods as an - * array of strings. The caller must free the returned array items and the - * array. - */ -char ** eap_get_names_as_string_array(size_t *num) -{ - struct eap_method *m; - size_t array_len = 0; - char **array; - int i = 0, j; - - for (m = eap_methods; m; m = m->next) - array_len++; - - array = os_zalloc(sizeof(char *) * (array_len + 1)); - if (array == NULL) - return NULL; - - for (m = eap_methods; m; m = m->next) { - array[i++] = os_strdup(m->name); - if (array[i - 1] == NULL) { - for (j = 0; j < i; j++) - os_free(array[j]); - os_free(array); - return NULL; - } - } - array[i] = NULL; - - if (num) - *num = array_len; - - return array; -} - - -/** - * eap_peer_get_methods - Get a list of enabled EAP peer methods - * @count: Set to number of available methods - * Returns: List of enabled EAP peer methods - */ -const struct eap_method * eap_peer_get_methods(size_t *count) -{ - int c = 0; - struct eap_method *m; - - for (m = eap_methods; m; m = m->next) - c++; - - *count = c; - return eap_methods; -} - - -#ifdef CONFIG_DYNAMIC_EAP_METHODS -/** - * eap_peer_method_load - Load a dynamic EAP method library (shared object) - * @so: File path for the shared object file to load - * Returns: 0 on success, -1 on failure - */ -int eap_peer_method_load(const char *so) -{ - void *handle; - int (*dyn_init)(void); - int ret; - - handle = dlopen(so, RTLD_LAZY); - if (handle == NULL) { - wpa_printf(MSG_ERROR, "EAP: Failed to open dynamic EAP method " - "'%s': %s", so, dlerror()); - return -1; - } - - dyn_init = dlsym(handle, "eap_peer_method_dynamic_init"); - if (dyn_init == NULL) { - dlclose(handle); - wpa_printf(MSG_ERROR, "EAP: Invalid EAP method '%s' - no " - "eap_peer_method_dynamic_init()", so); - return -1; - } - - ret = dyn_init(); - if (ret) { - dlclose(handle); - wpa_printf(MSG_ERROR, "EAP: Failed to add EAP method '%s' - " - "ret %d", so, ret); - return ret; - } - - /* Store the handle for this shared object. It will be freed with - * dlclose() when the EAP method is unregistered. */ - eap_methods->dl_handle = handle; - - wpa_printf(MSG_DEBUG, "EAP: Loaded dynamic EAP method: '%s'", so); - - return 0; -} - - -/** - * eap_peer_method_unload - Unload a dynamic EAP method library (shared object) - * @method: Pointer to the dynamically loaded EAP method - * Returns: 0 on success, -1 on failure - * - * This function can be used to unload EAP methods that have been previously - * loaded with eap_peer_method_load(). Before unloading the method, all - * references to the method must be removed to make sure that no dereferences - * of freed memory will occur after unloading. - */ -int eap_peer_method_unload(struct eap_method *method) -{ - struct eap_method *m, *prev; - void *handle; - - m = eap_methods; - prev = NULL; - while (m) { - if (m == method) - break; - prev = m; - m = m->next; - } - - if (m == NULL || m->dl_handle == NULL) - return -1; - - if (prev) - prev->next = m->next; - else - eap_methods = m->next; - - handle = m->dl_handle; - - if (m->free) - m->free(m); - else - eap_peer_method_free(m); - - dlclose(handle); - - return 0; -} -#endif /* CONFIG_DYNAMIC_EAP_METHODS */ - - -/** - * eap_peer_method_alloc - Allocate EAP peer method structure - * @version: Version of the EAP peer method interface (set to - * EAP_PEER_METHOD_INTERFACE_VERSION) - * @vendor: EAP Vendor-ID (EAP_VENDOR_*) (0 = IETF) - * @method: EAP type number (EAP_TYPE_*) - * @name: Name of the method (e.g., "TLS") - * Returns: Allocated EAP method structure or %NULL on failure - * - * The returned structure should be freed with eap_peer_method_free() when it - * is not needed anymore. - */ -struct eap_method * eap_peer_method_alloc(int version, int vendor, - EapType method, const char *name) -{ - struct eap_method *eap; - eap = os_zalloc(sizeof(*eap)); - if (eap == NULL) - return NULL; - eap->version = version; - eap->vendor = vendor; - eap->method = method; - eap->name = name; - return eap; -} - - -/** - * eap_peer_method_free - Free EAP peer method structure - * @method: Method structure allocated with eap_peer_method_alloc() - */ -void eap_peer_method_free(struct eap_method *method) -{ - os_free(method); -} - - -/** - * eap_peer_method_register - Register an EAP peer method - * @method: EAP method to register - * Returns: 0 on success, -1 on invalid method, or -2 if a matching EAP method - * has already been registered - * - * Each EAP peer method needs to call this function to register itself as a - * supported EAP method. - */ -int eap_peer_method_register(struct eap_method *method) -{ - struct eap_method *m, *last = NULL; - - if (method == NULL || method->name == NULL || - method->version != EAP_PEER_METHOD_INTERFACE_VERSION) - return -1; - - for (m = eap_methods; m; m = m->next) { - if ((m->vendor == method->vendor && - m->method == method->method) || - os_strcmp(m->name, method->name) == 0) - return -2; - last = m; - } - - if (last) - last->next = method; - else - eap_methods = method; - - return 0; -} - - -/** - * eap_peer_unregister_methods - Unregister EAP peer methods - * - * This function is called at program termination to unregister all EAP peer - * methods. - */ -void eap_peer_unregister_methods(void) -{ - struct eap_method *m; -#ifdef CONFIG_DYNAMIC_EAP_METHODS - void *handle; -#endif /* CONFIG_DYNAMIC_EAP_METHODS */ - - while (eap_methods) { - m = eap_methods; - eap_methods = eap_methods->next; - -#ifdef CONFIG_DYNAMIC_EAP_METHODS - handle = m->dl_handle; -#endif /* CONFIG_DYNAMIC_EAP_METHODS */ - - if (m->free) - m->free(m); - else - eap_peer_method_free(m); - -#ifdef CONFIG_DYNAMIC_EAP_METHODS - if (handle) - dlclose(handle); -#endif /* CONFIG_DYNAMIC_EAP_METHODS */ - } -} diff --git a/hostapd-0.8/src/eap_peer/eap_methods.h b/hostapd-0.8/src/eap_peer/eap_methods.h deleted file mode 100644 index 4330b57..0000000 --- a/hostapd-0.8/src/eap_peer/eap_methods.h +++ /dev/null @@ -1,114 +0,0 @@ -/* - * EAP peer: Method registration - * Copyright (c) 2004-2007, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#ifndef EAP_METHODS_H -#define EAP_METHODS_H - -#include "eap_common/eap_defs.h" - -const struct eap_method * eap_peer_get_eap_method(int vendor, EapType method); -const struct eap_method * eap_peer_get_methods(size_t *count); - -struct eap_method * eap_peer_method_alloc(int version, int vendor, - EapType method, const char *name); -void eap_peer_method_free(struct eap_method *method); -int eap_peer_method_register(struct eap_method *method); - - -#ifdef IEEE8021X_EAPOL - -EapType eap_peer_get_type(const char *name, int *vendor); -const char * eap_get_name(int vendor, EapType type); -size_t eap_get_names(char *buf, size_t buflen); -char ** eap_get_names_as_string_array(size_t *num); -void eap_peer_unregister_methods(void); - -#else /* IEEE8021X_EAPOL */ - -static inline EapType eap_peer_get_type(const char *name, int *vendor) -{ - *vendor = EAP_VENDOR_IETF; - return EAP_TYPE_NONE; -} - -static inline const char * eap_get_name(int vendor, EapType type) -{ - return NULL; -} - -static inline size_t eap_get_names(char *buf, size_t buflen) -{ - return 0; -} - -static inline int eap_peer_register_methods(void) -{ - return 0; -} - -static inline void eap_peer_unregister_methods(void) -{ -} - -static inline char ** eap_get_names_as_string_array(size_t *num) -{ - return NULL; -} - -#endif /* IEEE8021X_EAPOL */ - - -#ifdef CONFIG_DYNAMIC_EAP_METHODS - -int eap_peer_method_load(const char *so); -int eap_peer_method_unload(struct eap_method *method); - -#else /* CONFIG_DYNAMIC_EAP_METHODS */ - -static inline int eap_peer_method_load(const char *so) -{ - return 0; -} - -static inline int eap_peer_method_unload(struct eap_method *method) -{ - return 0; -} - -#endif /* CONFIG_DYNAMIC_EAP_METHODS */ - -/* EAP peer method registration calls for statically linked in methods */ -int eap_peer_md5_register(void); -int eap_peer_tls_register(void); -int eap_peer_mschapv2_register(void); -int eap_peer_peap_register(void); -int eap_peer_ttls_register(void); -int eap_peer_gtc_register(void); -int eap_peer_otp_register(void); -int eap_peer_sim_register(void); -int eap_peer_leap_register(void); -int eap_peer_psk_register(void); -int eap_peer_aka_register(void); -int eap_peer_aka_prime_register(void); -int eap_peer_fast_register(void); -int eap_peer_pax_register(void); -int eap_peer_sake_register(void); -int eap_peer_gpsk_register(void); -int eap_peer_wsc_register(void); -int eap_peer_ikev2_register(void); -int eap_peer_vendor_test_register(void); -int eap_peer_tnc_register(void); -int eap_peer_pwd_register(void); - -#endif /* EAP_METHODS_H */ diff --git a/hostapd-0.8/src/eap_peer/eap_mschapv2.c b/hostapd-0.8/src/eap_peer/eap_mschapv2.c deleted file mode 100644 index 321e9f7..0000000 --- a/hostapd-0.8/src/eap_peer/eap_mschapv2.c +++ /dev/null @@ -1,883 +0,0 @@ -/* - * EAP peer method: EAP-MSCHAPV2 (draft-kamath-pppext-eap-mschapv2-00.txt) - * Copyright (c) 2004-2008, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - * - * This file implements EAP peer part of EAP-MSCHAPV2 method (EAP type 26). - * draft-kamath-pppext-eap-mschapv2-00.txt defines the Microsoft EAP CHAP - * Extensions Protocol, Version 2, for mutual authentication and key - * derivation. This encapsulates MS-CHAP-v2 protocol which is defined in - * RFC 2759. Use of EAP-MSCHAPV2 derived keys with MPPE cipher is described in - * RFC 3079. - */ - -#include "includes.h" - -#include "common.h" -#include "crypto/ms_funcs.h" -#include "crypto/random.h" -#include "common/wpa_ctrl.h" -#include "mschapv2.h" -#include "eap_i.h" -#include "eap_config.h" - - -#ifdef _MSC_VER -#pragma pack(push, 1) -#endif /* _MSC_VER */ - -struct eap_mschapv2_hdr { - u8 op_code; /* MSCHAPV2_OP_* */ - u8 mschapv2_id; /* usually same as EAP identifier; must be changed - * for challenges, but not for success/failure */ - u8 ms_length[2]; /* Note: misaligned; length - 5 */ - /* followed by data */ -} STRUCT_PACKED; - -/* Response Data field */ -struct ms_response { - u8 peer_challenge[MSCHAPV2_CHAL_LEN]; - u8 reserved[8]; - u8 nt_response[MSCHAPV2_NT_RESPONSE_LEN]; - u8 flags; -} STRUCT_PACKED; - -/* Change-Password Data field */ -struct ms_change_password { - u8 encr_password[516]; - u8 encr_hash[16]; - u8 peer_challenge[MSCHAPV2_CHAL_LEN]; - u8 reserved[8]; - u8 nt_response[MSCHAPV2_NT_RESPONSE_LEN]; - u8 flags[2]; -} STRUCT_PACKED; - -#ifdef _MSC_VER -#pragma pack(pop) -#endif /* _MSC_VER */ - -#define MSCHAPV2_OP_CHALLENGE 1 -#define MSCHAPV2_OP_RESPONSE 2 -#define MSCHAPV2_OP_SUCCESS 3 -#define MSCHAPV2_OP_FAILURE 4 -#define MSCHAPV2_OP_CHANGE_PASSWORD 7 - -#define ERROR_RESTRICTED_LOGON_HOURS 646 -#define ERROR_ACCT_DISABLED 647 -#define ERROR_PASSWD_EXPIRED 648 -#define ERROR_NO_DIALIN_PERMISSION 649 -#define ERROR_AUTHENTICATION_FAILURE 691 -#define ERROR_CHANGING_PASSWORD 709 - -#define PASSWD_CHANGE_CHAL_LEN 16 -#define MSCHAPV2_KEY_LEN 16 - - -struct eap_mschapv2_data { - u8 auth_response[MSCHAPV2_AUTH_RESPONSE_LEN]; - int auth_response_valid; - - int prev_error; - u8 passwd_change_challenge[PASSWD_CHANGE_CHAL_LEN]; - int passwd_change_challenge_valid; - int passwd_change_version; - - /* Optional challenge values generated in EAP-FAST Phase 1 negotiation - */ - u8 *peer_challenge; - u8 *auth_challenge; - - int phase2; - u8 master_key[MSCHAPV2_MASTER_KEY_LEN]; - int master_key_valid; - int success; - - struct wpabuf *prev_challenge; -}; - - -static void eap_mschapv2_deinit(struct eap_sm *sm, void *priv); - - -static void * eap_mschapv2_init(struct eap_sm *sm) -{ - struct eap_mschapv2_data *data; - data = os_zalloc(sizeof(*data)); - if (data == NULL) - return NULL; - - if (sm->peer_challenge) { - data->peer_challenge = os_malloc(MSCHAPV2_CHAL_LEN); - if (data->peer_challenge == NULL) { - eap_mschapv2_deinit(sm, data); - return NULL; - } - os_memcpy(data->peer_challenge, sm->peer_challenge, - MSCHAPV2_CHAL_LEN); - } - - if (sm->auth_challenge) { - data->auth_challenge = os_malloc(MSCHAPV2_CHAL_LEN); - if (data->auth_challenge == NULL) { - eap_mschapv2_deinit(sm, data); - return NULL; - } - os_memcpy(data->auth_challenge, sm->auth_challenge, - MSCHAPV2_CHAL_LEN); - } - - data->phase2 = sm->init_phase2; - - return data; -} - - -static void eap_mschapv2_deinit(struct eap_sm *sm, void *priv) -{ - struct eap_mschapv2_data *data = priv; - os_free(data->peer_challenge); - os_free(data->auth_challenge); - wpabuf_free(data->prev_challenge); - os_free(data); -} - - -static struct wpabuf * eap_mschapv2_challenge_reply( - struct eap_sm *sm, struct eap_mschapv2_data *data, u8 id, - u8 mschapv2_id, const u8 *auth_challenge) -{ - struct wpabuf *resp; - struct eap_mschapv2_hdr *ms; - u8 *peer_challenge; - int ms_len; - struct ms_response *r; - size_t identity_len, password_len; - const u8 *identity, *password; - int pwhash; - - wpa_printf(MSG_DEBUG, "EAP-MSCHAPV2: Generating Challenge Response"); - - identity = eap_get_config_identity(sm, &identity_len); - password = eap_get_config_password2(sm, &password_len, &pwhash); - if (identity == NULL || password == NULL) - return NULL; - - ms_len = sizeof(*ms) + 1 + sizeof(*r) + identity_len; - resp = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_MSCHAPV2, ms_len, - EAP_CODE_RESPONSE, id); - if (resp == NULL) - return NULL; - - ms = wpabuf_put(resp, sizeof(*ms)); - ms->op_code = MSCHAPV2_OP_RESPONSE; - ms->mschapv2_id = mschapv2_id; - if (data->prev_error) { - /* - * TODO: this does not seem to be enough when processing two - * or more failure messages. IAS did not increment mschapv2_id - * in its own packets, but it seemed to expect the peer to - * increment this for all packets(?). - */ - ms->mschapv2_id++; - } - WPA_PUT_BE16(ms->ms_length, ms_len); - - wpabuf_put_u8(resp, sizeof(*r)); /* Value-Size */ - - /* Response */ - r = wpabuf_put(resp, sizeof(*r)); - peer_challenge = r->peer_challenge; - if (data->peer_challenge) { - wpa_printf(MSG_DEBUG, "EAP-MSCHAPV2: peer_challenge generated " - "in Phase 1"); - peer_challenge = data->peer_challenge; - os_memset(r->peer_challenge, 0, MSCHAPV2_CHAL_LEN); - } else if (random_get_bytes(peer_challenge, MSCHAPV2_CHAL_LEN)) { - wpabuf_free(resp); - return NULL; - } - os_memset(r->reserved, 0, 8); - if (data->auth_challenge) { - wpa_printf(MSG_DEBUG, "EAP-MSCHAPV2: auth_challenge generated " - "in Phase 1"); - auth_challenge = data->auth_challenge; - } - if (mschapv2_derive_response(identity, identity_len, password, - password_len, pwhash, auth_challenge, - peer_challenge, r->nt_response, - data->auth_response, data->master_key)) { - wpa_printf(MSG_ERROR, "EAP-MSCHAPV2: Failed to derive " - "response"); - wpabuf_free(resp); - return NULL; - } - data->auth_response_valid = 1; - data->master_key_valid = 1; - - r->flags = 0; /* reserved, must be zero */ - - wpabuf_put_data(resp, identity, identity_len); - wpa_printf(MSG_DEBUG, "EAP-MSCHAPV2: TX identifier %d mschapv2_id %d " - "(response)", id, ms->mschapv2_id); - return resp; -} - - -/** - * eap_mschapv2_process - Process an EAP-MSCHAPv2 challenge message - * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init() - * @data: Pointer to private EAP method data from eap_mschapv2_init() - * @ret: Return values from EAP request validation and processing - * @req: Pointer to EAP-MSCHAPv2 header from the request - * @req_len: Length of the EAP-MSCHAPv2 data - * @id: EAP identifier used in the request - * Returns: Pointer to allocated EAP response packet (eapRespData) or %NULL if - * no reply available - */ -static struct wpabuf * eap_mschapv2_challenge( - struct eap_sm *sm, struct eap_mschapv2_data *data, - struct eap_method_ret *ret, const struct eap_mschapv2_hdr *req, - size_t req_len, u8 id) -{ - size_t len, challenge_len; - const u8 *pos, *challenge; - - if (eap_get_config_identity(sm, &len) == NULL || - eap_get_config_password(sm, &len) == NULL) - return NULL; - - wpa_printf(MSG_DEBUG, "EAP-MSCHAPV2: Received challenge"); - if (req_len < sizeof(*req) + 1) { - wpa_printf(MSG_INFO, "EAP-MSCHAPV2: Too short challenge data " - "(len %lu)", (unsigned long) req_len); - ret->ignore = TRUE; - return NULL; - } - pos = (const u8 *) (req + 1); - challenge_len = *pos++; - len = req_len - sizeof(*req) - 1; - if (challenge_len != MSCHAPV2_CHAL_LEN) { - wpa_printf(MSG_INFO, "EAP-MSCHAPV2: Invalid challenge length " - "%lu", (unsigned long) challenge_len); - ret->ignore = TRUE; - return NULL; - } - - if (len < challenge_len) { - wpa_printf(MSG_INFO, "EAP-MSCHAPV2: Too short challenge" - " packet: len=%lu challenge_len=%lu", - (unsigned long) len, (unsigned long) challenge_len); - ret->ignore = TRUE; - return NULL; - } - - if (data->passwd_change_challenge_valid) { - wpa_printf(MSG_DEBUG, "EAP-MSCHAPV2: Using challenge from the " - "failure message"); - challenge = data->passwd_change_challenge; - } else - challenge = pos; - pos += challenge_len; - len -= challenge_len; - wpa_hexdump_ascii(MSG_DEBUG, "EAP-MSCHAPV2: Authentication Servername", - pos, len); - - ret->ignore = FALSE; - ret->methodState = METHOD_MAY_CONT; - ret->decision = DECISION_FAIL; - ret->allowNotifications = TRUE; - - return eap_mschapv2_challenge_reply(sm, data, id, req->mschapv2_id, - challenge); -} - - -static void eap_mschapv2_password_changed(struct eap_sm *sm, - struct eap_mschapv2_data *data) -{ - struct eap_peer_config *config = eap_get_config(sm); - if (config && config->new_password) { - wpa_msg(sm->msg_ctx, MSG_INFO, - WPA_EVENT_PASSWORD_CHANGED - "EAP-MSCHAPV2: Password changed successfully"); - data->prev_error = 0; - os_free(config->password); - if (config->flags & EAP_CONFIG_FLAGS_PASSWORD_NTHASH) { - config->password = os_malloc(16); - config->password_len = 16; - if (config->password) { - nt_password_hash(config->new_password, - config->new_password_len, - config->password); - } - os_free(config->new_password); - } else { - config->password = config->new_password; - config->password_len = config->new_password_len; - } - config->new_password = NULL; - config->new_password_len = 0; - } -} - - -/** - * eap_mschapv2_process - Process an EAP-MSCHAPv2 success message - * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init() - * @data: Pointer to private EAP method data from eap_mschapv2_init() - * @ret: Return values from EAP request validation and processing - * @req: Pointer to EAP-MSCHAPv2 header from the request - * @req_len: Length of the EAP-MSCHAPv2 data - * @id: EAP identifier used in th erequest - * Returns: Pointer to allocated EAP response packet (eapRespData) or %NULL if - * no reply available - */ -static struct wpabuf * eap_mschapv2_success(struct eap_sm *sm, - struct eap_mschapv2_data *data, - struct eap_method_ret *ret, - const struct eap_mschapv2_hdr *req, - size_t req_len, u8 id) -{ - struct wpabuf *resp; - const u8 *pos; - size_t len; - - wpa_printf(MSG_DEBUG, "EAP-MSCHAPV2: Received success"); - len = req_len - sizeof(*req); - pos = (const u8 *) (req + 1); - if (!data->auth_response_valid || - mschapv2_verify_auth_response(data->auth_response, pos, len)) { - wpa_printf(MSG_WARNING, "EAP-MSCHAPV2: Invalid authenticator " - "response in success request"); - ret->methodState = METHOD_DONE; - ret->decision = DECISION_FAIL; - return NULL; - } - pos += 2 + 2 * MSCHAPV2_AUTH_RESPONSE_LEN; - len -= 2 + 2 * MSCHAPV2_AUTH_RESPONSE_LEN; - while (len > 0 && *pos == ' ') { - pos++; - len--; - } - wpa_hexdump_ascii(MSG_DEBUG, "EAP-MSCHAPV2: Success message", - pos, len); - wpa_printf(MSG_INFO, "EAP-MSCHAPV2: Authentication succeeded"); - - /* Note: Only op_code of the EAP-MSCHAPV2 header is included in success - * message. */ - resp = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_MSCHAPV2, 1, - EAP_CODE_RESPONSE, id); - if (resp == NULL) { - wpa_printf(MSG_DEBUG, "EAP-MSCHAPV2: Failed to allocate " - "buffer for success response"); - ret->ignore = TRUE; - return NULL; - } - - wpabuf_put_u8(resp, MSCHAPV2_OP_SUCCESS); /* op_code */ - - ret->methodState = METHOD_DONE; - ret->decision = DECISION_UNCOND_SUCC; - ret->allowNotifications = FALSE; - data->success = 1; - - if (data->prev_error == ERROR_PASSWD_EXPIRED) - eap_mschapv2_password_changed(sm, data); - - return resp; -} - - -static int eap_mschapv2_failure_txt(struct eap_sm *sm, - struct eap_mschapv2_data *data, char *txt) -{ - char *pos, *msg = ""; - int retry = 1; - struct eap_peer_config *config = eap_get_config(sm); - - /* For example: - * E=691 R=1 C=<32 octets hex challenge> V=3 M=Authentication Failure - */ - - pos = txt; - - if (pos && os_strncmp(pos, "E=", 2) == 0) { - pos += 2; - data->prev_error = atoi(pos); - wpa_printf(MSG_DEBUG, "EAP-MSCHAPV2: error %d", - data->prev_error); - pos = os_strchr(pos, ' '); - if (pos) - pos++; - } - - if (pos && os_strncmp(pos, "R=", 2) == 0) { - pos += 2; - retry = atoi(pos); - wpa_printf(MSG_DEBUG, "EAP-MSCHAPV2: retry is %sallowed", - retry == 1 ? "" : "not "); - pos = os_strchr(pos, ' '); - if (pos) - pos++; - } - - if (pos && os_strncmp(pos, "C=", 2) == 0) { - int hex_len; - pos += 2; - hex_len = os_strchr(pos, ' ') - (char *) pos; - if (hex_len == PASSWD_CHANGE_CHAL_LEN * 2) { - if (hexstr2bin(pos, data->passwd_change_challenge, - PASSWD_CHANGE_CHAL_LEN)) { - wpa_printf(MSG_DEBUG, "EAP-MSCHAPV2: invalid " - "failure challenge"); - } else { - wpa_hexdump(MSG_DEBUG, "EAP-MSCHAPV2: failure " - "challenge", - data->passwd_change_challenge, - PASSWD_CHANGE_CHAL_LEN); - data->passwd_change_challenge_valid = 1; - } - } else { - wpa_printf(MSG_DEBUG, "EAP-MSCHAPV2: invalid failure " - "challenge len %d", hex_len); - } - pos = os_strchr(pos, ' '); - if (pos) - pos++; - } else { - wpa_printf(MSG_DEBUG, "EAP-MSCHAPV2: required challenge field " - "was not present in failure message"); - } - - if (pos && os_strncmp(pos, "V=", 2) == 0) { - pos += 2; - data->passwd_change_version = atoi(pos); - wpa_printf(MSG_DEBUG, "EAP-MSCHAPV2: password changing " - "protocol version %d", data->passwd_change_version); - pos = os_strchr(pos, ' '); - if (pos) - pos++; - } - - if (pos && os_strncmp(pos, "M=", 2) == 0) { - pos += 2; - msg = pos; - } - wpa_msg(sm->msg_ctx, MSG_WARNING, - "EAP-MSCHAPV2: failure message: '%s' (retry %sallowed, error " - "%d)", - msg, retry == 1 ? "" : "not ", data->prev_error); - if (data->prev_error == ERROR_PASSWD_EXPIRED && - data->passwd_change_version == 3 && config) { - if (config->new_password == NULL) { - wpa_msg(sm->msg_ctx, MSG_INFO, - "EAP-MSCHAPV2: Password expired - password " - "change required"); - eap_sm_request_new_password(sm); - } - } else if (retry == 1 && config) { - /* TODO: could prevent the current password from being used - * again at least for some period of time */ - if (!config->mschapv2_retry) - eap_sm_request_identity(sm); - eap_sm_request_password(sm); - config->mschapv2_retry = 1; - } else if (config) { - /* TODO: prevent retries using same username/password */ - config->mschapv2_retry = 0; - } - - return retry == 1; -} - - -static struct wpabuf * eap_mschapv2_change_password( - struct eap_sm *sm, struct eap_mschapv2_data *data, - struct eap_method_ret *ret, const struct eap_mschapv2_hdr *req, u8 id) -{ - struct wpabuf *resp; - int ms_len; - const u8 *username, *password, *new_password; - size_t username_len, password_len, new_password_len; - struct eap_mschapv2_hdr *ms; - struct ms_change_password *cp; - u8 password_hash[16], password_hash_hash[16]; - int pwhash; - - username = eap_get_config_identity(sm, &username_len); - password = eap_get_config_password2(sm, &password_len, &pwhash); - new_password = eap_get_config_new_password(sm, &new_password_len); - if (username == NULL || password == NULL || new_password == NULL) - return NULL; - - username = mschapv2_remove_domain(username, &username_len); - - ret->ignore = FALSE; - ret->methodState = METHOD_MAY_CONT; - ret->decision = DECISION_COND_SUCC; - ret->allowNotifications = TRUE; - - ms_len = sizeof(*ms) + sizeof(*cp); - resp = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_MSCHAPV2, ms_len, - EAP_CODE_RESPONSE, id); - if (resp == NULL) - return NULL; - - ms = wpabuf_put(resp, sizeof(*ms)); - ms->op_code = MSCHAPV2_OP_CHANGE_PASSWORD; - ms->mschapv2_id = req->mschapv2_id + 1; - WPA_PUT_BE16(ms->ms_length, ms_len); - cp = wpabuf_put(resp, sizeof(*cp)); - - /* Encrypted-Password */ - if (pwhash) { - if (encrypt_pw_block_with_password_hash( - new_password, new_password_len, - password, cp->encr_password)) - goto fail; - } else { - if (new_password_encrypted_with_old_nt_password_hash( - new_password, new_password_len, - password, password_len, cp->encr_password)) - goto fail; - } - - /* Encrypted-Hash */ - if (pwhash) { - u8 new_password_hash[16]; - nt_password_hash(new_password, new_password_len, - new_password_hash); - nt_password_hash_encrypted_with_block(password, - new_password_hash, - cp->encr_hash); - } else { - old_nt_password_hash_encrypted_with_new_nt_password_hash( - new_password, new_password_len, - password, password_len, cp->encr_hash); - } - - /* Peer-Challenge */ - if (random_get_bytes(cp->peer_challenge, MSCHAPV2_CHAL_LEN)) - goto fail; - - /* Reserved, must be zero */ - os_memset(cp->reserved, 0, 8); - - /* NT-Response */ - wpa_hexdump(MSG_DEBUG, "EAP-MSCHAPV2: auth_challenge", - data->passwd_change_challenge, PASSWD_CHANGE_CHAL_LEN); - wpa_hexdump(MSG_DEBUG, "EAP-MSCHAPV2: peer_challenge", - cp->peer_challenge, MSCHAPV2_CHAL_LEN); - wpa_hexdump_ascii(MSG_DEBUG, "EAP-MSCHAPV2: username", - username, username_len); - wpa_hexdump_ascii_key(MSG_DEBUG, "EAP-MSCHAPV2: new password", - new_password, new_password_len); - generate_nt_response(data->passwd_change_challenge, cp->peer_challenge, - username, username_len, - new_password, new_password_len, - cp->nt_response); - wpa_hexdump(MSG_DEBUG, "EAP-MSCHAPV2: NT-Response", - cp->nt_response, MSCHAPV2_NT_RESPONSE_LEN); - - /* Authenticator response is not really needed yet, but calculate it - * here so that challenges need not be saved. */ - generate_authenticator_response(new_password, new_password_len, - cp->peer_challenge, - data->passwd_change_challenge, - username, username_len, - cp->nt_response, data->auth_response); - data->auth_response_valid = 1; - - /* Likewise, generate master_key here since we have the needed data - * available. */ - nt_password_hash(new_password, new_password_len, password_hash); - hash_nt_password_hash(password_hash, password_hash_hash); - get_master_key(password_hash_hash, cp->nt_response, data->master_key); - data->master_key_valid = 1; - - /* Flags */ - os_memset(cp->flags, 0, 2); - - wpa_printf(MSG_DEBUG, "EAP-MSCHAPV2: TX identifier %d mschapv2_id %d " - "(change pw)", id, ms->mschapv2_id); - - return resp; - -fail: - wpabuf_free(resp); - return NULL; -} - - -/** - * eap_mschapv2_process - Process an EAP-MSCHAPv2 failure message - * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init() - * @data: Pointer to private EAP method data from eap_mschapv2_init() - * @ret: Return values from EAP request validation and processing - * @req: Pointer to EAP-MSCHAPv2 header from the request - * @req_len: Length of the EAP-MSCHAPv2 data - * @id: EAP identifier used in th erequest - * Returns: Pointer to allocated EAP response packet (eapRespData) or %NULL if - * no reply available - */ -static struct wpabuf * eap_mschapv2_failure(struct eap_sm *sm, - struct eap_mschapv2_data *data, - struct eap_method_ret *ret, - const struct eap_mschapv2_hdr *req, - size_t req_len, u8 id) -{ - struct wpabuf *resp; - const u8 *msdata = (const u8 *) (req + 1); - char *buf; - size_t len = req_len - sizeof(*req); - int retry = 0; - - wpa_printf(MSG_DEBUG, "EAP-MSCHAPV2: Received failure"); - wpa_hexdump_ascii(MSG_DEBUG, "EAP-MSCHAPV2: Failure data", - msdata, len); - /* - * eap_mschapv2_failure_txt() expects a nul terminated string, so we - * must allocate a large enough temporary buffer to create that since - * the received message does not include nul termination. - */ - buf = os_malloc(len + 1); - if (buf) { - os_memcpy(buf, msdata, len); - buf[len] = '\0'; - retry = eap_mschapv2_failure_txt(sm, data, buf); - os_free(buf); - } - - ret->ignore = FALSE; - ret->methodState = METHOD_DONE; - ret->decision = DECISION_FAIL; - ret->allowNotifications = FALSE; - - if (data->prev_error == ERROR_PASSWD_EXPIRED && - data->passwd_change_version == 3) { - struct eap_peer_config *config = eap_get_config(sm); - if (config && config->new_password) - return eap_mschapv2_change_password(sm, data, ret, req, - id); - if (config && config->pending_req_new_password) - return NULL; - } else if (retry && data->prev_error == ERROR_AUTHENTICATION_FAILURE) { - /* TODO: could try to retry authentication, e.g, after having - * changed the username/password. In this case, EAP MS-CHAP-v2 - * Failure Response would not be sent here. */ - return NULL; - } - - /* Note: Only op_code of the EAP-MSCHAPV2 header is included in failure - * message. */ - resp = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_MSCHAPV2, 1, - EAP_CODE_RESPONSE, id); - if (resp == NULL) - return NULL; - - wpabuf_put_u8(resp, MSCHAPV2_OP_FAILURE); /* op_code */ - - return resp; -} - - -static int eap_mschapv2_check_config(struct eap_sm *sm) -{ - size_t len; - - if (eap_get_config_identity(sm, &len) == NULL) { - wpa_printf(MSG_INFO, "EAP-MSCHAPV2: Identity not configured"); - eap_sm_request_identity(sm); - return -1; - } - - if (eap_get_config_password(sm, &len) == NULL) { - wpa_printf(MSG_INFO, "EAP-MSCHAPV2: Password not configured"); - eap_sm_request_password(sm); - return -1; - } - - return 0; -} - - -static int eap_mschapv2_check_mslen(struct eap_sm *sm, size_t len, - const struct eap_mschapv2_hdr *ms) -{ - size_t ms_len = WPA_GET_BE16(ms->ms_length); - - if (ms_len == len) - return 0; - - wpa_printf(MSG_INFO, "EAP-MSCHAPV2: Invalid header: len=%lu " - "ms_len=%lu", (unsigned long) len, (unsigned long) ms_len); - if (sm->workaround) { - /* Some authentication servers use invalid ms_len, - * ignore it for interoperability. */ - wpa_printf(MSG_INFO, "EAP-MSCHAPV2: workaround, ignore" - " invalid ms_len %lu (len %lu)", - (unsigned long) ms_len, - (unsigned long) len); - return 0; - } - - return -1; -} - - -static void eap_mschapv2_copy_challenge(struct eap_mschapv2_data *data, - const struct wpabuf *reqData) -{ - /* - * Store a copy of the challenge message, so that it can be processed - * again in case retry is allowed after a possible failure. - */ - wpabuf_free(data->prev_challenge); - data->prev_challenge = wpabuf_dup(reqData); -} - - -/** - * eap_mschapv2_process - Process an EAP-MSCHAPv2 request - * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init() - * @priv: Pointer to private EAP method data from eap_mschapv2_init() - * @ret: Return values from EAP request validation and processing - * @reqData: EAP request to be processed (eapReqData) - * Returns: Pointer to allocated EAP response packet (eapRespData) or %NULL if - * no reply available - */ -static struct wpabuf * eap_mschapv2_process(struct eap_sm *sm, void *priv, - struct eap_method_ret *ret, - const struct wpabuf *reqData) -{ - struct eap_mschapv2_data *data = priv; - struct eap_peer_config *config = eap_get_config(sm); - const struct eap_mschapv2_hdr *ms; - int using_prev_challenge = 0; - const u8 *pos; - size_t len; - u8 id; - - if (eap_mschapv2_check_config(sm)) { - ret->ignore = TRUE; - return NULL; - } - - if (config->mschapv2_retry && data->prev_challenge && - data->prev_error == ERROR_AUTHENTICATION_FAILURE) { - wpa_printf(MSG_DEBUG, "EAP-MSCHAPV2: Replacing pending packet " - "with the previous challenge"); - - reqData = data->prev_challenge; - using_prev_challenge = 1; - config->mschapv2_retry = 0; - } - - pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_MSCHAPV2, reqData, - &len); - if (pos == NULL || len < sizeof(*ms) + 1) { - ret->ignore = TRUE; - return NULL; - } - - ms = (const struct eap_mschapv2_hdr *) pos; - if (eap_mschapv2_check_mslen(sm, len, ms)) { - ret->ignore = TRUE; - return NULL; - } - - id = eap_get_id(reqData); - wpa_printf(MSG_DEBUG, "EAP-MSCHAPV2: RX identifier %d mschapv2_id %d", - id, ms->mschapv2_id); - - switch (ms->op_code) { - case MSCHAPV2_OP_CHALLENGE: - if (!using_prev_challenge) - eap_mschapv2_copy_challenge(data, reqData); - return eap_mschapv2_challenge(sm, data, ret, ms, len, id); - case MSCHAPV2_OP_SUCCESS: - return eap_mschapv2_success(sm, data, ret, ms, len, id); - case MSCHAPV2_OP_FAILURE: - return eap_mschapv2_failure(sm, data, ret, ms, len, id); - default: - wpa_printf(MSG_INFO, "EAP-MSCHAPV2: Unknown op %d - ignored", - ms->op_code); - ret->ignore = TRUE; - return NULL; - } -} - - -static Boolean eap_mschapv2_isKeyAvailable(struct eap_sm *sm, void *priv) -{ - struct eap_mschapv2_data *data = priv; - return data->success && data->master_key_valid; -} - - -static u8 * eap_mschapv2_getKey(struct eap_sm *sm, void *priv, size_t *len) -{ - struct eap_mschapv2_data *data = priv; - u8 *key; - int key_len; - - if (!data->master_key_valid || !data->success) - return NULL; - - key_len = 2 * MSCHAPV2_KEY_LEN; - - key = os_malloc(key_len); - if (key == NULL) - return NULL; - - /* MSK = server MS-MPPE-Recv-Key | MS-MPPE-Send-Key, i.e., - * peer MS-MPPE-Send-Key | MS-MPPE-Recv-Key */ - get_asymetric_start_key(data->master_key, key, MSCHAPV2_KEY_LEN, 1, 0); - get_asymetric_start_key(data->master_key, key + MSCHAPV2_KEY_LEN, - MSCHAPV2_KEY_LEN, 0, 0); - - wpa_hexdump_key(MSG_DEBUG, "EAP-MSCHAPV2: Derived key", - key, key_len); - - *len = key_len; - return key; -} - - -/** - * eap_peer_mschapv2_register - Register EAP-MSCHAPv2 peer method - * Returns: 0 on success, -1 on failure - * - * This function is used to register EAP-MSCHAPv2 peer method into the EAP - * method list. - */ -int eap_peer_mschapv2_register(void) -{ - struct eap_method *eap; - int ret; - - eap = eap_peer_method_alloc(EAP_PEER_METHOD_INTERFACE_VERSION, - EAP_VENDOR_IETF, EAP_TYPE_MSCHAPV2, - "MSCHAPV2"); - if (eap == NULL) - return -1; - - eap->init = eap_mschapv2_init; - eap->deinit = eap_mschapv2_deinit; - eap->process = eap_mschapv2_process; - eap->isKeyAvailable = eap_mschapv2_isKeyAvailable; - eap->getKey = eap_mschapv2_getKey; - - ret = eap_peer_method_register(eap); - if (ret) - eap_peer_method_free(eap); - return ret; -} diff --git a/hostapd-0.8/src/eap_peer/eap_otp.c b/hostapd-0.8/src/eap_peer/eap_otp.c deleted file mode 100644 index 556c22f..0000000 --- a/hostapd-0.8/src/eap_peer/eap_otp.c +++ /dev/null @@ -1,107 +0,0 @@ -/* - * EAP peer method: EAP-OTP (RFC 3748) - * Copyright (c) 2004-2006, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#include "includes.h" - -#include "common.h" -#include "eap_i.h" - - -static void * eap_otp_init(struct eap_sm *sm) -{ - /* No need for private data. However, must return non-NULL to indicate - * success. */ - return (void *) 1; -} - - -static void eap_otp_deinit(struct eap_sm *sm, void *priv) -{ -} - - -static struct wpabuf * eap_otp_process(struct eap_sm *sm, void *priv, - struct eap_method_ret *ret, - const struct wpabuf *reqData) -{ - struct wpabuf *resp; - const u8 *pos, *password; - size_t password_len, len; - int otp; - - pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_OTP, reqData, &len); - if (pos == NULL) { - ret->ignore = TRUE; - return NULL; - } - wpa_hexdump_ascii(MSG_MSGDUMP, "EAP-OTP: Request message", - pos, len); - - password = eap_get_config_otp(sm, &password_len); - if (password) - otp = 1; - else { - password = eap_get_config_password(sm, &password_len); - otp = 0; - } - - if (password == NULL) { - wpa_printf(MSG_INFO, "EAP-OTP: Password not configured"); - eap_sm_request_otp(sm, (const char *) pos, len); - ret->ignore = TRUE; - return NULL; - } - - ret->ignore = FALSE; - - ret->methodState = METHOD_DONE; - ret->decision = DECISION_COND_SUCC; - ret->allowNotifications = FALSE; - - resp = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_OTP, password_len, - EAP_CODE_RESPONSE, eap_get_id(reqData)); - if (resp == NULL) - return NULL; - wpabuf_put_data(resp, password, password_len); - wpa_hexdump_ascii_key(MSG_MSGDUMP, "EAP-OTP: Response", - password, password_len); - - if (otp) { - wpa_printf(MSG_DEBUG, "EAP-OTP: Forgetting used password"); - eap_clear_config_otp(sm); - } - - return resp; -} - - -int eap_peer_otp_register(void) -{ - struct eap_method *eap; - int ret; - - eap = eap_peer_method_alloc(EAP_PEER_METHOD_INTERFACE_VERSION, - EAP_VENDOR_IETF, EAP_TYPE_OTP, "OTP"); - if (eap == NULL) - return -1; - - eap->init = eap_otp_init; - eap->deinit = eap_otp_deinit; - eap->process = eap_otp_process; - - ret = eap_peer_method_register(eap); - if (ret) - eap_peer_method_free(eap); - return ret; -} diff --git a/hostapd-0.8/src/eap_peer/eap_pax.c b/hostapd-0.8/src/eap_peer/eap_pax.c deleted file mode 100644 index d42a7f8..0000000 --- a/hostapd-0.8/src/eap_peer/eap_pax.c +++ /dev/null @@ -1,531 +0,0 @@ -/* - * EAP peer method: EAP-PAX (RFC 4746) - * Copyright (c) 2005-2008, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#include "includes.h" - -#include "common.h" -#include "crypto/random.h" -#include "eap_common/eap_pax_common.h" -#include "eap_i.h" - -/* - * Note: only PAX_STD subprotocol is currently supported - * - * TODO: Add support with PAX_SEC with the mandatory to implement ciphersuite - * (HMAC_SHA1_128, IANA DH Group 14 (2048 bits), RSA-PKCS1-V1_5) and - * recommended ciphersuite (HMAC_SHA256_128, IANA DH Group 15 (3072 bits), - * RSAES-OAEP). - */ - -struct eap_pax_data { - enum { PAX_INIT, PAX_STD_2_SENT, PAX_DONE } state; - u8 mac_id, dh_group_id, public_key_id; - union { - u8 e[2 * EAP_PAX_RAND_LEN]; - struct { - u8 x[EAP_PAX_RAND_LEN]; /* server rand */ - u8 y[EAP_PAX_RAND_LEN]; /* client rand */ - } r; - } rand; - char *cid; - size_t cid_len; - u8 ak[EAP_PAX_AK_LEN]; - u8 mk[EAP_PAX_MK_LEN]; - u8 ck[EAP_PAX_CK_LEN]; - u8 ick[EAP_PAX_ICK_LEN]; -}; - - -static void eap_pax_deinit(struct eap_sm *sm, void *priv); - - -static void * eap_pax_init(struct eap_sm *sm) -{ - struct eap_pax_data *data; - const u8 *identity, *password; - size_t identity_len, password_len; - - identity = eap_get_config_identity(sm, &identity_len); - password = eap_get_config_password(sm, &password_len); - if (!identity || !password) { - wpa_printf(MSG_INFO, "EAP-PAX: CID (nai) or key (password) " - "not configured"); - return NULL; - } - - if (password_len != EAP_PAX_AK_LEN) { - wpa_printf(MSG_INFO, "EAP-PAX: Invalid PSK length"); - return NULL; - } - - data = os_zalloc(sizeof(*data)); - if (data == NULL) - return NULL; - data->state = PAX_INIT; - - data->cid = os_malloc(identity_len); - if (data->cid == NULL) { - eap_pax_deinit(sm, data); - return NULL; - } - os_memcpy(data->cid, identity, identity_len); - data->cid_len = identity_len; - - os_memcpy(data->ak, password, EAP_PAX_AK_LEN); - - return data; -} - - -static void eap_pax_deinit(struct eap_sm *sm, void *priv) -{ - struct eap_pax_data *data = priv; - os_free(data->cid); - os_free(data); -} - - -static struct wpabuf * eap_pax_alloc_resp(const struct eap_pax_hdr *req, - u8 id, u8 op_code, size_t plen) -{ - struct wpabuf *resp; - struct eap_pax_hdr *pax; - - resp = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_PAX, - sizeof(*pax) + plen, EAP_CODE_RESPONSE, id); - if (resp == NULL) - return NULL; - - pax = wpabuf_put(resp, sizeof(*pax)); - pax->op_code = op_code; - pax->flags = 0; - pax->mac_id = req->mac_id; - pax->dh_group_id = req->dh_group_id; - pax->public_key_id = req->public_key_id; - - return resp; -} - - -static struct wpabuf * eap_pax_process_std_1(struct eap_pax_data *data, - struct eap_method_ret *ret, u8 id, - const struct eap_pax_hdr *req, - size_t req_plen) -{ - struct wpabuf *resp; - const u8 *pos; - u8 *rpos; - size_t left, plen; - - wpa_printf(MSG_DEBUG, "EAP-PAX: PAX_STD-1 (received)"); - - if (data->state != PAX_INIT) { - wpa_printf(MSG_INFO, "EAP-PAX: PAX_STD-1 received in " - "unexpected state (%d) - ignored", data->state); - ret->ignore = TRUE; - return NULL; - } - - if (req->flags & EAP_PAX_FLAGS_CE) { - wpa_printf(MSG_INFO, "EAP-PAX: PAX_STD-1 with CE flag set - " - "ignored"); - ret->ignore = TRUE; - return NULL; - } - - left = req_plen - sizeof(*req); - - if (left < 2 + EAP_PAX_RAND_LEN) { - wpa_printf(MSG_INFO, "EAP-PAX: PAX_STD-1 with too short " - "payload"); - ret->ignore = TRUE; - return NULL; - } - - pos = (const u8 *) (req + 1); - if (WPA_GET_BE16(pos) != EAP_PAX_RAND_LEN) { - wpa_printf(MSG_INFO, "EAP-PAX: PAX_STD-1 with incorrect A " - "length %d (expected %d)", - WPA_GET_BE16(pos), EAP_PAX_RAND_LEN); - ret->ignore = TRUE; - return NULL; - } - - pos += 2; - left -= 2; - os_memcpy(data->rand.r.x, pos, EAP_PAX_RAND_LEN); - wpa_hexdump(MSG_MSGDUMP, "EAP-PAX: X (server rand)", - data->rand.r.x, EAP_PAX_RAND_LEN); - pos += EAP_PAX_RAND_LEN; - left -= EAP_PAX_RAND_LEN; - - if (left > 0) { - wpa_hexdump(MSG_MSGDUMP, "EAP-PAX: ignored extra payload", - pos, left); - } - - if (random_get_bytes(data->rand.r.y, EAP_PAX_RAND_LEN)) { - wpa_printf(MSG_ERROR, "EAP-PAX: Failed to get random data"); - ret->ignore = TRUE; - return NULL; - } - wpa_hexdump(MSG_MSGDUMP, "EAP-PAX: Y (client rand)", - data->rand.r.y, EAP_PAX_RAND_LEN); - - if (eap_pax_initial_key_derivation(req->mac_id, data->ak, data->rand.e, - data->mk, data->ck, data->ick) < 0) - { - ret->ignore = TRUE; - return NULL; - } - - wpa_printf(MSG_DEBUG, "EAP-PAX: PAX_STD-2 (sending)"); - - plen = 2 + EAP_PAX_RAND_LEN + 2 + data->cid_len + 2 + EAP_PAX_MAC_LEN + - EAP_PAX_ICV_LEN; - resp = eap_pax_alloc_resp(req, id, EAP_PAX_OP_STD_2, plen); - if (resp == NULL) - return NULL; - - wpabuf_put_be16(resp, EAP_PAX_RAND_LEN); - wpabuf_put_data(resp, data->rand.r.y, EAP_PAX_RAND_LEN); - wpa_hexdump(MSG_MSGDUMP, "EAP-PAX: B = Y (client rand)", - data->rand.r.y, EAP_PAX_RAND_LEN); - - wpabuf_put_be16(resp, data->cid_len); - wpabuf_put_data(resp, data->cid, data->cid_len); - wpa_hexdump_ascii(MSG_MSGDUMP, "EAP-PAX: CID", - (u8 *) data->cid, data->cid_len); - - wpabuf_put_be16(resp, EAP_PAX_MAC_LEN); - rpos = wpabuf_put(resp, EAP_PAX_MAC_LEN); - eap_pax_mac(req->mac_id, data->ck, EAP_PAX_CK_LEN, - data->rand.r.x, EAP_PAX_RAND_LEN, - data->rand.r.y, EAP_PAX_RAND_LEN, - (u8 *) data->cid, data->cid_len, rpos); - wpa_hexdump(MSG_MSGDUMP, "EAP-PAX: MAC_CK(A, B, CID)", - rpos, EAP_PAX_MAC_LEN); - - /* Optional ADE could be added here, if needed */ - - rpos = wpabuf_put(resp, EAP_PAX_ICV_LEN); - eap_pax_mac(req->mac_id, data->ick, EAP_PAX_ICK_LEN, - wpabuf_head(resp), wpabuf_len(resp) - EAP_PAX_ICV_LEN, - NULL, 0, NULL, 0, rpos); - wpa_hexdump(MSG_MSGDUMP, "EAP-PAX: ICV", rpos, EAP_PAX_ICV_LEN); - - data->state = PAX_STD_2_SENT; - data->mac_id = req->mac_id; - data->dh_group_id = req->dh_group_id; - data->public_key_id = req->public_key_id; - - return resp; -} - - -static struct wpabuf * eap_pax_process_std_3(struct eap_pax_data *data, - struct eap_method_ret *ret, u8 id, - const struct eap_pax_hdr *req, - size_t req_plen) -{ - struct wpabuf *resp; - u8 *rpos, mac[EAP_PAX_MAC_LEN]; - const u8 *pos; - size_t left; - - wpa_printf(MSG_DEBUG, "EAP-PAX: PAX_STD-3 (received)"); - - if (data->state != PAX_STD_2_SENT) { - wpa_printf(MSG_INFO, "EAP-PAX: PAX_STD-3 received in " - "unexpected state (%d) - ignored", data->state); - ret->ignore = TRUE; - return NULL; - } - - if (req->flags & EAP_PAX_FLAGS_CE) { - wpa_printf(MSG_INFO, "EAP-PAX: PAX_STD-3 with CE flag set - " - "ignored"); - ret->ignore = TRUE; - return NULL; - } - - left = req_plen - sizeof(*req); - - if (left < 2 + EAP_PAX_MAC_LEN) { - wpa_printf(MSG_INFO, "EAP-PAX: PAX_STD-3 with too short " - "payload"); - ret->ignore = TRUE; - return NULL; - } - - pos = (const u8 *) (req + 1); - if (WPA_GET_BE16(pos) != EAP_PAX_MAC_LEN) { - wpa_printf(MSG_INFO, "EAP-PAX: PAX_STD-3 with incorrect " - "MAC_CK length %d (expected %d)", - WPA_GET_BE16(pos), EAP_PAX_MAC_LEN); - ret->ignore = TRUE; - return NULL; - } - pos += 2; - left -= 2; - wpa_hexdump(MSG_MSGDUMP, "EAP-PAX: MAC_CK(B, CID)", - pos, EAP_PAX_MAC_LEN); - eap_pax_mac(data->mac_id, data->ck, EAP_PAX_CK_LEN, - data->rand.r.y, EAP_PAX_RAND_LEN, - (u8 *) data->cid, data->cid_len, NULL, 0, mac); - if (os_memcmp(pos, mac, EAP_PAX_MAC_LEN) != 0) { - wpa_printf(MSG_INFO, "EAP-PAX: Invalid MAC_CK(B, CID) " - "received"); - wpa_hexdump(MSG_MSGDUMP, "EAP-PAX: expected MAC_CK(B, CID)", - mac, EAP_PAX_MAC_LEN); - ret->methodState = METHOD_DONE; - ret->decision = DECISION_FAIL; - return NULL; - } - - pos += EAP_PAX_MAC_LEN; - left -= EAP_PAX_MAC_LEN; - - if (left > 0) { - wpa_hexdump(MSG_MSGDUMP, "EAP-PAX: ignored extra payload", - pos, left); - } - - wpa_printf(MSG_DEBUG, "EAP-PAX: PAX-ACK (sending)"); - - resp = eap_pax_alloc_resp(req, id, EAP_PAX_OP_ACK, EAP_PAX_ICV_LEN); - if (resp == NULL) - return NULL; - - /* Optional ADE could be added here, if needed */ - - rpos = wpabuf_put(resp, EAP_PAX_ICV_LEN); - eap_pax_mac(data->mac_id, data->ick, EAP_PAX_ICK_LEN, - wpabuf_head(resp), wpabuf_len(resp) - EAP_PAX_ICV_LEN, - NULL, 0, NULL, 0, rpos); - wpa_hexdump(MSG_MSGDUMP, "EAP-PAX: ICV", rpos, EAP_PAX_ICV_LEN); - - data->state = PAX_DONE; - ret->methodState = METHOD_DONE; - ret->decision = DECISION_UNCOND_SUCC; - ret->allowNotifications = FALSE; - - return resp; -} - - -static struct wpabuf * eap_pax_process(struct eap_sm *sm, void *priv, - struct eap_method_ret *ret, - const struct wpabuf *reqData) -{ - struct eap_pax_data *data = priv; - const struct eap_pax_hdr *req; - struct wpabuf *resp; - u8 icvbuf[EAP_PAX_ICV_LEN], id; - const u8 *icv, *pos; - size_t len; - u16 flen, mlen; - - pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_PAX, reqData, &len); - if (pos == NULL || len < EAP_PAX_ICV_LEN) { - ret->ignore = TRUE; - return NULL; - } - id = eap_get_id(reqData); - req = (const struct eap_pax_hdr *) pos; - flen = len - EAP_PAX_ICV_LEN; - mlen = wpabuf_len(reqData) - EAP_PAX_ICV_LEN; - - wpa_printf(MSG_DEBUG, "EAP-PAX: received frame: op_code 0x%x " - "flags 0x%x mac_id 0x%x dh_group_id 0x%x " - "public_key_id 0x%x", - req->op_code, req->flags, req->mac_id, req->dh_group_id, - req->public_key_id); - wpa_hexdump(MSG_MSGDUMP, "EAP-PAX: received payload", - pos, len - EAP_PAX_ICV_LEN); - - if (data->state != PAX_INIT && data->mac_id != req->mac_id) { - wpa_printf(MSG_INFO, "EAP-PAX: MAC ID changed during " - "authentication (was 0x%d, is 0x%d)", - data->mac_id, req->mac_id); - ret->ignore = TRUE; - return NULL; - } - - if (data->state != PAX_INIT && data->dh_group_id != req->dh_group_id) { - wpa_printf(MSG_INFO, "EAP-PAX: DH Group ID changed during " - "authentication (was 0x%d, is 0x%d)", - data->dh_group_id, req->dh_group_id); - ret->ignore = TRUE; - return NULL; - } - - if (data->state != PAX_INIT && - data->public_key_id != req->public_key_id) { - wpa_printf(MSG_INFO, "EAP-PAX: Public Key ID changed during " - "authentication (was 0x%d, is 0x%d)", - data->public_key_id, req->public_key_id); - ret->ignore = TRUE; - return NULL; - } - - /* TODO: add support EAP_PAX_HMAC_SHA256_128 */ - if (req->mac_id != EAP_PAX_MAC_HMAC_SHA1_128) { - wpa_printf(MSG_INFO, "EAP-PAX: Unsupported MAC ID 0x%x", - req->mac_id); - ret->ignore = TRUE; - return NULL; - } - - if (req->dh_group_id != EAP_PAX_DH_GROUP_NONE) { - wpa_printf(MSG_INFO, "EAP-PAX: Unsupported DH Group ID 0x%x", - req->dh_group_id); - ret->ignore = TRUE; - return NULL; - } - - if (req->public_key_id != EAP_PAX_PUBLIC_KEY_NONE) { - wpa_printf(MSG_INFO, "EAP-PAX: Unsupported Public Key ID 0x%x", - req->public_key_id); - ret->ignore = TRUE; - return NULL; - } - - if (req->flags & EAP_PAX_FLAGS_MF) { - /* TODO: add support for reassembling fragments */ - wpa_printf(MSG_INFO, "EAP-PAX: fragmentation not supported - " - "ignored packet"); - ret->ignore = TRUE; - return NULL; - } - - icv = pos + len - EAP_PAX_ICV_LEN; - wpa_hexdump(MSG_MSGDUMP, "EAP-PAX: ICV", icv, EAP_PAX_ICV_LEN); - if (req->op_code == EAP_PAX_OP_STD_1) { - eap_pax_mac(req->mac_id, (u8 *) "", 0, - wpabuf_head(reqData), mlen, NULL, 0, NULL, 0, - icvbuf); - } else { - eap_pax_mac(req->mac_id, data->ick, EAP_PAX_ICK_LEN, - wpabuf_head(reqData), mlen, NULL, 0, NULL, 0, - icvbuf); - } - if (os_memcmp(icv, icvbuf, EAP_PAX_ICV_LEN) != 0) { - wpa_printf(MSG_DEBUG, "EAP-PAX: invalid ICV - ignoring the " - "message"); - wpa_hexdump(MSG_MSGDUMP, "EAP-PAX: expected ICV", - icvbuf, EAP_PAX_ICV_LEN); - ret->ignore = TRUE; - return NULL; - } - - ret->ignore = FALSE; - ret->methodState = METHOD_MAY_CONT; - ret->decision = DECISION_FAIL; - ret->allowNotifications = TRUE; - - switch (req->op_code) { - case EAP_PAX_OP_STD_1: - resp = eap_pax_process_std_1(data, ret, id, req, flen); - break; - case EAP_PAX_OP_STD_3: - resp = eap_pax_process_std_3(data, ret, id, req, flen); - break; - default: - wpa_printf(MSG_DEBUG, "EAP-PAX: ignoring message with unknown " - "op_code %d", req->op_code); - ret->ignore = TRUE; - return NULL; - } - - if (ret->methodState == METHOD_DONE) { - ret->allowNotifications = FALSE; - } - - return resp; -} - - -static Boolean eap_pax_isKeyAvailable(struct eap_sm *sm, void *priv) -{ - struct eap_pax_data *data = priv; - return data->state == PAX_DONE; -} - - -static u8 * eap_pax_getKey(struct eap_sm *sm, void *priv, size_t *len) -{ - struct eap_pax_data *data = priv; - u8 *key; - - if (data->state != PAX_DONE) - return NULL; - - key = os_malloc(EAP_MSK_LEN); - if (key == NULL) - return NULL; - - *len = EAP_MSK_LEN; - eap_pax_kdf(data->mac_id, data->mk, EAP_PAX_MK_LEN, - "Master Session Key", data->rand.e, 2 * EAP_PAX_RAND_LEN, - EAP_MSK_LEN, key); - - return key; -} - - -static u8 * eap_pax_get_emsk(struct eap_sm *sm, void *priv, size_t *len) -{ - struct eap_pax_data *data = priv; - u8 *key; - - if (data->state != PAX_DONE) - return NULL; - - key = os_malloc(EAP_EMSK_LEN); - if (key == NULL) - return NULL; - - *len = EAP_EMSK_LEN; - eap_pax_kdf(data->mac_id, data->mk, EAP_PAX_MK_LEN, - "Extended Master Session Key", - data->rand.e, 2 * EAP_PAX_RAND_LEN, - EAP_EMSK_LEN, key); - - return key; -} - - -int eap_peer_pax_register(void) -{ - struct eap_method *eap; - int ret; - - eap = eap_peer_method_alloc(EAP_PEER_METHOD_INTERFACE_VERSION, - EAP_VENDOR_IETF, EAP_TYPE_PAX, "PAX"); - if (eap == NULL) - return -1; - - eap->init = eap_pax_init; - eap->deinit = eap_pax_deinit; - eap->process = eap_pax_process; - eap->isKeyAvailable = eap_pax_isKeyAvailable; - eap->getKey = eap_pax_getKey; - eap->get_emsk = eap_pax_get_emsk; - - ret = eap_peer_method_register(eap); - if (ret) - eap_peer_method_free(eap); - return ret; -} diff --git a/hostapd-0.8/src/eap_peer/eap_peap.c b/hostapd-0.8/src/eap_peer/eap_peap.c deleted file mode 100644 index 2b72084..0000000 --- a/hostapd-0.8/src/eap_peer/eap_peap.c +++ /dev/null @@ -1,1288 +0,0 @@ -/* - * EAP peer method: EAP-PEAP (draft-josefsson-pppext-eap-tls-eap-10.txt) - * Copyright (c) 2004-2008, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#include "includes.h" - -#include "common.h" -#include "crypto/sha1.h" -#include "crypto/tls.h" -#include "eap_common/eap_tlv_common.h" -#include "eap_common/eap_peap_common.h" -#include "eap_i.h" -#include "eap_tls_common.h" -#include "eap_config.h" -#include "tncc.h" - - -/* Maximum supported PEAP version - * 0 = Microsoft's PEAP version 0; draft-kamath-pppext-peapv0-00.txt - * 1 = draft-josefsson-ppext-eap-tls-eap-05.txt - * 2 = draft-josefsson-ppext-eap-tls-eap-10.txt - */ -#define EAP_PEAP_VERSION 1 - - -static void eap_peap_deinit(struct eap_sm *sm, void *priv); - - -struct eap_peap_data { - struct eap_ssl_data ssl; - - int peap_version, force_peap_version, force_new_label; - - const struct eap_method *phase2_method; - void *phase2_priv; - int phase2_success; - int phase2_eap_success; - int phase2_eap_started; - - struct eap_method_type phase2_type; - struct eap_method_type *phase2_types; - size_t num_phase2_types; - - int peap_outer_success; /* 0 = PEAP terminated on Phase 2 inner - * EAP-Success - * 1 = reply with tunneled EAP-Success to inner - * EAP-Success and expect AS to send outer - * (unencrypted) EAP-Success after this - * 2 = reply with PEAP/TLS ACK to inner - * EAP-Success and expect AS to send outer - * (unencrypted) EAP-Success after this */ - int resuming; /* starting a resumed session */ - int reauth; /* reauthentication */ - u8 *key_data; - - struct wpabuf *pending_phase2_req; - enum { NO_BINDING, OPTIONAL_BINDING, REQUIRE_BINDING } crypto_binding; - int crypto_binding_used; - u8 binding_nonce[32]; - u8 ipmk[40]; - u8 cmk[20]; - int soh; /* Whether IF-TNCCS-SOH (Statement of Health; Microsoft NAP) - * is enabled. */ -}; - - -static int eap_peap_parse_phase1(struct eap_peap_data *data, - const char *phase1) -{ - const char *pos; - - pos = os_strstr(phase1, "peapver="); - if (pos) { - data->force_peap_version = atoi(pos + 8); - data->peap_version = data->force_peap_version; - wpa_printf(MSG_DEBUG, "EAP-PEAP: Forced PEAP version %d", - data->force_peap_version); - } - - if (os_strstr(phase1, "peaplabel=1")) { - data->force_new_label = 1; - wpa_printf(MSG_DEBUG, "EAP-PEAP: Force new label for key " - "derivation"); - } - - if (os_strstr(phase1, "peap_outer_success=0")) { - data->peap_outer_success = 0; - wpa_printf(MSG_DEBUG, "EAP-PEAP: terminate authentication on " - "tunneled EAP-Success"); - } else if (os_strstr(phase1, "peap_outer_success=1")) { - data->peap_outer_success = 1; - wpa_printf(MSG_DEBUG, "EAP-PEAP: send tunneled EAP-Success " - "after receiving tunneled EAP-Success"); - } else if (os_strstr(phase1, "peap_outer_success=2")) { - data->peap_outer_success = 2; - wpa_printf(MSG_DEBUG, "EAP-PEAP: send PEAP/TLS ACK after " - "receiving tunneled EAP-Success"); - } - - if (os_strstr(phase1, "crypto_binding=0")) { - data->crypto_binding = NO_BINDING; - wpa_printf(MSG_DEBUG, "EAP-PEAP: Do not use cryptobinding"); - } else if (os_strstr(phase1, "crypto_binding=1")) { - data->crypto_binding = OPTIONAL_BINDING; - wpa_printf(MSG_DEBUG, "EAP-PEAP: Optional cryptobinding"); - } else if (os_strstr(phase1, "crypto_binding=2")) { - data->crypto_binding = REQUIRE_BINDING; - wpa_printf(MSG_DEBUG, "EAP-PEAP: Require cryptobinding"); - } - -#ifdef EAP_TNC - if (os_strstr(phase1, "tnc=soh2")) { - data->soh = 2; - wpa_printf(MSG_DEBUG, "EAP-PEAP: SoH version 2 enabled"); - } else if (os_strstr(phase1, "tnc=soh1")) { - data->soh = 1; - wpa_printf(MSG_DEBUG, "EAP-PEAP: SoH version 1 enabled"); - } else if (os_strstr(phase1, "tnc=soh")) { - data->soh = 2; - wpa_printf(MSG_DEBUG, "EAP-PEAP: SoH version 2 enabled"); - } -#endif /* EAP_TNC */ - - return 0; -} - - -static void * eap_peap_init(struct eap_sm *sm) -{ - struct eap_peap_data *data; - struct eap_peer_config *config = eap_get_config(sm); - - data = os_zalloc(sizeof(*data)); - if (data == NULL) - return NULL; - sm->peap_done = FALSE; - data->peap_version = EAP_PEAP_VERSION; - data->force_peap_version = -1; - data->peap_outer_success = 2; - data->crypto_binding = OPTIONAL_BINDING; - - if (config && config->phase1 && - eap_peap_parse_phase1(data, config->phase1) < 0) { - eap_peap_deinit(sm, data); - return NULL; - } - - if (eap_peer_select_phase2_methods(config, "auth=", - &data->phase2_types, - &data->num_phase2_types) < 0) { - eap_peap_deinit(sm, data); - return NULL; - } - - data->phase2_type.vendor = EAP_VENDOR_IETF; - data->phase2_type.method = EAP_TYPE_NONE; - - if (eap_peer_tls_ssl_init(sm, &data->ssl, config)) { - wpa_printf(MSG_INFO, "EAP-PEAP: Failed to initialize SSL."); - eap_peap_deinit(sm, data); - return NULL; - } - - return data; -} - - -static void eap_peap_deinit(struct eap_sm *sm, void *priv) -{ - struct eap_peap_data *data = priv; - if (data == NULL) - return; - if (data->phase2_priv && data->phase2_method) - data->phase2_method->deinit(sm, data->phase2_priv); - os_free(data->phase2_types); - eap_peer_tls_ssl_deinit(sm, &data->ssl); - os_free(data->key_data); - wpabuf_free(data->pending_phase2_req); - os_free(data); -} - - -/** - * eap_tlv_build_nak - Build EAP-TLV NAK message - * @id: EAP identifier for the header - * @nak_type: TLV type (EAP_TLV_*) - * Returns: Buffer to the allocated EAP-TLV NAK message or %NULL on failure - * - * This funtion builds an EAP-TLV NAK message. The caller is responsible for - * freeing the returned buffer. - */ -static struct wpabuf * eap_tlv_build_nak(int id, u16 nak_type) -{ - struct wpabuf *msg; - - msg = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_TLV, 10, - EAP_CODE_RESPONSE, id); - if (msg == NULL) - return NULL; - - wpabuf_put_u8(msg, 0x80); /* Mandatory */ - wpabuf_put_u8(msg, EAP_TLV_NAK_TLV); - wpabuf_put_be16(msg, 6); /* Length */ - wpabuf_put_be32(msg, 0); /* Vendor-Id */ - wpabuf_put_be16(msg, nak_type); /* NAK-Type */ - - return msg; -} - - -static int eap_peap_get_isk(struct eap_sm *sm, struct eap_peap_data *data, - u8 *isk, size_t isk_len) -{ - u8 *key; - size_t key_len; - - os_memset(isk, 0, isk_len); - if (data->phase2_method == NULL || data->phase2_priv == NULL || - data->phase2_method->isKeyAvailable == NULL || - data->phase2_method->getKey == NULL) - return 0; - - if (!data->phase2_method->isKeyAvailable(sm, data->phase2_priv) || - (key = data->phase2_method->getKey(sm, data->phase2_priv, - &key_len)) == NULL) { - wpa_printf(MSG_DEBUG, "EAP-PEAP: Could not get key material " - "from Phase 2"); - return -1; - } - - if (key_len > isk_len) - key_len = isk_len; - os_memcpy(isk, key, key_len); - os_free(key); - - return 0; -} - - -static int eap_peap_derive_cmk(struct eap_sm *sm, struct eap_peap_data *data) -{ - u8 *tk; - u8 isk[32], imck[60]; - - /* - * Tunnel key (TK) is the first 60 octets of the key generated by - * phase 1 of PEAP (based on TLS). - */ - tk = data->key_data; - if (tk == NULL) - return -1; - wpa_hexdump_key(MSG_DEBUG, "EAP-PEAP: TK", tk, 60); - - if (data->reauth && - tls_connection_resumed(sm->ssl_ctx, data->ssl.conn)) { - /* Fast-connect: IPMK|CMK = TK */ - os_memcpy(data->ipmk, tk, 40); - wpa_hexdump_key(MSG_DEBUG, "EAP-PEAP: IPMK from TK", - data->ipmk, 40); - os_memcpy(data->cmk, tk + 40, 20); - wpa_hexdump_key(MSG_DEBUG, "EAP-PEAP: CMK from TK", - data->cmk, 20); - return 0; - } - - if (eap_peap_get_isk(sm, data, isk, sizeof(isk)) < 0) - return -1; - wpa_hexdump_key(MSG_DEBUG, "EAP-PEAP: ISK", isk, sizeof(isk)); - - /* - * IPMK Seed = "Inner Methods Compound Keys" | ISK - * TempKey = First 40 octets of TK - * IPMK|CMK = PRF+(TempKey, IPMK Seed, 60) - * (note: draft-josefsson-pppext-eap-tls-eap-10.txt includes a space - * in the end of the label just before ISK; is that just a typo?) - */ - wpa_hexdump_key(MSG_DEBUG, "EAP-PEAP: TempKey", tk, 40); - peap_prfplus(data->peap_version, tk, 40, "Inner Methods Compound Keys", - isk, sizeof(isk), imck, sizeof(imck)); - wpa_hexdump_key(MSG_DEBUG, "EAP-PEAP: IMCK (IPMKj)", - imck, sizeof(imck)); - - os_memcpy(data->ipmk, imck, 40); - wpa_hexdump_key(MSG_DEBUG, "EAP-PEAP: IPMK (S-IPMKj)", data->ipmk, 40); - os_memcpy(data->cmk, imck + 40, 20); - wpa_hexdump_key(MSG_DEBUG, "EAP-PEAP: CMK (CMKj)", data->cmk, 20); - - return 0; -} - - -static int eap_tlv_add_cryptobinding(struct eap_sm *sm, - struct eap_peap_data *data, - struct wpabuf *buf) -{ - u8 *mac; - u8 eap_type = EAP_TYPE_PEAP; - const u8 *addr[2]; - size_t len[2]; - u16 tlv_type; - - /* Compound_MAC: HMAC-SHA1-160(cryptobinding TLV | EAP type) */ - addr[0] = wpabuf_put(buf, 0); - len[0] = 60; - addr[1] = &eap_type; - len[1] = 1; - - tlv_type = EAP_TLV_CRYPTO_BINDING_TLV; - if (data->peap_version >= 2) - tlv_type |= EAP_TLV_TYPE_MANDATORY; - wpabuf_put_be16(buf, tlv_type); - wpabuf_put_be16(buf, 56); - - wpabuf_put_u8(buf, 0); /* Reserved */ - wpabuf_put_u8(buf, data->peap_version); /* Version */ - wpabuf_put_u8(buf, data->peap_version); /* RecvVersion */ - wpabuf_put_u8(buf, 1); /* SubType: 0 = Request, 1 = Response */ - wpabuf_put_data(buf, data->binding_nonce, 32); /* Nonce */ - mac = wpabuf_put(buf, 20); /* Compound_MAC */ - wpa_hexdump(MSG_MSGDUMP, "EAP-PEAP: Compound_MAC CMK", data->cmk, 20); - wpa_hexdump(MSG_MSGDUMP, "EAP-PEAP: Compound_MAC data 1", - addr[0], len[0]); - wpa_hexdump(MSG_MSGDUMP, "EAP-PEAP: Compound_MAC data 2", - addr[1], len[1]); - hmac_sha1_vector(data->cmk, 20, 2, addr, len, mac); - wpa_hexdump(MSG_MSGDUMP, "EAP-PEAP: Compound_MAC", mac, SHA1_MAC_LEN); - data->crypto_binding_used = 1; - - return 0; -} - - -/** - * eap_tlv_build_result - Build EAP-TLV Result message - * @id: EAP identifier for the header - * @status: Status (EAP_TLV_RESULT_SUCCESS or EAP_TLV_RESULT_FAILURE) - * Returns: Buffer to the allocated EAP-TLV Result message or %NULL on failure - * - * This funtion builds an EAP-TLV Result message. The caller is responsible for - * freeing the returned buffer. - */ -static struct wpabuf * eap_tlv_build_result(struct eap_sm *sm, - struct eap_peap_data *data, - int crypto_tlv_used, - int id, u16 status) -{ - struct wpabuf *msg; - size_t len; - - if (data->crypto_binding == NO_BINDING) - crypto_tlv_used = 0; - - len = 6; - if (crypto_tlv_used) - len += 60; /* Cryptobinding TLV */ - msg = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_TLV, len, - EAP_CODE_RESPONSE, id); - if (msg == NULL) - return NULL; - - wpabuf_put_u8(msg, 0x80); /* Mandatory */ - wpabuf_put_u8(msg, EAP_TLV_RESULT_TLV); - wpabuf_put_be16(msg, 2); /* Length */ - wpabuf_put_be16(msg, status); /* Status */ - - if (crypto_tlv_used && eap_tlv_add_cryptobinding(sm, data, msg)) { - wpabuf_free(msg); - return NULL; - } - - return msg; -} - - -static int eap_tlv_validate_cryptobinding(struct eap_sm *sm, - struct eap_peap_data *data, - const u8 *crypto_tlv, - size_t crypto_tlv_len) -{ - u8 buf[61], mac[SHA1_MAC_LEN]; - const u8 *pos; - - if (eap_peap_derive_cmk(sm, data) < 0) { - wpa_printf(MSG_DEBUG, "EAP-PEAP: Could not derive CMK"); - return -1; - } - - if (crypto_tlv_len != 4 + 56) { - wpa_printf(MSG_DEBUG, "EAP-PEAP: Invalid cryptobinding TLV " - "length %d", (int) crypto_tlv_len); - return -1; - } - - pos = crypto_tlv; - pos += 4; /* TLV header */ - if (pos[1] != data->peap_version) { - wpa_printf(MSG_DEBUG, "EAP-PEAP: Cryptobinding TLV Version " - "mismatch (was %d; expected %d)", - pos[1], data->peap_version); - return -1; - } - - if (pos[3] != 0) { - wpa_printf(MSG_DEBUG, "EAP-PEAP: Unexpected Cryptobinding TLV " - "SubType %d", pos[3]); - return -1; - } - pos += 4; - os_memcpy(data->binding_nonce, pos, 32); - pos += 32; /* Nonce */ - - /* Compound_MAC: HMAC-SHA1-160(cryptobinding TLV | EAP type) */ - os_memcpy(buf, crypto_tlv, 60); - os_memset(buf + 4 + 4 + 32, 0, 20); /* Compound_MAC */ - buf[60] = EAP_TYPE_PEAP; - wpa_hexdump(MSG_DEBUG, "EAP-PEAP: Compound_MAC data", - buf, sizeof(buf)); - hmac_sha1(data->cmk, 20, buf, sizeof(buf), mac); - - if (os_memcmp(mac, pos, SHA1_MAC_LEN) != 0) { - wpa_printf(MSG_DEBUG, "EAP-PEAP: Invalid Compound_MAC in " - "cryptobinding TLV"); - wpa_hexdump(MSG_DEBUG, "EAP-PEAP: Received MAC", - pos, SHA1_MAC_LEN); - wpa_hexdump(MSG_DEBUG, "EAP-PEAP: Expected MAC", - mac, SHA1_MAC_LEN); - return -1; - } - - wpa_printf(MSG_DEBUG, "EAP-PEAP: Valid cryptobinding TLV received"); - - return 0; -} - - -/** - * eap_tlv_process - Process a received EAP-TLV message and generate a response - * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init() - * @ret: Return values from EAP request validation and processing - * @req: EAP-TLV request to be processed. The caller must have validated that - * the buffer is large enough to contain full request (hdr->length bytes) and - * that the EAP type is EAP_TYPE_TLV. - * @resp: Buffer to return a pointer to the allocated response message. This - * field should be initialized to %NULL before the call. The value will be - * updated if a response message is generated. The caller is responsible for - * freeing the allocated message. - * @force_failure: Force negotiation to fail - * Returns: 0 on success, -1 on failure - */ -static int eap_tlv_process(struct eap_sm *sm, struct eap_peap_data *data, - struct eap_method_ret *ret, - const struct wpabuf *req, struct wpabuf **resp, - int force_failure) -{ - size_t left, tlv_len; - const u8 *pos; - const u8 *result_tlv = NULL, *crypto_tlv = NULL; - size_t result_tlv_len = 0, crypto_tlv_len = 0; - int tlv_type, mandatory; - - /* Parse TLVs */ - pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_TLV, req, &left); - if (pos == NULL) - return -1; - wpa_hexdump(MSG_DEBUG, "EAP-TLV: Received TLVs", pos, left); - while (left >= 4) { - mandatory = !!(pos[0] & 0x80); - tlv_type = WPA_GET_BE16(pos) & 0x3fff; - pos += 2; - tlv_len = WPA_GET_BE16(pos); - pos += 2; - left -= 4; - if (tlv_len > left) { - wpa_printf(MSG_DEBUG, "EAP-TLV: TLV underrun " - "(tlv_len=%lu left=%lu)", - (unsigned long) tlv_len, - (unsigned long) left); - return -1; - } - switch (tlv_type) { - case EAP_TLV_RESULT_TLV: - result_tlv = pos; - result_tlv_len = tlv_len; - break; - case EAP_TLV_CRYPTO_BINDING_TLV: - crypto_tlv = pos; - crypto_tlv_len = tlv_len; - break; - default: - wpa_printf(MSG_DEBUG, "EAP-TLV: Unsupported TLV Type " - "%d%s", tlv_type, - mandatory ? " (mandatory)" : ""); - if (mandatory) { - /* NAK TLV and ignore all TLVs in this packet. - */ - *resp = eap_tlv_build_nak(eap_get_id(req), - tlv_type); - return *resp == NULL ? -1 : 0; - } - /* Ignore this TLV, but process other TLVs */ - break; - } - - pos += tlv_len; - left -= tlv_len; - } - if (left) { - wpa_printf(MSG_DEBUG, "EAP-TLV: Last TLV too short in " - "Request (left=%lu)", (unsigned long) left); - return -1; - } - - /* Process supported TLVs */ - if (crypto_tlv && data->crypto_binding != NO_BINDING) { - wpa_hexdump(MSG_DEBUG, "EAP-PEAP: Cryptobinding TLV", - crypto_tlv, crypto_tlv_len); - if (eap_tlv_validate_cryptobinding(sm, data, crypto_tlv - 4, - crypto_tlv_len + 4) < 0) { - if (result_tlv == NULL) - return -1; - force_failure = 1; - crypto_tlv = NULL; /* do not include Cryptobinding TLV - * in response, if the received - * cryptobinding was invalid. */ - } - } else if (!crypto_tlv && data->crypto_binding == REQUIRE_BINDING) { - wpa_printf(MSG_DEBUG, "EAP-PEAP: No cryptobinding TLV"); - return -1; - } - - if (result_tlv) { - int status, resp_status; - wpa_hexdump(MSG_DEBUG, "EAP-TLV: Result TLV", - result_tlv, result_tlv_len); - if (result_tlv_len < 2) { - wpa_printf(MSG_INFO, "EAP-TLV: Too short Result TLV " - "(len=%lu)", - (unsigned long) result_tlv_len); - return -1; - } - status = WPA_GET_BE16(result_tlv); - if (status == EAP_TLV_RESULT_SUCCESS) { - wpa_printf(MSG_INFO, "EAP-TLV: TLV Result - Success " - "- EAP-TLV/Phase2 Completed"); - if (force_failure) { - wpa_printf(MSG_INFO, "EAP-TLV: Earlier failure" - " - force failed Phase 2"); - resp_status = EAP_TLV_RESULT_FAILURE; - ret->decision = DECISION_FAIL; - } else { - resp_status = EAP_TLV_RESULT_SUCCESS; - ret->decision = DECISION_UNCOND_SUCC; - } - } else if (status == EAP_TLV_RESULT_FAILURE) { - wpa_printf(MSG_INFO, "EAP-TLV: TLV Result - Failure"); - resp_status = EAP_TLV_RESULT_FAILURE; - ret->decision = DECISION_FAIL; - } else { - wpa_printf(MSG_INFO, "EAP-TLV: Unknown TLV Result " - "Status %d", status); - resp_status = EAP_TLV_RESULT_FAILURE; - ret->decision = DECISION_FAIL; - } - ret->methodState = METHOD_DONE; - - *resp = eap_tlv_build_result(sm, data, crypto_tlv != NULL, - eap_get_id(req), resp_status); - } - - return 0; -} - - -static struct wpabuf * eap_peapv2_tlv_eap_payload(struct wpabuf *buf) -{ - struct wpabuf *e; - struct eap_tlv_hdr *tlv; - - if (buf == NULL) - return NULL; - - /* Encapsulate EAP packet in EAP-Payload TLV */ - wpa_printf(MSG_DEBUG, "EAP-PEAPv2: Add EAP-Payload TLV"); - e = wpabuf_alloc(sizeof(*tlv) + wpabuf_len(buf)); - if (e == NULL) { - wpa_printf(MSG_DEBUG, "EAP-PEAPv2: Failed to allocate memory " - "for TLV encapsulation"); - wpabuf_free(buf); - return NULL; - } - tlv = wpabuf_put(e, sizeof(*tlv)); - tlv->tlv_type = host_to_be16(EAP_TLV_TYPE_MANDATORY | - EAP_TLV_EAP_PAYLOAD_TLV); - tlv->length = host_to_be16(wpabuf_len(buf)); - wpabuf_put_buf(e, buf); - wpabuf_free(buf); - return e; -} - - -static int eap_peap_phase2_request(struct eap_sm *sm, - struct eap_peap_data *data, - struct eap_method_ret *ret, - struct wpabuf *req, - struct wpabuf **resp) -{ - struct eap_hdr *hdr = wpabuf_mhead(req); - size_t len = be_to_host16(hdr->length); - u8 *pos; - struct eap_method_ret iret; - struct eap_peer_config *config = eap_get_config(sm); - - if (len <= sizeof(struct eap_hdr)) { - wpa_printf(MSG_INFO, "EAP-PEAP: too short " - "Phase 2 request (len=%lu)", (unsigned long) len); - return -1; - } - pos = (u8 *) (hdr + 1); - wpa_printf(MSG_DEBUG, "EAP-PEAP: Phase 2 Request: type=%d", *pos); - switch (*pos) { - case EAP_TYPE_IDENTITY: - *resp = eap_sm_buildIdentity(sm, hdr->identifier, 1); - break; - case EAP_TYPE_TLV: - os_memset(&iret, 0, sizeof(iret)); - if (eap_tlv_process(sm, data, &iret, req, resp, - data->phase2_eap_started && - !data->phase2_eap_success)) { - ret->methodState = METHOD_DONE; - ret->decision = DECISION_FAIL; - return -1; - } - if (iret.methodState == METHOD_DONE || - iret.methodState == METHOD_MAY_CONT) { - ret->methodState = iret.methodState; - ret->decision = iret.decision; - data->phase2_success = 1; - } - break; - case EAP_TYPE_EXPANDED: -#ifdef EAP_TNC - if (data->soh) { - const u8 *epos; - size_t eleft; - - epos = eap_hdr_validate(EAP_VENDOR_MICROSOFT, 0x21, - req, &eleft); - if (epos) { - struct wpabuf *buf; - wpa_printf(MSG_DEBUG, - "EAP-PEAP: SoH EAP Extensions"); - buf = tncc_process_soh_request(data->soh, - epos, eleft); - if (buf) { - *resp = eap_msg_alloc( - EAP_VENDOR_MICROSOFT, 0x21, - wpabuf_len(buf), - EAP_CODE_RESPONSE, - hdr->identifier); - if (*resp == NULL) { - ret->methodState = METHOD_DONE; - ret->decision = DECISION_FAIL; - return -1; - } - wpabuf_put_buf(*resp, buf); - wpabuf_free(buf); - break; - } - } - } -#endif /* EAP_TNC */ - /* fall through */ - default: - if (data->phase2_type.vendor == EAP_VENDOR_IETF && - data->phase2_type.method == EAP_TYPE_NONE) { - size_t i; - for (i = 0; i < data->num_phase2_types; i++) { - if (data->phase2_types[i].vendor != - EAP_VENDOR_IETF || - data->phase2_types[i].method != *pos) - continue; - - data->phase2_type.vendor = - data->phase2_types[i].vendor; - data->phase2_type.method = - data->phase2_types[i].method; - wpa_printf(MSG_DEBUG, "EAP-PEAP: Selected " - "Phase 2 EAP vendor %d method %d", - data->phase2_type.vendor, - data->phase2_type.method); - break; - } - } - if (*pos != data->phase2_type.method || - *pos == EAP_TYPE_NONE) { - if (eap_peer_tls_phase2_nak(data->phase2_types, - data->num_phase2_types, - hdr, resp)) - return -1; - return 0; - } - - if (data->phase2_priv == NULL) { - data->phase2_method = eap_peer_get_eap_method( - data->phase2_type.vendor, - data->phase2_type.method); - if (data->phase2_method) { - sm->init_phase2 = 1; - data->phase2_priv = - data->phase2_method->init(sm); - sm->init_phase2 = 0; - } - } - if (data->phase2_priv == NULL || data->phase2_method == NULL) { - wpa_printf(MSG_INFO, "EAP-PEAP: failed to initialize " - "Phase 2 EAP method %d", *pos); - ret->methodState = METHOD_DONE; - ret->decision = DECISION_FAIL; - return -1; - } - data->phase2_eap_started = 1; - os_memset(&iret, 0, sizeof(iret)); - *resp = data->phase2_method->process(sm, data->phase2_priv, - &iret, req); - if ((iret.methodState == METHOD_DONE || - iret.methodState == METHOD_MAY_CONT) && - (iret.decision == DECISION_UNCOND_SUCC || - iret.decision == DECISION_COND_SUCC)) { - data->phase2_eap_success = 1; - data->phase2_success = 1; - } - break; - } - - if (*resp == NULL && - (config->pending_req_identity || config->pending_req_password || - config->pending_req_otp || config->pending_req_new_password)) { - wpabuf_free(data->pending_phase2_req); - data->pending_phase2_req = wpabuf_alloc_copy(hdr, len); - } - - return 0; -} - - -static int eap_peap_decrypt(struct eap_sm *sm, struct eap_peap_data *data, - struct eap_method_ret *ret, - const struct eap_hdr *req, - const struct wpabuf *in_data, - struct wpabuf **out_data) -{ - struct wpabuf *in_decrypted = NULL; - int res, skip_change = 0; - struct eap_hdr *hdr, *rhdr; - struct wpabuf *resp = NULL; - size_t len; - - wpa_printf(MSG_DEBUG, "EAP-PEAP: received %lu bytes encrypted data for" - " Phase 2", (unsigned long) wpabuf_len(in_data)); - - if (data->pending_phase2_req) { - wpa_printf(MSG_DEBUG, "EAP-PEAP: Pending Phase 2 request - " - "skip decryption and use old data"); - /* Clear TLS reassembly state. */ - eap_peer_tls_reset_input(&data->ssl); - in_decrypted = data->pending_phase2_req; - data->pending_phase2_req = NULL; - skip_change = 1; - goto continue_req; - } - - if (wpabuf_len(in_data) == 0 && sm->workaround && - data->phase2_success) { - /* - * Cisco ACS seems to be using TLS ACK to terminate - * EAP-PEAPv0/GTC. Try to reply with TLS ACK. - */ - wpa_printf(MSG_DEBUG, "EAP-PEAP: Received TLS ACK, but " - "expected data - acknowledge with TLS ACK since " - "Phase 2 has been completed"); - ret->decision = DECISION_COND_SUCC; - ret->methodState = METHOD_DONE; - return 1; - } else if (wpabuf_len(in_data) == 0) { - /* Received TLS ACK - requesting more fragments */ - return eap_peer_tls_encrypt(sm, &data->ssl, EAP_TYPE_PEAP, - data->peap_version, - req->identifier, NULL, out_data); - } - - res = eap_peer_tls_decrypt(sm, &data->ssl, in_data, &in_decrypted); - if (res) - return res; - -continue_req: - wpa_hexdump_buf(MSG_DEBUG, "EAP-PEAP: Decrypted Phase 2 EAP", - in_decrypted); - - hdr = wpabuf_mhead(in_decrypted); - if (wpabuf_len(in_decrypted) == 5 && hdr->code == EAP_CODE_REQUEST && - be_to_host16(hdr->length) == 5 && - eap_get_type(in_decrypted) == EAP_TYPE_IDENTITY) { - /* At least FreeRADIUS seems to send full EAP header with - * EAP Request Identity */ - skip_change = 1; - } - if (wpabuf_len(in_decrypted) >= 5 && hdr->code == EAP_CODE_REQUEST && - eap_get_type(in_decrypted) == EAP_TYPE_TLV) { - skip_change = 1; - } - - if (data->peap_version == 0 && !skip_change) { - struct eap_hdr *nhdr; - struct wpabuf *nmsg = wpabuf_alloc(sizeof(struct eap_hdr) + - wpabuf_len(in_decrypted)); - if (nmsg == NULL) { - wpabuf_free(in_decrypted); - return 0; - } - nhdr = wpabuf_put(nmsg, sizeof(*nhdr)); - wpabuf_put_buf(nmsg, in_decrypted); - nhdr->code = req->code; - nhdr->identifier = req->identifier; - nhdr->length = host_to_be16(sizeof(struct eap_hdr) + - wpabuf_len(in_decrypted)); - - wpabuf_free(in_decrypted); - in_decrypted = nmsg; - } - - if (data->peap_version >= 2) { - struct eap_tlv_hdr *tlv; - struct wpabuf *nmsg; - - if (wpabuf_len(in_decrypted) < sizeof(*tlv) + sizeof(*hdr)) { - wpa_printf(MSG_INFO, "EAP-PEAPv2: Too short Phase 2 " - "EAP TLV"); - wpabuf_free(in_decrypted); - return 0; - } - tlv = wpabuf_mhead(in_decrypted); - if ((be_to_host16(tlv->tlv_type) & 0x3fff) != - EAP_TLV_EAP_PAYLOAD_TLV) { - wpa_printf(MSG_INFO, "EAP-PEAPv2: Not an EAP TLV"); - wpabuf_free(in_decrypted); - return 0; - } - if (sizeof(*tlv) + be_to_host16(tlv->length) > - wpabuf_len(in_decrypted)) { - wpa_printf(MSG_INFO, "EAP-PEAPv2: Invalid EAP TLV " - "length"); - wpabuf_free(in_decrypted); - return 0; - } - hdr = (struct eap_hdr *) (tlv + 1); - if (be_to_host16(hdr->length) > be_to_host16(tlv->length)) { - wpa_printf(MSG_INFO, "EAP-PEAPv2: No room for full " - "EAP packet in EAP TLV"); - wpabuf_free(in_decrypted); - return 0; - } - - nmsg = wpabuf_alloc(be_to_host16(hdr->length)); - if (nmsg == NULL) { - wpabuf_free(in_decrypted); - return 0; - } - - wpabuf_put_data(nmsg, hdr, be_to_host16(hdr->length)); - wpabuf_free(in_decrypted); - in_decrypted = nmsg; - } - - hdr = wpabuf_mhead(in_decrypted); - if (wpabuf_len(in_decrypted) < sizeof(*hdr)) { - wpa_printf(MSG_INFO, "EAP-PEAP: Too short Phase 2 " - "EAP frame (len=%lu)", - (unsigned long) wpabuf_len(in_decrypted)); - wpabuf_free(in_decrypted); - return 0; - } - len = be_to_host16(hdr->length); - if (len > wpabuf_len(in_decrypted)) { - wpa_printf(MSG_INFO, "EAP-PEAP: Length mismatch in " - "Phase 2 EAP frame (len=%lu hdr->length=%lu)", - (unsigned long) wpabuf_len(in_decrypted), - (unsigned long) len); - wpabuf_free(in_decrypted); - return 0; - } - if (len < wpabuf_len(in_decrypted)) { - wpa_printf(MSG_INFO, "EAP-PEAP: Odd.. Phase 2 EAP header has " - "shorter length than full decrypted data " - "(%lu < %lu)", - (unsigned long) len, - (unsigned long) wpabuf_len(in_decrypted)); - } - wpa_printf(MSG_DEBUG, "EAP-PEAP: received Phase 2: code=%d " - "identifier=%d length=%lu", hdr->code, hdr->identifier, - (unsigned long) len); - switch (hdr->code) { - case EAP_CODE_REQUEST: - if (eap_peap_phase2_request(sm, data, ret, in_decrypted, - &resp)) { - wpabuf_free(in_decrypted); - wpa_printf(MSG_INFO, "EAP-PEAP: Phase2 Request " - "processing failed"); - return 0; - } - break; - case EAP_CODE_SUCCESS: - wpa_printf(MSG_DEBUG, "EAP-PEAP: Phase 2 Success"); - if (data->peap_version == 1) { - /* EAP-Success within TLS tunnel is used to indicate - * shutdown of the TLS channel. The authentication has - * been completed. */ - if (data->phase2_eap_started && - !data->phase2_eap_success) { - wpa_printf(MSG_DEBUG, "EAP-PEAP: Phase 2 " - "Success used to indicate success, " - "but Phase 2 EAP was not yet " - "completed successfully"); - ret->methodState = METHOD_DONE; - ret->decision = DECISION_FAIL; - wpabuf_free(in_decrypted); - return 0; - } - wpa_printf(MSG_DEBUG, "EAP-PEAP: Version 1 - " - "EAP-Success within TLS tunnel - " - "authentication completed"); - ret->decision = DECISION_UNCOND_SUCC; - ret->methodState = METHOD_DONE; - data->phase2_success = 1; - if (data->peap_outer_success == 2) { - wpabuf_free(in_decrypted); - wpa_printf(MSG_DEBUG, "EAP-PEAP: Use TLS ACK " - "to finish authentication"); - return 1; - } else if (data->peap_outer_success == 1) { - /* Reply with EAP-Success within the TLS - * channel to complete the authentication. */ - resp = wpabuf_alloc(sizeof(struct eap_hdr)); - if (resp) { - rhdr = wpabuf_put(resp, sizeof(*rhdr)); - rhdr->code = EAP_CODE_SUCCESS; - rhdr->identifier = hdr->identifier; - rhdr->length = - host_to_be16(sizeof(*rhdr)); - } - } else { - /* No EAP-Success expected for Phase 1 (outer, - * unencrypted auth), so force EAP state - * machine to SUCCESS state. */ - sm->peap_done = TRUE; - } - } else { - /* FIX: ? */ - } - break; - case EAP_CODE_FAILURE: - wpa_printf(MSG_DEBUG, "EAP-PEAP: Phase 2 Failure"); - ret->decision = DECISION_FAIL; - ret->methodState = METHOD_MAY_CONT; - ret->allowNotifications = FALSE; - /* Reply with EAP-Failure within the TLS channel to complete - * failure reporting. */ - resp = wpabuf_alloc(sizeof(struct eap_hdr)); - if (resp) { - rhdr = wpabuf_put(resp, sizeof(*rhdr)); - rhdr->code = EAP_CODE_FAILURE; - rhdr->identifier = hdr->identifier; - rhdr->length = host_to_be16(sizeof(*rhdr)); - } - break; - default: - wpa_printf(MSG_INFO, "EAP-PEAP: Unexpected code=%d in " - "Phase 2 EAP header", hdr->code); - break; - } - - wpabuf_free(in_decrypted); - - if (resp) { - int skip_change2 = 0; - struct wpabuf *rmsg, buf; - - wpa_hexdump_buf_key(MSG_DEBUG, - "EAP-PEAP: Encrypting Phase 2 data", resp); - /* PEAP version changes */ - if (data->peap_version >= 2) { - resp = eap_peapv2_tlv_eap_payload(resp); - if (resp == NULL) - return -1; - } - if (wpabuf_len(resp) >= 5 && - wpabuf_head_u8(resp)[0] == EAP_CODE_RESPONSE && - eap_get_type(resp) == EAP_TYPE_TLV) - skip_change2 = 1; - rmsg = resp; - if (data->peap_version == 0 && !skip_change2) { - wpabuf_set(&buf, wpabuf_head_u8(resp) + - sizeof(struct eap_hdr), - wpabuf_len(resp) - sizeof(struct eap_hdr)); - rmsg = &buf; - } - - if (eap_peer_tls_encrypt(sm, &data->ssl, EAP_TYPE_PEAP, - data->peap_version, req->identifier, - rmsg, out_data)) { - wpa_printf(MSG_INFO, "EAP-PEAP: Failed to encrypt " - "a Phase 2 frame"); - } - wpabuf_free(resp); - } - - return 0; -} - - -static struct wpabuf * eap_peap_process(struct eap_sm *sm, void *priv, - struct eap_method_ret *ret, - const struct wpabuf *reqData) -{ - const struct eap_hdr *req; - size_t left; - int res; - u8 flags, id; - struct wpabuf *resp; - const u8 *pos; - struct eap_peap_data *data = priv; - - pos = eap_peer_tls_process_init(sm, &data->ssl, EAP_TYPE_PEAP, ret, - reqData, &left, &flags); - if (pos == NULL) - return NULL; - req = wpabuf_head(reqData); - id = req->identifier; - - if (flags & EAP_TLS_FLAGS_START) { - wpa_printf(MSG_DEBUG, "EAP-PEAP: Start (server ver=%d, own " - "ver=%d)", flags & EAP_TLS_VERSION_MASK, - data->peap_version); - if ((flags & EAP_TLS_VERSION_MASK) < data->peap_version) - data->peap_version = flags & EAP_TLS_VERSION_MASK; - if (data->force_peap_version >= 0 && - data->force_peap_version != data->peap_version) { - wpa_printf(MSG_WARNING, "EAP-PEAP: Failed to select " - "forced PEAP version %d", - data->force_peap_version); - ret->methodState = METHOD_DONE; - ret->decision = DECISION_FAIL; - ret->allowNotifications = FALSE; - return NULL; - } - wpa_printf(MSG_DEBUG, "EAP-PEAP: Using PEAP version %d", - data->peap_version); - left = 0; /* make sure that this frame is empty, even though it - * should always be, anyway */ - } - - resp = NULL; - if (tls_connection_established(sm->ssl_ctx, data->ssl.conn) && - !data->resuming) { - struct wpabuf msg; - wpabuf_set(&msg, pos, left); - res = eap_peap_decrypt(sm, data, ret, req, &msg, &resp); - } else { - res = eap_peer_tls_process_helper(sm, &data->ssl, - EAP_TYPE_PEAP, - data->peap_version, id, pos, - left, &resp); - - if (tls_connection_established(sm->ssl_ctx, data->ssl.conn)) { - char *label; - wpa_printf(MSG_DEBUG, - "EAP-PEAP: TLS done, proceed to Phase 2"); - os_free(data->key_data); - /* draft-josefsson-ppext-eap-tls-eap-05.txt - * specifies that PEAPv1 would use "client PEAP - * encryption" as the label. However, most existing - * PEAPv1 implementations seem to be using the old - * label, "client EAP encryption", instead. Use the old - * label by default, but allow it to be configured with - * phase1 parameter peaplabel=1. */ - if (data->peap_version > 1 || data->force_new_label) - label = "client PEAP encryption"; - else - label = "client EAP encryption"; - wpa_printf(MSG_DEBUG, "EAP-PEAP: using label '%s' in " - "key derivation", label); - data->key_data = - eap_peer_tls_derive_key(sm, &data->ssl, label, - EAP_TLS_KEY_LEN); - if (data->key_data) { - wpa_hexdump_key(MSG_DEBUG, - "EAP-PEAP: Derived key", - data->key_data, - EAP_TLS_KEY_LEN); - } else { - wpa_printf(MSG_DEBUG, "EAP-PEAP: Failed to " - "derive key"); - } - - if (sm->workaround && data->resuming) { - /* - * At least few RADIUS servers (Aegis v1.1.6; - * but not v1.1.4; and Cisco ACS) seem to be - * terminating PEAPv1 (Aegis) or PEAPv0 (Cisco - * ACS) session resumption with outer - * EAP-Success. This does not seem to follow - * draft-josefsson-pppext-eap-tls-eap-05.txt - * section 4.2, so only allow this if EAP - * workarounds are enabled. - */ - wpa_printf(MSG_DEBUG, "EAP-PEAP: Workaround - " - "allow outer EAP-Success to " - "terminate PEAP resumption"); - ret->decision = DECISION_COND_SUCC; - data->phase2_success = 1; - } - - data->resuming = 0; - } - - if (res == 2) { - struct wpabuf msg; - /* - * Application data included in the handshake message. - */ - wpabuf_free(data->pending_phase2_req); - data->pending_phase2_req = resp; - resp = NULL; - wpabuf_set(&msg, pos, left); - res = eap_peap_decrypt(sm, data, ret, req, &msg, - &resp); - } - } - - if (ret->methodState == METHOD_DONE) { - ret->allowNotifications = FALSE; - } - - if (res == 1) { - wpabuf_free(resp); - return eap_peer_tls_build_ack(id, EAP_TYPE_PEAP, - data->peap_version); - } - - return resp; -} - - -static Boolean eap_peap_has_reauth_data(struct eap_sm *sm, void *priv) -{ - struct eap_peap_data *data = priv; - return tls_connection_established(sm->ssl_ctx, data->ssl.conn) && - data->phase2_success; -} - - -static void eap_peap_deinit_for_reauth(struct eap_sm *sm, void *priv) -{ - struct eap_peap_data *data = priv; - wpabuf_free(data->pending_phase2_req); - data->pending_phase2_req = NULL; - data->crypto_binding_used = 0; -} - - -static void * eap_peap_init_for_reauth(struct eap_sm *sm, void *priv) -{ - struct eap_peap_data *data = priv; - os_free(data->key_data); - data->key_data = NULL; - if (eap_peer_tls_reauth_init(sm, &data->ssl)) { - os_free(data); - return NULL; - } - if (data->phase2_priv && data->phase2_method && - data->phase2_method->init_for_reauth) - data->phase2_method->init_for_reauth(sm, data->phase2_priv); - data->phase2_success = 0; - data->phase2_eap_success = 0; - data->phase2_eap_started = 0; - data->resuming = 1; - data->reauth = 1; - sm->peap_done = FALSE; - return priv; -} - - -static int eap_peap_get_status(struct eap_sm *sm, void *priv, char *buf, - size_t buflen, int verbose) -{ - struct eap_peap_data *data = priv; - int len, ret; - - len = eap_peer_tls_status(sm, &data->ssl, buf, buflen, verbose); - if (data->phase2_method) { - ret = os_snprintf(buf + len, buflen - len, - "EAP-PEAPv%d Phase2 method=%s\n", - data->peap_version, - data->phase2_method->name); - if (ret < 0 || (size_t) ret >= buflen - len) - return len; - len += ret; - } - return len; -} - - -static Boolean eap_peap_isKeyAvailable(struct eap_sm *sm, void *priv) -{ - struct eap_peap_data *data = priv; - return data->key_data != NULL && data->phase2_success; -} - - -static u8 * eap_peap_getKey(struct eap_sm *sm, void *priv, size_t *len) -{ - struct eap_peap_data *data = priv; - u8 *key; - - if (data->key_data == NULL || !data->phase2_success) - return NULL; - - key = os_malloc(EAP_TLS_KEY_LEN); - if (key == NULL) - return NULL; - - *len = EAP_TLS_KEY_LEN; - - if (data->crypto_binding_used) { - u8 csk[128]; - /* - * Note: It looks like Microsoft implementation requires null - * termination for this label while the one used for deriving - * IPMK|CMK did not use null termination. - */ - peap_prfplus(data->peap_version, data->ipmk, 40, - "Session Key Generating Function", - (u8 *) "\00", 1, csk, sizeof(csk)); - wpa_hexdump_key(MSG_DEBUG, "EAP-PEAP: CSK", csk, sizeof(csk)); - os_memcpy(key, csk, EAP_TLS_KEY_LEN); - wpa_hexdump(MSG_DEBUG, "EAP-PEAP: Derived key", - key, EAP_TLS_KEY_LEN); - } else - os_memcpy(key, data->key_data, EAP_TLS_KEY_LEN); - - return key; -} - - -int eap_peer_peap_register(void) -{ - struct eap_method *eap; - int ret; - - eap = eap_peer_method_alloc(EAP_PEER_METHOD_INTERFACE_VERSION, - EAP_VENDOR_IETF, EAP_TYPE_PEAP, "PEAP"); - if (eap == NULL) - return -1; - - eap->init = eap_peap_init; - eap->deinit = eap_peap_deinit; - eap->process = eap_peap_process; - eap->isKeyAvailable = eap_peap_isKeyAvailable; - eap->getKey = eap_peap_getKey; - eap->get_status = eap_peap_get_status; - eap->has_reauth_data = eap_peap_has_reauth_data; - eap->deinit_for_reauth = eap_peap_deinit_for_reauth; - eap->init_for_reauth = eap_peap_init_for_reauth; - - ret = eap_peer_method_register(eap); - if (ret) - eap_peer_method_free(eap); - return ret; -} diff --git a/hostapd-0.8/src/eap_peer/eap_psk.c b/hostapd-0.8/src/eap_peer/eap_psk.c deleted file mode 100644 index 592ef13..0000000 --- a/hostapd-0.8/src/eap_peer/eap_psk.c +++ /dev/null @@ -1,483 +0,0 @@ -/* - * EAP peer method: EAP-PSK (RFC 4764) - * Copyright (c) 2004-2008, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - * - * Note: EAP-PSK is an EAP authentication method and as such, completely - * different from WPA-PSK. This file is not needed for WPA-PSK functionality. - */ - -#include "includes.h" - -#include "common.h" -#include "crypto/aes_wrap.h" -#include "crypto/random.h" -#include "eap_common/eap_psk_common.h" -#include "eap_i.h" - - -struct eap_psk_data { - enum { PSK_INIT, PSK_MAC_SENT, PSK_DONE } state; - u8 rand_p[EAP_PSK_RAND_LEN]; - u8 ak[EAP_PSK_AK_LEN], kdk[EAP_PSK_KDK_LEN], tek[EAP_PSK_TEK_LEN]; - u8 *id_s, *id_p; - size_t id_s_len, id_p_len; - u8 msk[EAP_MSK_LEN]; - u8 emsk[EAP_EMSK_LEN]; -}; - - -static void * eap_psk_init(struct eap_sm *sm) -{ - struct eap_psk_data *data; - const u8 *identity, *password; - size_t identity_len, password_len; - - password = eap_get_config_password(sm, &password_len); - if (!password || password_len != 16) { - wpa_printf(MSG_INFO, "EAP-PSK: 16-octet pre-shared key not " - "configured"); - return NULL; - } - - data = os_zalloc(sizeof(*data)); - if (data == NULL) - return NULL; - if (eap_psk_key_setup(password, data->ak, data->kdk)) { - os_free(data); - return NULL; - } - wpa_hexdump_key(MSG_DEBUG, "EAP-PSK: AK", data->ak, EAP_PSK_AK_LEN); - wpa_hexdump_key(MSG_DEBUG, "EAP-PSK: KDK", data->kdk, EAP_PSK_KDK_LEN); - data->state = PSK_INIT; - - identity = eap_get_config_identity(sm, &identity_len); - if (identity) { - data->id_p = os_malloc(identity_len); - if (data->id_p) - os_memcpy(data->id_p, identity, identity_len); - data->id_p_len = identity_len; - } - if (data->id_p == NULL) { - wpa_printf(MSG_INFO, "EAP-PSK: could not get own identity"); - os_free(data); - return NULL; - } - - return data; -} - - -static void eap_psk_deinit(struct eap_sm *sm, void *priv) -{ - struct eap_psk_data *data = priv; - os_free(data->id_s); - os_free(data->id_p); - os_free(data); -} - - -static struct wpabuf * eap_psk_process_1(struct eap_psk_data *data, - struct eap_method_ret *ret, - const struct wpabuf *reqData) -{ - const struct eap_psk_hdr_1 *hdr1; - struct eap_psk_hdr_2 *hdr2; - struct wpabuf *resp; - u8 *buf, *pos; - size_t buflen, len; - const u8 *cpos; - - wpa_printf(MSG_DEBUG, "EAP-PSK: in INIT state"); - - cpos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_PSK, reqData, &len); - hdr1 = (const struct eap_psk_hdr_1 *) cpos; - if (cpos == NULL || len < sizeof(*hdr1)) { - wpa_printf(MSG_INFO, "EAP-PSK: Invalid first message " - "length (%lu; expected %lu or more)", - (unsigned long) len, - (unsigned long) sizeof(*hdr1)); - ret->ignore = TRUE; - return NULL; - } - wpa_printf(MSG_DEBUG, "EAP-PSK: Flags=0x%x", hdr1->flags); - if (EAP_PSK_FLAGS_GET_T(hdr1->flags) != 0) { - wpa_printf(MSG_INFO, "EAP-PSK: Unexpected T=%d (expected 0)", - EAP_PSK_FLAGS_GET_T(hdr1->flags)); - ret->methodState = METHOD_DONE; - ret->decision = DECISION_FAIL; - return NULL; - } - wpa_hexdump(MSG_DEBUG, "EAP-PSK: RAND_S", hdr1->rand_s, - EAP_PSK_RAND_LEN); - os_free(data->id_s); - data->id_s_len = len - sizeof(*hdr1); - data->id_s = os_malloc(data->id_s_len); - if (data->id_s == NULL) { - wpa_printf(MSG_ERROR, "EAP-PSK: Failed to allocate memory for " - "ID_S (len=%lu)", (unsigned long) data->id_s_len); - ret->ignore = TRUE; - return NULL; - } - os_memcpy(data->id_s, (u8 *) (hdr1 + 1), data->id_s_len); - wpa_hexdump_ascii(MSG_DEBUG, "EAP-PSK: ID_S", - data->id_s, data->id_s_len); - - if (random_get_bytes(data->rand_p, EAP_PSK_RAND_LEN)) { - wpa_printf(MSG_ERROR, "EAP-PSK: Failed to get random data"); - ret->ignore = TRUE; - return NULL; - } - - resp = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_PSK, - sizeof(*hdr2) + data->id_p_len, EAP_CODE_RESPONSE, - eap_get_id(reqData)); - if (resp == NULL) - return NULL; - hdr2 = wpabuf_put(resp, sizeof(*hdr2)); - hdr2->flags = EAP_PSK_FLAGS_SET_T(1); /* T=1 */ - os_memcpy(hdr2->rand_s, hdr1->rand_s, EAP_PSK_RAND_LEN); - os_memcpy(hdr2->rand_p, data->rand_p, EAP_PSK_RAND_LEN); - wpabuf_put_data(resp, data->id_p, data->id_p_len); - /* MAC_P = OMAC1-AES-128(AK, ID_P||ID_S||RAND_S||RAND_P) */ - buflen = data->id_p_len + data->id_s_len + 2 * EAP_PSK_RAND_LEN; - buf = os_malloc(buflen); - if (buf == NULL) { - wpabuf_free(resp); - return NULL; - } - os_memcpy(buf, data->id_p, data->id_p_len); - pos = buf + data->id_p_len; - os_memcpy(pos, data->id_s, data->id_s_len); - pos += data->id_s_len; - os_memcpy(pos, hdr1->rand_s, EAP_PSK_RAND_LEN); - pos += EAP_PSK_RAND_LEN; - os_memcpy(pos, data->rand_p, EAP_PSK_RAND_LEN); - if (omac1_aes_128(data->ak, buf, buflen, hdr2->mac_p)) { - os_free(buf); - wpabuf_free(resp); - return NULL; - } - os_free(buf); - wpa_hexdump(MSG_DEBUG, "EAP-PSK: RAND_P", hdr2->rand_p, - EAP_PSK_RAND_LEN); - wpa_hexdump(MSG_DEBUG, "EAP-PSK: MAC_P", hdr2->mac_p, EAP_PSK_MAC_LEN); - wpa_hexdump_ascii(MSG_DEBUG, "EAP-PSK: ID_P", - data->id_p, data->id_p_len); - - data->state = PSK_MAC_SENT; - - return resp; -} - - -static struct wpabuf * eap_psk_process_3(struct eap_psk_data *data, - struct eap_method_ret *ret, - const struct wpabuf *reqData) -{ - const struct eap_psk_hdr_3 *hdr3; - struct eap_psk_hdr_4 *hdr4; - struct wpabuf *resp; - u8 *buf, *rpchannel, nonce[16], *decrypted; - const u8 *pchannel, *tag, *msg; - u8 mac[EAP_PSK_MAC_LEN]; - size_t buflen, left, data_len, len, plen; - int failed = 0; - const u8 *pos; - - wpa_printf(MSG_DEBUG, "EAP-PSK: in MAC_SENT state"); - - pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_PSK, - reqData, &len); - hdr3 = (const struct eap_psk_hdr_3 *) pos; - if (pos == NULL || len < sizeof(*hdr3)) { - wpa_printf(MSG_INFO, "EAP-PSK: Invalid third message " - "length (%lu; expected %lu or more)", - (unsigned long) len, - (unsigned long) sizeof(*hdr3)); - ret->ignore = TRUE; - return NULL; - } - left = len - sizeof(*hdr3); - pchannel = (const u8 *) (hdr3 + 1); - wpa_printf(MSG_DEBUG, "EAP-PSK: Flags=0x%x", hdr3->flags); - if (EAP_PSK_FLAGS_GET_T(hdr3->flags) != 2) { - wpa_printf(MSG_INFO, "EAP-PSK: Unexpected T=%d (expected 2)", - EAP_PSK_FLAGS_GET_T(hdr3->flags)); - ret->methodState = METHOD_DONE; - ret->decision = DECISION_FAIL; - return NULL; - } - wpa_hexdump(MSG_DEBUG, "EAP-PSK: RAND_S", hdr3->rand_s, - EAP_PSK_RAND_LEN); - wpa_hexdump(MSG_DEBUG, "EAP-PSK: MAC_S", hdr3->mac_s, EAP_PSK_MAC_LEN); - wpa_hexdump(MSG_DEBUG, "EAP-PSK: PCHANNEL", pchannel, left); - - if (left < 4 + 16 + 1) { - wpa_printf(MSG_INFO, "EAP-PSK: Too short PCHANNEL data in " - "third message (len=%lu, expected 21)", - (unsigned long) left); - ret->ignore = TRUE; - return NULL; - } - - /* MAC_S = OMAC1-AES-128(AK, ID_S||RAND_P) */ - buflen = data->id_s_len + EAP_PSK_RAND_LEN; - buf = os_malloc(buflen); - if (buf == NULL) - return NULL; - os_memcpy(buf, data->id_s, data->id_s_len); - os_memcpy(buf + data->id_s_len, data->rand_p, EAP_PSK_RAND_LEN); - if (omac1_aes_128(data->ak, buf, buflen, mac)) { - os_free(buf); - return NULL; - } - os_free(buf); - if (os_memcmp(mac, hdr3->mac_s, EAP_PSK_MAC_LEN) != 0) { - wpa_printf(MSG_WARNING, "EAP-PSK: Invalid MAC_S in third " - "message"); - ret->methodState = METHOD_DONE; - ret->decision = DECISION_FAIL; - return NULL; - } - wpa_printf(MSG_DEBUG, "EAP-PSK: MAC_S verified successfully"); - - if (eap_psk_derive_keys(data->kdk, data->rand_p, data->tek, - data->msk, data->emsk)) { - ret->methodState = METHOD_DONE; - ret->decision = DECISION_FAIL; - return NULL; - } - wpa_hexdump_key(MSG_DEBUG, "EAP-PSK: TEK", data->tek, EAP_PSK_TEK_LEN); - wpa_hexdump_key(MSG_DEBUG, "EAP-PSK: MSK", data->msk, EAP_MSK_LEN); - wpa_hexdump_key(MSG_DEBUG, "EAP-PSK: EMSK", data->emsk, EAP_EMSK_LEN); - - os_memset(nonce, 0, 12); - os_memcpy(nonce + 12, pchannel, 4); - pchannel += 4; - left -= 4; - - tag = pchannel; - pchannel += 16; - left -= 16; - - msg = pchannel; - - wpa_hexdump(MSG_MSGDUMP, "EAP-PSK: PCHANNEL - nonce", - nonce, sizeof(nonce)); - wpa_hexdump(MSG_MSGDUMP, "EAP-PSK: PCHANNEL - hdr", - wpabuf_head(reqData), 5); - wpa_hexdump(MSG_MSGDUMP, "EAP-PSK: PCHANNEL - cipher msg", msg, left); - - decrypted = os_malloc(left); - if (decrypted == NULL) { - ret->methodState = METHOD_DONE; - ret->decision = DECISION_FAIL; - return NULL; - } - os_memcpy(decrypted, msg, left); - - if (aes_128_eax_decrypt(data->tek, nonce, sizeof(nonce), - wpabuf_head(reqData), - sizeof(struct eap_hdr) + 1 + - sizeof(*hdr3) - EAP_PSK_MAC_LEN, decrypted, - left, tag)) { - wpa_printf(MSG_WARNING, "EAP-PSK: PCHANNEL decryption failed"); - os_free(decrypted); - return NULL; - } - wpa_hexdump(MSG_DEBUG, "EAP-PSK: Decrypted PCHANNEL message", - decrypted, left); - - /* Verify R flag */ - switch (decrypted[0] >> 6) { - case EAP_PSK_R_FLAG_CONT: - wpa_printf(MSG_DEBUG, "EAP-PSK: R flag - CONT - unsupported"); - failed = 1; - break; - case EAP_PSK_R_FLAG_DONE_SUCCESS: - wpa_printf(MSG_DEBUG, "EAP-PSK: R flag - DONE_SUCCESS"); - break; - case EAP_PSK_R_FLAG_DONE_FAILURE: - wpa_printf(MSG_DEBUG, "EAP-PSK: R flag - DONE_FAILURE"); - wpa_printf(MSG_INFO, "EAP-PSK: Authentication server rejected " - "authentication"); - failed = 1; - break; - } - - data_len = 1; - if ((decrypted[0] & EAP_PSK_E_FLAG) && left > 1) - data_len++; - plen = sizeof(*hdr4) + 4 + 16 + data_len; - resp = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_PSK, plen, - EAP_CODE_RESPONSE, eap_get_id(reqData)); - if (resp == NULL) { - os_free(decrypted); - return NULL; - } - hdr4 = wpabuf_put(resp, sizeof(*hdr4)); - hdr4->flags = EAP_PSK_FLAGS_SET_T(3); /* T=3 */ - os_memcpy(hdr4->rand_s, hdr3->rand_s, EAP_PSK_RAND_LEN); - rpchannel = wpabuf_put(resp, 4 + 16 + data_len); - - /* nonce++ */ - inc_byte_array(nonce, sizeof(nonce)); - os_memcpy(rpchannel, nonce + 12, 4); - - if (decrypted[0] & EAP_PSK_E_FLAG) { - wpa_printf(MSG_DEBUG, "EAP-PSK: Unsupported E (Ext) flag"); - failed = 1; - rpchannel[4 + 16] = (EAP_PSK_R_FLAG_DONE_FAILURE << 6) | - EAP_PSK_E_FLAG; - if (left > 1) { - /* Add empty EXT_Payload with same EXT_Type */ - rpchannel[4 + 16 + 1] = decrypted[1]; - } - } else if (failed) - rpchannel[4 + 16] = EAP_PSK_R_FLAG_DONE_FAILURE << 6; - else - rpchannel[4 + 16] = EAP_PSK_R_FLAG_DONE_SUCCESS << 6; - - wpa_hexdump(MSG_DEBUG, "EAP-PSK: reply message (plaintext)", - rpchannel + 4 + 16, data_len); - if (aes_128_eax_encrypt(data->tek, nonce, sizeof(nonce), - wpabuf_head(resp), - sizeof(struct eap_hdr) + 1 + sizeof(*hdr4), - rpchannel + 4 + 16, data_len, rpchannel + 4)) { - os_free(decrypted); - wpabuf_free(resp); - return NULL; - } - wpa_hexdump(MSG_DEBUG, "EAP-PSK: reply message (PCHANNEL)", - rpchannel, 4 + 16 + data_len); - - wpa_printf(MSG_DEBUG, "EAP-PSK: Completed %ssuccessfully", - failed ? "un" : ""); - data->state = PSK_DONE; - ret->methodState = METHOD_DONE; - ret->decision = failed ? DECISION_FAIL : DECISION_UNCOND_SUCC; - - os_free(decrypted); - - return resp; -} - - -static struct wpabuf * eap_psk_process(struct eap_sm *sm, void *priv, - struct eap_method_ret *ret, - const struct wpabuf *reqData) -{ - struct eap_psk_data *data = priv; - const u8 *pos; - struct wpabuf *resp = NULL; - size_t len; - - pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_PSK, reqData, &len); - if (pos == NULL) { - ret->ignore = TRUE; - return NULL; - } - - ret->ignore = FALSE; - ret->methodState = METHOD_MAY_CONT; - ret->decision = DECISION_FAIL; - ret->allowNotifications = TRUE; - - switch (data->state) { - case PSK_INIT: - resp = eap_psk_process_1(data, ret, reqData); - break; - case PSK_MAC_SENT: - resp = eap_psk_process_3(data, ret, reqData); - break; - case PSK_DONE: - wpa_printf(MSG_DEBUG, "EAP-PSK: in DONE state - ignore " - "unexpected message"); - ret->ignore = TRUE; - return NULL; - } - - if (ret->methodState == METHOD_DONE) { - ret->allowNotifications = FALSE; - } - - return resp; -} - - -static Boolean eap_psk_isKeyAvailable(struct eap_sm *sm, void *priv) -{ - struct eap_psk_data *data = priv; - return data->state == PSK_DONE; -} - - -static u8 * eap_psk_getKey(struct eap_sm *sm, void *priv, size_t *len) -{ - struct eap_psk_data *data = priv; - u8 *key; - - if (data->state != PSK_DONE) - return NULL; - - key = os_malloc(EAP_MSK_LEN); - if (key == NULL) - return NULL; - - *len = EAP_MSK_LEN; - os_memcpy(key, data->msk, EAP_MSK_LEN); - - return key; -} - - -static u8 * eap_psk_get_emsk(struct eap_sm *sm, void *priv, size_t *len) -{ - struct eap_psk_data *data = priv; - u8 *key; - - if (data->state != PSK_DONE) - return NULL; - - key = os_malloc(EAP_EMSK_LEN); - if (key == NULL) - return NULL; - - *len = EAP_EMSK_LEN; - os_memcpy(key, data->emsk, EAP_EMSK_LEN); - - return key; -} - - -int eap_peer_psk_register(void) -{ - struct eap_method *eap; - int ret; - - eap = eap_peer_method_alloc(EAP_PEER_METHOD_INTERFACE_VERSION, - EAP_VENDOR_IETF, EAP_TYPE_PSK, "PSK"); - if (eap == NULL) - return -1; - - eap->init = eap_psk_init; - eap->deinit = eap_psk_deinit; - eap->process = eap_psk_process; - eap->isKeyAvailable = eap_psk_isKeyAvailable; - eap->getKey = eap_psk_getKey; - eap->get_emsk = eap_psk_get_emsk; - - ret = eap_peer_method_register(eap); - if (ret) - eap_peer_method_free(eap); - return ret; -} diff --git a/hostapd-0.8/src/eap_peer/eap_pwd.c b/hostapd-0.8/src/eap_peer/eap_pwd.c deleted file mode 100644 index e4705b7..0000000 --- a/hostapd-0.8/src/eap_peer/eap_pwd.c +++ /dev/null @@ -1,744 +0,0 @@ -/* - * EAP peer method: EAP-pwd (RFC 5931) - * Copyright (c) 2010, Dan Harkins - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the BSD license. - * - * Alternatively, this software may be distributed under the terms of the - * GNU General Public License version 2 as published by the Free Software - * Foundation. - * - * See README and COPYING for more details. - */ - -#include "includes.h" - -#include "common.h" -#include "eap_peer/eap_i.h" -#include "eap_common/eap_pwd_common.h" - - -struct eap_pwd_data { - enum { - PWD_ID_Req, PWD_Commit_Req, PWD_Confirm_Req, SUCCESS, FAILURE - } state; - u8 *id_peer; - size_t id_peer_len; - u8 *id_server; - size_t id_server_len; - u8 *password; - size_t password_len; - u16 group_num; - EAP_PWD_group *grp; - - BIGNUM *k; - BIGNUM *private_value; - BIGNUM *server_scalar; - BIGNUM *my_scalar; - EC_POINT *my_element; - EC_POINT *server_element; - - u8 msk[EAP_MSK_LEN]; - u8 emsk[EAP_EMSK_LEN]; - - BN_CTX *bnctx; -}; - - -#ifndef CONFIG_NO_STDOUT_DEBUG -static const char * eap_pwd_state_txt(int state) -{ - switch (state) { - case PWD_ID_Req: - return "PWD-ID-Req"; - case PWD_Commit_Req: - return "PWD-Commit-Req"; - case PWD_Confirm_Req: - return "PWD-Confirm-Req"; - case SUCCESS: - return "SUCCESS"; - case FAILURE: - return "FAILURE"; - default: - return "PWD-UNK"; - } -} -#endif /* CONFIG_NO_STDOUT_DEBUG */ - - -static void eap_pwd_state(struct eap_pwd_data *data, int state) -{ - wpa_printf(MSG_INFO, "EAP-PWD: %s -> %s", - eap_pwd_state_txt(data->state), eap_pwd_state_txt(state)); - data->state = state; -} - - -static void * eap_pwd_init(struct eap_sm *sm) -{ - struct eap_pwd_data *data; - const u8 *identity, *password; - size_t identity_len, password_len; - - password = eap_get_config_password(sm, &password_len); - if (password == NULL) { - wpa_printf(MSG_INFO, "EAP-PWD: No password configured!"); - return NULL; - } - - identity = eap_get_config_identity(sm, &identity_len); - if (identity == NULL) { - wpa_printf(MSG_INFO, "EAP-PWD: No identity configured!"); - return NULL; - } - - if ((data = os_zalloc(sizeof(*data))) == NULL) { - wpa_printf(MSG_INFO, "EAP-PWD: memory allocation data fail"); - return NULL; - } - - if ((data->bnctx = BN_CTX_new()) == NULL) { - wpa_printf(MSG_INFO, "EAP-PWD: bn context allocation fail"); - os_free(data); - return NULL; - } - - if ((data->id_peer = os_malloc(identity_len)) == NULL) { - wpa_printf(MSG_INFO, "EAP-PWD: memory allocation id fail"); - BN_CTX_free(data->bnctx); - os_free(data); - return NULL; - } - - os_memcpy(data->id_peer, identity, identity_len); - data->id_peer_len = identity_len; - - if ((data->password = os_malloc(password_len)) == NULL) { - wpa_printf(MSG_INFO, "EAP-PWD: memory allocation psk fail"); - BN_CTX_free(data->bnctx); - os_free(data->id_peer); - os_free(data); - return NULL; - } - os_memcpy(data->password, password, password_len); - data->password_len = password_len; - - data->state = PWD_ID_Req; - - return data; -} - - -static void eap_pwd_deinit(struct eap_sm *sm, void *priv) -{ - struct eap_pwd_data *data = priv; - - BN_free(data->private_value); - BN_free(data->server_scalar); - BN_free(data->my_scalar); - BN_free(data->k); - BN_CTX_free(data->bnctx); - EC_POINT_free(data->my_element); - EC_POINT_free(data->server_element); - os_free(data->id_peer); - os_free(data->id_server); - os_free(data->password); - if (data->grp) { - EC_GROUP_free(data->grp->group); - EC_POINT_free(data->grp->pwe); - BN_free(data->grp->order); - BN_free(data->grp->prime); - os_free(data->grp); - } - os_free(data); -} - - -static u8 * eap_pwd_getkey(struct eap_sm *sm, void *priv, size_t *len) -{ - struct eap_pwd_data *data = priv; - u8 *key; - - if (data->state != SUCCESS) - return NULL; - - key = os_malloc(EAP_MSK_LEN); - if (key == NULL) - return NULL; - - os_memcpy(key, data->msk, EAP_MSK_LEN); - *len = EAP_MSK_LEN; - - return key; -} - - -static struct wpabuf * -eap_pwd_perform_id_exchange(struct eap_sm *sm, struct eap_pwd_data *data, - struct eap_method_ret *ret, - const struct wpabuf *reqData, - const u8 *payload, size_t payload_len) -{ - struct eap_pwd_id *id; - struct wpabuf *resp; - - if (data->state != PWD_ID_Req) { - ret->ignore = TRUE; - return NULL; - } - - if (payload_len < sizeof(struct eap_pwd_id)) { - ret->ignore = TRUE; - return NULL; - } - - id = (struct eap_pwd_id *) payload; - data->group_num = be_to_host16(id->group_num); - if ((id->random_function != EAP_PWD_DEFAULT_RAND_FUNC) || - (id->prf != EAP_PWD_DEFAULT_PRF)) { - ret->ignore = TRUE; - return NULL; - } - - wpa_printf(MSG_DEBUG, "EAP-PWD (peer): server said group %d", - data->group_num); - - data->id_server = os_malloc(payload_len - sizeof(struct eap_pwd_id)); - if (data->id_server == NULL) { - wpa_printf(MSG_INFO, "EAP-PWD: memory allocation id fail"); - return NULL; - } - data->id_server_len = payload_len - sizeof(struct eap_pwd_id); - os_memcpy(data->id_server, id->identity, data->id_server_len); - wpa_hexdump_ascii(MSG_INFO, "EAP-PWD (peer): server sent id of", - data->id_server, data->id_server_len); - - if ((data->grp = (EAP_PWD_group *) os_malloc(sizeof(EAP_PWD_group))) == - NULL) { - wpa_printf(MSG_INFO, "EAP-PWD: failed to allocate memory for " - "group"); - return NULL; - } - - /* compute PWE */ - if (compute_password_element(data->grp, data->group_num, - data->password, data->password_len, - data->id_server, data->id_server_len, - data->id_peer, data->id_peer_len, - id->token)) { - wpa_printf(MSG_INFO, "EAP-PWD (peer): unable to compute PWE"); - return NULL; - } - - wpa_printf(MSG_INFO, "EAP-PWD (peer): computed %d bit PWE...", - BN_num_bits(data->grp->prime)); - - resp = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_PWD, - 1 + sizeof(struct eap_pwd_id) + data->id_peer_len, - EAP_CODE_RESPONSE, eap_get_id(reqData)); - if (resp == NULL) - return NULL; - - wpabuf_put_u8(resp, EAP_PWD_OPCODE_ID_EXCH); - wpabuf_put_be16(resp, data->group_num); - wpabuf_put_u8(resp, EAP_PWD_DEFAULT_RAND_FUNC); - wpabuf_put_u8(resp, EAP_PWD_DEFAULT_PRF); - wpabuf_put_data(resp, id->token, sizeof(id->token)); - wpabuf_put_u8(resp, EAP_PWD_PREP_NONE); - wpabuf_put_data(resp, data->id_peer, data->id_peer_len); - - eap_pwd_state(data, PWD_Commit_Req); - - return resp; -} - - -static struct wpabuf * -eap_pwd_perform_commit_exchange(struct eap_sm *sm, struct eap_pwd_data *data, - struct eap_method_ret *ret, - const struct wpabuf *reqData, - const u8 *payload, size_t payload_len) -{ - struct wpabuf *resp = NULL; - EC_POINT *K = NULL, *point = NULL; - BIGNUM *mask = NULL, *x = NULL, *y = NULL, *cofactor = NULL; - u16 offset; - u8 *ptr, *scalar = NULL, *element = NULL; - - if (((data->private_value = BN_new()) == NULL) || - ((data->my_element = EC_POINT_new(data->grp->group)) == NULL) || - ((cofactor = BN_new()) == NULL) || - ((data->my_scalar = BN_new()) == NULL) || - ((mask = BN_new()) == NULL)) { - wpa_printf(MSG_INFO, "EAP-PWD (peer): scalar allocation fail"); - goto fin; - } - - if (!EC_GROUP_get_cofactor(data->grp->group, cofactor, NULL)) { - wpa_printf(MSG_INFO, "EAP-pwd (peer): unable to get cofactor " - "for curve"); - goto fin; - } - - BN_rand_range(data->private_value, data->grp->order); - BN_rand_range(mask, data->grp->order); - BN_add(data->my_scalar, data->private_value, mask); - BN_mod(data->my_scalar, data->my_scalar, data->grp->order, - data->bnctx); - - if (!EC_POINT_mul(data->grp->group, data->my_element, NULL, - data->grp->pwe, mask, data->bnctx)) { - wpa_printf(MSG_INFO, "EAP-PWD (peer): element allocation " - "fail"); - eap_pwd_state(data, FAILURE); - goto fin; - } - - if (!EC_POINT_invert(data->grp->group, data->my_element, data->bnctx)) - { - wpa_printf(MSG_INFO, "EAP-PWD (peer): element inversion fail"); - goto fin; - } - BN_free(mask); - - if (((x = BN_new()) == NULL) || - ((y = BN_new()) == NULL)) { - wpa_printf(MSG_INFO, "EAP-PWD (peer): point allocation fail"); - goto fin; - } - - /* process the request */ - if (((data->server_scalar = BN_new()) == NULL) || - ((data->k = BN_new()) == NULL) || - ((K = EC_POINT_new(data->grp->group)) == NULL) || - ((point = EC_POINT_new(data->grp->group)) == NULL) || - ((data->server_element = EC_POINT_new(data->grp->group)) == NULL)) - { - wpa_printf(MSG_INFO, "EAP-PWD (peer): peer data allocation " - "fail"); - goto fin; - } - - /* element, x then y, followed by scalar */ - ptr = (u8 *) payload; - BN_bin2bn(ptr, BN_num_bytes(data->grp->prime), x); - ptr += BN_num_bytes(data->grp->prime); - BN_bin2bn(ptr, BN_num_bytes(data->grp->prime), y); - ptr += BN_num_bytes(data->grp->prime); - BN_bin2bn(ptr, BN_num_bytes(data->grp->order), data->server_scalar); - if (!EC_POINT_set_affine_coordinates_GFp(data->grp->group, - data->server_element, x, y, - data->bnctx)) { - wpa_printf(MSG_INFO, "EAP-PWD (peer): setting peer element " - "fail"); - goto fin; - } - - /* check to ensure server's element is not in a small sub-group */ - if (BN_cmp(cofactor, BN_value_one())) { - if (!EC_POINT_mul(data->grp->group, point, NULL, - data->server_element, cofactor, NULL)) { - wpa_printf(MSG_INFO, "EAP-PWD (peer): cannot multiply " - "server element by order!\n"); - goto fin; - } - if (EC_POINT_is_at_infinity(data->grp->group, point)) { - wpa_printf(MSG_INFO, "EAP-PWD (peer): server element " - "is at infinity!\n"); - goto fin; - } - } - - /* compute the shared key, k */ - if ((!EC_POINT_mul(data->grp->group, K, NULL, data->grp->pwe, - data->server_scalar, data->bnctx)) || - (!EC_POINT_add(data->grp->group, K, K, data->server_element, - data->bnctx)) || - (!EC_POINT_mul(data->grp->group, K, NULL, K, data->private_value, - data->bnctx))) { - wpa_printf(MSG_INFO, "EAP-PWD (peer): computing shared key " - "fail"); - goto fin; - } - - /* ensure that the shared key isn't in a small sub-group */ - if (BN_cmp(cofactor, BN_value_one())) { - if (!EC_POINT_mul(data->grp->group, K, NULL, K, cofactor, - NULL)) { - wpa_printf(MSG_INFO, "EAP-PWD (peer): cannot multiply " - "shared key point by order"); - goto fin; - } - } - - /* - * This check is strictly speaking just for the case above where - * co-factor > 1 but it was suggested that even though this is probably - * never going to happen it is a simple and safe check "just to be - * sure" so let's be safe. - */ - if (EC_POINT_is_at_infinity(data->grp->group, K)) { - wpa_printf(MSG_INFO, "EAP-PWD (peer): shared key point is at " - "infinity!\n"); - goto fin; - } - - if (!EC_POINT_get_affine_coordinates_GFp(data->grp->group, K, data->k, - NULL, data->bnctx)) { - wpa_printf(MSG_INFO, "EAP-PWD (peer): unable to extract " - "shared secret from point"); - goto fin; - } - - /* now do the response */ - if (!EC_POINT_get_affine_coordinates_GFp(data->grp->group, - data->my_element, x, y, - data->bnctx)) { - wpa_printf(MSG_INFO, "EAP-PWD (peer): point assignment fail"); - goto fin; - } - - if (((scalar = os_malloc(BN_num_bytes(data->grp->order))) == NULL) || - ((element = os_malloc(BN_num_bytes(data->grp->prime) * 2)) == - NULL)) { - wpa_printf(MSG_INFO, "EAP-PWD (peer): data allocation fail"); - goto fin; - } - - /* - * bignums occupy as little memory as possible so one that is - * sufficiently smaller than the prime or order might need pre-pending - * with zeros. - */ - os_memset(scalar, 0, BN_num_bytes(data->grp->order)); - os_memset(element, 0, BN_num_bytes(data->grp->prime) * 2); - offset = BN_num_bytes(data->grp->order) - - BN_num_bytes(data->my_scalar); - BN_bn2bin(data->my_scalar, scalar + offset); - - offset = BN_num_bytes(data->grp->prime) - BN_num_bytes(x); - BN_bn2bin(x, element + offset); - offset = BN_num_bytes(data->grp->prime) - BN_num_bytes(y); - BN_bn2bin(y, element + BN_num_bytes(data->grp->prime) + offset); - - resp = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_PWD, - sizeof(struct eap_pwd_hdr) + - BN_num_bytes(data->grp->order) + - (2 * BN_num_bytes(data->grp->prime)), - EAP_CODE_RESPONSE, eap_get_id(reqData)); - if (resp == NULL) - goto fin; - - wpabuf_put_u8(resp, EAP_PWD_OPCODE_COMMIT_EXCH); - - /* we send the element as (x,y) follwed by the scalar */ - wpabuf_put_data(resp, element, (2 * BN_num_bytes(data->grp->prime))); - wpabuf_put_data(resp, scalar, BN_num_bytes(data->grp->order)); - -fin: - os_free(scalar); - os_free(element); - BN_free(x); - BN_free(y); - BN_free(cofactor); - EC_POINT_free(K); - EC_POINT_free(point); - if (resp == NULL) - eap_pwd_state(data, FAILURE); - else - eap_pwd_state(data, PWD_Confirm_Req); - - return resp; -} - - -static struct wpabuf * -eap_pwd_perform_confirm_exchange(struct eap_sm *sm, struct eap_pwd_data *data, - struct eap_method_ret *ret, - const struct wpabuf *reqData, - const u8 *payload, size_t payload_len) -{ - struct wpabuf *resp = NULL; - BIGNUM *x = NULL, *y = NULL; - HMAC_CTX ctx; - u32 cs; - u16 grp; - u8 conf[SHA256_DIGEST_LENGTH], *cruft = NULL, *ptr; - - /* - * first build up the ciphersuite which is group | random_function | - * prf - */ - grp = htons(data->group_num); - ptr = (u8 *) &cs; - os_memcpy(ptr, &grp, sizeof(u16)); - ptr += sizeof(u16); - *ptr = EAP_PWD_DEFAULT_RAND_FUNC; - ptr += sizeof(u8); - *ptr = EAP_PWD_DEFAULT_PRF; - - /* each component of the cruft will be at most as big as the prime */ - if (((cruft = os_malloc(BN_num_bytes(data->grp->prime))) == NULL) || - ((x = BN_new()) == NULL) || ((y = BN_new()) == NULL)) { - wpa_printf(MSG_INFO, "EAP-PWD (server): debug allocation " - "fail"); - goto fin; - } - - /* - * server's commit is H(k | server_element | server_scalar | - * peer_element | peer_scalar | ciphersuite) - */ - H_Init(&ctx); - - /* - * zero the memory each time because this is mod prime math and some - * value may start with a few zeros and the previous one did not. - */ - os_memset(cruft, 0, BN_num_bytes(data->grp->prime)); - BN_bn2bin(data->k, cruft); - H_Update(&ctx, cruft, BN_num_bytes(data->grp->prime)); - - /* server element: x, y */ - if (!EC_POINT_get_affine_coordinates_GFp(data->grp->group, - data->server_element, x, y, - data->bnctx)) { - wpa_printf(MSG_INFO, "EAP-PWD (server): confirm point " - "assignment fail"); - goto fin; - } - os_memset(cruft, 0, BN_num_bytes(data->grp->prime)); - BN_bn2bin(x, cruft); - H_Update(&ctx, cruft, BN_num_bytes(data->grp->prime)); - os_memset(cruft, 0, BN_num_bytes(data->grp->prime)); - BN_bn2bin(y, cruft); - H_Update(&ctx, cruft, BN_num_bytes(data->grp->prime)); - - /* server scalar */ - os_memset(cruft, 0, BN_num_bytes(data->grp->prime)); - BN_bn2bin(data->server_scalar, cruft); - H_Update(&ctx, cruft, BN_num_bytes(data->grp->order)); - - /* my element: x, y */ - if (!EC_POINT_get_affine_coordinates_GFp(data->grp->group, - data->my_element, x, y, - data->bnctx)) { - wpa_printf(MSG_INFO, "EAP-PWD (server): confirm point " - "assignment fail"); - goto fin; - } - - os_memset(cruft, 0, BN_num_bytes(data->grp->prime)); - BN_bn2bin(x, cruft); - H_Update(&ctx, cruft, BN_num_bytes(data->grp->prime)); - os_memset(cruft, 0, BN_num_bytes(data->grp->prime)); - BN_bn2bin(y, cruft); - H_Update(&ctx, cruft, BN_num_bytes(data->grp->prime)); - - /* my scalar */ - os_memset(cruft, 0, BN_num_bytes(data->grp->prime)); - BN_bn2bin(data->my_scalar, cruft); - H_Update(&ctx, cruft, BN_num_bytes(data->grp->order)); - - /* the ciphersuite */ - H_Update(&ctx, (u8 *) &cs, sizeof(u32)); - - /* random function fin */ - H_Final(&ctx, conf); - - ptr = (u8 *) payload; - if (os_memcmp(conf, ptr, SHA256_DIGEST_LENGTH)) { - wpa_printf(MSG_INFO, "EAP-PWD (peer): confirm did not verify"); - goto fin; - } - - wpa_printf(MSG_DEBUG, "EAP-pwd (peer): confirm verified"); - - /* - * compute confirm: - * H(k | peer_element | peer_scalar | server_element | server_scalar | - * ciphersuite) - */ - H_Init(&ctx); - - /* k */ - os_memset(cruft, 0, BN_num_bytes(data->grp->prime)); - BN_bn2bin(data->k, cruft); - H_Update(&ctx, cruft, BN_num_bytes(data->grp->prime)); - - /* my element */ - if (!EC_POINT_get_affine_coordinates_GFp(data->grp->group, - data->my_element, x, y, - data->bnctx)) { - wpa_printf(MSG_INFO, "EAP-PWD (peer): confirm point " - "assignment fail"); - goto fin; - } - os_memset(cruft, 0, BN_num_bytes(data->grp->prime)); - BN_bn2bin(x, cruft); - H_Update(&ctx, cruft, BN_num_bytes(data->grp->prime)); - os_memset(cruft, 0, BN_num_bytes(data->grp->prime)); - BN_bn2bin(y, cruft); - H_Update(&ctx, cruft, BN_num_bytes(data->grp->prime)); - - /* my scalar */ - os_memset(cruft, 0, BN_num_bytes(data->grp->prime)); - BN_bn2bin(data->my_scalar, cruft); - H_Update(&ctx, cruft, BN_num_bytes(data->grp->order)); - - /* server element: x, y */ - if (!EC_POINT_get_affine_coordinates_GFp(data->grp->group, - data->server_element, x, y, - data->bnctx)) { - wpa_printf(MSG_INFO, "EAP-PWD (peer): confirm point " - "assignment fail"); - goto fin; - } - os_memset(cruft, 0, BN_num_bytes(data->grp->prime)); - BN_bn2bin(x, cruft); - H_Update(&ctx, cruft, BN_num_bytes(data->grp->prime)); - os_memset(cruft, 0, BN_num_bytes(data->grp->prime)); - BN_bn2bin(y, cruft); - H_Update(&ctx, cruft, BN_num_bytes(data->grp->prime)); - - /* server scalar */ - os_memset(cruft, 0, BN_num_bytes(data->grp->prime)); - BN_bn2bin(data->server_scalar, cruft); - H_Update(&ctx, cruft, BN_num_bytes(data->grp->order)); - - /* the ciphersuite */ - H_Update(&ctx, (u8 *) &cs, sizeof(u32)); - - /* all done */ - H_Final(&ctx, conf); - - resp = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_PWD, - sizeof(struct eap_pwd_hdr) + SHA256_DIGEST_LENGTH, - EAP_CODE_RESPONSE, eap_get_id(reqData)); - if (resp == NULL) - goto fin; - - wpabuf_put_u8(resp, EAP_PWD_OPCODE_CONFIRM_EXCH); - wpabuf_put_data(resp, conf, SHA256_DIGEST_LENGTH); - - if (compute_keys(data->grp, data->bnctx, data->k, - data->my_scalar, data->server_scalar, conf, ptr, - &cs, data->msk, data->emsk) < 0) { - wpa_printf(MSG_INFO, "EAP-PWD (peer): unable to compute MSK | " - "EMSK"); - goto fin; - } - -fin: - os_free(cruft); - BN_free(x); - BN_free(y); - ret->methodState = METHOD_DONE; - if (resp == NULL) { - ret->decision = DECISION_FAIL; - eap_pwd_state(data, FAILURE); - } else { - ret->decision = DECISION_UNCOND_SUCC; - eap_pwd_state(data, SUCCESS); - } - - return resp; -} - - -static struct wpabuf * -eap_pwd_process(struct eap_sm *sm, void *priv, struct eap_method_ret *ret, - const struct wpabuf *reqData) -{ - struct eap_pwd_data *data = priv; - struct wpabuf *resp = NULL; - const u8 *pos; - size_t len; - u8 exch; - - pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_PWD, reqData, &len); - if ((pos == NULL) || (len < 1)) { - ret->ignore = TRUE; - return NULL; - } - - wpa_printf(MSG_INFO, "EAP-pwd: Received frame: opcode %d", *pos); - - ret->ignore = FALSE; - ret->methodState = METHOD_MAY_CONT; - ret->decision = DECISION_FAIL; - ret->allowNotifications = FALSE; - - exch = *pos & 0x3f; - switch (exch) { - case EAP_PWD_OPCODE_ID_EXCH: - resp = eap_pwd_perform_id_exchange(sm, data, ret, reqData, - pos + 1, len - 1); - break; - case EAP_PWD_OPCODE_COMMIT_EXCH: - resp = eap_pwd_perform_commit_exchange(sm, data, ret, reqData, - pos + 1, len - 1); - break; - case EAP_PWD_OPCODE_CONFIRM_EXCH: - resp = eap_pwd_perform_confirm_exchange(sm, data, ret, reqData, - pos + 1, len - 1); - break; - default: - wpa_printf(MSG_INFO, "EAP-pwd: Ignoring message with unknown " - "opcode %d", exch); - break; - } - - return resp; -} - - -static Boolean eap_pwd_key_available(struct eap_sm *sm, void *priv) -{ - struct eap_pwd_data *data = priv; - return data->state == SUCCESS; -} - - -static u8 * eap_pwd_get_emsk(struct eap_sm *sm, void *priv, size_t *len) -{ - struct eap_pwd_data *data = priv; - u8 *key; - - if (data->state != SUCCESS) - return NULL; - - if ((key = os_malloc(EAP_EMSK_LEN)) == NULL) - return NULL; - - os_memcpy(key, data->emsk, EAP_EMSK_LEN); - *len = EAP_EMSK_LEN; - - return key; -} - - -int eap_peer_pwd_register(void) -{ - struct eap_method *eap; - int ret; - - EVP_add_digest(EVP_sha256()); - eap = eap_peer_method_alloc(EAP_PEER_METHOD_INTERFACE_VERSION, - EAP_VENDOR_IETF, EAP_TYPE_PWD, "PWD"); - if (eap == NULL) - return -1; - - eap->init = eap_pwd_init; - eap->deinit = eap_pwd_deinit; - eap->process = eap_pwd_process; - eap->isKeyAvailable = eap_pwd_key_available; - eap->getKey = eap_pwd_getkey; - eap->get_emsk = eap_pwd_get_emsk; - - ret = eap_peer_method_register(eap); - if (ret) - eap_peer_method_free(eap); - return ret; -} diff --git a/hostapd-0.8/src/eap_peer/eap_sake.c b/hostapd-0.8/src/eap_peer/eap_sake.c deleted file mode 100644 index 1474b7f..0000000 --- a/hostapd-0.8/src/eap_peer/eap_sake.c +++ /dev/null @@ -1,500 +0,0 @@ -/* - * EAP peer method: EAP-SAKE (RFC 4763) - * Copyright (c) 2006-2008, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#include "includes.h" - -#include "common.h" -#include "crypto/random.h" -#include "eap_peer/eap_i.h" -#include "eap_common/eap_sake_common.h" - -struct eap_sake_data { - enum { IDENTITY, CHALLENGE, CONFIRM, SUCCESS, FAILURE } state; - u8 root_secret_a[EAP_SAKE_ROOT_SECRET_LEN]; - u8 root_secret_b[EAP_SAKE_ROOT_SECRET_LEN]; - u8 rand_s[EAP_SAKE_RAND_LEN]; - u8 rand_p[EAP_SAKE_RAND_LEN]; - struct { - u8 auth[EAP_SAKE_TEK_AUTH_LEN]; - u8 cipher[EAP_SAKE_TEK_CIPHER_LEN]; - } tek; - u8 msk[EAP_MSK_LEN]; - u8 emsk[EAP_EMSK_LEN]; - u8 session_id; - int session_id_set; - u8 *peerid; - size_t peerid_len; - u8 *serverid; - size_t serverid_len; -}; - - -static const char * eap_sake_state_txt(int state) -{ - switch (state) { - case IDENTITY: - return "IDENTITY"; - case CHALLENGE: - return "CHALLENGE"; - case CONFIRM: - return "CONFIRM"; - case SUCCESS: - return "SUCCESS"; - case FAILURE: - return "FAILURE"; - default: - return "?"; - } -} - - -static void eap_sake_state(struct eap_sake_data *data, int state) -{ - wpa_printf(MSG_DEBUG, "EAP-SAKE: %s -> %s", - eap_sake_state_txt(data->state), - eap_sake_state_txt(state)); - data->state = state; -} - - -static void eap_sake_deinit(struct eap_sm *sm, void *priv); - - -static void * eap_sake_init(struct eap_sm *sm) -{ - struct eap_sake_data *data; - const u8 *identity, *password; - size_t identity_len, password_len; - - password = eap_get_config_password(sm, &password_len); - if (!password || password_len != 2 * EAP_SAKE_ROOT_SECRET_LEN) { - wpa_printf(MSG_INFO, "EAP-SAKE: No key of correct length " - "configured"); - return NULL; - } - - data = os_zalloc(sizeof(*data)); - if (data == NULL) - return NULL; - data->state = IDENTITY; - - identity = eap_get_config_identity(sm, &identity_len); - if (identity) { - data->peerid = os_malloc(identity_len); - if (data->peerid == NULL) { - eap_sake_deinit(sm, data); - return NULL; - } - os_memcpy(data->peerid, identity, identity_len); - data->peerid_len = identity_len; - } - - os_memcpy(data->root_secret_a, password, EAP_SAKE_ROOT_SECRET_LEN); - os_memcpy(data->root_secret_b, - password + EAP_SAKE_ROOT_SECRET_LEN, - EAP_SAKE_ROOT_SECRET_LEN); - - return data; -} - - -static void eap_sake_deinit(struct eap_sm *sm, void *priv) -{ - struct eap_sake_data *data = priv; - os_free(data->serverid); - os_free(data->peerid); - os_free(data); -} - - -static struct wpabuf * eap_sake_build_msg(struct eap_sake_data *data, - int id, size_t length, u8 subtype) -{ - struct eap_sake_hdr *sake; - struct wpabuf *msg; - size_t plen; - - plen = length + sizeof(struct eap_sake_hdr); - - msg = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_SAKE, plen, - EAP_CODE_RESPONSE, id); - if (msg == NULL) { - wpa_printf(MSG_ERROR, "EAP-SAKE: Failed to allocate memory " - "request"); - return NULL; - } - - sake = wpabuf_put(msg, sizeof(*sake)); - sake->version = EAP_SAKE_VERSION; - sake->session_id = data->session_id; - sake->subtype = subtype; - - return msg; -} - - -static struct wpabuf * eap_sake_process_identity(struct eap_sm *sm, - struct eap_sake_data *data, - struct eap_method_ret *ret, - const struct wpabuf *reqData, - const u8 *payload, - size_t payload_len) -{ - struct eap_sake_parse_attr attr; - struct wpabuf *resp; - - if (data->state != IDENTITY) { - ret->ignore = TRUE; - return NULL; - } - - wpa_printf(MSG_DEBUG, "EAP-SAKE: Received Request/Identity"); - - if (eap_sake_parse_attributes(payload, payload_len, &attr)) - return NULL; - - if (!attr.perm_id_req && !attr.any_id_req) { - wpa_printf(MSG_INFO, "EAP-SAKE: No AT_PERM_ID_REQ or " - "AT_ANY_ID_REQ in Request/Identity"); - return NULL; - } - - wpa_printf(MSG_DEBUG, "EAP-SAKE: Sending Response/Identity"); - - resp = eap_sake_build_msg(data, eap_get_id(reqData), - 2 + data->peerid_len, - EAP_SAKE_SUBTYPE_IDENTITY); - if (resp == NULL) - return NULL; - - wpa_printf(MSG_DEBUG, "EAP-SAKE: * AT_PEERID"); - eap_sake_add_attr(resp, EAP_SAKE_AT_PEERID, - data->peerid, data->peerid_len); - - eap_sake_state(data, CHALLENGE); - - return resp; -} - - -static struct wpabuf * eap_sake_process_challenge(struct eap_sm *sm, - struct eap_sake_data *data, - struct eap_method_ret *ret, - const struct wpabuf *reqData, - const u8 *payload, - size_t payload_len) -{ - struct eap_sake_parse_attr attr; - struct wpabuf *resp; - u8 *rpos; - size_t rlen; - - if (data->state != IDENTITY && data->state != CHALLENGE) { - wpa_printf(MSG_DEBUG, "EAP-SAKE: Request/Challenge received " - "in unexpected state (%d)", data->state); - ret->ignore = TRUE; - return NULL; - } - if (data->state == IDENTITY) - eap_sake_state(data, CHALLENGE); - - wpa_printf(MSG_DEBUG, "EAP-SAKE: Received Request/Challenge"); - - if (eap_sake_parse_attributes(payload, payload_len, &attr)) - return NULL; - - if (!attr.rand_s) { - wpa_printf(MSG_INFO, "EAP-SAKE: Request/Challenge did not " - "include AT_RAND_S"); - return NULL; - } - - os_memcpy(data->rand_s, attr.rand_s, EAP_SAKE_RAND_LEN); - wpa_hexdump(MSG_MSGDUMP, "EAP-SAKE: RAND_S (server rand)", - data->rand_s, EAP_SAKE_RAND_LEN); - - if (random_get_bytes(data->rand_p, EAP_SAKE_RAND_LEN)) { - wpa_printf(MSG_ERROR, "EAP-SAKE: Failed to get random data"); - return NULL; - } - wpa_hexdump(MSG_MSGDUMP, "EAP-SAKE: RAND_P (peer rand)", - data->rand_p, EAP_SAKE_RAND_LEN); - - os_free(data->serverid); - data->serverid = NULL; - data->serverid_len = 0; - if (attr.serverid) { - wpa_hexdump_ascii(MSG_MSGDUMP, "EAP-SAKE: SERVERID", - attr.serverid, attr.serverid_len); - data->serverid = os_malloc(attr.serverid_len); - if (data->serverid == NULL) - return NULL; - os_memcpy(data->serverid, attr.serverid, attr.serverid_len); - data->serverid_len = attr.serverid_len; - } - - eap_sake_derive_keys(data->root_secret_a, data->root_secret_b, - data->rand_s, data->rand_p, - (u8 *) &data->tek, data->msk, data->emsk); - - wpa_printf(MSG_DEBUG, "EAP-SAKE: Sending Response/Challenge"); - - rlen = 2 + EAP_SAKE_RAND_LEN + 2 + EAP_SAKE_MIC_LEN; - if (data->peerid) - rlen += 2 + data->peerid_len; - resp = eap_sake_build_msg(data, eap_get_id(reqData), rlen, - EAP_SAKE_SUBTYPE_CHALLENGE); - if (resp == NULL) - return NULL; - - wpa_printf(MSG_DEBUG, "EAP-SAKE: * AT_RAND_P"); - eap_sake_add_attr(resp, EAP_SAKE_AT_RAND_P, - data->rand_p, EAP_SAKE_RAND_LEN); - - if (data->peerid) { - wpa_printf(MSG_DEBUG, "EAP-SAKE: * AT_PEERID"); - eap_sake_add_attr(resp, EAP_SAKE_AT_PEERID, - data->peerid, data->peerid_len); - } - - wpa_printf(MSG_DEBUG, "EAP-SAKE: * AT_MIC_P"); - wpabuf_put_u8(resp, EAP_SAKE_AT_MIC_P); - wpabuf_put_u8(resp, 2 + EAP_SAKE_MIC_LEN); - rpos = wpabuf_put(resp, EAP_SAKE_MIC_LEN); - if (eap_sake_compute_mic(data->tek.auth, data->rand_s, data->rand_p, - data->serverid, data->serverid_len, - data->peerid, data->peerid_len, 1, - wpabuf_head(resp), wpabuf_len(resp), rpos, - rpos)) { - wpa_printf(MSG_INFO, "EAP-SAKE: Failed to compute MIC"); - wpabuf_free(resp); - return NULL; - } - - eap_sake_state(data, CONFIRM); - - return resp; -} - - -static struct wpabuf * eap_sake_process_confirm(struct eap_sm *sm, - struct eap_sake_data *data, - struct eap_method_ret *ret, - const struct wpabuf *reqData, - const u8 *payload, - size_t payload_len) -{ - struct eap_sake_parse_attr attr; - u8 mic_s[EAP_SAKE_MIC_LEN]; - struct wpabuf *resp; - u8 *rpos; - - if (data->state != CONFIRM) { - ret->ignore = TRUE; - return NULL; - } - - wpa_printf(MSG_DEBUG, "EAP-SAKE: Received Request/Confirm"); - - if (eap_sake_parse_attributes(payload, payload_len, &attr)) - return NULL; - - if (!attr.mic_s) { - wpa_printf(MSG_INFO, "EAP-SAKE: Request/Confirm did not " - "include AT_MIC_S"); - return NULL; - } - - eap_sake_compute_mic(data->tek.auth, data->rand_s, data->rand_p, - data->serverid, data->serverid_len, - data->peerid, data->peerid_len, 0, - wpabuf_head(reqData), wpabuf_len(reqData), - attr.mic_s, mic_s); - if (os_memcmp(attr.mic_s, mic_s, EAP_SAKE_MIC_LEN) != 0) { - wpa_printf(MSG_INFO, "EAP-SAKE: Incorrect AT_MIC_S"); - eap_sake_state(data, FAILURE); - ret->methodState = METHOD_DONE; - ret->decision = DECISION_FAIL; - ret->allowNotifications = FALSE; - wpa_printf(MSG_DEBUG, "EAP-SAKE: Sending " - "Response/Auth-Reject"); - return eap_sake_build_msg(data, eap_get_id(reqData), 0, - EAP_SAKE_SUBTYPE_AUTH_REJECT); - } - - wpa_printf(MSG_DEBUG, "EAP-SAKE: Sending Response/Confirm"); - - resp = eap_sake_build_msg(data, eap_get_id(reqData), - 2 + EAP_SAKE_MIC_LEN, - EAP_SAKE_SUBTYPE_CONFIRM); - if (resp == NULL) - return NULL; - - wpa_printf(MSG_DEBUG, "EAP-SAKE: * AT_MIC_P"); - wpabuf_put_u8(resp, EAP_SAKE_AT_MIC_P); - wpabuf_put_u8(resp, 2 + EAP_SAKE_MIC_LEN); - rpos = wpabuf_put(resp, EAP_SAKE_MIC_LEN); - if (eap_sake_compute_mic(data->tek.auth, data->rand_s, data->rand_p, - data->serverid, data->serverid_len, - data->peerid, data->peerid_len, 1, - wpabuf_head(resp), wpabuf_len(resp), rpos, - rpos)) { - wpa_printf(MSG_INFO, "EAP-SAKE: Failed to compute MIC"); - wpabuf_free(resp); - return NULL; - } - - eap_sake_state(data, SUCCESS); - ret->methodState = METHOD_DONE; - ret->decision = DECISION_UNCOND_SUCC; - ret->allowNotifications = FALSE; - - return resp; -} - - -static struct wpabuf * eap_sake_process(struct eap_sm *sm, void *priv, - struct eap_method_ret *ret, - const struct wpabuf *reqData) -{ - struct eap_sake_data *data = priv; - const struct eap_sake_hdr *req; - struct wpabuf *resp; - const u8 *pos, *end; - size_t len; - u8 subtype, session_id; - - pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_SAKE, reqData, &len); - if (pos == NULL || len < sizeof(struct eap_sake_hdr)) { - ret->ignore = TRUE; - return NULL; - } - - req = (const struct eap_sake_hdr *) pos; - end = pos + len; - subtype = req->subtype; - session_id = req->session_id; - pos = (const u8 *) (req + 1); - - wpa_printf(MSG_DEBUG, "EAP-SAKE: Received frame: subtype %d " - "session_id %d", subtype, session_id); - wpa_hexdump(MSG_DEBUG, "EAP-SAKE: Received attributes", - pos, end - pos); - - if (data->session_id_set && data->session_id != session_id) { - wpa_printf(MSG_INFO, "EAP-SAKE: Session ID mismatch (%d,%d)", - session_id, data->session_id); - ret->ignore = TRUE; - return NULL; - } - data->session_id = session_id; - data->session_id_set = 1; - - ret->ignore = FALSE; - ret->methodState = METHOD_MAY_CONT; - ret->decision = DECISION_FAIL; - ret->allowNotifications = TRUE; - - switch (subtype) { - case EAP_SAKE_SUBTYPE_IDENTITY: - resp = eap_sake_process_identity(sm, data, ret, reqData, - pos, end - pos); - break; - case EAP_SAKE_SUBTYPE_CHALLENGE: - resp = eap_sake_process_challenge(sm, data, ret, reqData, - pos, end - pos); - break; - case EAP_SAKE_SUBTYPE_CONFIRM: - resp = eap_sake_process_confirm(sm, data, ret, reqData, - pos, end - pos); - break; - default: - wpa_printf(MSG_DEBUG, "EAP-SAKE: Ignoring message with " - "unknown subtype %d", subtype); - ret->ignore = TRUE; - return NULL; - } - - if (ret->methodState == METHOD_DONE) - ret->allowNotifications = FALSE; - - return resp; -} - - -static Boolean eap_sake_isKeyAvailable(struct eap_sm *sm, void *priv) -{ - struct eap_sake_data *data = priv; - return data->state == SUCCESS; -} - - -static u8 * eap_sake_getKey(struct eap_sm *sm, void *priv, size_t *len) -{ - struct eap_sake_data *data = priv; - u8 *key; - - if (data->state != SUCCESS) - return NULL; - - key = os_malloc(EAP_MSK_LEN); - if (key == NULL) - return NULL; - os_memcpy(key, data->msk, EAP_MSK_LEN); - *len = EAP_MSK_LEN; - - return key; -} - - -static u8 * eap_sake_get_emsk(struct eap_sm *sm, void *priv, size_t *len) -{ - struct eap_sake_data *data = priv; - u8 *key; - - if (data->state != SUCCESS) - return NULL; - - key = os_malloc(EAP_EMSK_LEN); - if (key == NULL) - return NULL; - os_memcpy(key, data->emsk, EAP_EMSK_LEN); - *len = EAP_EMSK_LEN; - - return key; -} - - -int eap_peer_sake_register(void) -{ - struct eap_method *eap; - int ret; - - eap = eap_peer_method_alloc(EAP_PEER_METHOD_INTERFACE_VERSION, - EAP_VENDOR_IETF, EAP_TYPE_SAKE, "SAKE"); - if (eap == NULL) - return -1; - - eap->init = eap_sake_init; - eap->deinit = eap_sake_deinit; - eap->process = eap_sake_process; - eap->isKeyAvailable = eap_sake_isKeyAvailable; - eap->getKey = eap_sake_getKey; - eap->get_emsk = eap_sake_get_emsk; - - ret = eap_peer_method_register(eap); - if (ret) - eap_peer_method_free(eap); - return ret; -} diff --git a/hostapd-0.8/src/eap_peer/eap_sim.c b/hostapd-0.8/src/eap_peer/eap_sim.c deleted file mode 100644 index 6677063..0000000 --- a/hostapd-0.8/src/eap_peer/eap_sim.c +++ /dev/null @@ -1,1101 +0,0 @@ -/* - * EAP peer method: EAP-SIM (RFC 4186) - * Copyright (c) 2004-2008, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#include "includes.h" - -#include "common.h" -#include "pcsc_funcs.h" -#include "crypto/milenage.h" -#include "crypto/random.h" -#include "eap_peer/eap_i.h" -#include "eap_config.h" -#include "eap_common/eap_sim_common.h" - - -struct eap_sim_data { - u8 *ver_list; - size_t ver_list_len; - int selected_version; - size_t min_num_chal, num_chal; - - u8 kc[3][EAP_SIM_KC_LEN]; - u8 sres[3][EAP_SIM_SRES_LEN]; - u8 nonce_mt[EAP_SIM_NONCE_MT_LEN], nonce_s[EAP_SIM_NONCE_S_LEN]; - u8 mk[EAP_SIM_MK_LEN]; - u8 k_aut[EAP_SIM_K_AUT_LEN]; - u8 k_encr[EAP_SIM_K_ENCR_LEN]; - u8 msk[EAP_SIM_KEYING_DATA_LEN]; - u8 emsk[EAP_EMSK_LEN]; - u8 rand[3][GSM_RAND_LEN]; - - int num_id_req, num_notification; - u8 *pseudonym; - size_t pseudonym_len; - u8 *reauth_id; - size_t reauth_id_len; - int reauth; - unsigned int counter, counter_too_small; - u8 *last_eap_identity; - size_t last_eap_identity_len; - enum { - CONTINUE, RESULT_SUCCESS, RESULT_FAILURE, SUCCESS, FAILURE - } state; - int result_ind, use_result_ind; -}; - - -#ifndef CONFIG_NO_STDOUT_DEBUG -static const char * eap_sim_state_txt(int state) -{ - switch (state) { - case CONTINUE: - return "CONTINUE"; - case RESULT_SUCCESS: - return "RESULT_SUCCESS"; - case RESULT_FAILURE: - return "RESULT_FAILURE"; - case SUCCESS: - return "SUCCESS"; - case FAILURE: - return "FAILURE"; - default: - return "?"; - } -} -#endif /* CONFIG_NO_STDOUT_DEBUG */ - - -static void eap_sim_state(struct eap_sim_data *data, int state) -{ - wpa_printf(MSG_DEBUG, "EAP-SIM: %s -> %s", - eap_sim_state_txt(data->state), - eap_sim_state_txt(state)); - data->state = state; -} - - -static void * eap_sim_init(struct eap_sm *sm) -{ - struct eap_sim_data *data; - struct eap_peer_config *config = eap_get_config(sm); - - data = os_zalloc(sizeof(*data)); - if (data == NULL) - return NULL; - - if (random_get_bytes(data->nonce_mt, EAP_SIM_NONCE_MT_LEN)) { - wpa_printf(MSG_WARNING, "EAP-SIM: Failed to get random data " - "for NONCE_MT"); - os_free(data); - return NULL; - } - - data->min_num_chal = 2; - if (config && config->phase1) { - char *pos = os_strstr(config->phase1, "sim_min_num_chal="); - if (pos) { - data->min_num_chal = atoi(pos + 17); - if (data->min_num_chal < 2 || data->min_num_chal > 3) { - wpa_printf(MSG_WARNING, "EAP-SIM: Invalid " - "sim_min_num_chal configuration " - "(%lu, expected 2 or 3)", - (unsigned long) data->min_num_chal); - os_free(data); - return NULL; - } - wpa_printf(MSG_DEBUG, "EAP-SIM: Set minimum number of " - "challenges to %lu", - (unsigned long) data->min_num_chal); - } - - data->result_ind = os_strstr(config->phase1, "result_ind=1") != - NULL; - } - - eap_sim_state(data, CONTINUE); - - return data; -} - - -static void eap_sim_deinit(struct eap_sm *sm, void *priv) -{ - struct eap_sim_data *data = priv; - if (data) { - os_free(data->ver_list); - os_free(data->pseudonym); - os_free(data->reauth_id); - os_free(data->last_eap_identity); - os_free(data); - } -} - - -static int eap_sim_gsm_auth(struct eap_sm *sm, struct eap_sim_data *data) -{ - struct eap_peer_config *conf; - - wpa_printf(MSG_DEBUG, "EAP-SIM: GSM authentication algorithm"); - - conf = eap_get_config(sm); - if (conf == NULL) - return -1; - if (conf->pcsc) { - if (scard_gsm_auth(sm->scard_ctx, data->rand[0], - data->sres[0], data->kc[0]) || - scard_gsm_auth(sm->scard_ctx, data->rand[1], - data->sres[1], data->kc[1]) || - (data->num_chal > 2 && - scard_gsm_auth(sm->scard_ctx, data->rand[2], - data->sres[2], data->kc[2]))) { - wpa_printf(MSG_DEBUG, "EAP-SIM: GSM SIM " - "authentication could not be completed"); - return -1; - } - return 0; - } - -#ifdef CONFIG_SIM_SIMULATOR - if (conf->password) { - u8 opc[16], k[16]; - const char *pos; - size_t i; - wpa_printf(MSG_DEBUG, "EAP-SIM: Use internal GSM-Milenage " - "implementation for authentication"); - if (conf->password_len < 65) { - wpa_printf(MSG_DEBUG, "EAP-SIM: invalid GSM-Milenage " - "password"); - return -1; - } - pos = (const char *) conf->password; - if (hexstr2bin(pos, k, 16)) - return -1; - pos += 32; - if (*pos != ':') - return -1; - pos++; - - if (hexstr2bin(pos, opc, 16)) - return -1; - - for (i = 0; i < data->num_chal; i++) { - if (gsm_milenage(opc, k, data->rand[i], - data->sres[i], data->kc[i])) { - wpa_printf(MSG_DEBUG, "EAP-SIM: " - "GSM-Milenage authentication " - "could not be completed"); - return -1; - } - wpa_hexdump(MSG_DEBUG, "EAP-SIM: RAND", - data->rand[i], GSM_RAND_LEN); - wpa_hexdump_key(MSG_DEBUG, "EAP-SIM: SRES", - data->sres[i], EAP_SIM_SRES_LEN); - wpa_hexdump_key(MSG_DEBUG, "EAP-SIM: Kc", - data->kc[i], EAP_SIM_KC_LEN); - } - return 0; - } -#endif /* CONFIG_SIM_SIMULATOR */ - -#ifdef CONFIG_SIM_HARDCODED - /* These hardcoded Kc and SRES values are used for testing. RAND to - * KC/SREC mapping is very bogus as far as real authentication is - * concerned, but it is quite useful for cases where the AS is rotating - * the order of pre-configured values. */ - { - size_t i; - - wpa_printf(MSG_DEBUG, "EAP-SIM: Use hardcoded Kc and SRES " - "values for testing"); - - for (i = 0; i < data->num_chal; i++) { - if (data->rand[i][0] == 0xaa) { - os_memcpy(data->kc[i], - "\xa0\xa1\xa2\xa3\xa4\xa5\xa6\xa7", - EAP_SIM_KC_LEN); - os_memcpy(data->sres[i], "\xd1\xd2\xd3\xd4", - EAP_SIM_SRES_LEN); - } else if (data->rand[i][0] == 0xbb) { - os_memcpy(data->kc[i], - "\xb0\xb1\xb2\xb3\xb4\xb5\xb6\xb7", - EAP_SIM_KC_LEN); - os_memcpy(data->sres[i], "\xe1\xe2\xe3\xe4", - EAP_SIM_SRES_LEN); - } else { - os_memcpy(data->kc[i], - "\xc0\xc1\xc2\xc3\xc4\xc5\xc6\xc7", - EAP_SIM_KC_LEN); - os_memcpy(data->sres[i], "\xf1\xf2\xf3\xf4", - EAP_SIM_SRES_LEN); - } - } - } - - return 0; - -#else /* CONFIG_SIM_HARDCODED */ - - wpa_printf(MSG_DEBUG, "EAP-SIM: No GSM authentication algorithm " - "enabled"); - return -1; - -#endif /* CONFIG_SIM_HARDCODED */ -} - - -static int eap_sim_supported_ver(int version) -{ - return version == EAP_SIM_VERSION; -} - - -#define CLEAR_PSEUDONYM 0x01 -#define CLEAR_REAUTH_ID 0x02 -#define CLEAR_EAP_ID 0x04 - -static void eap_sim_clear_identities(struct eap_sim_data *data, int id) -{ - wpa_printf(MSG_DEBUG, "EAP-SIM: forgetting old%s%s%s", - id & CLEAR_PSEUDONYM ? " pseudonym" : "", - id & CLEAR_REAUTH_ID ? " reauth_id" : "", - id & CLEAR_EAP_ID ? " eap_id" : ""); - if (id & CLEAR_PSEUDONYM) { - os_free(data->pseudonym); - data->pseudonym = NULL; - data->pseudonym_len = 0; - } - if (id & CLEAR_REAUTH_ID) { - os_free(data->reauth_id); - data->reauth_id = NULL; - data->reauth_id_len = 0; - } - if (id & CLEAR_EAP_ID) { - os_free(data->last_eap_identity); - data->last_eap_identity = NULL; - data->last_eap_identity_len = 0; - } -} - - -static int eap_sim_learn_ids(struct eap_sim_data *data, - struct eap_sim_attrs *attr) -{ - if (attr->next_pseudonym) { - os_free(data->pseudonym); - data->pseudonym = os_malloc(attr->next_pseudonym_len); - if (data->pseudonym == NULL) { - wpa_printf(MSG_INFO, "EAP-SIM: (encr) No memory for " - "next pseudonym"); - return -1; - } - os_memcpy(data->pseudonym, attr->next_pseudonym, - attr->next_pseudonym_len); - data->pseudonym_len = attr->next_pseudonym_len; - wpa_hexdump_ascii(MSG_DEBUG, - "EAP-SIM: (encr) AT_NEXT_PSEUDONYM", - data->pseudonym, - data->pseudonym_len); - } - - if (attr->next_reauth_id) { - os_free(data->reauth_id); - data->reauth_id = os_malloc(attr->next_reauth_id_len); - if (data->reauth_id == NULL) { - wpa_printf(MSG_INFO, "EAP-SIM: (encr) No memory for " - "next reauth_id"); - return -1; - } - os_memcpy(data->reauth_id, attr->next_reauth_id, - attr->next_reauth_id_len); - data->reauth_id_len = attr->next_reauth_id_len; - wpa_hexdump_ascii(MSG_DEBUG, - "EAP-SIM: (encr) AT_NEXT_REAUTH_ID", - data->reauth_id, - data->reauth_id_len); - } - - return 0; -} - - -static struct wpabuf * eap_sim_client_error(struct eap_sim_data *data, u8 id, - int err) -{ - struct eap_sim_msg *msg; - - eap_sim_state(data, FAILURE); - data->num_id_req = 0; - data->num_notification = 0; - - msg = eap_sim_msg_init(EAP_CODE_RESPONSE, id, EAP_TYPE_SIM, - EAP_SIM_SUBTYPE_CLIENT_ERROR); - eap_sim_msg_add(msg, EAP_SIM_AT_CLIENT_ERROR_CODE, err, NULL, 0); - return eap_sim_msg_finish(msg, NULL, NULL, 0); -} - - -static struct wpabuf * eap_sim_response_start(struct eap_sm *sm, - struct eap_sim_data *data, u8 id, - enum eap_sim_id_req id_req) -{ - const u8 *identity = NULL; - size_t identity_len = 0; - struct eap_sim_msg *msg; - - data->reauth = 0; - if (id_req == ANY_ID && data->reauth_id) { - identity = data->reauth_id; - identity_len = data->reauth_id_len; - data->reauth = 1; - } else if ((id_req == ANY_ID || id_req == FULLAUTH_ID) && - data->pseudonym) { - identity = data->pseudonym; - identity_len = data->pseudonym_len; - eap_sim_clear_identities(data, CLEAR_REAUTH_ID); - } else if (id_req != NO_ID_REQ) { - identity = eap_get_config_identity(sm, &identity_len); - if (identity) { - eap_sim_clear_identities(data, CLEAR_PSEUDONYM | - CLEAR_REAUTH_ID); - } - } - if (id_req != NO_ID_REQ) - eap_sim_clear_identities(data, CLEAR_EAP_ID); - - wpa_printf(MSG_DEBUG, "Generating EAP-SIM Start (id=%d)", id); - msg = eap_sim_msg_init(EAP_CODE_RESPONSE, id, - EAP_TYPE_SIM, EAP_SIM_SUBTYPE_START); - if (!data->reauth) { - wpa_hexdump(MSG_DEBUG, " AT_NONCE_MT", - data->nonce_mt, EAP_SIM_NONCE_MT_LEN); - eap_sim_msg_add(msg, EAP_SIM_AT_NONCE_MT, 0, - data->nonce_mt, EAP_SIM_NONCE_MT_LEN); - wpa_printf(MSG_DEBUG, " AT_SELECTED_VERSION %d", - data->selected_version); - eap_sim_msg_add(msg, EAP_SIM_AT_SELECTED_VERSION, - data->selected_version, NULL, 0); - } - - if (identity) { - wpa_hexdump_ascii(MSG_DEBUG, " AT_IDENTITY", - identity, identity_len); - eap_sim_msg_add(msg, EAP_SIM_AT_IDENTITY, identity_len, - identity, identity_len); - } - - return eap_sim_msg_finish(msg, NULL, NULL, 0); -} - - -static struct wpabuf * eap_sim_response_challenge(struct eap_sim_data *data, - u8 id) -{ - struct eap_sim_msg *msg; - - wpa_printf(MSG_DEBUG, "Generating EAP-SIM Challenge (id=%d)", id); - msg = eap_sim_msg_init(EAP_CODE_RESPONSE, id, EAP_TYPE_SIM, - EAP_SIM_SUBTYPE_CHALLENGE); - if (data->use_result_ind) { - wpa_printf(MSG_DEBUG, " AT_RESULT_IND"); - eap_sim_msg_add(msg, EAP_SIM_AT_RESULT_IND, 0, NULL, 0); - } - wpa_printf(MSG_DEBUG, " AT_MAC"); - eap_sim_msg_add_mac(msg, EAP_SIM_AT_MAC); - return eap_sim_msg_finish(msg, data->k_aut, (u8 *) data->sres, - data->num_chal * EAP_SIM_SRES_LEN); -} - - -static struct wpabuf * eap_sim_response_reauth(struct eap_sim_data *data, - u8 id, int counter_too_small) -{ - struct eap_sim_msg *msg; - unsigned int counter; - - wpa_printf(MSG_DEBUG, "Generating EAP-SIM Reauthentication (id=%d)", - id); - msg = eap_sim_msg_init(EAP_CODE_RESPONSE, id, EAP_TYPE_SIM, - EAP_SIM_SUBTYPE_REAUTHENTICATION); - wpa_printf(MSG_DEBUG, " AT_IV"); - wpa_printf(MSG_DEBUG, " AT_ENCR_DATA"); - eap_sim_msg_add_encr_start(msg, EAP_SIM_AT_IV, EAP_SIM_AT_ENCR_DATA); - - if (counter_too_small) { - wpa_printf(MSG_DEBUG, " *AT_COUNTER_TOO_SMALL"); - eap_sim_msg_add(msg, EAP_SIM_AT_COUNTER_TOO_SMALL, 0, NULL, 0); - counter = data->counter_too_small; - } else - counter = data->counter; - - wpa_printf(MSG_DEBUG, " *AT_COUNTER %d", counter); - eap_sim_msg_add(msg, EAP_SIM_AT_COUNTER, counter, NULL, 0); - - if (eap_sim_msg_add_encr_end(msg, data->k_encr, EAP_SIM_AT_PADDING)) { - wpa_printf(MSG_WARNING, "EAP-SIM: Failed to encrypt " - "AT_ENCR_DATA"); - eap_sim_msg_free(msg); - return NULL; - } - if (data->use_result_ind) { - wpa_printf(MSG_DEBUG, " AT_RESULT_IND"); - eap_sim_msg_add(msg, EAP_SIM_AT_RESULT_IND, 0, NULL, 0); - } - wpa_printf(MSG_DEBUG, " AT_MAC"); - eap_sim_msg_add_mac(msg, EAP_SIM_AT_MAC); - return eap_sim_msg_finish(msg, data->k_aut, data->nonce_s, - EAP_SIM_NONCE_S_LEN); -} - - -static struct wpabuf * eap_sim_response_notification(struct eap_sim_data *data, - u8 id, u16 notification) -{ - struct eap_sim_msg *msg; - u8 *k_aut = (notification & 0x4000) == 0 ? data->k_aut : NULL; - - wpa_printf(MSG_DEBUG, "Generating EAP-SIM Notification (id=%d)", id); - msg = eap_sim_msg_init(EAP_CODE_RESPONSE, id, - EAP_TYPE_SIM, EAP_SIM_SUBTYPE_NOTIFICATION); - if (k_aut && data->reauth) { - wpa_printf(MSG_DEBUG, " AT_IV"); - wpa_printf(MSG_DEBUG, " AT_ENCR_DATA"); - eap_sim_msg_add_encr_start(msg, EAP_SIM_AT_IV, - EAP_SIM_AT_ENCR_DATA); - wpa_printf(MSG_DEBUG, " *AT_COUNTER %d", data->counter); - eap_sim_msg_add(msg, EAP_SIM_AT_COUNTER, data->counter, - NULL, 0); - if (eap_sim_msg_add_encr_end(msg, data->k_encr, - EAP_SIM_AT_PADDING)) { - wpa_printf(MSG_WARNING, "EAP-SIM: Failed to encrypt " - "AT_ENCR_DATA"); - eap_sim_msg_free(msg); - return NULL; - } - } - if (k_aut) { - wpa_printf(MSG_DEBUG, " AT_MAC"); - eap_sim_msg_add_mac(msg, EAP_SIM_AT_MAC); - } - return eap_sim_msg_finish(msg, k_aut, (u8 *) "", 0); -} - - -static struct wpabuf * eap_sim_process_start(struct eap_sm *sm, - struct eap_sim_data *data, u8 id, - struct eap_sim_attrs *attr) -{ - int selected_version = -1, id_error; - size_t i; - u8 *pos; - - wpa_printf(MSG_DEBUG, "EAP-SIM: subtype Start"); - if (attr->version_list == NULL) { - wpa_printf(MSG_INFO, "EAP-SIM: No AT_VERSION_LIST in " - "SIM/Start"); - return eap_sim_client_error(data, id, - EAP_SIM_UNSUPPORTED_VERSION); - } - - os_free(data->ver_list); - data->ver_list = os_malloc(attr->version_list_len); - if (data->ver_list == NULL) { - wpa_printf(MSG_DEBUG, "EAP-SIM: Failed to allocate " - "memory for version list"); - return eap_sim_client_error(data, id, - EAP_SIM_UNABLE_TO_PROCESS_PACKET); - } - os_memcpy(data->ver_list, attr->version_list, attr->version_list_len); - data->ver_list_len = attr->version_list_len; - pos = data->ver_list; - for (i = 0; i < data->ver_list_len / 2; i++) { - int ver = pos[0] * 256 + pos[1]; - pos += 2; - if (eap_sim_supported_ver(ver)) { - selected_version = ver; - break; - } - } - if (selected_version < 0) { - wpa_printf(MSG_INFO, "EAP-SIM: Could not find a supported " - "version"); - return eap_sim_client_error(data, id, - EAP_SIM_UNSUPPORTED_VERSION); - } - wpa_printf(MSG_DEBUG, "EAP-SIM: Selected Version %d", - selected_version); - data->selected_version = selected_version; - - id_error = 0; - switch (attr->id_req) { - case NO_ID_REQ: - break; - case ANY_ID: - if (data->num_id_req > 0) - id_error++; - data->num_id_req++; - break; - case FULLAUTH_ID: - if (data->num_id_req > 1) - id_error++; - data->num_id_req++; - break; - case PERMANENT_ID: - if (data->num_id_req > 2) - id_error++; - data->num_id_req++; - break; - } - if (id_error) { - wpa_printf(MSG_INFO, "EAP-SIM: Too many ID requests " - "used within one authentication"); - return eap_sim_client_error(data, id, - EAP_SIM_UNABLE_TO_PROCESS_PACKET); - } - - return eap_sim_response_start(sm, data, id, attr->id_req); -} - - -static struct wpabuf * eap_sim_process_challenge(struct eap_sm *sm, - struct eap_sim_data *data, - u8 id, - const struct wpabuf *reqData, - struct eap_sim_attrs *attr) -{ - const u8 *identity; - size_t identity_len; - struct eap_sim_attrs eattr; - - wpa_printf(MSG_DEBUG, "EAP-SIM: subtype Challenge"); - data->reauth = 0; - if (!attr->mac || !attr->rand) { - wpa_printf(MSG_WARNING, "EAP-SIM: Challenge message " - "did not include%s%s", - !attr->mac ? " AT_MAC" : "", - !attr->rand ? " AT_RAND" : ""); - return eap_sim_client_error(data, id, - EAP_SIM_UNABLE_TO_PROCESS_PACKET); - } - - wpa_printf(MSG_DEBUG, "EAP-SIM: %lu challenges", - (unsigned long) attr->num_chal); - if (attr->num_chal < data->min_num_chal) { - wpa_printf(MSG_INFO, "EAP-SIM: Insufficient number of " - "challenges (%lu)", (unsigned long) attr->num_chal); - return eap_sim_client_error(data, id, - EAP_SIM_INSUFFICIENT_NUM_OF_CHAL); - } - if (attr->num_chal > 3) { - wpa_printf(MSG_INFO, "EAP-SIM: Too many challenges " - "(%lu)", (unsigned long) attr->num_chal); - return eap_sim_client_error(data, id, - EAP_SIM_UNABLE_TO_PROCESS_PACKET); - } - - /* Verify that RANDs are different */ - if (os_memcmp(attr->rand, attr->rand + GSM_RAND_LEN, - GSM_RAND_LEN) == 0 || - (attr->num_chal > 2 && - (os_memcmp(attr->rand, attr->rand + 2 * GSM_RAND_LEN, - GSM_RAND_LEN) == 0 || - os_memcmp(attr->rand + GSM_RAND_LEN, - attr->rand + 2 * GSM_RAND_LEN, - GSM_RAND_LEN) == 0))) { - wpa_printf(MSG_INFO, "EAP-SIM: Same RAND used multiple times"); - return eap_sim_client_error(data, id, - EAP_SIM_RAND_NOT_FRESH); - } - - os_memcpy(data->rand, attr->rand, attr->num_chal * GSM_RAND_LEN); - data->num_chal = attr->num_chal; - - if (eap_sim_gsm_auth(sm, data)) { - wpa_printf(MSG_WARNING, "EAP-SIM: GSM authentication failed"); - return eap_sim_client_error(data, id, - EAP_SIM_UNABLE_TO_PROCESS_PACKET); - } - if (data->last_eap_identity) { - identity = data->last_eap_identity; - identity_len = data->last_eap_identity_len; - } else if (data->pseudonym) { - identity = data->pseudonym; - identity_len = data->pseudonym_len; - } else - identity = eap_get_config_identity(sm, &identity_len); - wpa_hexdump_ascii(MSG_DEBUG, "EAP-SIM: Selected identity for MK " - "derivation", identity, identity_len); - eap_sim_derive_mk(identity, identity_len, data->nonce_mt, - data->selected_version, data->ver_list, - data->ver_list_len, data->num_chal, - (const u8 *) data->kc, data->mk); - eap_sim_derive_keys(data->mk, data->k_encr, data->k_aut, data->msk, - data->emsk); - if (eap_sim_verify_mac(data->k_aut, reqData, attr->mac, data->nonce_mt, - EAP_SIM_NONCE_MT_LEN)) { - wpa_printf(MSG_WARNING, "EAP-SIM: Challenge message " - "used invalid AT_MAC"); - return eap_sim_client_error(data, id, - EAP_SIM_UNABLE_TO_PROCESS_PACKET); - } - - /* Old reauthentication and pseudonym identities must not be used - * anymore. In other words, if no new identities are received, full - * authentication will be used on next reauthentication. */ - eap_sim_clear_identities(data, CLEAR_PSEUDONYM | CLEAR_REAUTH_ID | - CLEAR_EAP_ID); - - if (attr->encr_data) { - u8 *decrypted; - decrypted = eap_sim_parse_encr(data->k_encr, attr->encr_data, - attr->encr_data_len, attr->iv, - &eattr, 0); - if (decrypted == NULL) { - return eap_sim_client_error( - data, id, EAP_SIM_UNABLE_TO_PROCESS_PACKET); - } - eap_sim_learn_ids(data, &eattr); - os_free(decrypted); - } - - if (data->result_ind && attr->result_ind) - data->use_result_ind = 1; - - if (data->state != FAILURE && data->state != RESULT_FAILURE) { - eap_sim_state(data, data->use_result_ind ? - RESULT_SUCCESS : SUCCESS); - } - - data->num_id_req = 0; - data->num_notification = 0; - /* RFC 4186 specifies that counter is initialized to one after - * fullauth, but initializing it to zero makes it easier to implement - * reauth verification. */ - data->counter = 0; - return eap_sim_response_challenge(data, id); -} - - -static int eap_sim_process_notification_reauth(struct eap_sim_data *data, - struct eap_sim_attrs *attr) -{ - struct eap_sim_attrs eattr; - u8 *decrypted; - - if (attr->encr_data == NULL || attr->iv == NULL) { - wpa_printf(MSG_WARNING, "EAP-SIM: Notification message after " - "reauth did not include encrypted data"); - return -1; - } - - decrypted = eap_sim_parse_encr(data->k_encr, attr->encr_data, - attr->encr_data_len, attr->iv, &eattr, - 0); - if (decrypted == NULL) { - wpa_printf(MSG_WARNING, "EAP-SIM: Failed to parse encrypted " - "data from notification message"); - return -1; - } - - if (eattr.counter < 0 || (size_t) eattr.counter != data->counter) { - wpa_printf(MSG_WARNING, "EAP-SIM: Counter in notification " - "message does not match with counter in reauth " - "message"); - os_free(decrypted); - return -1; - } - - os_free(decrypted); - return 0; -} - - -static int eap_sim_process_notification_auth(struct eap_sim_data *data, - const struct wpabuf *reqData, - struct eap_sim_attrs *attr) -{ - if (attr->mac == NULL) { - wpa_printf(MSG_INFO, "EAP-SIM: no AT_MAC in after_auth " - "Notification message"); - return -1; - } - - if (eap_sim_verify_mac(data->k_aut, reqData, attr->mac, (u8 *) "", 0)) - { - wpa_printf(MSG_WARNING, "EAP-SIM: Notification message " - "used invalid AT_MAC"); - return -1; - } - - if (data->reauth && - eap_sim_process_notification_reauth(data, attr)) { - wpa_printf(MSG_WARNING, "EAP-SIM: Invalid notification " - "message after reauth"); - return -1; - } - - return 0; -} - - -static struct wpabuf * eap_sim_process_notification( - struct eap_sm *sm, struct eap_sim_data *data, u8 id, - const struct wpabuf *reqData, struct eap_sim_attrs *attr) -{ - wpa_printf(MSG_DEBUG, "EAP-SIM: subtype Notification"); - if (data->num_notification > 0) { - wpa_printf(MSG_INFO, "EAP-SIM: too many notification " - "rounds (only one allowed)"); - return eap_sim_client_error(data, id, - EAP_SIM_UNABLE_TO_PROCESS_PACKET); - } - data->num_notification++; - if (attr->notification == -1) { - wpa_printf(MSG_INFO, "EAP-SIM: no AT_NOTIFICATION in " - "Notification message"); - return eap_sim_client_error(data, id, - EAP_SIM_UNABLE_TO_PROCESS_PACKET); - } - - if ((attr->notification & 0x4000) == 0 && - eap_sim_process_notification_auth(data, reqData, attr)) { - return eap_sim_client_error(data, id, - EAP_SIM_UNABLE_TO_PROCESS_PACKET); - } - - eap_sim_report_notification(sm->msg_ctx, attr->notification, 0); - if (attr->notification >= 0 && attr->notification < 32768) { - eap_sim_state(data, FAILURE); - } else if (attr->notification == EAP_SIM_SUCCESS && - data->state == RESULT_SUCCESS) - eap_sim_state(data, SUCCESS); - return eap_sim_response_notification(data, id, attr->notification); -} - - -static struct wpabuf * eap_sim_process_reauthentication( - struct eap_sm *sm, struct eap_sim_data *data, u8 id, - const struct wpabuf *reqData, struct eap_sim_attrs *attr) -{ - struct eap_sim_attrs eattr; - u8 *decrypted; - - wpa_printf(MSG_DEBUG, "EAP-SIM: subtype Reauthentication"); - - if (data->reauth_id == NULL) { - wpa_printf(MSG_WARNING, "EAP-SIM: Server is trying " - "reauthentication, but no reauth_id available"); - return eap_sim_client_error(data, id, - EAP_SIM_UNABLE_TO_PROCESS_PACKET); - } - - data->reauth = 1; - if (eap_sim_verify_mac(data->k_aut, reqData, attr->mac, (u8 *) "", 0)) - { - wpa_printf(MSG_WARNING, "EAP-SIM: Reauthentication " - "did not have valid AT_MAC"); - return eap_sim_client_error(data, id, - EAP_SIM_UNABLE_TO_PROCESS_PACKET); - } - - if (attr->encr_data == NULL || attr->iv == NULL) { - wpa_printf(MSG_WARNING, "EAP-SIM: Reauthentication " - "message did not include encrypted data"); - return eap_sim_client_error(data, id, - EAP_SIM_UNABLE_TO_PROCESS_PACKET); - } - - decrypted = eap_sim_parse_encr(data->k_encr, attr->encr_data, - attr->encr_data_len, attr->iv, &eattr, - 0); - if (decrypted == NULL) { - wpa_printf(MSG_WARNING, "EAP-SIM: Failed to parse encrypted " - "data from reauthentication message"); - return eap_sim_client_error(data, id, - EAP_SIM_UNABLE_TO_PROCESS_PACKET); - } - - if (eattr.nonce_s == NULL || eattr.counter < 0) { - wpa_printf(MSG_INFO, "EAP-SIM: (encr) No%s%s in reauth packet", - !eattr.nonce_s ? " AT_NONCE_S" : "", - eattr.counter < 0 ? " AT_COUNTER" : ""); - os_free(decrypted); - return eap_sim_client_error(data, id, - EAP_SIM_UNABLE_TO_PROCESS_PACKET); - } - - if (eattr.counter < 0 || (size_t) eattr.counter <= data->counter) { - wpa_printf(MSG_INFO, "EAP-SIM: (encr) Invalid counter " - "(%d <= %d)", eattr.counter, data->counter); - data->counter_too_small = eattr.counter; - /* Reply using Re-auth w/ AT_COUNTER_TOO_SMALL. The current - * reauth_id must not be used to start a new reauthentication. - * However, since it was used in the last EAP-Response-Identity - * packet, it has to saved for the following fullauth to be - * used in MK derivation. */ - os_free(data->last_eap_identity); - data->last_eap_identity = data->reauth_id; - data->last_eap_identity_len = data->reauth_id_len; - data->reauth_id = NULL; - data->reauth_id_len = 0; - os_free(decrypted); - return eap_sim_response_reauth(data, id, 1); - } - data->counter = eattr.counter; - - os_memcpy(data->nonce_s, eattr.nonce_s, EAP_SIM_NONCE_S_LEN); - wpa_hexdump(MSG_DEBUG, "EAP-SIM: (encr) AT_NONCE_S", - data->nonce_s, EAP_SIM_NONCE_S_LEN); - - eap_sim_derive_keys_reauth(data->counter, - data->reauth_id, data->reauth_id_len, - data->nonce_s, data->mk, data->msk, - data->emsk); - eap_sim_clear_identities(data, CLEAR_REAUTH_ID | CLEAR_EAP_ID); - eap_sim_learn_ids(data, &eattr); - - if (data->result_ind && attr->result_ind) - data->use_result_ind = 1; - - if (data->state != FAILURE && data->state != RESULT_FAILURE) { - eap_sim_state(data, data->use_result_ind ? - RESULT_SUCCESS : SUCCESS); - } - - data->num_id_req = 0; - data->num_notification = 0; - if (data->counter > EAP_SIM_MAX_FAST_REAUTHS) { - wpa_printf(MSG_DEBUG, "EAP-SIM: Maximum number of " - "fast reauths performed - force fullauth"); - eap_sim_clear_identities(data, CLEAR_REAUTH_ID | CLEAR_EAP_ID); - } - os_free(decrypted); - return eap_sim_response_reauth(data, id, 0); -} - - -static struct wpabuf * eap_sim_process(struct eap_sm *sm, void *priv, - struct eap_method_ret *ret, - const struct wpabuf *reqData) -{ - struct eap_sim_data *data = priv; - const struct eap_hdr *req; - u8 subtype, id; - struct wpabuf *res; - const u8 *pos; - struct eap_sim_attrs attr; - size_t len; - - wpa_hexdump_buf(MSG_DEBUG, "EAP-SIM: EAP data", reqData); - if (eap_get_config_identity(sm, &len) == NULL) { - wpa_printf(MSG_INFO, "EAP-SIM: Identity not configured"); - eap_sm_request_identity(sm); - ret->ignore = TRUE; - return NULL; - } - - pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_SIM, reqData, &len); - if (pos == NULL || len < 1) { - ret->ignore = TRUE; - return NULL; - } - req = wpabuf_head(reqData); - id = req->identifier; - len = be_to_host16(req->length); - - ret->ignore = FALSE; - ret->methodState = METHOD_MAY_CONT; - ret->decision = DECISION_FAIL; - ret->allowNotifications = TRUE; - - subtype = *pos++; - wpa_printf(MSG_DEBUG, "EAP-SIM: Subtype=%d", subtype); - pos += 2; /* Reserved */ - - if (eap_sim_parse_attr(pos, wpabuf_head_u8(reqData) + len, &attr, 0, - 0)) { - res = eap_sim_client_error(data, id, - EAP_SIM_UNABLE_TO_PROCESS_PACKET); - goto done; - } - - switch (subtype) { - case EAP_SIM_SUBTYPE_START: - res = eap_sim_process_start(sm, data, id, &attr); - break; - case EAP_SIM_SUBTYPE_CHALLENGE: - res = eap_sim_process_challenge(sm, data, id, reqData, &attr); - break; - case EAP_SIM_SUBTYPE_NOTIFICATION: - res = eap_sim_process_notification(sm, data, id, reqData, - &attr); - break; - case EAP_SIM_SUBTYPE_REAUTHENTICATION: - res = eap_sim_process_reauthentication(sm, data, id, reqData, - &attr); - break; - case EAP_SIM_SUBTYPE_CLIENT_ERROR: - wpa_printf(MSG_DEBUG, "EAP-SIM: subtype Client-Error"); - res = eap_sim_client_error(data, id, - EAP_SIM_UNABLE_TO_PROCESS_PACKET); - break; - default: - wpa_printf(MSG_DEBUG, "EAP-SIM: Unknown subtype=%d", subtype); - res = eap_sim_client_error(data, id, - EAP_SIM_UNABLE_TO_PROCESS_PACKET); - break; - } - -done: - if (data->state == FAILURE) { - ret->decision = DECISION_FAIL; - ret->methodState = METHOD_DONE; - } else if (data->state == SUCCESS) { - ret->decision = data->use_result_ind ? - DECISION_UNCOND_SUCC : DECISION_COND_SUCC; - ret->methodState = data->use_result_ind ? - METHOD_DONE : METHOD_MAY_CONT; - } else if (data->state == RESULT_FAILURE) - ret->methodState = METHOD_CONT; - else if (data->state == RESULT_SUCCESS) - ret->methodState = METHOD_CONT; - - if (ret->methodState == METHOD_DONE) { - ret->allowNotifications = FALSE; - } - - return res; -} - - -static Boolean eap_sim_has_reauth_data(struct eap_sm *sm, void *priv) -{ - struct eap_sim_data *data = priv; - return data->pseudonym || data->reauth_id; -} - - -static void eap_sim_deinit_for_reauth(struct eap_sm *sm, void *priv) -{ - struct eap_sim_data *data = priv; - eap_sim_clear_identities(data, CLEAR_EAP_ID); - data->use_result_ind = 0; -} - - -static void * eap_sim_init_for_reauth(struct eap_sm *sm, void *priv) -{ - struct eap_sim_data *data = priv; - if (random_get_bytes(data->nonce_mt, EAP_SIM_NONCE_MT_LEN)) { - wpa_printf(MSG_WARNING, "EAP-SIM: Failed to get random data " - "for NONCE_MT"); - os_free(data); - return NULL; - } - data->num_id_req = 0; - data->num_notification = 0; - eap_sim_state(data, CONTINUE); - return priv; -} - - -static const u8 * eap_sim_get_identity(struct eap_sm *sm, void *priv, - size_t *len) -{ - struct eap_sim_data *data = priv; - - if (data->reauth_id) { - *len = data->reauth_id_len; - return data->reauth_id; - } - - if (data->pseudonym) { - *len = data->pseudonym_len; - return data->pseudonym; - } - - return NULL; -} - - -static Boolean eap_sim_isKeyAvailable(struct eap_sm *sm, void *priv) -{ - struct eap_sim_data *data = priv; - return data->state == SUCCESS; -} - - -static u8 * eap_sim_getKey(struct eap_sm *sm, void *priv, size_t *len) -{ - struct eap_sim_data *data = priv; - u8 *key; - - if (data->state != SUCCESS) - return NULL; - - key = os_malloc(EAP_SIM_KEYING_DATA_LEN); - if (key == NULL) - return NULL; - - *len = EAP_SIM_KEYING_DATA_LEN; - os_memcpy(key, data->msk, EAP_SIM_KEYING_DATA_LEN); - - return key; -} - - -static u8 * eap_sim_get_emsk(struct eap_sm *sm, void *priv, size_t *len) -{ - struct eap_sim_data *data = priv; - u8 *key; - - if (data->state != SUCCESS) - return NULL; - - key = os_malloc(EAP_EMSK_LEN); - if (key == NULL) - return NULL; - - *len = EAP_EMSK_LEN; - os_memcpy(key, data->emsk, EAP_EMSK_LEN); - - return key; -} - - -int eap_peer_sim_register(void) -{ - struct eap_method *eap; - int ret; - - eap = eap_peer_method_alloc(EAP_PEER_METHOD_INTERFACE_VERSION, - EAP_VENDOR_IETF, EAP_TYPE_SIM, "SIM"); - if (eap == NULL) - return -1; - - eap->init = eap_sim_init; - eap->deinit = eap_sim_deinit; - eap->process = eap_sim_process; - eap->isKeyAvailable = eap_sim_isKeyAvailable; - eap->getKey = eap_sim_getKey; - eap->has_reauth_data = eap_sim_has_reauth_data; - eap->deinit_for_reauth = eap_sim_deinit_for_reauth; - eap->init_for_reauth = eap_sim_init_for_reauth; - eap->get_identity = eap_sim_get_identity; - eap->get_emsk = eap_sim_get_emsk; - - ret = eap_peer_method_register(eap); - if (ret) - eap_peer_method_free(eap); - return ret; -} diff --git a/hostapd-0.8/src/eap_peer/eap_tls.c b/hostapd-0.8/src/eap_peer/eap_tls.c deleted file mode 100644 index 20b2212..0000000 --- a/hostapd-0.8/src/eap_peer/eap_tls.c +++ /dev/null @@ -1,289 +0,0 @@ -/* - * EAP peer method: EAP-TLS (RFC 2716) - * Copyright (c) 2004-2008, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#include "includes.h" - -#include "common.h" -#include "crypto/tls.h" -#include "eap_i.h" -#include "eap_tls_common.h" -#include "eap_config.h" - - -static void eap_tls_deinit(struct eap_sm *sm, void *priv); - - -struct eap_tls_data { - struct eap_ssl_data ssl; - u8 *key_data; -}; - - -static void * eap_tls_init(struct eap_sm *sm) -{ - struct eap_tls_data *data; - struct eap_peer_config *config = eap_get_config(sm); - if (config == NULL || - ((sm->init_phase2 ? config->private_key2 : config->private_key) - == NULL && - (sm->init_phase2 ? config->engine2 : config->engine) == 0)) { - wpa_printf(MSG_INFO, "EAP-TLS: Private key not configured"); - return NULL; - } - - data = os_zalloc(sizeof(*data)); - if (data == NULL) - return NULL; - - if (eap_peer_tls_ssl_init(sm, &data->ssl, config)) { - wpa_printf(MSG_INFO, "EAP-TLS: Failed to initialize SSL."); - eap_tls_deinit(sm, data); - if (config->engine) { - wpa_printf(MSG_DEBUG, "EAP-TLS: Requesting Smartcard " - "PIN"); - eap_sm_request_pin(sm); - sm->ignore = TRUE; - } else if (config->private_key && !config->private_key_passwd) - { - wpa_printf(MSG_DEBUG, "EAP-TLS: Requesting private " - "key passphrase"); - eap_sm_request_passphrase(sm); - sm->ignore = TRUE; - } - return NULL; - } - - return data; -} - - -static void eap_tls_deinit(struct eap_sm *sm, void *priv) -{ - struct eap_tls_data *data = priv; - if (data == NULL) - return; - eap_peer_tls_ssl_deinit(sm, &data->ssl); - os_free(data->key_data); - os_free(data); -} - - -static struct wpabuf * eap_tls_failure(struct eap_sm *sm, - struct eap_tls_data *data, - struct eap_method_ret *ret, int res, - struct wpabuf *resp, u8 id) -{ - wpa_printf(MSG_DEBUG, "EAP-TLS: TLS processing failed"); - - ret->methodState = METHOD_DONE; - ret->decision = DECISION_FAIL; - - if (res == -1) { - struct eap_peer_config *config = eap_get_config(sm); - if (config) { - /* - * The TLS handshake failed. So better forget the old - * PIN. It may be wrong, we cannot be sure but trying - * the wrong one again might block it on the card--so - * better ask the user again. - */ - os_free(config->pin); - config->pin = NULL; - } - } - - if (resp) { - /* - * This is likely an alert message, so send it instead of just - * ACKing the error. - */ - return resp; - } - - return eap_peer_tls_build_ack(id, EAP_TYPE_TLS, 0); -} - - -static void eap_tls_success(struct eap_sm *sm, struct eap_tls_data *data, - struct eap_method_ret *ret) -{ - wpa_printf(MSG_DEBUG, "EAP-TLS: Done"); - - ret->methodState = METHOD_DONE; - ret->decision = DECISION_UNCOND_SUCC; - - os_free(data->key_data); - data->key_data = eap_peer_tls_derive_key(sm, &data->ssl, - "client EAP encryption", - EAP_TLS_KEY_LEN + - EAP_EMSK_LEN); - if (data->key_data) { - wpa_hexdump_key(MSG_DEBUG, "EAP-TLS: Derived key", - data->key_data, EAP_TLS_KEY_LEN); - wpa_hexdump_key(MSG_DEBUG, "EAP-TLS: Derived EMSK", - data->key_data + EAP_TLS_KEY_LEN, - EAP_EMSK_LEN); - } else { - wpa_printf(MSG_INFO, "EAP-TLS: Failed to derive key"); - } -} - - -static struct wpabuf * eap_tls_process(struct eap_sm *sm, void *priv, - struct eap_method_ret *ret, - const struct wpabuf *reqData) -{ - size_t left; - int res; - struct wpabuf *resp; - u8 flags, id; - const u8 *pos; - struct eap_tls_data *data = priv; - - pos = eap_peer_tls_process_init(sm, &data->ssl, EAP_TYPE_TLS, ret, - reqData, &left, &flags); - if (pos == NULL) - return NULL; - id = eap_get_id(reqData); - - if (flags & EAP_TLS_FLAGS_START) { - wpa_printf(MSG_DEBUG, "EAP-TLS: Start"); - left = 0; /* make sure that this frame is empty, even though it - * should always be, anyway */ - } - - resp = NULL; - res = eap_peer_tls_process_helper(sm, &data->ssl, EAP_TYPE_TLS, 0, id, - pos, left, &resp); - - if (res < 0) { - return eap_tls_failure(sm, data, ret, res, resp, id); - } - - if (tls_connection_established(sm->ssl_ctx, data->ssl.conn)) - eap_tls_success(sm, data, ret); - - if (res == 1) { - wpabuf_free(resp); - return eap_peer_tls_build_ack(id, EAP_TYPE_TLS, 0); - } - - return resp; -} - - -static Boolean eap_tls_has_reauth_data(struct eap_sm *sm, void *priv) -{ - struct eap_tls_data *data = priv; - return tls_connection_established(sm->ssl_ctx, data->ssl.conn); -} - - -static void eap_tls_deinit_for_reauth(struct eap_sm *sm, void *priv) -{ -} - - -static void * eap_tls_init_for_reauth(struct eap_sm *sm, void *priv) -{ - struct eap_tls_data *data = priv; - os_free(data->key_data); - data->key_data = NULL; - if (eap_peer_tls_reauth_init(sm, &data->ssl)) { - os_free(data); - return NULL; - } - return priv; -} - - -static int eap_tls_get_status(struct eap_sm *sm, void *priv, char *buf, - size_t buflen, int verbose) -{ - struct eap_tls_data *data = priv; - return eap_peer_tls_status(sm, &data->ssl, buf, buflen, verbose); -} - - -static Boolean eap_tls_isKeyAvailable(struct eap_sm *sm, void *priv) -{ - struct eap_tls_data *data = priv; - return data->key_data != NULL; -} - - -static u8 * eap_tls_getKey(struct eap_sm *sm, void *priv, size_t *len) -{ - struct eap_tls_data *data = priv; - u8 *key; - - if (data->key_data == NULL) - return NULL; - - key = os_malloc(EAP_TLS_KEY_LEN); - if (key == NULL) - return NULL; - - *len = EAP_TLS_KEY_LEN; - os_memcpy(key, data->key_data, EAP_TLS_KEY_LEN); - - return key; -} - - -static u8 * eap_tls_get_emsk(struct eap_sm *sm, void *priv, size_t *len) -{ - struct eap_tls_data *data = priv; - u8 *key; - - if (data->key_data == NULL) - return NULL; - - key = os_malloc(EAP_EMSK_LEN); - if (key == NULL) - return NULL; - - *len = EAP_EMSK_LEN; - os_memcpy(key, data->key_data + EAP_TLS_KEY_LEN, EAP_EMSK_LEN); - - return key; -} - - -int eap_peer_tls_register(void) -{ - struct eap_method *eap; - int ret; - - eap = eap_peer_method_alloc(EAP_PEER_METHOD_INTERFACE_VERSION, - EAP_VENDOR_IETF, EAP_TYPE_TLS, "TLS"); - if (eap == NULL) - return -1; - - eap->init = eap_tls_init; - eap->deinit = eap_tls_deinit; - eap->process = eap_tls_process; - eap->isKeyAvailable = eap_tls_isKeyAvailable; - eap->getKey = eap_tls_getKey; - eap->get_status = eap_tls_get_status; - eap->has_reauth_data = eap_tls_has_reauth_data; - eap->deinit_for_reauth = eap_tls_deinit_for_reauth; - eap->init_for_reauth = eap_tls_init_for_reauth; - eap->get_emsk = eap_tls_get_emsk; - - ret = eap_peer_method_register(eap); - if (ret) - eap_peer_method_free(eap); - return ret; -} diff --git a/hostapd-0.8/src/eap_peer/eap_tls_common.c b/hostapd-0.8/src/eap_peer/eap_tls_common.c deleted file mode 100644 index d1567e9..0000000 --- a/hostapd-0.8/src/eap_peer/eap_tls_common.c +++ /dev/null @@ -1,1021 +0,0 @@ -/* - * EAP peer: EAP-TLS/PEAP/TTLS/FAST common functions - * Copyright (c) 2004-2009, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#include "includes.h" - -#include "common.h" -#include "crypto/sha1.h" -#include "crypto/tls.h" -#include "eap_i.h" -#include "eap_tls_common.h" -#include "eap_config.h" - - -static int eap_tls_check_blob(struct eap_sm *sm, const char **name, - const u8 **data, size_t *data_len) -{ - const struct wpa_config_blob *blob; - - if (*name == NULL || os_strncmp(*name, "blob://", 7) != 0) - return 0; - - blob = eap_get_config_blob(sm, *name + 7); - if (blob == NULL) { - wpa_printf(MSG_ERROR, "%s: Named configuration blob '%s' not " - "found", __func__, *name + 7); - return -1; - } - - *name = NULL; - *data = blob->data; - *data_len = blob->len; - - return 0; -} - - -static void eap_tls_params_flags(struct tls_connection_params *params, - const char *txt) -{ - if (txt == NULL) - return; - if (os_strstr(txt, "tls_allow_md5=1")) - params->flags |= TLS_CONN_ALLOW_SIGN_RSA_MD5; - if (os_strstr(txt, "tls_disable_time_checks=1")) - params->flags |= TLS_CONN_DISABLE_TIME_CHECKS; -} - - -static void eap_tls_params_from_conf1(struct tls_connection_params *params, - struct eap_peer_config *config) -{ - params->ca_cert = (char *) config->ca_cert; - params->ca_path = (char *) config->ca_path; - params->client_cert = (char *) config->client_cert; - params->private_key = (char *) config->private_key; - params->private_key_passwd = (char *) config->private_key_passwd; - params->dh_file = (char *) config->dh_file; - params->subject_match = (char *) config->subject_match; - params->altsubject_match = (char *) config->altsubject_match; - params->engine = config->engine; - params->engine_id = config->engine_id; - params->pin = config->pin; - params->key_id = config->key_id; - params->cert_id = config->cert_id; - params->ca_cert_id = config->ca_cert_id; - eap_tls_params_flags(params, config->phase1); -} - - -static void eap_tls_params_from_conf2(struct tls_connection_params *params, - struct eap_peer_config *config) -{ - params->ca_cert = (char *) config->ca_cert2; - params->ca_path = (char *) config->ca_path2; - params->client_cert = (char *) config->client_cert2; - params->private_key = (char *) config->private_key2; - params->private_key_passwd = (char *) config->private_key2_passwd; - params->dh_file = (char *) config->dh_file2; - params->subject_match = (char *) config->subject_match2; - params->altsubject_match = (char *) config->altsubject_match2; - params->engine = config->engine2; - params->engine_id = config->engine2_id; - params->pin = config->pin2; - params->key_id = config->key2_id; - params->cert_id = config->cert2_id; - params->ca_cert_id = config->ca_cert2_id; - eap_tls_params_flags(params, config->phase2); -} - - -static int eap_tls_params_from_conf(struct eap_sm *sm, - struct eap_ssl_data *data, - struct tls_connection_params *params, - struct eap_peer_config *config, int phase2) -{ - os_memset(params, 0, sizeof(*params)); - if (phase2) { - wpa_printf(MSG_DEBUG, "TLS: using phase2 config options"); - eap_tls_params_from_conf2(params, config); - } else { - wpa_printf(MSG_DEBUG, "TLS: using phase1 config options"); - eap_tls_params_from_conf1(params, config); - } - params->tls_ia = data->tls_ia; - - /* - * Use blob data, if available. Otherwise, leave reference to external - * file as-is. - */ - if (eap_tls_check_blob(sm, ¶ms->ca_cert, ¶ms->ca_cert_blob, - ¶ms->ca_cert_blob_len) || - eap_tls_check_blob(sm, ¶ms->client_cert, - ¶ms->client_cert_blob, - ¶ms->client_cert_blob_len) || - eap_tls_check_blob(sm, ¶ms->private_key, - ¶ms->private_key_blob, - ¶ms->private_key_blob_len) || - eap_tls_check_blob(sm, ¶ms->dh_file, ¶ms->dh_blob, - ¶ms->dh_blob_len)) { - wpa_printf(MSG_INFO, "SSL: Failed to get configuration blobs"); - return -1; - } - - return 0; -} - - -static int eap_tls_init_connection(struct eap_sm *sm, - struct eap_ssl_data *data, - struct eap_peer_config *config, - struct tls_connection_params *params) -{ - int res; - - data->conn = tls_connection_init(sm->ssl_ctx); - if (data->conn == NULL) { - wpa_printf(MSG_INFO, "SSL: Failed to initialize new TLS " - "connection"); - return -1; - } - - res = tls_connection_set_params(sm->ssl_ctx, data->conn, params); - if (res == TLS_SET_PARAMS_ENGINE_PRV_INIT_FAILED) { - /* - * At this point with the pkcs11 engine the PIN might be wrong. - * We reset the PIN in the configuration to be sure to not use - * it again and the calling function must request a new one. - */ - os_free(config->pin); - config->pin = NULL; - } else if (res == TLS_SET_PARAMS_ENGINE_PRV_VERIFY_FAILED) { - wpa_printf(MSG_INFO, "TLS: Failed to load private key"); - /* - * We do not know exactly but maybe the PIN was wrong, - * so ask for a new one. - */ - os_free(config->pin); - config->pin = NULL; - eap_sm_request_pin(sm); - sm->ignore = TRUE; - tls_connection_deinit(sm->ssl_ctx, data->conn); - data->conn = NULL; - return -1; - } else if (res) { - wpa_printf(MSG_INFO, "TLS: Failed to set TLS connection " - "parameters"); - tls_connection_deinit(sm->ssl_ctx, data->conn); - data->conn = NULL; - return -1; - } - - return 0; -} - - -/** - * eap_peer_tls_ssl_init - Initialize shared TLS functionality - * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init() - * @data: Data for TLS processing - * @config: Pointer to the network configuration - * Returns: 0 on success, -1 on failure - * - * This function is used to initialize shared TLS functionality for EAP-TLS, - * EAP-PEAP, EAP-TTLS, and EAP-FAST. - */ -int eap_peer_tls_ssl_init(struct eap_sm *sm, struct eap_ssl_data *data, - struct eap_peer_config *config) -{ - struct tls_connection_params params; - - if (config == NULL) - return -1; - - data->eap = sm; - data->phase2 = sm->init_phase2; - if (eap_tls_params_from_conf(sm, data, ¶ms, config, data->phase2) < - 0) - return -1; - - if (eap_tls_init_connection(sm, data, config, ¶ms) < 0) - return -1; - - data->tls_out_limit = config->fragment_size; - if (data->phase2) { - /* Limit the fragment size in the inner TLS authentication - * since the outer authentication with EAP-PEAP does not yet - * support fragmentation */ - if (data->tls_out_limit > 100) - data->tls_out_limit -= 100; - } - - if (config->phase1 && - os_strstr(config->phase1, "include_tls_length=1")) { - wpa_printf(MSG_DEBUG, "TLS: Include TLS Message Length in " - "unfragmented packets"); - data->include_tls_length = 1; - } - - return 0; -} - - -/** - * eap_peer_tls_ssl_deinit - Deinitialize shared TLS functionality - * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init() - * @data: Data for TLS processing - * - * This function deinitializes shared TLS functionality that was initialized - * with eap_peer_tls_ssl_init(). - */ -void eap_peer_tls_ssl_deinit(struct eap_sm *sm, struct eap_ssl_data *data) -{ - tls_connection_deinit(sm->ssl_ctx, data->conn); - eap_peer_tls_reset_input(data); - eap_peer_tls_reset_output(data); -} - - -/** - * eap_peer_tls_derive_key - Derive a key based on TLS session data - * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init() - * @data: Data for TLS processing - * @label: Label string for deriving the keys, e.g., "client EAP encryption" - * @len: Length of the key material to generate (usually 64 for MSK) - * Returns: Pointer to allocated key on success or %NULL on failure - * - * This function uses TLS-PRF to generate pseudo-random data based on the TLS - * session data (client/server random and master key). Each key type may use a - * different label to bind the key usage into the generated material. - * - * The caller is responsible for freeing the returned buffer. - */ -u8 * eap_peer_tls_derive_key(struct eap_sm *sm, struct eap_ssl_data *data, - const char *label, size_t len) -{ - struct tls_keys keys; - u8 *rnd = NULL, *out; - - out = os_malloc(len); - if (out == NULL) - return NULL; - - /* First, try to use TLS library function for PRF, if available. */ - if (tls_connection_prf(sm->ssl_ctx, data->conn, label, 0, out, len) == - 0) - return out; - - /* - * TLS library did not support key generation, so get the needed TLS - * session parameters and use an internal implementation of TLS PRF to - * derive the key. - */ - if (tls_connection_get_keys(sm->ssl_ctx, data->conn, &keys)) - goto fail; - - if (keys.client_random == NULL || keys.server_random == NULL || - keys.master_key == NULL) - goto fail; - - rnd = os_malloc(keys.client_random_len + keys.server_random_len); - if (rnd == NULL) - goto fail; - os_memcpy(rnd, keys.client_random, keys.client_random_len); - os_memcpy(rnd + keys.client_random_len, keys.server_random, - keys.server_random_len); - - if (tls_prf(keys.master_key, keys.master_key_len, - label, rnd, keys.client_random_len + - keys.server_random_len, out, len)) - goto fail; - - os_free(rnd); - return out; - -fail: - os_free(out); - os_free(rnd); - return NULL; -} - - -/** - * eap_peer_tls_reassemble_fragment - Reassemble a received fragment - * @data: Data for TLS processing - * @in_data: Next incoming TLS segment - * Returns: 0 on success, 1 if more data is needed for the full message, or - * -1 on error - */ -static int eap_peer_tls_reassemble_fragment(struct eap_ssl_data *data, - const struct wpabuf *in_data) -{ - size_t tls_in_len, in_len; - - tls_in_len = data->tls_in ? wpabuf_len(data->tls_in) : 0; - in_len = in_data ? wpabuf_len(in_data) : 0; - - if (tls_in_len + in_len == 0) { - /* No message data received?! */ - wpa_printf(MSG_WARNING, "SSL: Invalid reassembly state: " - "tls_in_left=%lu tls_in_len=%lu in_len=%lu", - (unsigned long) data->tls_in_left, - (unsigned long) tls_in_len, - (unsigned long) in_len); - eap_peer_tls_reset_input(data); - return -1; - } - - if (tls_in_len + in_len > 65536) { - /* - * Limit length to avoid rogue servers from causing large - * memory allocations. - */ - wpa_printf(MSG_INFO, "SSL: Too long TLS fragment (size over " - "64 kB)"); - eap_peer_tls_reset_input(data); - return -1; - } - - if (in_len > data->tls_in_left) { - /* Sender is doing something odd - reject message */ - wpa_printf(MSG_INFO, "SSL: more data than TLS message length " - "indicated"); - eap_peer_tls_reset_input(data); - return -1; - } - - if (wpabuf_resize(&data->tls_in, in_len) < 0) { - wpa_printf(MSG_INFO, "SSL: Could not allocate memory for TLS " - "data"); - eap_peer_tls_reset_input(data); - return -1; - } - if (in_data) - wpabuf_put_buf(data->tls_in, in_data); - data->tls_in_left -= in_len; - - if (data->tls_in_left > 0) { - wpa_printf(MSG_DEBUG, "SSL: Need %lu bytes more input " - "data", (unsigned long) data->tls_in_left); - return 1; - } - - return 0; -} - - -/** - * eap_peer_tls_data_reassemble - Reassemble TLS data - * @data: Data for TLS processing - * @in_data: Next incoming TLS segment - * @need_more_input: Variable for returning whether more input data is needed - * to reassemble this TLS packet - * Returns: Pointer to output data, %NULL on error or when more data is needed - * for the full message (in which case, *need_more_input is also set to 1). - * - * This function reassembles TLS fragments. Caller must not free the returned - * data buffer since an internal pointer to it is maintained. - */ -static const struct wpabuf * eap_peer_tls_data_reassemble( - struct eap_ssl_data *data, const struct wpabuf *in_data, - int *need_more_input) -{ - *need_more_input = 0; - - if (data->tls_in_left > wpabuf_len(in_data) || data->tls_in) { - /* Message has fragments */ - int res = eap_peer_tls_reassemble_fragment(data, in_data); - if (res) { - if (res == 1) - *need_more_input = 1; - return NULL; - } - - /* Message is now fully reassembled. */ - } else { - /* No fragments in this message, so just make a copy of it. */ - data->tls_in_left = 0; - data->tls_in = wpabuf_dup(in_data); - if (data->tls_in == NULL) - return NULL; - } - - return data->tls_in; -} - - -/** - * eap_tls_process_input - Process incoming TLS message - * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init() - * @data: Data for TLS processing - * @in_data: Message received from the server - * @in_len: Length of in_data - * @out_data: Buffer for returning a pointer to application data (if available) - * Returns: 0 on success, 1 if more input data is needed, 2 if application data - * is available, -1 on failure - */ -static int eap_tls_process_input(struct eap_sm *sm, struct eap_ssl_data *data, - const u8 *in_data, size_t in_len, - struct wpabuf **out_data) -{ - const struct wpabuf *msg; - int need_more_input; - struct wpabuf *appl_data; - struct wpabuf buf; - - wpabuf_set(&buf, in_data, in_len); - msg = eap_peer_tls_data_reassemble(data, &buf, &need_more_input); - if (msg == NULL) - return need_more_input ? 1 : -1; - - /* Full TLS message reassembled - continue handshake processing */ - if (data->tls_out) { - /* This should not happen.. */ - wpa_printf(MSG_INFO, "SSL: eap_tls_process_input - pending " - "tls_out data even though tls_out_len = 0"); - wpabuf_free(data->tls_out); - WPA_ASSERT(data->tls_out == NULL); - } - appl_data = NULL; - data->tls_out = tls_connection_handshake(sm->ssl_ctx, data->conn, - msg, &appl_data); - - eap_peer_tls_reset_input(data); - - if (appl_data && - tls_connection_established(sm->ssl_ctx, data->conn) && - !tls_connection_get_failed(sm->ssl_ctx, data->conn)) { - wpa_hexdump_buf_key(MSG_MSGDUMP, "SSL: Application data", - appl_data); - *out_data = appl_data; - return 2; - } - - wpabuf_free(appl_data); - - return 0; -} - - -/** - * eap_tls_process_output - Process outgoing TLS message - * @data: Data for TLS processing - * @eap_type: EAP type (EAP_TYPE_TLS, EAP_TYPE_PEAP, ...) - * @peap_version: Version number for EAP-PEAP/TTLS - * @id: EAP identifier for the response - * @ret: Return value to use on success - * @out_data: Buffer for returning the allocated output buffer - * Returns: ret (0 or 1) on success, -1 on failure - */ -static int eap_tls_process_output(struct eap_ssl_data *data, EapType eap_type, - int peap_version, u8 id, int ret, - struct wpabuf **out_data) -{ - size_t len; - u8 *flags; - int more_fragments, length_included; - - if (data->tls_out == NULL) - return -1; - len = wpabuf_len(data->tls_out) - data->tls_out_pos; - wpa_printf(MSG_DEBUG, "SSL: %lu bytes left to be sent out (of total " - "%lu bytes)", - (unsigned long) len, - (unsigned long) wpabuf_len(data->tls_out)); - - /* - * Limit outgoing message to the configured maximum size. Fragment - * message if needed. - */ - if (len > data->tls_out_limit) { - more_fragments = 1; - len = data->tls_out_limit; - wpa_printf(MSG_DEBUG, "SSL: sending %lu bytes, more fragments " - "will follow", (unsigned long) len); - } else - more_fragments = 0; - - length_included = data->tls_out_pos == 0 && - (wpabuf_len(data->tls_out) > data->tls_out_limit || - data->include_tls_length); - if (!length_included && - eap_type == EAP_TYPE_PEAP && peap_version == 0 && - !tls_connection_established(data->eap->ssl_ctx, data->conn)) { - /* - * Windows Server 2008 NPS really wants to have the TLS Message - * length included in phase 0 even for unfragmented frames or - * it will get very confused with Compound MAC calculation and - * Outer TLVs. - */ - length_included = 1; - } - - *out_data = eap_msg_alloc(EAP_VENDOR_IETF, eap_type, - 1 + length_included * 4 + len, - EAP_CODE_RESPONSE, id); - if (*out_data == NULL) - return -1; - - flags = wpabuf_put(*out_data, 1); - *flags = peap_version; - if (more_fragments) - *flags |= EAP_TLS_FLAGS_MORE_FRAGMENTS; - if (length_included) { - *flags |= EAP_TLS_FLAGS_LENGTH_INCLUDED; - wpabuf_put_be32(*out_data, wpabuf_len(data->tls_out)); - } - - wpabuf_put_data(*out_data, - wpabuf_head_u8(data->tls_out) + data->tls_out_pos, - len); - data->tls_out_pos += len; - - if (!more_fragments) - eap_peer_tls_reset_output(data); - - return ret; -} - - -/** - * eap_peer_tls_process_helper - Process TLS handshake message - * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init() - * @data: Data for TLS processing - * @eap_type: EAP type (EAP_TYPE_TLS, EAP_TYPE_PEAP, ...) - * @peap_version: Version number for EAP-PEAP/TTLS - * @id: EAP identifier for the response - * @in_data: Message received from the server - * @in_len: Length of in_data - * @out_data: Buffer for returning a pointer to the response message - * Returns: 0 on success, 1 if more input data is needed, 2 if application data - * is available, or -1 on failure - * - * This function can be used to process TLS handshake messages. It reassembles - * the received fragments and uses a TLS library to process the messages. The - * response data from the TLS library is fragmented to suitable output messages - * that the caller can send out. - * - * out_data is used to return the response message if the return value of this - * function is 0, 2, or -1. In case of failure, the message is likely a TLS - * alarm message. The caller is responsible for freeing the allocated buffer if - * *out_data is not %NULL. - * - * This function is called for each received TLS message during the TLS - * handshake after eap_peer_tls_process_init() call and possible processing of - * TLS Flags field. Once the handshake has been completed, i.e., when - * tls_connection_established() returns 1, EAP method specific decrypting of - * the tunneled data is used. - */ -int eap_peer_tls_process_helper(struct eap_sm *sm, struct eap_ssl_data *data, - EapType eap_type, int peap_version, - u8 id, const u8 *in_data, size_t in_len, - struct wpabuf **out_data) -{ - int ret = 0; - - *out_data = NULL; - - if (data->tls_out && wpabuf_len(data->tls_out) > 0 && in_len > 0) { - wpa_printf(MSG_DEBUG, "SSL: Received non-ACK when output " - "fragments are waiting to be sent out"); - return -1; - } - - if (data->tls_out == NULL || wpabuf_len(data->tls_out) == 0) { - /* - * No more data to send out - expect to receive more data from - * the AS. - */ - int res = eap_tls_process_input(sm, data, in_data, in_len, - out_data); - if (res) { - /* - * Input processing failed (res = -1) or more data is - * needed (res = 1). - */ - return res; - } - - /* - * The incoming message has been reassembled and processed. The - * response was allocated into data->tls_out buffer. - */ - } - - if (data->tls_out == NULL) { - /* - * No outgoing fragments remaining from the previous message - * and no new message generated. This indicates an error in TLS - * processing. - */ - eap_peer_tls_reset_output(data); - return -1; - } - - if (tls_connection_get_failed(sm->ssl_ctx, data->conn)) { - /* TLS processing has failed - return error */ - wpa_printf(MSG_DEBUG, "SSL: Failed - tls_out available to " - "report error"); - ret = -1; - /* TODO: clean pin if engine used? */ - } - - if (data->tls_out == NULL || wpabuf_len(data->tls_out) == 0) { - /* - * TLS negotiation should now be complete since all other cases - * needing more data should have been caught above based on - * the TLS Message Length field. - */ - wpa_printf(MSG_DEBUG, "SSL: No data to be sent out"); - wpabuf_free(data->tls_out); - data->tls_out = NULL; - return 1; - } - - /* Send the pending message (in fragments, if needed). */ - return eap_tls_process_output(data, eap_type, peap_version, id, ret, - out_data); -} - - -/** - * eap_peer_tls_build_ack - Build a TLS ACK frame - * @id: EAP identifier for the response - * @eap_type: EAP type (EAP_TYPE_TLS, EAP_TYPE_PEAP, ...) - * @peap_version: Version number for EAP-PEAP/TTLS - * Returns: Pointer to the allocated ACK frame or %NULL on failure - */ -struct wpabuf * eap_peer_tls_build_ack(u8 id, EapType eap_type, - int peap_version) -{ - struct wpabuf *resp; - - resp = eap_msg_alloc(EAP_VENDOR_IETF, eap_type, 1, EAP_CODE_RESPONSE, - id); - if (resp == NULL) - return NULL; - wpa_printf(MSG_DEBUG, "SSL: Building ACK (type=%d id=%d ver=%d)", - (int) eap_type, id, peap_version); - wpabuf_put_u8(resp, peap_version); /* Flags */ - return resp; -} - - -/** - * eap_peer_tls_reauth_init - Re-initialize shared TLS for session resumption - * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init() - * @data: Data for TLS processing - * Returns: 0 on success, -1 on failure - */ -int eap_peer_tls_reauth_init(struct eap_sm *sm, struct eap_ssl_data *data) -{ - eap_peer_tls_reset_input(data); - eap_peer_tls_reset_output(data); - return tls_connection_shutdown(sm->ssl_ctx, data->conn); -} - - -/** - * eap_peer_tls_status - Get TLS status - * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init() - * @data: Data for TLS processing - * @buf: Buffer for status information - * @buflen: Maximum buffer length - * @verbose: Whether to include verbose status information - * Returns: Number of bytes written to buf. - */ -int eap_peer_tls_status(struct eap_sm *sm, struct eap_ssl_data *data, - char *buf, size_t buflen, int verbose) -{ - char name[128]; - int len = 0, ret; - - if (tls_get_cipher(sm->ssl_ctx, data->conn, name, sizeof(name)) == 0) { - ret = os_snprintf(buf + len, buflen - len, - "EAP TLS cipher=%s\n", name); - if (ret < 0 || (size_t) ret >= buflen - len) - return len; - len += ret; - } - - return len; -} - - -/** - * eap_peer_tls_process_init - Initial validation/processing of EAP requests - * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init() - * @data: Data for TLS processing - * @eap_type: EAP type (EAP_TYPE_TLS, EAP_TYPE_PEAP, ...) - * @ret: Return values from EAP request validation and processing - * @reqData: EAP request to be processed (eapReqData) - * @len: Buffer for returning length of the remaining payload - * @flags: Buffer for returning TLS flags - * Returns: Pointer to payload after TLS flags and length or %NULL on failure - * - * This function validates the EAP header and processes the optional TLS - * Message Length field. If this is the first fragment of a TLS message, the - * TLS reassembly code is initialized to receive the indicated number of bytes. - * - * EAP-TLS, EAP-PEAP, EAP-TTLS, and EAP-FAST methods are expected to use this - * function as the first step in processing received messages. They will need - * to process the flags (apart from Message Length Included) that are returned - * through the flags pointer and the message payload that will be returned (and - * the length is returned through the len pointer). Return values (ret) are set - * for continuation of EAP method processing. The caller is responsible for - * setting these to indicate completion (either success or failure) based on - * the authentication result. - */ -const u8 * eap_peer_tls_process_init(struct eap_sm *sm, - struct eap_ssl_data *data, - EapType eap_type, - struct eap_method_ret *ret, - const struct wpabuf *reqData, - size_t *len, u8 *flags) -{ - const u8 *pos; - size_t left; - unsigned int tls_msg_len; - - if (tls_get_errors(sm->ssl_ctx)) { - wpa_printf(MSG_INFO, "SSL: TLS errors detected"); - ret->ignore = TRUE; - return NULL; - } - - pos = eap_hdr_validate(EAP_VENDOR_IETF, eap_type, reqData, &left); - if (pos == NULL) { - ret->ignore = TRUE; - return NULL; - } - if (left == 0) { - wpa_printf(MSG_DEBUG, "SSL: Invalid TLS message: no Flags " - "octet included"); - if (!sm->workaround) { - ret->ignore = TRUE; - return NULL; - } - - wpa_printf(MSG_DEBUG, "SSL: Workaround - assume no Flags " - "indicates ACK frame"); - *flags = 0; - } else { - *flags = *pos++; - left--; - } - wpa_printf(MSG_DEBUG, "SSL: Received packet(len=%lu) - " - "Flags 0x%02x", (unsigned long) wpabuf_len(reqData), - *flags); - if (*flags & EAP_TLS_FLAGS_LENGTH_INCLUDED) { - if (left < 4) { - wpa_printf(MSG_INFO, "SSL: Short frame with TLS " - "length"); - ret->ignore = TRUE; - return NULL; - } - tls_msg_len = WPA_GET_BE32(pos); - wpa_printf(MSG_DEBUG, "SSL: TLS Message Length: %d", - tls_msg_len); - if (data->tls_in_left == 0) { - data->tls_in_total = tls_msg_len; - data->tls_in_left = tls_msg_len; - wpabuf_free(data->tls_in); - data->tls_in = NULL; - } - pos += 4; - left -= 4; - } - - ret->ignore = FALSE; - ret->methodState = METHOD_MAY_CONT; - ret->decision = DECISION_FAIL; - ret->allowNotifications = TRUE; - - *len = left; - return pos; -} - - -/** - * eap_peer_tls_reset_input - Reset input buffers - * @data: Data for TLS processing - * - * This function frees any allocated memory for input buffers and resets input - * state. - */ -void eap_peer_tls_reset_input(struct eap_ssl_data *data) -{ - data->tls_in_left = data->tls_in_total = 0; - wpabuf_free(data->tls_in); - data->tls_in = NULL; -} - - -/** - * eap_peer_tls_reset_output - Reset output buffers - * @data: Data for TLS processing - * - * This function frees any allocated memory for output buffers and resets - * output state. - */ -void eap_peer_tls_reset_output(struct eap_ssl_data *data) -{ - data->tls_out_pos = 0; - wpabuf_free(data->tls_out); - data->tls_out = NULL; -} - - -/** - * eap_peer_tls_decrypt - Decrypt received phase 2 TLS message - * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init() - * @data: Data for TLS processing - * @in_data: Message received from the server - * @in_decrypted: Buffer for returning a pointer to the decrypted message - * Returns: 0 on success, 1 if more input data is needed, or -1 on failure - */ -int eap_peer_tls_decrypt(struct eap_sm *sm, struct eap_ssl_data *data, - const struct wpabuf *in_data, - struct wpabuf **in_decrypted) -{ - const struct wpabuf *msg; - int need_more_input; - - msg = eap_peer_tls_data_reassemble(data, in_data, &need_more_input); - if (msg == NULL) - return need_more_input ? 1 : -1; - - *in_decrypted = tls_connection_decrypt(sm->ssl_ctx, data->conn, msg); - eap_peer_tls_reset_input(data); - if (*in_decrypted == NULL) { - wpa_printf(MSG_INFO, "SSL: Failed to decrypt Phase 2 data"); - return -1; - } - return 0; -} - - -/** - * eap_peer_tls_encrypt - Encrypt phase 2 TLS message - * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init() - * @data: Data for TLS processing - * @eap_type: EAP type (EAP_TYPE_TLS, EAP_TYPE_PEAP, ...) - * @peap_version: Version number for EAP-PEAP/TTLS - * @id: EAP identifier for the response - * @in_data: Plaintext phase 2 data to encrypt or %NULL to continue fragments - * @out_data: Buffer for returning a pointer to the encrypted response message - * Returns: 0 on success, -1 on failure - */ -int eap_peer_tls_encrypt(struct eap_sm *sm, struct eap_ssl_data *data, - EapType eap_type, int peap_version, u8 id, - const struct wpabuf *in_data, - struct wpabuf **out_data) -{ - if (in_data) { - eap_peer_tls_reset_output(data); - data->tls_out = tls_connection_encrypt(sm->ssl_ctx, data->conn, - in_data); - if (data->tls_out == NULL) { - wpa_printf(MSG_INFO, "SSL: Failed to encrypt Phase 2 " - "data (in_len=%lu)", - (unsigned long) wpabuf_len(in_data)); - eap_peer_tls_reset_output(data); - return -1; - } - } - - return eap_tls_process_output(data, eap_type, peap_version, id, 0, - out_data); -} - - -/** - * eap_peer_select_phase2_methods - Select phase 2 EAP method - * @config: Pointer to the network configuration - * @prefix: 'phase2' configuration prefix, e.g., "auth=" - * @types: Buffer for returning allocated list of allowed EAP methods - * @num_types: Buffer for returning number of allocated EAP methods - * Returns: 0 on success, -1 on failure - * - * This function is used to parse EAP method list and select allowed methods - * for Phase2 authentication. - */ -int eap_peer_select_phase2_methods(struct eap_peer_config *config, - const char *prefix, - struct eap_method_type **types, - size_t *num_types) -{ - char *start, *pos, *buf; - struct eap_method_type *methods = NULL, *_methods; - u8 method; - size_t num_methods = 0, prefix_len; - - if (config == NULL || config->phase2 == NULL) - goto get_defaults; - - start = buf = os_strdup(config->phase2); - if (buf == NULL) - return -1; - - prefix_len = os_strlen(prefix); - - while (start && *start != '\0') { - int vendor; - pos = os_strstr(start, prefix); - if (pos == NULL) - break; - if (start != pos && *(pos - 1) != ' ') { - start = pos + prefix_len; - continue; - } - - start = pos + prefix_len; - pos = os_strchr(start, ' '); - if (pos) - *pos++ = '\0'; - method = eap_get_phase2_type(start, &vendor); - if (vendor == EAP_VENDOR_IETF && method == EAP_TYPE_NONE) { - wpa_printf(MSG_ERROR, "TLS: Unsupported Phase2 EAP " - "method '%s'", start); - } else { - num_methods++; - _methods = os_realloc(methods, - num_methods * sizeof(*methods)); - if (_methods == NULL) { - os_free(methods); - os_free(buf); - return -1; - } - methods = _methods; - methods[num_methods - 1].vendor = vendor; - methods[num_methods - 1].method = method; - } - - start = pos; - } - - os_free(buf); - -get_defaults: - if (methods == NULL) - methods = eap_get_phase2_types(config, &num_methods); - - if (methods == NULL) { - wpa_printf(MSG_ERROR, "TLS: No Phase2 EAP methods available"); - return -1; - } - wpa_hexdump(MSG_DEBUG, "TLS: Phase2 EAP types", - (u8 *) methods, - num_methods * sizeof(struct eap_method_type)); - - *types = methods; - *num_types = num_methods; - - return 0; -} - - -/** - * eap_peer_tls_phase2_nak - Generate EAP-Nak for Phase 2 - * @types: Buffer for returning allocated list of allowed EAP methods - * @num_types: Buffer for returning number of allocated EAP methods - * @hdr: EAP-Request header (and the following EAP type octet) - * @resp: Buffer for returning the EAP-Nak message - * Returns: 0 on success, -1 on failure - */ -int eap_peer_tls_phase2_nak(struct eap_method_type *types, size_t num_types, - struct eap_hdr *hdr, struct wpabuf **resp) -{ - u8 *pos = (u8 *) (hdr + 1); - size_t i; - - /* TODO: add support for expanded Nak */ - wpa_printf(MSG_DEBUG, "TLS: Phase 2 Request: Nak type=%d", *pos); - wpa_hexdump(MSG_DEBUG, "TLS: Allowed Phase2 EAP types", - (u8 *) types, num_types * sizeof(struct eap_method_type)); - *resp = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_NAK, num_types, - EAP_CODE_RESPONSE, hdr->identifier); - if (*resp == NULL) - return -1; - - for (i = 0; i < num_types; i++) { - if (types[i].vendor == EAP_VENDOR_IETF && - types[i].method < 256) - wpabuf_put_u8(*resp, types[i].method); - } - - eap_update_len(*resp); - - return 0; -} diff --git a/hostapd-0.8/src/eap_peer/eap_tls_common.h b/hostapd-0.8/src/eap_peer/eap_tls_common.h deleted file mode 100644 index e9e0998..0000000 --- a/hostapd-0.8/src/eap_peer/eap_tls_common.h +++ /dev/null @@ -1,126 +0,0 @@ -/* - * EAP peer: EAP-TLS/PEAP/TTLS/FAST common functions - * Copyright (c) 2004-2009, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#ifndef EAP_TLS_COMMON_H -#define EAP_TLS_COMMON_H - -/** - * struct eap_ssl_data - TLS data for EAP methods - */ -struct eap_ssl_data { - /** - * conn - TLS connection context data from tls_connection_init() - */ - struct tls_connection *conn; - - /** - * tls_out - TLS message to be sent out in fragments - */ - struct wpabuf *tls_out; - - /** - * tls_out_pos - The current position in the outgoing TLS message - */ - size_t tls_out_pos; - - /** - * tls_out_limit - Maximum fragment size for outgoing TLS messages - */ - size_t tls_out_limit; - - /** - * tls_in - Received TLS message buffer for re-assembly - */ - struct wpabuf *tls_in; - - /** - * tls_in_left - Number of remaining bytes in the incoming TLS message - */ - size_t tls_in_left; - - /** - * tls_in_total - Total number of bytes in the incoming TLS message - */ - size_t tls_in_total; - - /** - * phase2 - Whether this TLS connection is used in EAP phase 2 (tunnel) - */ - int phase2; - - /** - * include_tls_length - Whether the TLS length field is included even - * if the TLS data is not fragmented - */ - int include_tls_length; - - /** - * tls_ia - Whether TLS/IA is enabled for this TLS connection - */ - int tls_ia; - - /** - * eap - EAP state machine allocated with eap_peer_sm_init() - */ - struct eap_sm *eap; -}; - - -/* EAP TLS Flags */ -#define EAP_TLS_FLAGS_LENGTH_INCLUDED 0x80 -#define EAP_TLS_FLAGS_MORE_FRAGMENTS 0x40 -#define EAP_TLS_FLAGS_START 0x20 -#define EAP_TLS_VERSION_MASK 0x07 - - /* could be up to 128 bytes, but only the first 64 bytes are used */ -#define EAP_TLS_KEY_LEN 64 - - -int eap_peer_tls_ssl_init(struct eap_sm *sm, struct eap_ssl_data *data, - struct eap_peer_config *config); -void eap_peer_tls_ssl_deinit(struct eap_sm *sm, struct eap_ssl_data *data); -u8 * eap_peer_tls_derive_key(struct eap_sm *sm, struct eap_ssl_data *data, - const char *label, size_t len); -int eap_peer_tls_process_helper(struct eap_sm *sm, struct eap_ssl_data *data, - EapType eap_type, int peap_version, - u8 id, const u8 *in_data, size_t in_len, - struct wpabuf **out_data); -struct wpabuf * eap_peer_tls_build_ack(u8 id, EapType eap_type, - int peap_version); -int eap_peer_tls_reauth_init(struct eap_sm *sm, struct eap_ssl_data *data); -int eap_peer_tls_status(struct eap_sm *sm, struct eap_ssl_data *data, - char *buf, size_t buflen, int verbose); -const u8 * eap_peer_tls_process_init(struct eap_sm *sm, - struct eap_ssl_data *data, - EapType eap_type, - struct eap_method_ret *ret, - const struct wpabuf *reqData, - size_t *len, u8 *flags); -void eap_peer_tls_reset_input(struct eap_ssl_data *data); -void eap_peer_tls_reset_output(struct eap_ssl_data *data); -int eap_peer_tls_decrypt(struct eap_sm *sm, struct eap_ssl_data *data, - const struct wpabuf *in_data, - struct wpabuf **in_decrypted); -int eap_peer_tls_encrypt(struct eap_sm *sm, struct eap_ssl_data *data, - EapType eap_type, int peap_version, u8 id, - const struct wpabuf *in_data, - struct wpabuf **out_data); -int eap_peer_select_phase2_methods(struct eap_peer_config *config, - const char *prefix, - struct eap_method_type **types, - size_t *num_types); -int eap_peer_tls_phase2_nak(struct eap_method_type *types, size_t num_types, - struct eap_hdr *hdr, struct wpabuf **resp); - -#endif /* EAP_TLS_COMMON_H */ diff --git a/hostapd-0.8/src/eap_peer/eap_tnc.c b/hostapd-0.8/src/eap_peer/eap_tnc.c deleted file mode 100644 index 6c95f72..0000000 --- a/hostapd-0.8/src/eap_peer/eap_tnc.c +++ /dev/null @@ -1,434 +0,0 @@ -/* - * EAP peer method: EAP-TNC (Trusted Network Connect) - * Copyright (c) 2007, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#include "includes.h" - -#include "common.h" -#include "base64.h" -#include "eap_i.h" -#include "tncc.h" - - -struct eap_tnc_data { - enum { WAIT_START, PROC_MSG, WAIT_FRAG_ACK, DONE, FAIL } state; - struct tncc_data *tncc; - struct wpabuf *in_buf; - struct wpabuf *out_buf; - size_t out_used; - size_t fragment_size; -}; - - -/* EAP-TNC Flags */ -#define EAP_TNC_FLAGS_LENGTH_INCLUDED 0x80 -#define EAP_TNC_FLAGS_MORE_FRAGMENTS 0x40 -#define EAP_TNC_FLAGS_START 0x20 -#define EAP_TNC_VERSION_MASK 0x07 - -#define EAP_TNC_VERSION 1 - - -static void * eap_tnc_init(struct eap_sm *sm) -{ - struct eap_tnc_data *data; - - data = os_zalloc(sizeof(*data)); - if (data == NULL) - return NULL; - data->state = WAIT_START; - data->fragment_size = 1300; - data->tncc = tncc_init(); - if (data->tncc == NULL) { - os_free(data); - return NULL; - } - - return data; -} - - -static void eap_tnc_deinit(struct eap_sm *sm, void *priv) -{ - struct eap_tnc_data *data = priv; - - wpabuf_free(data->in_buf); - wpabuf_free(data->out_buf); - tncc_deinit(data->tncc); - os_free(data); -} - - -static struct wpabuf * eap_tnc_build_frag_ack(u8 id, u8 code) -{ - struct wpabuf *msg; - - msg = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_TNC, 1, code, id); - if (msg == NULL) { - wpa_printf(MSG_ERROR, "EAP-TNC: Failed to allocate memory " - "for fragment ack"); - return NULL; - } - wpabuf_put_u8(msg, EAP_TNC_VERSION); /* Flags */ - - wpa_printf(MSG_DEBUG, "EAP-TNC: Send fragment ack"); - - return msg; -} - - -static struct wpabuf * eap_tnc_build_msg(struct eap_tnc_data *data, - struct eap_method_ret *ret, u8 id) -{ - struct wpabuf *resp; - u8 flags; - size_t send_len, plen; - - ret->ignore = FALSE; - wpa_printf(MSG_DEBUG, "EAP-TNC: Generating Response"); - ret->allowNotifications = TRUE; - - flags = EAP_TNC_VERSION; - send_len = wpabuf_len(data->out_buf) - data->out_used; - if (1 + send_len > data->fragment_size) { - send_len = data->fragment_size - 1; - flags |= EAP_TNC_FLAGS_MORE_FRAGMENTS; - if (data->out_used == 0) { - flags |= EAP_TNC_FLAGS_LENGTH_INCLUDED; - send_len -= 4; - } - } - - plen = 1 + send_len; - if (flags & EAP_TNC_FLAGS_LENGTH_INCLUDED) - plen += 4; - resp = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_TNC, plen, - EAP_CODE_RESPONSE, id); - if (resp == NULL) - return NULL; - - wpabuf_put_u8(resp, flags); /* Flags */ - if (flags & EAP_TNC_FLAGS_LENGTH_INCLUDED) - wpabuf_put_be32(resp, wpabuf_len(data->out_buf)); - - wpabuf_put_data(resp, wpabuf_head_u8(data->out_buf) + data->out_used, - send_len); - data->out_used += send_len; - - ret->methodState = METHOD_MAY_CONT; - ret->decision = DECISION_FAIL; - - if (data->out_used == wpabuf_len(data->out_buf)) { - wpa_printf(MSG_DEBUG, "EAP-TNC: Sending out %lu bytes " - "(message sent completely)", - (unsigned long) send_len); - wpabuf_free(data->out_buf); - data->out_buf = NULL; - data->out_used = 0; - } else { - wpa_printf(MSG_DEBUG, "EAP-TNC: Sending out %lu bytes " - "(%lu more to send)", (unsigned long) send_len, - (unsigned long) wpabuf_len(data->out_buf) - - data->out_used); - data->state = WAIT_FRAG_ACK; - } - - return resp; -} - - -static int eap_tnc_process_cont(struct eap_tnc_data *data, - const u8 *buf, size_t len) -{ - /* Process continuation of a pending message */ - if (len > wpabuf_tailroom(data->in_buf)) { - wpa_printf(MSG_DEBUG, "EAP-TNC: Fragment overflow"); - data->state = FAIL; - return -1; - } - - wpabuf_put_data(data->in_buf, buf, len); - wpa_printf(MSG_DEBUG, "EAP-TNC: Received %lu bytes, waiting for " - "%lu bytes more", (unsigned long) len, - (unsigned long) wpabuf_tailroom(data->in_buf)); - - return 0; -} - - -static struct wpabuf * eap_tnc_process_fragment(struct eap_tnc_data *data, - struct eap_method_ret *ret, - u8 id, u8 flags, - u32 message_length, - const u8 *buf, size_t len) -{ - /* Process a fragment that is not the last one of the message */ - if (data->in_buf == NULL && !(flags & EAP_TNC_FLAGS_LENGTH_INCLUDED)) { - wpa_printf(MSG_DEBUG, "EAP-TNC: No Message Length field in a " - "fragmented packet"); - ret->ignore = TRUE; - return NULL; - } - - if (data->in_buf == NULL) { - /* First fragment of the message */ - data->in_buf = wpabuf_alloc(message_length); - if (data->in_buf == NULL) { - wpa_printf(MSG_DEBUG, "EAP-TNC: No memory for " - "message"); - ret->ignore = TRUE; - return NULL; - } - wpabuf_put_data(data->in_buf, buf, len); - wpa_printf(MSG_DEBUG, "EAP-TNC: Received %lu bytes in first " - "fragment, waiting for %lu bytes more", - (unsigned long) len, - (unsigned long) wpabuf_tailroom(data->in_buf)); - } - - return eap_tnc_build_frag_ack(id, EAP_CODE_RESPONSE); -} - - -static struct wpabuf * eap_tnc_process(struct eap_sm *sm, void *priv, - struct eap_method_ret *ret, - const struct wpabuf *reqData) -{ - struct eap_tnc_data *data = priv; - struct wpabuf *resp; - const u8 *pos, *end; - u8 *rpos, *rpos1; - size_t len, rlen; - size_t imc_len; - char *start_buf, *end_buf; - size_t start_len, end_len; - int tncs_done = 0; - u8 flags, id; - u32 message_length = 0; - struct wpabuf tmpbuf; - - pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_TNC, reqData, &len); - if (pos == NULL) { - wpa_printf(MSG_INFO, "EAP-TNC: Invalid frame (pos=%p len=%lu)", - pos, (unsigned long) len); - ret->ignore = TRUE; - return NULL; - } - - id = eap_get_id(reqData); - - end = pos + len; - - if (len == 0) - flags = 0; /* fragment ack */ - else - flags = *pos++; - - if (len > 0 && (flags & EAP_TNC_VERSION_MASK) != EAP_TNC_VERSION) { - wpa_printf(MSG_DEBUG, "EAP-TNC: Unsupported version %d", - flags & EAP_TNC_VERSION_MASK); - ret->ignore = TRUE; - return NULL; - } - - if (flags & EAP_TNC_FLAGS_LENGTH_INCLUDED) { - if (end - pos < 4) { - wpa_printf(MSG_DEBUG, "EAP-TNC: Message underflow"); - ret->ignore = TRUE; - return NULL; - } - message_length = WPA_GET_BE32(pos); - pos += 4; - - if (message_length < (u32) (end - pos)) { - wpa_printf(MSG_DEBUG, "EAP-TNC: Invalid Message " - "Length (%d; %ld remaining in this msg)", - message_length, (long) (end - pos)); - ret->ignore = TRUE; - return NULL; - } - } - - wpa_printf(MSG_DEBUG, "EAP-TNC: Received packet: Flags 0x%x " - "Message Length %u", flags, message_length); - - if (data->state == WAIT_FRAG_ACK) { - if (len > 1) { - wpa_printf(MSG_DEBUG, "EAP-TNC: Unexpected payload in " - "WAIT_FRAG_ACK state"); - ret->ignore = TRUE; - return NULL; - } - wpa_printf(MSG_DEBUG, "EAP-TNC: Fragment acknowledged"); - data->state = PROC_MSG; - return eap_tnc_build_msg(data, ret, id); - } - - if (data->in_buf && eap_tnc_process_cont(data, pos, end - pos) < 0) { - ret->ignore = TRUE; - return NULL; - } - - if (flags & EAP_TNC_FLAGS_MORE_FRAGMENTS) { - return eap_tnc_process_fragment(data, ret, id, flags, - message_length, pos, - end - pos); - } - - if (data->in_buf == NULL) { - /* Wrap unfragmented messages as wpabuf without extra copy */ - wpabuf_set(&tmpbuf, pos, end - pos); - data->in_buf = &tmpbuf; - } - - if (data->state == WAIT_START) { - if (!(flags & EAP_TNC_FLAGS_START)) { - wpa_printf(MSG_DEBUG, "EAP-TNC: Server did not use " - "start flag in the first message"); - ret->ignore = TRUE; - goto fail; - } - - tncc_init_connection(data->tncc); - - data->state = PROC_MSG; - } else { - enum tncc_process_res res; - - if (flags & EAP_TNC_FLAGS_START) { - wpa_printf(MSG_DEBUG, "EAP-TNC: Server used start " - "flag again"); - ret->ignore = TRUE; - goto fail; - } - - res = tncc_process_if_tnccs(data->tncc, - wpabuf_head(data->in_buf), - wpabuf_len(data->in_buf)); - switch (res) { - case TNCCS_PROCESS_ERROR: - ret->ignore = TRUE; - goto fail; - case TNCCS_PROCESS_OK_NO_RECOMMENDATION: - case TNCCS_RECOMMENDATION_ERROR: - wpa_printf(MSG_DEBUG, "EAP-TNC: No " - "TNCCS-Recommendation received"); - break; - case TNCCS_RECOMMENDATION_ALLOW: - wpa_msg(sm->msg_ctx, MSG_INFO, - "TNC: Recommendation = allow"); - tncs_done = 1; - break; - case TNCCS_RECOMMENDATION_NONE: - wpa_msg(sm->msg_ctx, MSG_INFO, - "TNC: Recommendation = none"); - tncs_done = 1; - break; - case TNCCS_RECOMMENDATION_ISOLATE: - wpa_msg(sm->msg_ctx, MSG_INFO, - "TNC: Recommendation = isolate"); - tncs_done = 1; - break; - } - } - - if (data->in_buf != &tmpbuf) - wpabuf_free(data->in_buf); - data->in_buf = NULL; - - ret->ignore = FALSE; - ret->methodState = METHOD_MAY_CONT; - ret->decision = DECISION_UNCOND_SUCC; - ret->allowNotifications = TRUE; - - if (data->out_buf) { - data->state = PROC_MSG; - return eap_tnc_build_msg(data, ret, id); - } - - if (tncs_done) { - resp = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_TNC, 1, - EAP_CODE_RESPONSE, eap_get_id(reqData)); - if (resp == NULL) - return NULL; - - wpabuf_put_u8(resp, EAP_TNC_VERSION); - wpa_printf(MSG_DEBUG, "EAP-TNC: TNCS done - reply with an " - "empty ACK message"); - return resp; - } - - imc_len = tncc_total_send_len(data->tncc); - - start_buf = tncc_if_tnccs_start(data->tncc); - if (start_buf == NULL) - return NULL; - start_len = os_strlen(start_buf); - end_buf = tncc_if_tnccs_end(); - if (end_buf == NULL) { - os_free(start_buf); - return NULL; - } - end_len = os_strlen(end_buf); - - rlen = start_len + imc_len + end_len; - resp = wpabuf_alloc(rlen); - if (resp == NULL) { - os_free(start_buf); - os_free(end_buf); - return NULL; - } - - wpabuf_put_data(resp, start_buf, start_len); - os_free(start_buf); - - rpos1 = wpabuf_put(resp, 0); - rpos = tncc_copy_send_buf(data->tncc, rpos1); - wpabuf_put(resp, rpos - rpos1); - - wpabuf_put_data(resp, end_buf, end_len); - os_free(end_buf); - - wpa_hexdump_ascii(MSG_MSGDUMP, "EAP-TNC: Response", - wpabuf_head(resp), wpabuf_len(resp)); - - data->out_buf = resp; - data->state = PROC_MSG; - return eap_tnc_build_msg(data, ret, id); - -fail: - if (data->in_buf == &tmpbuf) - data->in_buf = NULL; - return NULL; -} - - -int eap_peer_tnc_register(void) -{ - struct eap_method *eap; - int ret; - - eap = eap_peer_method_alloc(EAP_PEER_METHOD_INTERFACE_VERSION, - EAP_VENDOR_IETF, EAP_TYPE_TNC, "TNC"); - if (eap == NULL) - return -1; - - eap->init = eap_tnc_init; - eap->deinit = eap_tnc_deinit; - eap->process = eap_tnc_process; - - ret = eap_peer_method_register(eap); - if (ret) - eap_peer_method_free(eap); - return ret; -} diff --git a/hostapd-0.8/src/eap_peer/eap_ttls.c b/hostapd-0.8/src/eap_peer/eap_ttls.c deleted file mode 100644 index e8f0f38..0000000 --- a/hostapd-0.8/src/eap_peer/eap_ttls.c +++ /dev/null @@ -1,1986 +0,0 @@ -/* - * EAP peer method: EAP-TTLS (RFC 5281) - * Copyright (c) 2004-2008, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#include "includes.h" - -#include "common.h" -#include "crypto/ms_funcs.h" -#include "crypto/sha1.h" -#include "crypto/tls.h" -#include "eap_common/chap.h" -#include "eap_common/eap_ttls.h" -#include "mschapv2.h" -#include "eap_i.h" -#include "eap_tls_common.h" -#include "eap_config.h" - - -/* Maximum supported TTLS version - * 0 = RFC 5281 - * 1 = draft-funk-eap-ttls-v1-00.txt - */ -#ifndef EAP_TTLS_VERSION -#define EAP_TTLS_VERSION 0 /* TTLSv1 implementation is not yet complete */ -#endif /* EAP_TTLS_VERSION */ - - -#define MSCHAPV2_KEY_LEN 16 -#define MSCHAPV2_NT_RESPONSE_LEN 24 - - -static void eap_ttls_deinit(struct eap_sm *sm, void *priv); - - -struct eap_ttls_data { - struct eap_ssl_data ssl; - int ssl_initialized; - - int ttls_version, force_ttls_version; - - const struct eap_method *phase2_method; - void *phase2_priv; - int phase2_success; - int phase2_start; - - enum phase2_types { - EAP_TTLS_PHASE2_EAP, - EAP_TTLS_PHASE2_MSCHAPV2, - EAP_TTLS_PHASE2_MSCHAP, - EAP_TTLS_PHASE2_PAP, - EAP_TTLS_PHASE2_CHAP - } phase2_type; - struct eap_method_type phase2_eap_type; - struct eap_method_type *phase2_eap_types; - size_t num_phase2_eap_types; - - u8 auth_response[MSCHAPV2_AUTH_RESPONSE_LEN]; - int auth_response_valid; - u8 master_key[MSCHAPV2_MASTER_KEY_LEN]; /* MSCHAPv2 master key */ - u8 ident; - int resuming; /* starting a resumed session */ - int reauth; /* reauthentication */ - u8 *key_data; - - struct wpabuf *pending_phase2_req; - -#ifdef EAP_TNC - int ready_for_tnc; - int tnc_started; -#endif /* EAP_TNC */ -}; - - -static void * eap_ttls_init(struct eap_sm *sm) -{ - struct eap_ttls_data *data; - struct eap_peer_config *config = eap_get_config(sm); - char *selected; - - data = os_zalloc(sizeof(*data)); - if (data == NULL) - return NULL; - data->ttls_version = EAP_TTLS_VERSION; - data->force_ttls_version = -1; - selected = "EAP"; - data->phase2_type = EAP_TTLS_PHASE2_EAP; - -#if EAP_TTLS_VERSION > 0 - if (config && config->phase1) { - const char *pos = os_strstr(config->phase1, "ttlsver="); - if (pos) { - data->force_ttls_version = atoi(pos + 8); - data->ttls_version = data->force_ttls_version; - wpa_printf(MSG_DEBUG, "EAP-TTLS: Forced TTLS version " - "%d", data->force_ttls_version); - } - } -#endif /* EAP_TTLS_VERSION */ - - if (config && config->phase2) { - if (os_strstr(config->phase2, "autheap=")) { - selected = "EAP"; - data->phase2_type = EAP_TTLS_PHASE2_EAP; - } else if (os_strstr(config->phase2, "auth=MSCHAPV2")) { - selected = "MSCHAPV2"; - data->phase2_type = EAP_TTLS_PHASE2_MSCHAPV2; - } else if (os_strstr(config->phase2, "auth=MSCHAP")) { - selected = "MSCHAP"; - data->phase2_type = EAP_TTLS_PHASE2_MSCHAP; - } else if (os_strstr(config->phase2, "auth=PAP")) { - selected = "PAP"; - data->phase2_type = EAP_TTLS_PHASE2_PAP; - } else if (os_strstr(config->phase2, "auth=CHAP")) { - selected = "CHAP"; - data->phase2_type = EAP_TTLS_PHASE2_CHAP; - } - } - wpa_printf(MSG_DEBUG, "EAP-TTLS: Phase2 type: %s", selected); - - if (data->phase2_type == EAP_TTLS_PHASE2_EAP) { - if (eap_peer_select_phase2_methods(config, "autheap=", - &data->phase2_eap_types, - &data->num_phase2_eap_types) - < 0) { - eap_ttls_deinit(sm, data); - return NULL; - } - - data->phase2_eap_type.vendor = EAP_VENDOR_IETF; - data->phase2_eap_type.method = EAP_TYPE_NONE; - } - -#if EAP_TTLS_VERSION > 0 - if (!(tls_capabilities(sm->ssl_ctx) & TLS_CAPABILITY_IA) && - data->ttls_version > 0) { - if (data->force_ttls_version > 0) { - wpa_printf(MSG_INFO, "EAP-TTLS: Forced TTLSv%d and " - "TLS library does not support TLS/IA.", - data->force_ttls_version); - eap_ttls_deinit(sm, data); - return NULL; - } - data->ttls_version = 0; - } -#endif /* EAP_TTLS_VERSION */ - - return data; -} - - -static void eap_ttls_phase2_eap_deinit(struct eap_sm *sm, - struct eap_ttls_data *data) -{ - if (data->phase2_priv && data->phase2_method) { - data->phase2_method->deinit(sm, data->phase2_priv); - data->phase2_method = NULL; - data->phase2_priv = NULL; - } -} - - -static void eap_ttls_deinit(struct eap_sm *sm, void *priv) -{ - struct eap_ttls_data *data = priv; - if (data == NULL) - return; - eap_ttls_phase2_eap_deinit(sm, data); - os_free(data->phase2_eap_types); - if (data->ssl_initialized) - eap_peer_tls_ssl_deinit(sm, &data->ssl); - os_free(data->key_data); - wpabuf_free(data->pending_phase2_req); - os_free(data); -} - - -static u8 * eap_ttls_avp_hdr(u8 *avphdr, u32 avp_code, u32 vendor_id, - int mandatory, size_t len) -{ - struct ttls_avp_vendor *avp; - u8 flags; - size_t hdrlen; - - avp = (struct ttls_avp_vendor *) avphdr; - flags = mandatory ? AVP_FLAGS_MANDATORY : 0; - if (vendor_id) { - flags |= AVP_FLAGS_VENDOR; - hdrlen = sizeof(*avp); - avp->vendor_id = host_to_be32(vendor_id); - } else { - hdrlen = sizeof(struct ttls_avp); - } - - avp->avp_code = host_to_be32(avp_code); - avp->avp_length = host_to_be32((flags << 24) | (u32) (hdrlen + len)); - - return avphdr + hdrlen; -} - - -static u8 * eap_ttls_avp_add(u8 *start, u8 *avphdr, u32 avp_code, - u32 vendor_id, int mandatory, - const u8 *data, size_t len) -{ - u8 *pos; - pos = eap_ttls_avp_hdr(avphdr, avp_code, vendor_id, mandatory, len); - os_memcpy(pos, data, len); - pos += len; - AVP_PAD(start, pos); - return pos; -} - - -static int eap_ttls_avp_encapsulate(struct wpabuf **resp, u32 avp_code, - int mandatory) -{ - struct wpabuf *msg; - u8 *avp, *pos; - - msg = wpabuf_alloc(sizeof(struct ttls_avp) + wpabuf_len(*resp) + 4); - if (msg == NULL) { - wpabuf_free(*resp); - *resp = NULL; - return -1; - } - - avp = wpabuf_mhead(msg); - pos = eap_ttls_avp_hdr(avp, avp_code, 0, mandatory, wpabuf_len(*resp)); - os_memcpy(pos, wpabuf_head(*resp), wpabuf_len(*resp)); - pos += wpabuf_len(*resp); - AVP_PAD(avp, pos); - wpabuf_free(*resp); - wpabuf_put(msg, pos - avp); - *resp = msg; - return 0; -} - - -#if EAP_TTLS_VERSION > 0 -static int eap_ttls_ia_permute_inner_secret(struct eap_sm *sm, - struct eap_ttls_data *data, - const u8 *key, size_t key_len) -{ - u8 *buf; - size_t buf_len; - int ret; - - if (key) { - buf_len = 2 + key_len; - buf = os_malloc(buf_len); - if (buf == NULL) - return -1; - WPA_PUT_BE16(buf, key_len); - os_memcpy(buf + 2, key, key_len); - } else { - buf = NULL; - buf_len = 0; - } - - wpa_hexdump_key(MSG_DEBUG, "EAP-TTLS: Session keys for TLS/IA inner " - "secret permutation", buf, buf_len); - ret = tls_connection_ia_permute_inner_secret(sm->ssl_ctx, - data->ssl.conn, - buf, buf_len); - os_free(buf); - - return ret; -} -#endif /* EAP_TTLS_VERSION */ - - -static int eap_ttls_v0_derive_key(struct eap_sm *sm, - struct eap_ttls_data *data) -{ - os_free(data->key_data); - data->key_data = eap_peer_tls_derive_key(sm, &data->ssl, - "ttls keying material", - EAP_TLS_KEY_LEN); - if (!data->key_data) { - wpa_printf(MSG_INFO, "EAP-TTLS: Failed to derive key"); - return -1; - } - - wpa_hexdump_key(MSG_DEBUG, "EAP-TTLS: Derived key", - data->key_data, EAP_TLS_KEY_LEN); - - return 0; -} - - -#if EAP_TTLS_VERSION > 0 -static int eap_ttls_v1_derive_key(struct eap_sm *sm, - struct eap_ttls_data *data) -{ - struct tls_keys keys; - u8 *rnd; - - os_free(data->key_data); - data->key_data = NULL; - - os_memset(&keys, 0, sizeof(keys)); - if (tls_connection_get_keys(sm->ssl_ctx, data->ssl.conn, &keys) || - keys.client_random == NULL || keys.server_random == NULL || - keys.inner_secret == NULL) { - wpa_printf(MSG_INFO, "EAP-TTLS: Could not get inner secret, " - "client random, or server random to derive keying " - "material"); - return -1; - } - - rnd = os_malloc(keys.client_random_len + keys.server_random_len); - data->key_data = os_malloc(EAP_TLS_KEY_LEN); - if (rnd == NULL || data->key_data == NULL) { - wpa_printf(MSG_INFO, "EAP-TTLS: No memory for key derivation"); - os_free(rnd); - os_free(data->key_data); - data->key_data = NULL; - return -1; - } - os_memcpy(rnd, keys.client_random, keys.client_random_len); - os_memcpy(rnd + keys.client_random_len, keys.server_random, - keys.server_random_len); - - if (tls_prf(keys.inner_secret, keys.inner_secret_len, - "ttls v1 keying material", rnd, keys.client_random_len + - keys.server_random_len, data->key_data, EAP_TLS_KEY_LEN)) { - wpa_printf(MSG_DEBUG, "EAP-TTLS: Failed to derive key"); - os_free(rnd); - os_free(data->key_data); - data->key_data = NULL; - return -1; - } - - wpa_hexdump(MSG_DEBUG, "EAP-TTLS: client/server random", - rnd, keys.client_random_len + keys.server_random_len); - wpa_hexdump_key(MSG_DEBUG, "EAP-TTLS: TLS/IA inner secret", - keys.inner_secret, keys.inner_secret_len); - - os_free(rnd); - - wpa_hexdump_key(MSG_DEBUG, "EAP-TTLS: Derived key", - data->key_data, EAP_TLS_KEY_LEN); - - return 0; -} -#endif /* EAP_TTLS_VERSION */ - - -static u8 * eap_ttls_implicit_challenge(struct eap_sm *sm, - struct eap_ttls_data *data, size_t len) -{ -#if EAP_TTLS_VERSION > 0 - struct tls_keys keys; - u8 *challenge, *rnd; -#endif /* EAP_TTLS_VERSION */ - - if (data->ttls_version == 0) { - return eap_peer_tls_derive_key(sm, &data->ssl, - "ttls challenge", len); - } - -#if EAP_TTLS_VERSION > 0 - - os_memset(&keys, 0, sizeof(keys)); - if (tls_connection_get_keys(sm->ssl_ctx, data->ssl.conn, &keys) || - keys.client_random == NULL || keys.server_random == NULL || - keys.inner_secret == NULL) { - wpa_printf(MSG_INFO, "EAP-TTLS: Could not get inner secret, " - "client random, or server random to derive " - "implicit challenge"); - return NULL; - } - - rnd = os_malloc(keys.client_random_len + keys.server_random_len); - challenge = os_malloc(len); - if (rnd == NULL || challenge == NULL) { - wpa_printf(MSG_INFO, "EAP-TTLS: No memory for implicit " - "challenge derivation"); - os_free(rnd); - os_free(challenge); - return NULL; - } - os_memcpy(rnd, keys.server_random, keys.server_random_len); - os_memcpy(rnd + keys.server_random_len, keys.client_random, - keys.client_random_len); - - if (tls_prf(keys.inner_secret, keys.inner_secret_len, - "inner application challenge", rnd, - keys.client_random_len + keys.server_random_len, - challenge, len)) { - wpa_printf(MSG_DEBUG, "EAP-TTLS: Failed to derive implicit " - "challenge"); - os_free(rnd); - os_free(challenge); - return NULL; - } - - os_free(rnd); - - wpa_hexdump_key(MSG_DEBUG, "EAP-TTLS: Derived implicit challenge", - challenge, len); - - return challenge; - -#else /* EAP_TTLS_VERSION */ - - return NULL; - -#endif /* EAP_TTLS_VERSION */ -} - - -static void eap_ttlsv1_phase2_eap_finish(struct eap_sm *sm, - struct eap_ttls_data *data, - struct eap_method_ret *ret) -{ -#if EAP_TTLS_VERSION > 0 - if (data->ttls_version > 0) { - const struct eap_method *m = data->phase2_method; - void *priv = data->phase2_priv; - - /* TTLSv1 requires TLS/IA FinalPhaseFinished */ - if (ret->decision == DECISION_UNCOND_SUCC) - ret->decision = DECISION_COND_SUCC; - ret->methodState = METHOD_CONT; - - if (ret->decision == DECISION_COND_SUCC && - m->isKeyAvailable && m->getKey && - m->isKeyAvailable(sm, priv)) { - u8 *key; - size_t key_len; - key = m->getKey(sm, priv, &key_len); - if (key) { - eap_ttls_ia_permute_inner_secret( - sm, data, key, key_len); - os_free(key); - } - } - } -#endif /* EAP_TTLS_VERSION */ -} - - -static void eap_ttls_phase2_select_eap_method(struct eap_ttls_data *data, - u8 method) -{ - size_t i; - for (i = 0; i < data->num_phase2_eap_types; i++) { - if (data->phase2_eap_types[i].vendor != EAP_VENDOR_IETF || - data->phase2_eap_types[i].method != method) - continue; - - data->phase2_eap_type.vendor = - data->phase2_eap_types[i].vendor; - data->phase2_eap_type.method = - data->phase2_eap_types[i].method; - wpa_printf(MSG_DEBUG, "EAP-TTLS: Selected " - "Phase 2 EAP vendor %d method %d", - data->phase2_eap_type.vendor, - data->phase2_eap_type.method); - break; - } -} - - -static int eap_ttls_phase2_eap_process(struct eap_sm *sm, - struct eap_ttls_data *data, - struct eap_method_ret *ret, - struct eap_hdr *hdr, size_t len, - struct wpabuf **resp) -{ - struct wpabuf msg; - struct eap_method_ret iret; - - os_memset(&iret, 0, sizeof(iret)); - wpabuf_set(&msg, hdr, len); - *resp = data->phase2_method->process(sm, data->phase2_priv, &iret, - &msg); - if ((iret.methodState == METHOD_DONE || - iret.methodState == METHOD_MAY_CONT) && - (iret.decision == DECISION_UNCOND_SUCC || - iret.decision == DECISION_COND_SUCC || - iret.decision == DECISION_FAIL)) { - ret->methodState = iret.methodState; - ret->decision = iret.decision; - } - eap_ttlsv1_phase2_eap_finish(sm, data, ret); - - return 0; -} - - -static int eap_ttls_phase2_request_eap_method(struct eap_sm *sm, - struct eap_ttls_data *data, - struct eap_method_ret *ret, - struct eap_hdr *hdr, size_t len, - u8 method, struct wpabuf **resp) -{ -#ifdef EAP_TNC - if (data->tnc_started && data->phase2_method && - data->phase2_priv && method == EAP_TYPE_TNC && - data->phase2_eap_type.method == EAP_TYPE_TNC) - return eap_ttls_phase2_eap_process(sm, data, ret, hdr, len, - resp); - - if (data->ready_for_tnc && !data->tnc_started && - method == EAP_TYPE_TNC) { - wpa_printf(MSG_DEBUG, "EAP-TTLS: Start TNC after completed " - "EAP method"); - data->tnc_started = 1; - } - - if (data->tnc_started) { - if (data->phase2_eap_type.vendor != EAP_VENDOR_IETF || - data->phase2_eap_type.method == EAP_TYPE_TNC) { - wpa_printf(MSG_DEBUG, "EAP-TTLS: Unexpected EAP " - "type %d for TNC", method); - return -1; - } - - data->phase2_eap_type.vendor = EAP_VENDOR_IETF; - data->phase2_eap_type.method = method; - wpa_printf(MSG_DEBUG, "EAP-TTLS: Selected " - "Phase 2 EAP vendor %d method %d (TNC)", - data->phase2_eap_type.vendor, - data->phase2_eap_type.method); - - if (data->phase2_type == EAP_TTLS_PHASE2_EAP) - eap_ttls_phase2_eap_deinit(sm, data); - } -#endif /* EAP_TNC */ - - if (data->phase2_eap_type.vendor == EAP_VENDOR_IETF && - data->phase2_eap_type.method == EAP_TYPE_NONE) - eap_ttls_phase2_select_eap_method(data, method); - - if (method != data->phase2_eap_type.method || method == EAP_TYPE_NONE) - { - if (eap_peer_tls_phase2_nak(data->phase2_eap_types, - data->num_phase2_eap_types, - hdr, resp)) - return -1; - return 0; - } - - if (data->phase2_priv == NULL) { - data->phase2_method = eap_peer_get_eap_method( - EAP_VENDOR_IETF, method); - if (data->phase2_method) { - sm->init_phase2 = 1; - data->phase2_priv = data->phase2_method->init(sm); - sm->init_phase2 = 0; - } - } - if (data->phase2_priv == NULL || data->phase2_method == NULL) { - wpa_printf(MSG_INFO, "EAP-TTLS: failed to initialize " - "Phase 2 EAP method %d", method); - return -1; - } - - return eap_ttls_phase2_eap_process(sm, data, ret, hdr, len, resp); -} - - -static int eap_ttls_phase2_request_eap(struct eap_sm *sm, - struct eap_ttls_data *data, - struct eap_method_ret *ret, - struct eap_hdr *hdr, - struct wpabuf **resp) -{ - size_t len = be_to_host16(hdr->length); - u8 *pos; - struct eap_peer_config *config = eap_get_config(sm); - - if (len <= sizeof(struct eap_hdr)) { - wpa_printf(MSG_INFO, "EAP-TTLS: too short " - "Phase 2 request (len=%lu)", (unsigned long) len); - return -1; - } - pos = (u8 *) (hdr + 1); - wpa_printf(MSG_DEBUG, "EAP-TTLS: Phase 2 EAP Request: type=%d", *pos); - switch (*pos) { - case EAP_TYPE_IDENTITY: - *resp = eap_sm_buildIdentity(sm, hdr->identifier, 1); - break; - default: - if (eap_ttls_phase2_request_eap_method(sm, data, ret, hdr, len, - *pos, resp) < 0) - return -1; - break; - } - - if (*resp == NULL && - (config->pending_req_identity || config->pending_req_password || - config->pending_req_otp)) { - return 0; - } - - if (*resp == NULL) - return -1; - - wpa_hexdump_buf(MSG_DEBUG, "EAP-TTLS: AVP encapsulate EAP Response", - *resp); - return eap_ttls_avp_encapsulate(resp, RADIUS_ATTR_EAP_MESSAGE, 1); -} - - -static void eap_ttlsv1_permute_inner(struct eap_sm *sm, - struct eap_ttls_data *data) -{ -#if EAP_TTLS_VERSION > 0 - u8 session_key[2 * MSCHAPV2_KEY_LEN]; - - if (data->ttls_version == 0) - return; - - get_asymetric_start_key(data->master_key, session_key, - MSCHAPV2_KEY_LEN, 0, 0); - get_asymetric_start_key(data->master_key, - session_key + MSCHAPV2_KEY_LEN, - MSCHAPV2_KEY_LEN, 1, 0); - eap_ttls_ia_permute_inner_secret(sm, data, session_key, - sizeof(session_key)); -#endif /* EAP_TTLS_VERSION */ -} - - -static int eap_ttls_phase2_request_mschapv2(struct eap_sm *sm, - struct eap_ttls_data *data, - struct eap_method_ret *ret, - struct wpabuf **resp) -{ - struct wpabuf *msg; - u8 *buf, *pos, *challenge, *peer_challenge; - const u8 *identity, *password; - size_t identity_len, password_len; - int pwhash; - - wpa_printf(MSG_DEBUG, "EAP-TTLS: Phase 2 MSCHAPV2 Request"); - - identity = eap_get_config_identity(sm, &identity_len); - password = eap_get_config_password2(sm, &password_len, &pwhash); - if (identity == NULL || password == NULL) - return -1; - - msg = wpabuf_alloc(identity_len + 1000); - if (msg == NULL) { - wpa_printf(MSG_ERROR, - "EAP-TTLS/MSCHAPV2: Failed to allocate memory"); - return -1; - } - pos = buf = wpabuf_mhead(msg); - - /* User-Name */ - pos = eap_ttls_avp_add(buf, pos, RADIUS_ATTR_USER_NAME, 0, 1, - identity, identity_len); - - /* MS-CHAP-Challenge */ - challenge = eap_ttls_implicit_challenge( - sm, data, EAP_TTLS_MSCHAPV2_CHALLENGE_LEN + 1); - if (challenge == NULL) { - wpabuf_free(msg); - wpa_printf(MSG_ERROR, "EAP-TTLS/MSCHAPV2: Failed to derive " - "implicit challenge"); - return -1; - } - peer_challenge = challenge + 1 + EAP_TTLS_MSCHAPV2_CHALLENGE_LEN; - - pos = eap_ttls_avp_add(buf, pos, RADIUS_ATTR_MS_CHAP_CHALLENGE, - RADIUS_VENDOR_ID_MICROSOFT, 1, - challenge, EAP_TTLS_MSCHAPV2_CHALLENGE_LEN); - - /* MS-CHAP2-Response */ - pos = eap_ttls_avp_hdr(pos, RADIUS_ATTR_MS_CHAP2_RESPONSE, - RADIUS_VENDOR_ID_MICROSOFT, 1, - EAP_TTLS_MSCHAPV2_RESPONSE_LEN); - data->ident = challenge[EAP_TTLS_MSCHAPV2_CHALLENGE_LEN]; - *pos++ = data->ident; - *pos++ = 0; /* Flags */ - os_memcpy(pos, peer_challenge, EAP_TTLS_MSCHAPV2_CHALLENGE_LEN); - pos += EAP_TTLS_MSCHAPV2_CHALLENGE_LEN; - os_memset(pos, 0, 8); /* Reserved, must be zero */ - pos += 8; - if (mschapv2_derive_response(identity, identity_len, password, - password_len, pwhash, challenge, - peer_challenge, pos, data->auth_response, - data->master_key)) { - wpabuf_free(msg); - wpa_printf(MSG_ERROR, "EAP-TTLS/MSCHAPV2: Failed to derive " - "response"); - return -1; - } - data->auth_response_valid = 1; - - eap_ttlsv1_permute_inner(sm, data); - - pos += 24; - os_free(challenge); - AVP_PAD(buf, pos); - - wpabuf_put(msg, pos - buf); - *resp = msg; - - if (sm->workaround && data->ttls_version == 0) { - /* At least FreeRADIUS seems to be terminating - * EAP-TTLS/MSHCAPV2 without the expected MS-CHAP-v2 Success - * packet. */ - wpa_printf(MSG_DEBUG, "EAP-TTLS/MSCHAPV2: EAP workaround - " - "allow success without tunneled response"); - ret->methodState = METHOD_MAY_CONT; - ret->decision = DECISION_COND_SUCC; - } - - return 0; -} - - -static int eap_ttls_phase2_request_mschap(struct eap_sm *sm, - struct eap_ttls_data *data, - struct eap_method_ret *ret, - struct wpabuf **resp) -{ - struct wpabuf *msg; - u8 *buf, *pos, *challenge; - const u8 *identity, *password; - size_t identity_len, password_len; - int pwhash; - - wpa_printf(MSG_DEBUG, "EAP-TTLS: Phase 2 MSCHAP Request"); - - identity = eap_get_config_identity(sm, &identity_len); - password = eap_get_config_password2(sm, &password_len, &pwhash); - if (identity == NULL || password == NULL) - return -1; - - msg = wpabuf_alloc(identity_len + 1000); - if (msg == NULL) { - wpa_printf(MSG_ERROR, - "EAP-TTLS/MSCHAP: Failed to allocate memory"); - return -1; - } - pos = buf = wpabuf_mhead(msg); - - /* User-Name */ - pos = eap_ttls_avp_add(buf, pos, RADIUS_ATTR_USER_NAME, 0, 1, - identity, identity_len); - - /* MS-CHAP-Challenge */ - challenge = eap_ttls_implicit_challenge( - sm, data, EAP_TTLS_MSCHAP_CHALLENGE_LEN + 1); - if (challenge == NULL) { - wpabuf_free(msg); - wpa_printf(MSG_ERROR, "EAP-TTLS/MSCHAP: Failed to derive " - "implicit challenge"); - return -1; - } - - pos = eap_ttls_avp_add(buf, pos, RADIUS_ATTR_MS_CHAP_CHALLENGE, - RADIUS_VENDOR_ID_MICROSOFT, 1, - challenge, EAP_TTLS_MSCHAP_CHALLENGE_LEN); - - /* MS-CHAP-Response */ - pos = eap_ttls_avp_hdr(pos, RADIUS_ATTR_MS_CHAP_RESPONSE, - RADIUS_VENDOR_ID_MICROSOFT, 1, - EAP_TTLS_MSCHAP_RESPONSE_LEN); - data->ident = challenge[EAP_TTLS_MSCHAP_CHALLENGE_LEN]; - *pos++ = data->ident; - *pos++ = 1; /* Flags: Use NT style passwords */ - os_memset(pos, 0, 24); /* LM-Response */ - pos += 24; - if (pwhash) { - challenge_response(challenge, password, pos); /* NT-Response */ - wpa_hexdump_key(MSG_DEBUG, "EAP-TTLS: MSCHAP password hash", - password, 16); - } else { - nt_challenge_response(challenge, password, password_len, - pos); /* NT-Response */ - wpa_hexdump_ascii_key(MSG_DEBUG, "EAP-TTLS: MSCHAP password", - password, password_len); - } - wpa_hexdump(MSG_DEBUG, "EAP-TTLS: MSCHAP implicit challenge", - challenge, EAP_TTLS_MSCHAP_CHALLENGE_LEN); - wpa_hexdump(MSG_DEBUG, "EAP-TTLS: MSCHAP response", pos, 24); - pos += 24; - os_free(challenge); - AVP_PAD(buf, pos); - - wpabuf_put(msg, pos - buf); - *resp = msg; - - if (data->ttls_version > 0) { - /* EAP-TTLSv1 uses TLS/IA FinalPhaseFinished to report success, - * so do not allow connection to be terminated yet. */ - ret->methodState = METHOD_CONT; - ret->decision = DECISION_COND_SUCC; - } else { - /* EAP-TTLS/MSCHAP does not provide tunneled success - * notification, so assume that Phase2 succeeds. */ - ret->methodState = METHOD_DONE; - ret->decision = DECISION_COND_SUCC; - } - - return 0; -} - - -static int eap_ttls_phase2_request_pap(struct eap_sm *sm, - struct eap_ttls_data *data, - struct eap_method_ret *ret, - struct wpabuf **resp) -{ - struct wpabuf *msg; - u8 *buf, *pos; - size_t pad; - const u8 *identity, *password; - size_t identity_len, password_len; - - wpa_printf(MSG_DEBUG, "EAP-TTLS: Phase 2 PAP Request"); - - identity = eap_get_config_identity(sm, &identity_len); - password = eap_get_config_password(sm, &password_len); - if (identity == NULL || password == NULL) - return -1; - - msg = wpabuf_alloc(identity_len + password_len + 100); - if (msg == NULL) { - wpa_printf(MSG_ERROR, - "EAP-TTLS/PAP: Failed to allocate memory"); - return -1; - } - pos = buf = wpabuf_mhead(msg); - - /* User-Name */ - pos = eap_ttls_avp_add(buf, pos, RADIUS_ATTR_USER_NAME, 0, 1, - identity, identity_len); - - /* User-Password; in RADIUS, this is encrypted, but EAP-TTLS encrypts - * the data, so no separate encryption is used in the AVP itself. - * However, the password is padded to obfuscate its length. */ - pad = password_len == 0 ? 16 : (16 - (password_len & 15)) & 15; - pos = eap_ttls_avp_hdr(pos, RADIUS_ATTR_USER_PASSWORD, 0, 1, - password_len + pad); - os_memcpy(pos, password, password_len); - pos += password_len; - os_memset(pos, 0, pad); - pos += pad; - AVP_PAD(buf, pos); - - wpabuf_put(msg, pos - buf); - *resp = msg; - - if (data->ttls_version > 0) { - /* EAP-TTLSv1 uses TLS/IA FinalPhaseFinished to report success, - * so do not allow connection to be terminated yet. */ - ret->methodState = METHOD_CONT; - ret->decision = DECISION_COND_SUCC; - } else { - /* EAP-TTLS/PAP does not provide tunneled success notification, - * so assume that Phase2 succeeds. */ - ret->methodState = METHOD_DONE; - ret->decision = DECISION_COND_SUCC; - } - - return 0; -} - - -static int eap_ttls_phase2_request_chap(struct eap_sm *sm, - struct eap_ttls_data *data, - struct eap_method_ret *ret, - struct wpabuf **resp) -{ - struct wpabuf *msg; - u8 *buf, *pos, *challenge; - const u8 *identity, *password; - size_t identity_len, password_len; - - wpa_printf(MSG_DEBUG, "EAP-TTLS: Phase 2 CHAP Request"); - - identity = eap_get_config_identity(sm, &identity_len); - password = eap_get_config_password(sm, &password_len); - if (identity == NULL || password == NULL) - return -1; - - msg = wpabuf_alloc(identity_len + 1000); - if (msg == NULL) { - wpa_printf(MSG_ERROR, - "EAP-TTLS/CHAP: Failed to allocate memory"); - return -1; - } - pos = buf = wpabuf_mhead(msg); - - /* User-Name */ - pos = eap_ttls_avp_add(buf, pos, RADIUS_ATTR_USER_NAME, 0, 1, - identity, identity_len); - - /* CHAP-Challenge */ - challenge = eap_ttls_implicit_challenge( - sm, data, EAP_TTLS_CHAP_CHALLENGE_LEN + 1); - if (challenge == NULL) { - wpabuf_free(msg); - wpa_printf(MSG_ERROR, "EAP-TTLS/CHAP: Failed to derive " - "implicit challenge"); - return -1; - } - - pos = eap_ttls_avp_add(buf, pos, RADIUS_ATTR_CHAP_CHALLENGE, 0, 1, - challenge, EAP_TTLS_CHAP_CHALLENGE_LEN); - - /* CHAP-Password */ - pos = eap_ttls_avp_hdr(pos, RADIUS_ATTR_CHAP_PASSWORD, 0, 1, - 1 + EAP_TTLS_CHAP_PASSWORD_LEN); - data->ident = challenge[EAP_TTLS_CHAP_CHALLENGE_LEN]; - *pos++ = data->ident; - - /* MD5(Ident + Password + Challenge) */ - chap_md5(data->ident, password, password_len, challenge, - EAP_TTLS_CHAP_CHALLENGE_LEN, pos); - - wpa_hexdump_ascii(MSG_DEBUG, "EAP-TTLS: CHAP username", - identity, identity_len); - wpa_hexdump_ascii_key(MSG_DEBUG, "EAP-TTLS: CHAP password", - password, password_len); - wpa_hexdump(MSG_DEBUG, "EAP-TTLS: CHAP implicit challenge", - challenge, EAP_TTLS_CHAP_CHALLENGE_LEN); - wpa_hexdump(MSG_DEBUG, "EAP-TTLS: CHAP password", - pos, EAP_TTLS_CHAP_PASSWORD_LEN); - pos += EAP_TTLS_CHAP_PASSWORD_LEN; - os_free(challenge); - AVP_PAD(buf, pos); - - wpabuf_put(msg, pos - buf); - *resp = msg; - - if (data->ttls_version > 0) { - /* EAP-TTLSv1 uses TLS/IA FinalPhaseFinished to report success, - * so do not allow connection to be terminated yet. */ - ret->methodState = METHOD_CONT; - ret->decision = DECISION_COND_SUCC; - } else { - /* EAP-TTLS/CHAP does not provide tunneled success - * notification, so assume that Phase2 succeeds. */ - ret->methodState = METHOD_DONE; - ret->decision = DECISION_COND_SUCC; - } - - return 0; -} - - -static int eap_ttls_phase2_request(struct eap_sm *sm, - struct eap_ttls_data *data, - struct eap_method_ret *ret, - struct eap_hdr *hdr, - struct wpabuf **resp) -{ - int res = 0; - size_t len; - enum phase2_types phase2_type = data->phase2_type; - -#ifdef EAP_TNC - if (data->tnc_started) { - wpa_printf(MSG_DEBUG, "EAP-TTLS: Processing TNC"); - phase2_type = EAP_TTLS_PHASE2_EAP; - } -#endif /* EAP_TNC */ - - if (phase2_type == EAP_TTLS_PHASE2_MSCHAPV2 || - phase2_type == EAP_TTLS_PHASE2_MSCHAP || - phase2_type == EAP_TTLS_PHASE2_PAP || - phase2_type == EAP_TTLS_PHASE2_CHAP) { - if (eap_get_config_identity(sm, &len) == NULL) { - wpa_printf(MSG_INFO, - "EAP-TTLS: Identity not configured"); - eap_sm_request_identity(sm); - if (eap_get_config_password(sm, &len) == NULL) - eap_sm_request_password(sm); - return 0; - } - - if (eap_get_config_password(sm, &len) == NULL) { - wpa_printf(MSG_INFO, - "EAP-TTLS: Password not configured"); - eap_sm_request_password(sm); - return 0; - } - } - - switch (phase2_type) { - case EAP_TTLS_PHASE2_EAP: - res = eap_ttls_phase2_request_eap(sm, data, ret, hdr, resp); - break; - case EAP_TTLS_PHASE2_MSCHAPV2: - res = eap_ttls_phase2_request_mschapv2(sm, data, ret, resp); - break; - case EAP_TTLS_PHASE2_MSCHAP: - res = eap_ttls_phase2_request_mschap(sm, data, ret, resp); - break; - case EAP_TTLS_PHASE2_PAP: - res = eap_ttls_phase2_request_pap(sm, data, ret, resp); - break; - case EAP_TTLS_PHASE2_CHAP: - res = eap_ttls_phase2_request_chap(sm, data, ret, resp); - break; - default: - wpa_printf(MSG_ERROR, "EAP-TTLS: Phase 2 - Unknown"); - res = -1; - break; - } - - if (res < 0) { - ret->methodState = METHOD_DONE; - ret->decision = DECISION_FAIL; - } - - return res; -} - - -#if EAP_TTLS_VERSION > 0 -static struct wpabuf * eap_ttls_build_phase_finished( - struct eap_sm *sm, struct eap_ttls_data *data, int id, int final) -{ - struct wpabuf *req, *buf; - - buf = tls_connection_ia_send_phase_finished(sm->ssl_ctx, - data->ssl.conn, - final); - if (buf == NULL) - return NULL; - - req = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_TTLS, - 1 + wpabuf_len(buf), - EAP_CODE_RESPONSE, id); - if (req == NULL) { - wpabuf_free(buf); - return NULL; - } - - wpabuf_put_u8(req, data->ttls_version); - wpabuf_put_buf(req, buf); - wpabuf_free(buf); - eap_update_len(req); - - return req; -} -#endif /* EAP_TTLS_VERSION */ - - -struct ttls_parse_avp { - u8 *mschapv2; - u8 *eapdata; - size_t eap_len; - int mschapv2_error; -}; - - -static int eap_ttls_parse_attr_eap(const u8 *dpos, size_t dlen, - struct ttls_parse_avp *parse) -{ - wpa_printf(MSG_DEBUG, "EAP-TTLS: AVP - EAP Message"); - if (parse->eapdata == NULL) { - parse->eapdata = os_malloc(dlen); - if (parse->eapdata == NULL) { - wpa_printf(MSG_WARNING, "EAP-TTLS: Failed to allocate " - "memory for Phase 2 EAP data"); - return -1; - } - os_memcpy(parse->eapdata, dpos, dlen); - parse->eap_len = dlen; - } else { - u8 *neweap = os_realloc(parse->eapdata, parse->eap_len + dlen); - if (neweap == NULL) { - wpa_printf(MSG_WARNING, "EAP-TTLS: Failed to allocate " - "memory for Phase 2 EAP data"); - return -1; - } - os_memcpy(neweap + parse->eap_len, dpos, dlen); - parse->eapdata = neweap; - parse->eap_len += dlen; - } - - return 0; -} - - -static int eap_ttls_parse_avp(u8 *pos, size_t left, - struct ttls_parse_avp *parse) -{ - struct ttls_avp *avp; - u32 avp_code, avp_length, vendor_id = 0; - u8 avp_flags, *dpos; - size_t dlen; - - avp = (struct ttls_avp *) pos; - avp_code = be_to_host32(avp->avp_code); - avp_length = be_to_host32(avp->avp_length); - avp_flags = (avp_length >> 24) & 0xff; - avp_length &= 0xffffff; - wpa_printf(MSG_DEBUG, "EAP-TTLS: AVP: code=%d flags=0x%02x " - "length=%d", (int) avp_code, avp_flags, - (int) avp_length); - - if (avp_length > left) { - wpa_printf(MSG_WARNING, "EAP-TTLS: AVP overflow " - "(len=%d, left=%lu) - dropped", - (int) avp_length, (unsigned long) left); - return -1; - } - - if (avp_length < sizeof(*avp)) { - wpa_printf(MSG_WARNING, "EAP-TTLS: Invalid AVP length %d", - avp_length); - return -1; - } - - dpos = (u8 *) (avp + 1); - dlen = avp_length - sizeof(*avp); - if (avp_flags & AVP_FLAGS_VENDOR) { - if (dlen < 4) { - wpa_printf(MSG_WARNING, "EAP-TTLS: Vendor AVP " - "underflow"); - return -1; - } - vendor_id = WPA_GET_BE32(dpos); - wpa_printf(MSG_DEBUG, "EAP-TTLS: AVP vendor_id %d", - (int) vendor_id); - dpos += 4; - dlen -= 4; - } - - wpa_hexdump(MSG_DEBUG, "EAP-TTLS: AVP data", dpos, dlen); - - if (vendor_id == 0 && avp_code == RADIUS_ATTR_EAP_MESSAGE) { - if (eap_ttls_parse_attr_eap(dpos, dlen, parse) < 0) - return -1; - } else if (vendor_id == 0 && avp_code == RADIUS_ATTR_REPLY_MESSAGE) { - /* This is an optional message that can be displayed to - * the user. */ - wpa_hexdump_ascii(MSG_DEBUG, "EAP-TTLS: AVP - Reply-Message", - dpos, dlen); - } else if (vendor_id == RADIUS_VENDOR_ID_MICROSOFT && - avp_code == RADIUS_ATTR_MS_CHAP2_SUCCESS) { - wpa_hexdump_ascii(MSG_DEBUG, "EAP-TTLS: MS-CHAP2-Success", - dpos, dlen); - if (dlen != 43) { - wpa_printf(MSG_WARNING, "EAP-TTLS: Unexpected " - "MS-CHAP2-Success length " - "(len=%lu, expected 43)", - (unsigned long) dlen); - return -1; - } - parse->mschapv2 = dpos; - } else if (vendor_id == RADIUS_VENDOR_ID_MICROSOFT && - avp_code == RADIUS_ATTR_MS_CHAP_ERROR) { - wpa_hexdump_ascii(MSG_DEBUG, "EAP-TTLS: MS-CHAP-Error", - dpos, dlen); - parse->mschapv2_error = 1; - } else if (avp_flags & AVP_FLAGS_MANDATORY) { - wpa_printf(MSG_WARNING, "EAP-TTLS: Unsupported mandatory AVP " - "code %d vendor_id %d - dropped", - (int) avp_code, (int) vendor_id); - return -1; - } else { - wpa_printf(MSG_DEBUG, "EAP-TTLS: Ignoring unsupported AVP " - "code %d vendor_id %d", - (int) avp_code, (int) vendor_id); - } - - return avp_length; -} - - -static int eap_ttls_parse_avps(struct wpabuf *in_decrypted, - struct ttls_parse_avp *parse) -{ - u8 *pos; - size_t left, pad; - int avp_length; - - pos = wpabuf_mhead(in_decrypted); - left = wpabuf_len(in_decrypted); - wpa_hexdump(MSG_DEBUG, "EAP-TTLS: Decrypted Phase 2 AVPs", pos, left); - if (left < sizeof(struct ttls_avp)) { - wpa_printf(MSG_WARNING, "EAP-TTLS: Too short Phase 2 AVP frame" - " len=%lu expected %lu or more - dropped", - (unsigned long) left, - (unsigned long) sizeof(struct ttls_avp)); - return -1; - } - - /* Parse AVPs */ - os_memset(parse, 0, sizeof(*parse)); - - while (left > 0) { - avp_length = eap_ttls_parse_avp(pos, left, parse); - if (avp_length < 0) - return -1; - - pad = (4 - (avp_length & 3)) & 3; - pos += avp_length + pad; - if (left < avp_length + pad) - left = 0; - else - left -= avp_length + pad; - } - - return 0; -} - - -static u8 * eap_ttls_fake_identity_request(void) -{ - struct eap_hdr *hdr; - u8 *buf; - - wpa_printf(MSG_DEBUG, "EAP-TTLS: empty data in beginning of " - "Phase 2 - use fake EAP-Request Identity"); - buf = os_malloc(sizeof(*hdr) + 1); - if (buf == NULL) { - wpa_printf(MSG_WARNING, "EAP-TTLS: failed to allocate " - "memory for fake EAP-Identity Request"); - return NULL; - } - - hdr = (struct eap_hdr *) buf; - hdr->code = EAP_CODE_REQUEST; - hdr->identifier = 0; - hdr->length = host_to_be16(sizeof(*hdr) + 1); - buf[sizeof(*hdr)] = EAP_TYPE_IDENTITY; - - return buf; -} - - -static int eap_ttls_encrypt_response(struct eap_sm *sm, - struct eap_ttls_data *data, - struct wpabuf *resp, u8 identifier, - struct wpabuf **out_data) -{ - if (resp == NULL) - return 0; - - wpa_hexdump_buf_key(MSG_DEBUG, "EAP-TTLS: Encrypting Phase 2 data", - resp); - if (eap_peer_tls_encrypt(sm, &data->ssl, EAP_TYPE_TTLS, - data->ttls_version, identifier, - resp, out_data)) { - wpa_printf(MSG_INFO, "EAP-TTLS: Failed to encrypt a Phase 2 " - "frame"); - return -1; - } - wpabuf_free(resp); - - return 0; -} - - -static int eap_ttls_process_phase2_eap(struct eap_sm *sm, - struct eap_ttls_data *data, - struct eap_method_ret *ret, - struct ttls_parse_avp *parse, - struct wpabuf **resp) -{ - struct eap_hdr *hdr; - size_t len; - - if (parse->eapdata == NULL) { - wpa_printf(MSG_WARNING, "EAP-TTLS: No EAP Message in the " - "packet - dropped"); - return -1; - } - - wpa_hexdump(MSG_DEBUG, "EAP-TTLS: Phase 2 EAP", - parse->eapdata, parse->eap_len); - hdr = (struct eap_hdr *) parse->eapdata; - - if (parse->eap_len < sizeof(*hdr)) { - wpa_printf(MSG_WARNING, "EAP-TTLS: Too short Phase 2 EAP " - "frame (len=%lu, expected %lu or more) - dropped", - (unsigned long) parse->eap_len, - (unsigned long) sizeof(*hdr)); - return -1; - } - len = be_to_host16(hdr->length); - if (len > parse->eap_len) { - wpa_printf(MSG_INFO, "EAP-TTLS: Length mismatch in Phase 2 " - "EAP frame (EAP hdr len=%lu, EAP data len in " - "AVP=%lu)", - (unsigned long) len, - (unsigned long) parse->eap_len); - return -1; - } - wpa_printf(MSG_DEBUG, "EAP-TTLS: received Phase 2: code=%d " - "identifier=%d length=%lu", - hdr->code, hdr->identifier, (unsigned long) len); - switch (hdr->code) { - case EAP_CODE_REQUEST: - if (eap_ttls_phase2_request(sm, data, ret, hdr, resp)) { - wpa_printf(MSG_INFO, "EAP-TTLS: Phase2 Request " - "processing failed"); - return -1; - } - break; - default: - wpa_printf(MSG_INFO, "EAP-TTLS: Unexpected code=%d in " - "Phase 2 EAP header", hdr->code); - return -1; - } - - return 0; -} - - -static int eap_ttls_process_phase2_mschapv2(struct eap_sm *sm, - struct eap_ttls_data *data, - struct eap_method_ret *ret, - struct ttls_parse_avp *parse) -{ - if (parse->mschapv2_error) { - wpa_printf(MSG_DEBUG, "EAP-TTLS/MSCHAPV2: Received " - "MS-CHAP-Error - failed"); - ret->methodState = METHOD_DONE; - ret->decision = DECISION_FAIL; - /* Reply with empty data to ACK error */ - return 1; - } - - if (parse->mschapv2 == NULL) { -#ifdef EAP_TNC - if (data->phase2_success && parse->eapdata) { - /* - * Allow EAP-TNC to be started after successfully - * completed MSCHAPV2. - */ - return 1; - } -#endif /* EAP_TNC */ - wpa_printf(MSG_WARNING, "EAP-TTLS: no MS-CHAP2-Success AVP " - "received for Phase2 MSCHAPV2"); - return -1; - } - if (parse->mschapv2[0] != data->ident) { - wpa_printf(MSG_WARNING, "EAP-TTLS: Ident mismatch for Phase 2 " - "MSCHAPV2 (received Ident 0x%02x, expected 0x%02x)", - parse->mschapv2[0], data->ident); - return -1; - } - if (!data->auth_response_valid || - mschapv2_verify_auth_response(data->auth_response, - parse->mschapv2 + 1, 42)) { - wpa_printf(MSG_WARNING, "EAP-TTLS: Invalid authenticator " - "response in Phase 2 MSCHAPV2 success request"); - return -1; - } - - wpa_printf(MSG_INFO, "EAP-TTLS: Phase 2 MSCHAPV2 " - "authentication succeeded"); - if (data->ttls_version > 0) { - /* - * EAP-TTLSv1 uses TLS/IA FinalPhaseFinished to report - * success, so do not allow connection to be terminated - * yet. - */ - ret->methodState = METHOD_CONT; - ret->decision = DECISION_COND_SUCC; - } else { - ret->methodState = METHOD_DONE; - ret->decision = DECISION_UNCOND_SUCC; - data->phase2_success = 1; - } - - /* - * Reply with empty data; authentication server will reply - * with EAP-Success after this. - */ - return 1; -} - - -#ifdef EAP_TNC -static int eap_ttls_process_tnc_start(struct eap_sm *sm, - struct eap_ttls_data *data, - struct eap_method_ret *ret, - struct ttls_parse_avp *parse, - struct wpabuf **resp) -{ - /* TNC uses inner EAP method after non-EAP TTLS phase 2. */ - if (parse->eapdata == NULL) { - wpa_printf(MSG_INFO, "EAP-TTLS: Phase 2 received " - "unexpected tunneled data (no EAP)"); - return -1; - } - - if (!data->ready_for_tnc) { - wpa_printf(MSG_INFO, "EAP-TTLS: Phase 2 received " - "EAP after non-EAP, but not ready for TNC"); - return -1; - } - - wpa_printf(MSG_DEBUG, "EAP-TTLS: Start TNC after completed " - "non-EAP method"); - data->tnc_started = 1; - - if (eap_ttls_process_phase2_eap(sm, data, ret, parse, resp) < 0) - return -1; - - return 0; -} -#endif /* EAP_TNC */ - - -static int eap_ttls_process_decrypted(struct eap_sm *sm, - struct eap_ttls_data *data, - struct eap_method_ret *ret, - u8 identifier, - struct ttls_parse_avp *parse, - struct wpabuf *in_decrypted, - struct wpabuf **out_data) -{ - struct wpabuf *resp = NULL; - struct eap_peer_config *config = eap_get_config(sm); - int res; - enum phase2_types phase2_type = data->phase2_type; - -#ifdef EAP_TNC - if (data->tnc_started) - phase2_type = EAP_TTLS_PHASE2_EAP; -#endif /* EAP_TNC */ - - switch (phase2_type) { - case EAP_TTLS_PHASE2_EAP: - if (eap_ttls_process_phase2_eap(sm, data, ret, parse, &resp) < - 0) - return -1; - break; - case EAP_TTLS_PHASE2_MSCHAPV2: - res = eap_ttls_process_phase2_mschapv2(sm, data, ret, parse); -#ifdef EAP_TNC - if (res == 1 && parse->eapdata && data->phase2_success) { - /* - * TNC may be required as the next - * authentication method within the tunnel. - */ - ret->methodState = METHOD_MAY_CONT; - data->ready_for_tnc = 1; - if (eap_ttls_process_tnc_start(sm, data, ret, parse, - &resp) == 0) - break; - } -#endif /* EAP_TNC */ - return res; - case EAP_TTLS_PHASE2_MSCHAP: - case EAP_TTLS_PHASE2_PAP: - case EAP_TTLS_PHASE2_CHAP: -#ifdef EAP_TNC - if (eap_ttls_process_tnc_start(sm, data, ret, parse, &resp) < - 0) - return -1; - break; -#else /* EAP_TNC */ - /* EAP-TTLS/{MSCHAP,PAP,CHAP} should not send any TLS tunneled - * requests to the supplicant */ - wpa_printf(MSG_INFO, "EAP-TTLS: Phase 2 received unexpected " - "tunneled data"); - return -1; -#endif /* EAP_TNC */ - } - - if (resp) { - if (eap_ttls_encrypt_response(sm, data, resp, identifier, - out_data) < 0) - return -1; - } else if (config->pending_req_identity || - config->pending_req_password || - config->pending_req_otp || - config->pending_req_new_password) { - wpabuf_free(data->pending_phase2_req); - data->pending_phase2_req = wpabuf_dup(in_decrypted); - } - - return 0; -} - - -#if EAP_TTLS_VERSION > 0 -static void eap_ttls_final_phase_finished(struct eap_sm *sm, - struct eap_ttls_data *data, - struct eap_method_ret *ret, - u8 identifier, - struct wpabuf **out_data) -{ - wpa_printf(MSG_DEBUG, "EAP-TTLS: FinalPhaseFinished received"); - wpa_printf(MSG_INFO, "EAP-TTLS: TLS/IA authentication succeeded"); - ret->methodState = METHOD_DONE; - ret->decision = DECISION_UNCOND_SUCC; - data->phase2_success = 1; - *out_data = eap_ttls_build_phase_finished(sm, data, identifier, 1); - eap_ttls_v1_derive_key(sm, data); -} -#endif /* EAP_TTLS_VERSION */ - - -static int eap_ttls_implicit_identity_request(struct eap_sm *sm, - struct eap_ttls_data *data, - struct eap_method_ret *ret, - u8 identifier, - struct wpabuf **out_data) -{ - int retval = 0; - struct eap_hdr *hdr; - struct wpabuf *resp; - - hdr = (struct eap_hdr *) eap_ttls_fake_identity_request(); - if (hdr == NULL) { - ret->methodState = METHOD_DONE; - ret->decision = DECISION_FAIL; - return -1; - } - - resp = NULL; - if (eap_ttls_phase2_request(sm, data, ret, hdr, &resp)) { - wpa_printf(MSG_INFO, "EAP-TTLS: Phase2 Request " - "processing failed"); - retval = -1; - } else { - retval = eap_ttls_encrypt_response(sm, data, resp, identifier, - out_data); - } - - os_free(hdr); - - if (retval < 0) { - ret->methodState = METHOD_DONE; - ret->decision = DECISION_FAIL; - } - - return retval; -} - - -static int eap_ttls_phase2_start(struct eap_sm *sm, struct eap_ttls_data *data, - struct eap_method_ret *ret, u8 identifier, - struct wpabuf **out_data) -{ - data->phase2_start = 0; - - /* - * EAP-TTLS does not use Phase2 on fast re-auth; this must be done only - * if TLS part was indeed resuming a previous session. Most - * Authentication Servers terminate EAP-TTLS before reaching this - * point, but some do not. Make wpa_supplicant stop phase 2 here, if - * needed. - */ - if (data->reauth && - tls_connection_resumed(sm->ssl_ctx, data->ssl.conn)) { - wpa_printf(MSG_DEBUG, "EAP-TTLS: Session resumption - " - "skip phase 2"); - *out_data = eap_peer_tls_build_ack(identifier, EAP_TYPE_TTLS, - data->ttls_version); - ret->methodState = METHOD_DONE; - ret->decision = DECISION_UNCOND_SUCC; - data->phase2_success = 1; - return 0; - } - - return eap_ttls_implicit_identity_request(sm, data, ret, identifier, - out_data); -} - - -static int eap_ttls_decrypt(struct eap_sm *sm, struct eap_ttls_data *data, - struct eap_method_ret *ret, u8 identifier, - const struct wpabuf *in_data, - struct wpabuf **out_data) -{ - struct wpabuf *in_decrypted = NULL; - int retval = 0; - struct ttls_parse_avp parse; - - os_memset(&parse, 0, sizeof(parse)); - - wpa_printf(MSG_DEBUG, "EAP-TTLS: received %lu bytes encrypted data for" - " Phase 2", - in_data ? (unsigned long) wpabuf_len(in_data) : 0); - - if (data->pending_phase2_req) { - wpa_printf(MSG_DEBUG, "EAP-TTLS: Pending Phase 2 request - " - "skip decryption and use old data"); - /* Clear TLS reassembly state. */ - eap_peer_tls_reset_input(&data->ssl); - - in_decrypted = data->pending_phase2_req; - data->pending_phase2_req = NULL; - if (wpabuf_len(in_decrypted) == 0) { - wpabuf_free(in_decrypted); - return eap_ttls_implicit_identity_request( - sm, data, ret, identifier, out_data); - } - goto continue_req; - } - - if ((in_data == NULL || wpabuf_len(in_data) == 0) && - data->phase2_start) { - return eap_ttls_phase2_start(sm, data, ret, identifier, - out_data); - } - - if (in_data == NULL || wpabuf_len(in_data) == 0) { - /* Received TLS ACK - requesting more fragments */ - return eap_peer_tls_encrypt(sm, &data->ssl, EAP_TYPE_TTLS, - data->ttls_version, - identifier, NULL, out_data); - } - - retval = eap_peer_tls_decrypt(sm, &data->ssl, in_data, &in_decrypted); - if (retval) - goto done; - -#if EAP_TTLS_VERSION > 0 - if (data->ttls_version > 0 && - (in_decrypted == NULL || wpabuf_len(in_decrypted) == 0) && - tls_connection_ia_final_phase_finished(sm->ssl_ctx, - data->ssl.conn)) { - eap_ttls_final_phase_finished(sm, data, ret, identifier, - out_data); - goto done; - } -#endif /* EAP_TTLS_VERSION */ - -continue_req: - data->phase2_start = 0; - - if (eap_ttls_parse_avps(in_decrypted, &parse) < 0) { - retval = -1; - goto done; - } - - retval = eap_ttls_process_decrypted(sm, data, ret, identifier, - &parse, in_decrypted, out_data); - -done: - wpabuf_free(in_decrypted); - os_free(parse.eapdata); - - if (retval < 0) { - ret->methodState = METHOD_DONE; - ret->decision = DECISION_FAIL; - } - - return retval; -} - - -static int eap_ttls_process_start(struct eap_sm *sm, - struct eap_ttls_data *data, u8 flags, - struct eap_method_ret *ret) -{ - struct eap_peer_config *config = eap_get_config(sm); - - wpa_printf(MSG_DEBUG, "EAP-TTLS: Start (server ver=%d, own ver=%d)", - flags & EAP_TLS_VERSION_MASK, data->ttls_version); -#if EAP_TTLS_VERSION > 0 - if ((flags & EAP_TLS_VERSION_MASK) < data->ttls_version) - data->ttls_version = flags & EAP_TLS_VERSION_MASK; - if (data->force_ttls_version >= 0 && - data->force_ttls_version != data->ttls_version) { - wpa_printf(MSG_WARNING, "EAP-TTLS: Failed to select " - "forced TTLS version %d", - data->force_ttls_version); - ret->methodState = METHOD_DONE; - ret->decision = DECISION_FAIL; - ret->allowNotifications = FALSE; - return -1; - } - wpa_printf(MSG_DEBUG, "EAP-TTLS: Using TTLS version %d", - data->ttls_version); - - if (data->ttls_version > 0) - data->ssl.tls_ia = 1; -#endif /* EAP_TTLS_VERSION */ - if (!data->ssl_initialized && - eap_peer_tls_ssl_init(sm, &data->ssl, config)) { - wpa_printf(MSG_INFO, "EAP-TTLS: Failed to initialize SSL."); - return -1; - } - data->ssl_initialized = 1; - - wpa_printf(MSG_DEBUG, "EAP-TTLS: Start"); - - return 0; -} - - -static int eap_ttls_process_handshake(struct eap_sm *sm, - struct eap_ttls_data *data, - struct eap_method_ret *ret, - u8 identifier, - const u8 *in_data, size_t in_len, - struct wpabuf **out_data) -{ - int res; - - res = eap_peer_tls_process_helper(sm, &data->ssl, EAP_TYPE_TTLS, - data->ttls_version, identifier, - in_data, in_len, out_data); - - if (tls_connection_established(sm->ssl_ctx, data->ssl.conn)) { - wpa_printf(MSG_DEBUG, "EAP-TTLS: TLS done, proceed to " - "Phase 2"); - if (data->resuming) { - wpa_printf(MSG_DEBUG, "EAP-TTLS: fast reauth - may " - "skip Phase 2"); - ret->decision = DECISION_COND_SUCC; - ret->methodState = METHOD_MAY_CONT; - } - data->phase2_start = 1; - if (data->ttls_version == 0) - eap_ttls_v0_derive_key(sm, data); - - if (*out_data == NULL || wpabuf_len(*out_data) == 0) { - if (eap_ttls_decrypt(sm, data, ret, identifier, - NULL, out_data)) { - wpa_printf(MSG_WARNING, "EAP-TTLS: " - "failed to process early " - "start for Phase 2"); - } - res = 0; - } - data->resuming = 0; - } - - if (res == 2) { - struct wpabuf msg; - /* - * Application data included in the handshake message. - */ - wpabuf_free(data->pending_phase2_req); - data->pending_phase2_req = *out_data; - *out_data = NULL; - wpabuf_set(&msg, in_data, in_len); - res = eap_ttls_decrypt(sm, data, ret, identifier, &msg, - out_data); - } - - return res; -} - - -static void eap_ttls_check_auth_status(struct eap_sm *sm, - struct eap_ttls_data *data, - struct eap_method_ret *ret) -{ - if (data->ttls_version == 0 && ret->methodState == METHOD_DONE) { - ret->allowNotifications = FALSE; - if (ret->decision == DECISION_UNCOND_SUCC || - ret->decision == DECISION_COND_SUCC) { - wpa_printf(MSG_DEBUG, "EAP-TTLS: Authentication " - "completed successfully"); - data->phase2_success = 1; -#ifdef EAP_TNC - if (!data->ready_for_tnc && !data->tnc_started) { - /* - * TNC may be required as the next - * authentication method within the tunnel. - */ - ret->methodState = METHOD_MAY_CONT; - data->ready_for_tnc = 1; - } -#endif /* EAP_TNC */ - } - } else if (data->ttls_version == 0 && - ret->methodState == METHOD_MAY_CONT && - (ret->decision == DECISION_UNCOND_SUCC || - ret->decision == DECISION_COND_SUCC)) { - wpa_printf(MSG_DEBUG, "EAP-TTLS: Authentication " - "completed successfully (MAY_CONT)"); - data->phase2_success = 1; - } -} - - -static struct wpabuf * eap_ttls_process(struct eap_sm *sm, void *priv, - struct eap_method_ret *ret, - const struct wpabuf *reqData) -{ - size_t left; - int res; - u8 flags, id; - struct wpabuf *resp; - const u8 *pos; - struct eap_ttls_data *data = priv; - - pos = eap_peer_tls_process_init(sm, &data->ssl, EAP_TYPE_TTLS, ret, - reqData, &left, &flags); - if (pos == NULL) - return NULL; - id = eap_get_id(reqData); - - if (flags & EAP_TLS_FLAGS_START) { - if (eap_ttls_process_start(sm, data, flags, ret) < 0) - return NULL; - - /* RFC 5281, Ch. 9.2: - * "This packet MAY contain additional information in the form - * of AVPs, which may provide useful hints to the client" - * For now, ignore any potential extra data. - */ - left = 0; - } else if (!data->ssl_initialized) { - wpa_printf(MSG_DEBUG, "EAP-TTLS: First message did not " - "include Start flag"); - ret->methodState = METHOD_DONE; - ret->decision = DECISION_FAIL; - ret->allowNotifications = FALSE; - return NULL; - } - - resp = NULL; - if (tls_connection_established(sm->ssl_ctx, data->ssl.conn) && - !data->resuming) { - struct wpabuf msg; - wpabuf_set(&msg, pos, left); - res = eap_ttls_decrypt(sm, data, ret, id, &msg, &resp); - } else { - res = eap_ttls_process_handshake(sm, data, ret, id, - pos, left, &resp); - } - - eap_ttls_check_auth_status(sm, data, ret); - - /* FIX: what about res == -1? Could just move all error processing into - * the other functions and get rid of this res==1 case here. */ - if (res == 1) { - wpabuf_free(resp); - return eap_peer_tls_build_ack(id, EAP_TYPE_TTLS, - data->ttls_version); - } - return resp; -} - - -static Boolean eap_ttls_has_reauth_data(struct eap_sm *sm, void *priv) -{ - struct eap_ttls_data *data = priv; - return tls_connection_established(sm->ssl_ctx, data->ssl.conn) && - data->phase2_success; -} - - -static void eap_ttls_deinit_for_reauth(struct eap_sm *sm, void *priv) -{ - struct eap_ttls_data *data = priv; - wpabuf_free(data->pending_phase2_req); - data->pending_phase2_req = NULL; -#ifdef EAP_TNC - data->ready_for_tnc = 0; - data->tnc_started = 0; -#endif /* EAP_TNC */ -} - - -static void * eap_ttls_init_for_reauth(struct eap_sm *sm, void *priv) -{ - struct eap_ttls_data *data = priv; - os_free(data->key_data); - data->key_data = NULL; - if (eap_peer_tls_reauth_init(sm, &data->ssl)) { - os_free(data); - return NULL; - } - if (data->phase2_priv && data->phase2_method && - data->phase2_method->init_for_reauth) - data->phase2_method->init_for_reauth(sm, data->phase2_priv); - data->phase2_start = 0; - data->phase2_success = 0; - data->resuming = 1; - data->reauth = 1; - return priv; -} - - -static int eap_ttls_get_status(struct eap_sm *sm, void *priv, char *buf, - size_t buflen, int verbose) -{ - struct eap_ttls_data *data = priv; - int len, ret; - - len = eap_peer_tls_status(sm, &data->ssl, buf, buflen, verbose); - ret = os_snprintf(buf + len, buflen - len, - "EAP-TTLSv%d Phase2 method=", - data->ttls_version); - if (ret < 0 || (size_t) ret >= buflen - len) - return len; - len += ret; - switch (data->phase2_type) { - case EAP_TTLS_PHASE2_EAP: - ret = os_snprintf(buf + len, buflen - len, "EAP-%s\n", - data->phase2_method ? - data->phase2_method->name : "?"); - break; - case EAP_TTLS_PHASE2_MSCHAPV2: - ret = os_snprintf(buf + len, buflen - len, "MSCHAPV2\n"); - break; - case EAP_TTLS_PHASE2_MSCHAP: - ret = os_snprintf(buf + len, buflen - len, "MSCHAP\n"); - break; - case EAP_TTLS_PHASE2_PAP: - ret = os_snprintf(buf + len, buflen - len, "PAP\n"); - break; - case EAP_TTLS_PHASE2_CHAP: - ret = os_snprintf(buf + len, buflen - len, "CHAP\n"); - break; - default: - ret = 0; - break; - } - if (ret < 0 || (size_t) ret >= buflen - len) - return len; - len += ret; - - return len; -} - - -static Boolean eap_ttls_isKeyAvailable(struct eap_sm *sm, void *priv) -{ - struct eap_ttls_data *data = priv; - return data->key_data != NULL && data->phase2_success; -} - - -static u8 * eap_ttls_getKey(struct eap_sm *sm, void *priv, size_t *len) -{ - struct eap_ttls_data *data = priv; - u8 *key; - - if (data->key_data == NULL || !data->phase2_success) - return NULL; - - key = os_malloc(EAP_TLS_KEY_LEN); - if (key == NULL) - return NULL; - - *len = EAP_TLS_KEY_LEN; - os_memcpy(key, data->key_data, EAP_TLS_KEY_LEN); - - return key; -} - - -int eap_peer_ttls_register(void) -{ - struct eap_method *eap; - int ret; - - eap = eap_peer_method_alloc(EAP_PEER_METHOD_INTERFACE_VERSION, - EAP_VENDOR_IETF, EAP_TYPE_TTLS, "TTLS"); - if (eap == NULL) - return -1; - - eap->init = eap_ttls_init; - eap->deinit = eap_ttls_deinit; - eap->process = eap_ttls_process; - eap->isKeyAvailable = eap_ttls_isKeyAvailable; - eap->getKey = eap_ttls_getKey; - eap->get_status = eap_ttls_get_status; - eap->has_reauth_data = eap_ttls_has_reauth_data; - eap->deinit_for_reauth = eap_ttls_deinit_for_reauth; - eap->init_for_reauth = eap_ttls_init_for_reauth; - - ret = eap_peer_method_register(eap); - if (ret) - eap_peer_method_free(eap); - return ret; -} diff --git a/hostapd-0.8/src/eap_peer/eap_vendor_test.c b/hostapd-0.8/src/eap_peer/eap_vendor_test.c deleted file mode 100644 index 3e114c1..0000000 --- a/hostapd-0.8/src/eap_peer/eap_vendor_test.c +++ /dev/null @@ -1,195 +0,0 @@ -/* - * EAP peer method: Test method for vendor specific (expanded) EAP type - * Copyright (c) 2005-2006, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - * - * This file implements a vendor specific test method using EAP expanded types. - * This is only for test use and must not be used for authentication since no - * security is provided. - */ - -#include "includes.h" - -#include "common.h" -#include "eap_i.h" -#ifdef TEST_PENDING_REQUEST -#include "eloop.h" -#endif /* TEST_PENDING_REQUEST */ - - -#define EAP_VENDOR_ID 0xfffefd -#define EAP_VENDOR_TYPE 0xfcfbfaf9 - - -/* #define TEST_PENDING_REQUEST */ - -struct eap_vendor_test_data { - enum { INIT, CONFIRM, SUCCESS } state; - int first_try; -}; - - -static void * eap_vendor_test_init(struct eap_sm *sm) -{ - struct eap_vendor_test_data *data; - data = os_zalloc(sizeof(*data)); - if (data == NULL) - return NULL; - data->state = INIT; - data->first_try = 1; - return data; -} - - -static void eap_vendor_test_deinit(struct eap_sm *sm, void *priv) -{ - struct eap_vendor_test_data *data = priv; - os_free(data); -} - - -#ifdef TEST_PENDING_REQUEST -static void eap_vendor_ready(void *eloop_ctx, void *timeout_ctx) -{ - struct eap_sm *sm = eloop_ctx; - wpa_printf(MSG_DEBUG, "EAP-VENDOR-TEST: Ready to re-process pending " - "request"); - eap_notify_pending(sm); -} -#endif /* TEST_PENDING_REQUEST */ - - -static struct wpabuf * eap_vendor_test_process(struct eap_sm *sm, void *priv, - struct eap_method_ret *ret, - const struct wpabuf *reqData) -{ - struct eap_vendor_test_data *data = priv; - struct wpabuf *resp; - const u8 *pos; - size_t len; - - pos = eap_hdr_validate(EAP_VENDOR_ID, EAP_VENDOR_TYPE, reqData, &len); - if (pos == NULL || len < 1) { - ret->ignore = TRUE; - return NULL; - } - - if (data->state == INIT && *pos != 1) { - wpa_printf(MSG_DEBUG, "EAP-VENDOR-TEST: Unexpected message " - "%d in INIT state", *pos); - ret->ignore = TRUE; - return NULL; - } - - if (data->state == CONFIRM && *pos != 3) { - wpa_printf(MSG_DEBUG, "EAP-VENDOR-TEST: Unexpected message " - "%d in CONFIRM state", *pos); - ret->ignore = TRUE; - return NULL; - } - - if (data->state == SUCCESS) { - wpa_printf(MSG_DEBUG, "EAP-VENDOR-TEST: Unexpected message " - "in SUCCESS state"); - ret->ignore = TRUE; - return NULL; - } - - if (data->state == CONFIRM) { -#ifdef TEST_PENDING_REQUEST - if (data->first_try) { - data->first_try = 0; - wpa_printf(MSG_DEBUG, "EAP-VENDOR-TEST: Testing " - "pending request"); - ret->ignore = TRUE; - eloop_register_timeout(1, 0, eap_vendor_ready, sm, - NULL); - return NULL; - } -#endif /* TEST_PENDING_REQUEST */ - } - - ret->ignore = FALSE; - - wpa_printf(MSG_DEBUG, "EAP-VENDOR-TEST: Generating Response"); - ret->allowNotifications = TRUE; - - resp = eap_msg_alloc(EAP_VENDOR_ID, EAP_VENDOR_TYPE, 1, - EAP_CODE_RESPONSE, eap_get_id(reqData)); - if (resp == NULL) - return NULL; - - if (data->state == INIT) { - wpabuf_put_u8(resp, 2); - data->state = CONFIRM; - ret->methodState = METHOD_CONT; - ret->decision = DECISION_FAIL; - } else { - wpabuf_put_u8(resp, 4); - data->state = SUCCESS; - ret->methodState = METHOD_DONE; - ret->decision = DECISION_UNCOND_SUCC; - } - - return resp; -} - - -static Boolean eap_vendor_test_isKeyAvailable(struct eap_sm *sm, void *priv) -{ - struct eap_vendor_test_data *data = priv; - return data->state == SUCCESS; -} - - -static u8 * eap_vendor_test_getKey(struct eap_sm *sm, void *priv, size_t *len) -{ - struct eap_vendor_test_data *data = priv; - u8 *key; - const int key_len = 64; - - if (data->state != SUCCESS) - return NULL; - - key = os_malloc(key_len); - if (key == NULL) - return NULL; - - os_memset(key, 0x11, key_len / 2); - os_memset(key + key_len / 2, 0x22, key_len / 2); - *len = key_len; - - return key; -} - - -int eap_peer_vendor_test_register(void) -{ - struct eap_method *eap; - int ret; - - eap = eap_peer_method_alloc(EAP_PEER_METHOD_INTERFACE_VERSION, - EAP_VENDOR_ID, EAP_VENDOR_TYPE, - "VENDOR-TEST"); - if (eap == NULL) - return -1; - - eap->init = eap_vendor_test_init; - eap->deinit = eap_vendor_test_deinit; - eap->process = eap_vendor_test_process; - eap->isKeyAvailable = eap_vendor_test_isKeyAvailable; - eap->getKey = eap_vendor_test_getKey; - - ret = eap_peer_method_register(eap); - if (ret) - eap_peer_method_free(eap); - return ret; -} diff --git a/hostapd-0.8/src/eap_peer/eap_wsc.c b/hostapd-0.8/src/eap_peer/eap_wsc.c deleted file mode 100644 index 09d8a1c..0000000 --- a/hostapd-0.8/src/eap_peer/eap_wsc.c +++ /dev/null @@ -1,553 +0,0 @@ -/* - * EAP-WSC peer for Wi-Fi Protected Setup - * Copyright (c) 2007-2009, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#include "includes.h" - -#include "common.h" -#include "uuid.h" -#include "eap_i.h" -#include "eap_common/eap_wsc_common.h" -#include "wps/wps.h" -#include "wps/wps_defs.h" - - -struct eap_wsc_data { - enum { WAIT_START, MESG, FRAG_ACK, WAIT_FRAG_ACK, DONE, FAIL } state; - int registrar; - struct wpabuf *in_buf; - struct wpabuf *out_buf; - enum wsc_op_code in_op_code, out_op_code; - size_t out_used; - size_t fragment_size; - struct wps_data *wps; - struct wps_context *wps_ctx; -}; - - -static const char * eap_wsc_state_txt(int state) -{ - switch (state) { - case WAIT_START: - return "WAIT_START"; - case MESG: - return "MESG"; - case FRAG_ACK: - return "FRAG_ACK"; - case WAIT_FRAG_ACK: - return "WAIT_FRAG_ACK"; - case DONE: - return "DONE"; - case FAIL: - return "FAIL"; - default: - return "?"; - } -} - - -static void eap_wsc_state(struct eap_wsc_data *data, int state) -{ - wpa_printf(MSG_DEBUG, "EAP-WSC: %s -> %s", - eap_wsc_state_txt(data->state), - eap_wsc_state_txt(state)); - data->state = state; -} - - -static int eap_wsc_new_ap_settings(struct wps_credential *cred, - const char *params) -{ - const char *pos, *end; - size_t len; - - os_memset(cred, 0, sizeof(*cred)); - - pos = os_strstr(params, "new_ssid="); - if (pos == NULL) - return 0; - pos += 9; - end = os_strchr(pos, ' '); - if (end == NULL) - len = os_strlen(pos); - else - len = end - pos; - if ((len & 1) || len > 2 * sizeof(cred->ssid) || - hexstr2bin(pos, cred->ssid, len / 2)) - return -1; - cred->ssid_len = len / 2; - - pos = os_strstr(params, "new_auth="); - if (pos == NULL) - return -1; - if (os_strncmp(pos + 9, "OPEN", 4) == 0) - cred->auth_type = WPS_AUTH_OPEN; - else if (os_strncmp(pos + 9, "WPAPSK", 6) == 0) - cred->auth_type = WPS_AUTH_WPAPSK; - else if (os_strncmp(pos + 9, "WPA2PSK", 7) == 0) - cred->auth_type = WPS_AUTH_WPA2PSK; - else - return -1; - - pos = os_strstr(params, "new_encr="); - if (pos == NULL) - return -1; - if (os_strncmp(pos + 9, "NONE", 4) == 0) - cred->encr_type = WPS_ENCR_NONE; - else if (os_strncmp(pos + 9, "WEP", 3) == 0) - cred->encr_type = WPS_ENCR_WEP; - else if (os_strncmp(pos + 9, "TKIP", 4) == 0) - cred->encr_type = WPS_ENCR_TKIP; - else if (os_strncmp(pos + 9, "CCMP", 4) == 0) - cred->encr_type = WPS_ENCR_AES; - else - return -1; - - pos = os_strstr(params, "new_key="); - if (pos == NULL) - return 0; - pos += 8; - end = os_strchr(pos, ' '); - if (end == NULL) - len = os_strlen(pos); - else - len = end - pos; - if ((len & 1) || len > 2 * sizeof(cred->key) || - hexstr2bin(pos, cred->key, len / 2)) - return -1; - cred->key_len = len / 2; - - return 1; -} - - -static void * eap_wsc_init(struct eap_sm *sm) -{ - struct eap_wsc_data *data; - const u8 *identity; - size_t identity_len; - int registrar; - struct wps_config cfg; - const char *pos; - const char *phase1; - struct wps_context *wps; - struct wps_credential new_ap_settings; - int res; - - wps = sm->wps; - if (wps == NULL) { - wpa_printf(MSG_ERROR, "EAP-WSC: WPS context not available"); - return NULL; - } - - identity = eap_get_config_identity(sm, &identity_len); - - if (identity && identity_len == WSC_ID_REGISTRAR_LEN && - os_memcmp(identity, WSC_ID_REGISTRAR, WSC_ID_REGISTRAR_LEN) == 0) - registrar = 1; /* Supplicant is Registrar */ - else if (identity && identity_len == WSC_ID_ENROLLEE_LEN && - os_memcmp(identity, WSC_ID_ENROLLEE, WSC_ID_ENROLLEE_LEN) == 0) - registrar = 0; /* Supplicant is Enrollee */ - else { - wpa_hexdump_ascii(MSG_INFO, "EAP-WSC: Unexpected identity", - identity, identity_len); - return NULL; - } - - data = os_zalloc(sizeof(*data)); - if (data == NULL) - return NULL; - data->state = registrar ? MESG : WAIT_START; - data->registrar = registrar; - data->wps_ctx = wps; - - os_memset(&cfg, 0, sizeof(cfg)); - cfg.wps = wps; - cfg.registrar = registrar; - - phase1 = eap_get_config_phase1(sm); - if (phase1 == NULL) { - wpa_printf(MSG_INFO, "EAP-WSC: phase1 configuration data not " - "set"); - os_free(data); - return NULL; - } - - pos = os_strstr(phase1, "pin="); - if (pos) { - pos += 4; - cfg.pin = (const u8 *) pos; - while (*pos != '\0' && *pos != ' ') - pos++; - cfg.pin_len = pos - (const char *) cfg.pin; - } else { - pos = os_strstr(phase1, "pbc=1"); - if (pos) - cfg.pbc = 1; - } - - if (cfg.pin == NULL && !cfg.pbc) { - wpa_printf(MSG_INFO, "EAP-WSC: PIN or PBC not set in phase1 " - "configuration data"); - os_free(data); - return NULL; - } - - pos = os_strstr(phase1, "dev_pw_id="); - if (pos && cfg.pin) - cfg.dev_pw_id = atoi(pos + 10); - - res = eap_wsc_new_ap_settings(&new_ap_settings, phase1); - if (res < 0) { - os_free(data); - return NULL; - } - if (res == 1) { - wpa_printf(MSG_DEBUG, "EAP-WSC: Provide new AP settings for " - "WPS"); - cfg.new_ap_settings = &new_ap_settings; - } - - data->wps = wps_init(&cfg); - if (data->wps == NULL) { - os_free(data); - return NULL; - } - res = eap_get_config_fragment_size(sm); - if (res > 0) - data->fragment_size = res; - else - data->fragment_size = WSC_FRAGMENT_SIZE; - wpa_printf(MSG_DEBUG, "EAP-WSC: Fragment size limit %u", - (unsigned int) data->fragment_size); - - if (registrar && cfg.pin) { - wps_registrar_add_pin(data->wps_ctx->registrar, NULL, NULL, - cfg.pin, cfg.pin_len, 0); - } - - /* Use reduced client timeout for WPS to avoid long wait */ - if (sm->ClientTimeout > 30) - sm->ClientTimeout = 30; - - return data; -} - - -static void eap_wsc_deinit(struct eap_sm *sm, void *priv) -{ - struct eap_wsc_data *data = priv; - wpabuf_free(data->in_buf); - wpabuf_free(data->out_buf); - wps_deinit(data->wps); - os_free(data->wps_ctx->network_key); - data->wps_ctx->network_key = NULL; - os_free(data); -} - - -static struct wpabuf * eap_wsc_build_msg(struct eap_wsc_data *data, - struct eap_method_ret *ret, u8 id) -{ - struct wpabuf *resp; - u8 flags; - size_t send_len, plen; - - ret->ignore = FALSE; - wpa_printf(MSG_DEBUG, "EAP-WSC: Generating Response"); - ret->allowNotifications = TRUE; - - flags = 0; - send_len = wpabuf_len(data->out_buf) - data->out_used; - if (2 + send_len > data->fragment_size) { - send_len = data->fragment_size - 2; - flags |= WSC_FLAGS_MF; - if (data->out_used == 0) { - flags |= WSC_FLAGS_LF; - send_len -= 2; - } - } - plen = 2 + send_len; - if (flags & WSC_FLAGS_LF) - plen += 2; - resp = eap_msg_alloc(EAP_VENDOR_WFA, EAP_VENDOR_TYPE_WSC, plen, - EAP_CODE_RESPONSE, id); - if (resp == NULL) - return NULL; - - wpabuf_put_u8(resp, data->out_op_code); /* Op-Code */ - wpabuf_put_u8(resp, flags); /* Flags */ - if (flags & WSC_FLAGS_LF) - wpabuf_put_be16(resp, wpabuf_len(data->out_buf)); - - wpabuf_put_data(resp, wpabuf_head_u8(data->out_buf) + data->out_used, - send_len); - data->out_used += send_len; - - ret->methodState = METHOD_MAY_CONT; - ret->decision = DECISION_FAIL; - - if (data->out_used == wpabuf_len(data->out_buf)) { - wpa_printf(MSG_DEBUG, "EAP-WSC: Sending out %lu bytes " - "(message sent completely)", - (unsigned long) send_len); - wpabuf_free(data->out_buf); - data->out_buf = NULL; - data->out_used = 0; - if ((data->state == FAIL && data->out_op_code == WSC_ACK) || - data->out_op_code == WSC_NACK || - data->out_op_code == WSC_Done) { - eap_wsc_state(data, FAIL); - ret->methodState = METHOD_DONE; - } else - eap_wsc_state(data, MESG); - } else { - wpa_printf(MSG_DEBUG, "EAP-WSC: Sending out %lu bytes " - "(%lu more to send)", (unsigned long) send_len, - (unsigned long) wpabuf_len(data->out_buf) - - data->out_used); - eap_wsc_state(data, WAIT_FRAG_ACK); - } - - return resp; -} - - -static int eap_wsc_process_cont(struct eap_wsc_data *data, - const u8 *buf, size_t len, u8 op_code) -{ - /* Process continuation of a pending message */ - if (op_code != data->in_op_code) { - wpa_printf(MSG_DEBUG, "EAP-WSC: Unexpected Op-Code %d in " - "fragment (expected %d)", - op_code, data->in_op_code); - return -1; - } - - if (len > wpabuf_tailroom(data->in_buf)) { - wpa_printf(MSG_DEBUG, "EAP-WSC: Fragment overflow"); - eap_wsc_state(data, FAIL); - return -1; - } - - wpabuf_put_data(data->in_buf, buf, len); - wpa_printf(MSG_DEBUG, "EAP-WSC: Received %lu bytes, waiting " - "for %lu bytes more", (unsigned long) len, - (unsigned long) wpabuf_tailroom(data->in_buf)); - - return 0; -} - - -static struct wpabuf * eap_wsc_process_fragment(struct eap_wsc_data *data, - struct eap_method_ret *ret, - u8 id, u8 flags, u8 op_code, - u16 message_length, - const u8 *buf, size_t len) -{ - /* Process a fragment that is not the last one of the message */ - if (data->in_buf == NULL && !(flags & WSC_FLAGS_LF)) { - wpa_printf(MSG_DEBUG, "EAP-WSC: No Message Length field in a " - "fragmented packet"); - ret->ignore = TRUE; - return NULL; - } - - if (data->in_buf == NULL) { - /* First fragment of the message */ - data->in_buf = wpabuf_alloc(message_length); - if (data->in_buf == NULL) { - wpa_printf(MSG_DEBUG, "EAP-WSC: No memory for " - "message"); - ret->ignore = TRUE; - return NULL; - } - data->in_op_code = op_code; - wpabuf_put_data(data->in_buf, buf, len); - wpa_printf(MSG_DEBUG, "EAP-WSC: Received %lu bytes in first " - "fragment, waiting for %lu bytes more", - (unsigned long) len, - (unsigned long) wpabuf_tailroom(data->in_buf)); - } - - return eap_wsc_build_frag_ack(id, EAP_CODE_RESPONSE); -} - - -static struct wpabuf * eap_wsc_process(struct eap_sm *sm, void *priv, - struct eap_method_ret *ret, - const struct wpabuf *reqData) -{ - struct eap_wsc_data *data = priv; - const u8 *start, *pos, *end; - size_t len; - u8 op_code, flags, id; - u16 message_length = 0; - enum wps_process_res res; - struct wpabuf tmpbuf; - struct wpabuf *r; - - pos = eap_hdr_validate(EAP_VENDOR_WFA, EAP_VENDOR_TYPE_WSC, reqData, - &len); - if (pos == NULL || len < 2) { - ret->ignore = TRUE; - return NULL; - } - - id = eap_get_id(reqData); - - start = pos; - end = start + len; - - op_code = *pos++; - flags = *pos++; - if (flags & WSC_FLAGS_LF) { - if (end - pos < 2) { - wpa_printf(MSG_DEBUG, "EAP-WSC: Message underflow"); - ret->ignore = TRUE; - return NULL; - } - message_length = WPA_GET_BE16(pos); - pos += 2; - - if (message_length < end - pos) { - wpa_printf(MSG_DEBUG, "EAP-WSC: Invalid Message " - "Length"); - ret->ignore = TRUE; - return NULL; - } - } - - wpa_printf(MSG_DEBUG, "EAP-WSC: Received packet: Op-Code %d " - "Flags 0x%x Message Length %d", - op_code, flags, message_length); - - if (data->state == WAIT_FRAG_ACK) { - if (op_code != WSC_FRAG_ACK) { - wpa_printf(MSG_DEBUG, "EAP-WSC: Unexpected Op-Code %d " - "in WAIT_FRAG_ACK state", op_code); - ret->ignore = TRUE; - return NULL; - } - wpa_printf(MSG_DEBUG, "EAP-WSC: Fragment acknowledged"); - eap_wsc_state(data, MESG); - return eap_wsc_build_msg(data, ret, id); - } - - if (op_code != WSC_ACK && op_code != WSC_NACK && op_code != WSC_MSG && - op_code != WSC_Done && op_code != WSC_Start) { - wpa_printf(MSG_DEBUG, "EAP-WSC: Unexpected Op-Code %d", - op_code); - ret->ignore = TRUE; - return NULL; - } - - if (data->state == WAIT_START) { - if (op_code != WSC_Start) { - wpa_printf(MSG_DEBUG, "EAP-WSC: Unexpected Op-Code %d " - "in WAIT_START state", op_code); - ret->ignore = TRUE; - return NULL; - } - wpa_printf(MSG_DEBUG, "EAP-WSC: Received start"); - eap_wsc_state(data, MESG); - /* Start message has empty payload, skip processing */ - goto send_msg; - } else if (op_code == WSC_Start) { - wpa_printf(MSG_DEBUG, "EAP-WSC: Unexpected Op-Code %d", - op_code); - ret->ignore = TRUE; - return NULL; - } - - if (data->in_buf && - eap_wsc_process_cont(data, pos, end - pos, op_code) < 0) { - ret->ignore = TRUE; - return NULL; - } - - if (flags & WSC_FLAGS_MF) { - return eap_wsc_process_fragment(data, ret, id, flags, op_code, - message_length, pos, - end - pos); - } - - if (data->in_buf == NULL) { - /* Wrap unfragmented messages as wpabuf without extra copy */ - wpabuf_set(&tmpbuf, pos, end - pos); - data->in_buf = &tmpbuf; - } - - res = wps_process_msg(data->wps, op_code, data->in_buf); - switch (res) { - case WPS_DONE: - wpa_printf(MSG_DEBUG, "EAP-WSC: WPS processing completed " - "successfully - wait for EAP failure"); - eap_wsc_state(data, FAIL); - break; - case WPS_CONTINUE: - eap_wsc_state(data, MESG); - break; - case WPS_FAILURE: - case WPS_PENDING: - wpa_printf(MSG_DEBUG, "EAP-WSC: WPS processing failed"); - eap_wsc_state(data, FAIL); - break; - } - - if (data->in_buf != &tmpbuf) - wpabuf_free(data->in_buf); - data->in_buf = NULL; - -send_msg: - if (data->out_buf == NULL) { - data->out_buf = wps_get_msg(data->wps, &data->out_op_code); - if (data->out_buf == NULL) { - wpa_printf(MSG_DEBUG, "EAP-WSC: Failed to receive " - "message from WPS"); - return NULL; - } - data->out_used = 0; - } - - eap_wsc_state(data, MESG); - r = eap_wsc_build_msg(data, ret, id); - if (data->state == FAIL && ret->methodState == METHOD_DONE) { - /* Use reduced client timeout for WPS to avoid long wait */ - if (sm->ClientTimeout > 2) - sm->ClientTimeout = 2; - } - return r; -} - - -int eap_peer_wsc_register(void) -{ - struct eap_method *eap; - int ret; - - eap = eap_peer_method_alloc(EAP_PEER_METHOD_INTERFACE_VERSION, - EAP_VENDOR_WFA, EAP_VENDOR_TYPE_WSC, - "WSC"); - if (eap == NULL) - return -1; - - eap->init = eap_wsc_init; - eap->deinit = eap_wsc_deinit; - eap->process = eap_wsc_process; - - ret = eap_peer_method_register(eap); - if (ret) - eap_peer_method_free(eap); - return ret; -} diff --git a/hostapd-0.8/src/eap_peer/ikev2.c b/hostapd-0.8/src/eap_peer/ikev2.c deleted file mode 100644 index 1e169a0..0000000 --- a/hostapd-0.8/src/eap_peer/ikev2.c +++ /dev/null @@ -1,1304 +0,0 @@ -/* - * IKEv2 responder (RFC 4306) for EAP-IKEV2 - * Copyright (c) 2007, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#include "includes.h" - -#include "common.h" -#include "crypto/dh_groups.h" -#include "crypto/random.h" -#include "ikev2.h" - - -void ikev2_responder_deinit(struct ikev2_responder_data *data) -{ - ikev2_free_keys(&data->keys); - wpabuf_free(data->i_dh_public); - wpabuf_free(data->r_dh_private); - os_free(data->IDi); - os_free(data->IDr); - os_free(data->shared_secret); - wpabuf_free(data->i_sign_msg); - wpabuf_free(data->r_sign_msg); - os_free(data->key_pad); -} - - -static int ikev2_derive_keys(struct ikev2_responder_data *data) -{ - u8 *buf, *pos, *pad, skeyseed[IKEV2_MAX_HASH_LEN]; - size_t buf_len, pad_len; - struct wpabuf *shared; - const struct ikev2_integ_alg *integ; - const struct ikev2_prf_alg *prf; - const struct ikev2_encr_alg *encr; - int ret; - const u8 *addr[2]; - size_t len[2]; - - /* RFC 4306, Sect. 2.14 */ - - integ = ikev2_get_integ(data->proposal.integ); - prf = ikev2_get_prf(data->proposal.prf); - encr = ikev2_get_encr(data->proposal.encr); - if (integ == NULL || prf == NULL || encr == NULL) { - wpa_printf(MSG_INFO, "IKEV2: Unsupported proposal"); - return -1; - } - - shared = dh_derive_shared(data->i_dh_public, data->r_dh_private, - data->dh); - if (shared == NULL) - return -1; - - /* Construct Ni | Nr | SPIi | SPIr */ - - buf_len = data->i_nonce_len + data->r_nonce_len + 2 * IKEV2_SPI_LEN; - buf = os_malloc(buf_len); - if (buf == NULL) { - wpabuf_free(shared); - return -1; - } - - pos = buf; - os_memcpy(pos, data->i_nonce, data->i_nonce_len); - pos += data->i_nonce_len; - os_memcpy(pos, data->r_nonce, data->r_nonce_len); - pos += data->r_nonce_len; - os_memcpy(pos, data->i_spi, IKEV2_SPI_LEN); - pos += IKEV2_SPI_LEN; - os_memcpy(pos, data->r_spi, IKEV2_SPI_LEN); -#ifdef CCNS_PL -#if __BYTE_ORDER == __LITTLE_ENDIAN - { - int i; - u8 *tmp = pos - IKEV2_SPI_LEN; - /* Incorrect byte re-ordering on little endian hosts.. */ - for (i = 0; i < IKEV2_SPI_LEN; i++) - *tmp++ = data->i_spi[IKEV2_SPI_LEN - 1 - i]; - for (i = 0; i < IKEV2_SPI_LEN; i++) - *tmp++ = data->r_spi[IKEV2_SPI_LEN - 1 - i]; - } -#endif -#endif /* CCNS_PL */ - - /* SKEYSEED = prf(Ni | Nr, g^ir) */ - /* Use zero-padding per RFC 4306, Sect. 2.14 */ - pad_len = data->dh->prime_len - wpabuf_len(shared); -#ifdef CCNS_PL - /* Shared secret is not zero-padded correctly */ - pad_len = 0; -#endif /* CCNS_PL */ - pad = os_zalloc(pad_len ? pad_len : 1); - if (pad == NULL) { - wpabuf_free(shared); - os_free(buf); - return -1; - } - - addr[0] = pad; - len[0] = pad_len; - addr[1] = wpabuf_head(shared); - len[1] = wpabuf_len(shared); - if (ikev2_prf_hash(prf->id, buf, data->i_nonce_len + data->r_nonce_len, - 2, addr, len, skeyseed) < 0) { - wpabuf_free(shared); - os_free(buf); - os_free(pad); - return -1; - } - os_free(pad); - wpabuf_free(shared); - - /* DH parameters are not needed anymore, so free them */ - wpabuf_free(data->i_dh_public); - data->i_dh_public = NULL; - wpabuf_free(data->r_dh_private); - data->r_dh_private = NULL; - - wpa_hexdump_key(MSG_DEBUG, "IKEV2: SKEYSEED", - skeyseed, prf->hash_len); - - ret = ikev2_derive_sk_keys(prf, integ, encr, skeyseed, buf, buf_len, - &data->keys); - os_free(buf); - return ret; -} - - -static int ikev2_parse_transform(struct ikev2_proposal_data *prop, - const u8 *pos, const u8 *end) -{ - int transform_len; - const struct ikev2_transform *t; - u16 transform_id; - const u8 *tend; - - if (end - pos < (int) sizeof(*t)) { - wpa_printf(MSG_INFO, "IKEV2: Too short transform"); - return -1; - } - - t = (const struct ikev2_transform *) pos; - transform_len = WPA_GET_BE16(t->transform_length); - if (transform_len < (int) sizeof(*t) || pos + transform_len > end) { - wpa_printf(MSG_INFO, "IKEV2: Invalid transform length %d", - transform_len); - return -1; - } - tend = pos + transform_len; - - transform_id = WPA_GET_BE16(t->transform_id); - - wpa_printf(MSG_DEBUG, "IKEV2: Transform:"); - wpa_printf(MSG_DEBUG, "IKEV2: Type: %d Transform Length: %d " - "Transform Type: %d Transform ID: %d", - t->type, transform_len, t->transform_type, transform_id); - - if (t->type != 0 && t->type != 3) { - wpa_printf(MSG_INFO, "IKEV2: Unexpected Transform type"); - return -1; - } - - pos = (const u8 *) (t + 1); - if (pos < tend) { - wpa_hexdump(MSG_DEBUG, "IKEV2: Transform Attributes", - pos, tend - pos); - } - - switch (t->transform_type) { - case IKEV2_TRANSFORM_ENCR: - if (ikev2_get_encr(transform_id)) { - if (transform_id == ENCR_AES_CBC) { - if (tend - pos != 4) { - wpa_printf(MSG_DEBUG, "IKEV2: No " - "Transform Attr for AES"); - break; - } -#ifdef CCNS_PL - if (WPA_GET_BE16(pos) != 0x001d /* ?? */) { - wpa_printf(MSG_DEBUG, "IKEV2: Not a " - "Key Size attribute for " - "AES"); - break; - } -#else /* CCNS_PL */ - if (WPA_GET_BE16(pos) != 0x800e) { - wpa_printf(MSG_DEBUG, "IKEV2: Not a " - "Key Size attribute for " - "AES"); - break; - } -#endif /* CCNS_PL */ - if (WPA_GET_BE16(pos + 2) != 128) { - wpa_printf(MSG_DEBUG, "IKEV2: " - "Unsupported AES key size " - "%d bits", - WPA_GET_BE16(pos + 2)); - break; - } - } - prop->encr = transform_id; - } - break; - case IKEV2_TRANSFORM_PRF: - if (ikev2_get_prf(transform_id)) - prop->prf = transform_id; - break; - case IKEV2_TRANSFORM_INTEG: - if (ikev2_get_integ(transform_id)) - prop->integ = transform_id; - break; - case IKEV2_TRANSFORM_DH: - if (dh_groups_get(transform_id)) - prop->dh = transform_id; - break; - } - - return transform_len; -} - - -static int ikev2_parse_proposal(struct ikev2_proposal_data *prop, - const u8 *pos, const u8 *end) -{ - const u8 *pend, *ppos; - int proposal_len, i; - const struct ikev2_proposal *p; - - if (end - pos < (int) sizeof(*p)) { - wpa_printf(MSG_INFO, "IKEV2: Too short proposal"); - return -1; - } - - /* FIX: AND processing if multiple proposals use the same # */ - - p = (const struct ikev2_proposal *) pos; - proposal_len = WPA_GET_BE16(p->proposal_length); - if (proposal_len < (int) sizeof(*p) || pos + proposal_len > end) { - wpa_printf(MSG_INFO, "IKEV2: Invalid proposal length %d", - proposal_len); - return -1; - } - wpa_printf(MSG_DEBUG, "IKEV2: SAi1 Proposal # %d", - p->proposal_num); - wpa_printf(MSG_DEBUG, "IKEV2: Type: %d Proposal Length: %d " - " Protocol ID: %d", - p->type, proposal_len, p->protocol_id); - wpa_printf(MSG_DEBUG, "IKEV2: SPI Size: %d Transforms: %d", - p->spi_size, p->num_transforms); - - if (p->type != 0 && p->type != 2) { - wpa_printf(MSG_INFO, "IKEV2: Unexpected Proposal type"); - return -1; - } - - if (p->protocol_id != IKEV2_PROTOCOL_IKE) { - wpa_printf(MSG_DEBUG, "IKEV2: Unexpected Protocol ID " - "(only IKE allowed for EAP-IKEv2)"); - return -1; - } - - if (p->proposal_num != prop->proposal_num) { - if (p->proposal_num == prop->proposal_num + 1) - prop->proposal_num = p->proposal_num; - else { - wpa_printf(MSG_INFO, "IKEV2: Unexpected Proposal #"); - return -1; - } - } - - ppos = (const u8 *) (p + 1); - pend = pos + proposal_len; - if (ppos + p->spi_size > pend) { - wpa_printf(MSG_INFO, "IKEV2: Not enough room for SPI " - "in proposal"); - return -1; - } - if (p->spi_size) { - wpa_hexdump(MSG_DEBUG, "IKEV2: SPI", - ppos, p->spi_size); - ppos += p->spi_size; - } - - /* - * For initial IKE_SA negotiation, SPI Size MUST be zero; for - * subsequent negotiations, it must be 8 for IKE. We only support - * initial case for now. - */ - if (p->spi_size != 0) { - wpa_printf(MSG_INFO, "IKEV2: Unexpected SPI Size"); - return -1; - } - - if (p->num_transforms == 0) { - wpa_printf(MSG_INFO, "IKEV2: At least one transform required"); - return -1; - } - - for (i = 0; i < (int) p->num_transforms; i++) { - int tlen = ikev2_parse_transform(prop, ppos, pend); - if (tlen < 0) - return -1; - ppos += tlen; - } - - if (ppos != pend) { - wpa_printf(MSG_INFO, "IKEV2: Unexpected data after " - "transforms"); - return -1; - } - - return proposal_len; -} - - -static int ikev2_process_sai1(struct ikev2_responder_data *data, - const u8 *sai1, size_t sai1_len) -{ - struct ikev2_proposal_data prop; - const u8 *pos, *end; - int found = 0; - - /* Security Association Payloads: */ - - if (sai1 == NULL) { - wpa_printf(MSG_INFO, "IKEV2: SAi1 not received"); - return -1; - } - - os_memset(&prop, 0, sizeof(prop)); - prop.proposal_num = 1; - - pos = sai1; - end = sai1 + sai1_len; - - while (pos < end) { - int plen; - - prop.integ = -1; - prop.prf = -1; - prop.encr = -1; - prop.dh = -1; - plen = ikev2_parse_proposal(&prop, pos, end); - if (plen < 0) - return -1; - - if (!found && prop.integ != -1 && prop.prf != -1 && - prop.encr != -1 && prop.dh != -1) { - os_memcpy(&data->proposal, &prop, sizeof(prop)); - data->dh = dh_groups_get(prop.dh); - found = 1; - } - - pos += plen; - } - - if (pos != end) { - wpa_printf(MSG_INFO, "IKEV2: Unexpected data after proposals"); - return -1; - } - - if (!found) { - wpa_printf(MSG_INFO, "IKEV2: No acceptable proposal found"); - return -1; - } - - wpa_printf(MSG_DEBUG, "IKEV2: Accepted proposal #%d: ENCR:%d PRF:%d " - "INTEG:%d D-H:%d", data->proposal.proposal_num, - data->proposal.encr, data->proposal.prf, - data->proposal.integ, data->proposal.dh); - - return 0; -} - - -static int ikev2_process_kei(struct ikev2_responder_data *data, - const u8 *kei, size_t kei_len) -{ - u16 group; - - /* - * Key Exchange Payload: - * DH Group # (16 bits) - * RESERVED (16 bits) - * Key Exchange Data (Diffie-Hellman public value) - */ - - if (kei == NULL) { - wpa_printf(MSG_INFO, "IKEV2: KEi not received"); - return -1; - } - - if (kei_len < 4 + 96) { - wpa_printf(MSG_INFO, "IKEV2: Too show Key Exchange Payload"); - return -1; - } - - group = WPA_GET_BE16(kei); - wpa_printf(MSG_DEBUG, "IKEV2: KEi DH Group #%u", group); - - if (group != data->proposal.dh) { - wpa_printf(MSG_DEBUG, "IKEV2: KEi DH Group #%u does not match " - "with the selected proposal (%u)", - group, data->proposal.dh); - /* Reject message with Notify payload of type - * INVALID_KE_PAYLOAD (RFC 4306, Sect. 3.4) */ - data->error_type = INVALID_KE_PAYLOAD; - data->state = NOTIFY; - return -1; - } - - if (data->dh == NULL) { - wpa_printf(MSG_INFO, "IKEV2: Unsupported DH group"); - return -1; - } - - /* RFC 4306, Section 3.4: - * The length of DH public value MUST be equal to the lenght of the - * prime modulus. - */ - if (kei_len - 4 != data->dh->prime_len) { - wpa_printf(MSG_INFO, "IKEV2: Invalid DH public value length " - "%ld (expected %ld)", - (long) (kei_len - 4), (long) data->dh->prime_len); - return -1; - } - - wpabuf_free(data->i_dh_public); - data->i_dh_public = wpabuf_alloc(kei_len - 4); - if (data->i_dh_public == NULL) - return -1; - wpabuf_put_data(data->i_dh_public, kei + 4, kei_len - 4); - - wpa_hexdump_buf(MSG_DEBUG, "IKEV2: KEi Diffie-Hellman Public Value", - data->i_dh_public); - - return 0; -} - - -static int ikev2_process_ni(struct ikev2_responder_data *data, - const u8 *ni, size_t ni_len) -{ - if (ni == NULL) { - wpa_printf(MSG_INFO, "IKEV2: Ni not received"); - return -1; - } - - if (ni_len < IKEV2_NONCE_MIN_LEN || ni_len > IKEV2_NONCE_MAX_LEN) { - wpa_printf(MSG_INFO, "IKEV2: Invalid Ni length %ld", - (long) ni_len); - return -1; - } - -#ifdef CCNS_PL - /* Zeros are removed incorrectly from the beginning of the nonces */ - while (ni_len > 1 && *ni == 0) { - ni_len--; - ni++; - } -#endif /* CCNS_PL */ - - data->i_nonce_len = ni_len; - os_memcpy(data->i_nonce, ni, ni_len); - wpa_hexdump(MSG_MSGDUMP, "IKEV2: Ni", - data->i_nonce, data->i_nonce_len); - - return 0; -} - - -static int ikev2_process_sa_init(struct ikev2_responder_data *data, - const struct ikev2_hdr *hdr, - struct ikev2_payloads *pl) -{ - if (ikev2_process_sai1(data, pl->sa, pl->sa_len) < 0 || - ikev2_process_kei(data, pl->ke, pl->ke_len) < 0 || - ikev2_process_ni(data, pl->nonce, pl->nonce_len) < 0) - return -1; - - os_memcpy(data->i_spi, hdr->i_spi, IKEV2_SPI_LEN); - - return 0; -} - - -static int ikev2_process_idi(struct ikev2_responder_data *data, - const u8 *idi, size_t idi_len) -{ - u8 id_type; - - if (idi == NULL) { - wpa_printf(MSG_INFO, "IKEV2: No IDi received"); - return -1; - } - - if (idi_len < 4) { - wpa_printf(MSG_INFO, "IKEV2: Too short IDi payload"); - return -1; - } - - id_type = idi[0]; - idi += 4; - idi_len -= 4; - - wpa_printf(MSG_DEBUG, "IKEV2: IDi ID Type %d", id_type); - wpa_hexdump_ascii(MSG_DEBUG, "IKEV2: IDi", idi, idi_len); - os_free(data->IDi); - data->IDi = os_malloc(idi_len); - if (data->IDi == NULL) - return -1; - os_memcpy(data->IDi, idi, idi_len); - data->IDi_len = idi_len; - data->IDi_type = id_type; - - return 0; -} - - -static int ikev2_process_cert(struct ikev2_responder_data *data, - const u8 *cert, size_t cert_len) -{ - u8 cert_encoding; - - if (cert == NULL) { - if (data->peer_auth == PEER_AUTH_CERT) { - wpa_printf(MSG_INFO, "IKEV2: No Certificate received"); - return -1; - } - return 0; - } - - if (cert_len < 1) { - wpa_printf(MSG_INFO, "IKEV2: No Cert Encoding field"); - return -1; - } - - cert_encoding = cert[0]; - cert++; - cert_len--; - - wpa_printf(MSG_DEBUG, "IKEV2: Cert Encoding %d", cert_encoding); - wpa_hexdump(MSG_MSGDUMP, "IKEV2: Certificate Data", cert, cert_len); - - /* TODO: validate certificate */ - - return 0; -} - - -static int ikev2_process_auth_cert(struct ikev2_responder_data *data, - u8 method, const u8 *auth, size_t auth_len) -{ - if (method != AUTH_RSA_SIGN) { - wpa_printf(MSG_INFO, "IKEV2: Unsupported authentication " - "method %d", method); - return -1; - } - - /* TODO: validate AUTH */ - return 0; -} - - -static int ikev2_process_auth_secret(struct ikev2_responder_data *data, - u8 method, const u8 *auth, - size_t auth_len) -{ - u8 auth_data[IKEV2_MAX_HASH_LEN]; - const struct ikev2_prf_alg *prf; - - if (method != AUTH_SHARED_KEY_MIC) { - wpa_printf(MSG_INFO, "IKEV2: Unsupported authentication " - "method %d", method); - return -1; - } - - /* msg | Nr | prf(SK_pi,IDi') */ - if (ikev2_derive_auth_data(data->proposal.prf, data->i_sign_msg, - data->IDi, data->IDi_len, data->IDi_type, - &data->keys, 1, data->shared_secret, - data->shared_secret_len, - data->r_nonce, data->r_nonce_len, - data->key_pad, data->key_pad_len, - auth_data) < 0) { - wpa_printf(MSG_INFO, "IKEV2: Could not derive AUTH data"); - return -1; - } - - wpabuf_free(data->i_sign_msg); - data->i_sign_msg = NULL; - - prf = ikev2_get_prf(data->proposal.prf); - if (prf == NULL) - return -1; - - if (auth_len != prf->hash_len || - os_memcmp(auth, auth_data, auth_len) != 0) { - wpa_printf(MSG_INFO, "IKEV2: Invalid Authentication Data"); - wpa_hexdump(MSG_DEBUG, "IKEV2: Received Authentication Data", - auth, auth_len); - wpa_hexdump(MSG_DEBUG, "IKEV2: Expected Authentication Data", - auth_data, prf->hash_len); - data->error_type = AUTHENTICATION_FAILED; - data->state = NOTIFY; - return -1; - } - - wpa_printf(MSG_DEBUG, "IKEV2: Server authenticated successfully " - "using shared keys"); - - return 0; -} - - -static int ikev2_process_auth(struct ikev2_responder_data *data, - const u8 *auth, size_t auth_len) -{ - u8 auth_method; - - if (auth == NULL) { - wpa_printf(MSG_INFO, "IKEV2: No Authentication Payload"); - return -1; - } - - if (auth_len < 4) { - wpa_printf(MSG_INFO, "IKEV2: Too short Authentication " - "Payload"); - return -1; - } - - auth_method = auth[0]; - auth += 4; - auth_len -= 4; - - wpa_printf(MSG_DEBUG, "IKEV2: Auth Method %d", auth_method); - wpa_hexdump(MSG_MSGDUMP, "IKEV2: Authentication Data", auth, auth_len); - - switch (data->peer_auth) { - case PEER_AUTH_CERT: - return ikev2_process_auth_cert(data, auth_method, auth, - auth_len); - case PEER_AUTH_SECRET: - return ikev2_process_auth_secret(data, auth_method, auth, - auth_len); - } - - return -1; -} - - -static int ikev2_process_sa_auth_decrypted(struct ikev2_responder_data *data, - u8 next_payload, - u8 *payload, size_t payload_len) -{ - struct ikev2_payloads pl; - - wpa_printf(MSG_DEBUG, "IKEV2: Processing decrypted payloads"); - - if (ikev2_parse_payloads(&pl, next_payload, payload, payload + - payload_len) < 0) { - wpa_printf(MSG_INFO, "IKEV2: Failed to parse decrypted " - "payloads"); - return -1; - } - - if (ikev2_process_idi(data, pl.idi, pl.idi_len) < 0 || - ikev2_process_cert(data, pl.cert, pl.cert_len) < 0 || - ikev2_process_auth(data, pl.auth, pl.auth_len) < 0) - return -1; - - return 0; -} - - -static int ikev2_process_sa_auth(struct ikev2_responder_data *data, - const struct ikev2_hdr *hdr, - struct ikev2_payloads *pl) -{ - u8 *decrypted; - size_t decrypted_len; - int ret; - - decrypted = ikev2_decrypt_payload(data->proposal.encr, - data->proposal.integ, - &data->keys, 1, hdr, pl->encrypted, - pl->encrypted_len, &decrypted_len); - if (decrypted == NULL) - return -1; - - ret = ikev2_process_sa_auth_decrypted(data, pl->encr_next_payload, - decrypted, decrypted_len); - os_free(decrypted); - - return ret; -} - - -static int ikev2_validate_rx_state(struct ikev2_responder_data *data, - u8 exchange_type, u32 message_id) -{ - switch (data->state) { - case SA_INIT: - /* Expect to receive IKE_SA_INIT: HDR, SAi1, KEi, Ni */ - if (exchange_type != IKE_SA_INIT) { - wpa_printf(MSG_INFO, "IKEV2: Unexpected Exchange Type " - "%u in SA_INIT state", exchange_type); - return -1; - } - if (message_id != 0) { - wpa_printf(MSG_INFO, "IKEV2: Unexpected Message ID %u " - "in SA_INIT state", message_id); - return -1; - } - break; - case SA_AUTH: - /* Expect to receive IKE_SA_AUTH: - * HDR, SK {IDi, [CERT,] [CERTREQ,] [IDr,] - * AUTH, SAi2, TSi, TSr} - */ - if (exchange_type != IKE_SA_AUTH) { - wpa_printf(MSG_INFO, "IKEV2: Unexpected Exchange Type " - "%u in SA_AUTH state", exchange_type); - return -1; - } - if (message_id != 1) { - wpa_printf(MSG_INFO, "IKEV2: Unexpected Message ID %u " - "in SA_AUTH state", message_id); - return -1; - } - break; - case CHILD_SA: - if (exchange_type != CREATE_CHILD_SA) { - wpa_printf(MSG_INFO, "IKEV2: Unexpected Exchange Type " - "%u in CHILD_SA state", exchange_type); - return -1; - } - if (message_id != 2) { - wpa_printf(MSG_INFO, "IKEV2: Unexpected Message ID %u " - "in CHILD_SA state", message_id); - return -1; - } - break; - case NOTIFY: - case IKEV2_DONE: - case IKEV2_FAILED: - return -1; - } - - return 0; -} - - -int ikev2_responder_process(struct ikev2_responder_data *data, - const struct wpabuf *buf) -{ - const struct ikev2_hdr *hdr; - u32 length, message_id; - const u8 *pos, *end; - struct ikev2_payloads pl; - - wpa_printf(MSG_MSGDUMP, "IKEV2: Received message (len %lu)", - (unsigned long) wpabuf_len(buf)); - - if (wpabuf_len(buf) < sizeof(*hdr)) { - wpa_printf(MSG_INFO, "IKEV2: Too short frame to include HDR"); - return -1; - } - - data->error_type = 0; - hdr = (const struct ikev2_hdr *) wpabuf_head(buf); - end = wpabuf_head_u8(buf) + wpabuf_len(buf); - message_id = WPA_GET_BE32(hdr->message_id); - length = WPA_GET_BE32(hdr->length); - - wpa_hexdump(MSG_DEBUG, "IKEV2: IKE_SA Initiator's SPI", - hdr->i_spi, IKEV2_SPI_LEN); - wpa_hexdump(MSG_DEBUG, "IKEV2: IKE_SA Responder's SPI", - hdr->r_spi, IKEV2_SPI_LEN); - wpa_printf(MSG_DEBUG, "IKEV2: Next Payload: %u Version: 0x%x " - "Exchange Type: %u", - hdr->next_payload, hdr->version, hdr->exchange_type); - wpa_printf(MSG_DEBUG, "IKEV2: Message ID: %u Length: %u", - message_id, length); - - if (hdr->version != IKEV2_VERSION) { - wpa_printf(MSG_INFO, "IKEV2: Unsupported HDR version 0x%x " - "(expected 0x%x)", hdr->version, IKEV2_VERSION); - return -1; - } - - if (length != wpabuf_len(buf)) { - wpa_printf(MSG_INFO, "IKEV2: Invalid length (HDR: %lu != " - "RX: %lu)", (unsigned long) length, - (unsigned long) wpabuf_len(buf)); - return -1; - } - - if (ikev2_validate_rx_state(data, hdr->exchange_type, message_id) < 0) - return -1; - - if ((hdr->flags & (IKEV2_HDR_INITIATOR | IKEV2_HDR_RESPONSE)) != - IKEV2_HDR_INITIATOR) { - wpa_printf(MSG_INFO, "IKEV2: Unexpected Flags value 0x%x", - hdr->flags); - return -1; - } - - if (data->state != SA_INIT) { - if (os_memcmp(data->i_spi, hdr->i_spi, IKEV2_SPI_LEN) != 0) { - wpa_printf(MSG_INFO, "IKEV2: Unexpected IKE_SA " - "Initiator's SPI"); - return -1; - } - if (os_memcmp(data->r_spi, hdr->r_spi, IKEV2_SPI_LEN) != 0) { - wpa_printf(MSG_INFO, "IKEV2: Unexpected IKE_SA " - "Responder's SPI"); - return -1; - } - } - - pos = (const u8 *) (hdr + 1); - if (ikev2_parse_payloads(&pl, hdr->next_payload, pos, end) < 0) - return -1; - - if (data->state == SA_INIT) { - data->last_msg = LAST_MSG_SA_INIT; - if (ikev2_process_sa_init(data, hdr, &pl) < 0) { - if (data->state == NOTIFY) - return 0; - return -1; - } - wpabuf_free(data->i_sign_msg); - data->i_sign_msg = wpabuf_dup(buf); - } - - if (data->state == SA_AUTH) { - data->last_msg = LAST_MSG_SA_AUTH; - if (ikev2_process_sa_auth(data, hdr, &pl) < 0) { - if (data->state == NOTIFY) - return 0; - return -1; - } - } - - return 0; -} - - -static void ikev2_build_hdr(struct ikev2_responder_data *data, - struct wpabuf *msg, u8 exchange_type, - u8 next_payload, u32 message_id) -{ - struct ikev2_hdr *hdr; - - wpa_printf(MSG_DEBUG, "IKEV2: Adding HDR"); - - /* HDR - RFC 4306, Sect. 3.1 */ - hdr = wpabuf_put(msg, sizeof(*hdr)); - os_memcpy(hdr->i_spi, data->i_spi, IKEV2_SPI_LEN); - os_memcpy(hdr->r_spi, data->r_spi, IKEV2_SPI_LEN); - hdr->next_payload = next_payload; - hdr->version = IKEV2_VERSION; - hdr->exchange_type = exchange_type; - hdr->flags = IKEV2_HDR_RESPONSE; - WPA_PUT_BE32(hdr->message_id, message_id); -} - - -static int ikev2_build_sar1(struct ikev2_responder_data *data, - struct wpabuf *msg, u8 next_payload) -{ - struct ikev2_payload_hdr *phdr; - size_t plen; - struct ikev2_proposal *p; - struct ikev2_transform *t; - - wpa_printf(MSG_DEBUG, "IKEV2: Adding SAr1 payload"); - - /* SAr1 - RFC 4306, Sect. 2.7 and 3.3 */ - phdr = wpabuf_put(msg, sizeof(*phdr)); - phdr->next_payload = next_payload; - phdr->flags = 0; - - p = wpabuf_put(msg, sizeof(*p)); -#ifdef CCNS_PL - /* Seems to require that the Proposal # is 1 even though RFC 4306 - * Sect 3.3.1 has following requirement "When a proposal is accepted, - * all of the proposal numbers in the SA payload MUST be the same and - * MUST match the number on the proposal sent that was accepted.". - */ - p->proposal_num = 1; -#else /* CCNS_PL */ - p->proposal_num = data->proposal.proposal_num; -#endif /* CCNS_PL */ - p->protocol_id = IKEV2_PROTOCOL_IKE; - p->num_transforms = 4; - - t = wpabuf_put(msg, sizeof(*t)); - t->type = 3; - t->transform_type = IKEV2_TRANSFORM_ENCR; - WPA_PUT_BE16(t->transform_id, data->proposal.encr); - if (data->proposal.encr == ENCR_AES_CBC) { - /* Transform Attribute: Key Len = 128 bits */ -#ifdef CCNS_PL - wpabuf_put_be16(msg, 0x001d); /* ?? */ -#else /* CCNS_PL */ - wpabuf_put_be16(msg, 0x800e); /* AF=1, AttrType=14 */ -#endif /* CCNS_PL */ - wpabuf_put_be16(msg, 128); /* 128-bit key */ - } - plen = (u8 *) wpabuf_put(msg, 0) - (u8 *) t; - WPA_PUT_BE16(t->transform_length, plen); - - t = wpabuf_put(msg, sizeof(*t)); - t->type = 3; - WPA_PUT_BE16(t->transform_length, sizeof(*t)); - t->transform_type = IKEV2_TRANSFORM_PRF; - WPA_PUT_BE16(t->transform_id, data->proposal.prf); - - t = wpabuf_put(msg, sizeof(*t)); - t->type = 3; - WPA_PUT_BE16(t->transform_length, sizeof(*t)); - t->transform_type = IKEV2_TRANSFORM_INTEG; - WPA_PUT_BE16(t->transform_id, data->proposal.integ); - - t = wpabuf_put(msg, sizeof(*t)); - WPA_PUT_BE16(t->transform_length, sizeof(*t)); - t->transform_type = IKEV2_TRANSFORM_DH; - WPA_PUT_BE16(t->transform_id, data->proposal.dh); - - plen = (u8 *) wpabuf_put(msg, 0) - (u8 *) p; - WPA_PUT_BE16(p->proposal_length, plen); - - plen = (u8 *) wpabuf_put(msg, 0) - (u8 *) phdr; - WPA_PUT_BE16(phdr->payload_length, plen); - - return 0; -} - - -static int ikev2_build_ker(struct ikev2_responder_data *data, - struct wpabuf *msg, u8 next_payload) -{ - struct ikev2_payload_hdr *phdr; - size_t plen; - struct wpabuf *pv; - - wpa_printf(MSG_DEBUG, "IKEV2: Adding KEr payload"); - - pv = dh_init(data->dh, &data->r_dh_private); - if (pv == NULL) { - wpa_printf(MSG_DEBUG, "IKEV2: Failed to initialize DH"); - return -1; - } - - /* KEr - RFC 4306, Sect. 3.4 */ - phdr = wpabuf_put(msg, sizeof(*phdr)); - phdr->next_payload = next_payload; - phdr->flags = 0; - - wpabuf_put_be16(msg, data->proposal.dh); /* DH Group # */ - wpabuf_put(msg, 2); /* RESERVED */ - /* - * RFC 4306, Sect. 3.4: possible zero padding for public value to - * match the length of the prime. - */ - wpabuf_put(msg, data->dh->prime_len - wpabuf_len(pv)); - wpabuf_put_buf(msg, pv); - wpabuf_free(pv); - - plen = (u8 *) wpabuf_put(msg, 0) - (u8 *) phdr; - WPA_PUT_BE16(phdr->payload_length, plen); - return 0; -} - - -static int ikev2_build_nr(struct ikev2_responder_data *data, - struct wpabuf *msg, u8 next_payload) -{ - struct ikev2_payload_hdr *phdr; - size_t plen; - - wpa_printf(MSG_DEBUG, "IKEV2: Adding Nr payload"); - - /* Nr - RFC 4306, Sect. 3.9 */ - phdr = wpabuf_put(msg, sizeof(*phdr)); - phdr->next_payload = next_payload; - phdr->flags = 0; - wpabuf_put_data(msg, data->r_nonce, data->r_nonce_len); - plen = (u8 *) wpabuf_put(msg, 0) - (u8 *) phdr; - WPA_PUT_BE16(phdr->payload_length, plen); - return 0; -} - - -static int ikev2_build_idr(struct ikev2_responder_data *data, - struct wpabuf *msg, u8 next_payload) -{ - struct ikev2_payload_hdr *phdr; - size_t plen; - - wpa_printf(MSG_DEBUG, "IKEV2: Adding IDr payload"); - - if (data->IDr == NULL) { - wpa_printf(MSG_INFO, "IKEV2: No IDr available"); - return -1; - } - - /* IDr - RFC 4306, Sect. 3.5 */ - phdr = wpabuf_put(msg, sizeof(*phdr)); - phdr->next_payload = next_payload; - phdr->flags = 0; - wpabuf_put_u8(msg, ID_KEY_ID); - wpabuf_put(msg, 3); /* RESERVED */ - wpabuf_put_data(msg, data->IDr, data->IDr_len); - plen = (u8 *) wpabuf_put(msg, 0) - (u8 *) phdr; - WPA_PUT_BE16(phdr->payload_length, plen); - return 0; -} - - -static int ikev2_build_auth(struct ikev2_responder_data *data, - struct wpabuf *msg, u8 next_payload) -{ - struct ikev2_payload_hdr *phdr; - size_t plen; - const struct ikev2_prf_alg *prf; - - wpa_printf(MSG_DEBUG, "IKEV2: Adding AUTH payload"); - - prf = ikev2_get_prf(data->proposal.prf); - if (prf == NULL) - return -1; - - /* Authentication - RFC 4306, Sect. 3.8 */ - phdr = wpabuf_put(msg, sizeof(*phdr)); - phdr->next_payload = next_payload; - phdr->flags = 0; - wpabuf_put_u8(msg, AUTH_SHARED_KEY_MIC); - wpabuf_put(msg, 3); /* RESERVED */ - - /* msg | Ni | prf(SK_pr,IDr') */ - if (ikev2_derive_auth_data(data->proposal.prf, data->r_sign_msg, - data->IDr, data->IDr_len, ID_KEY_ID, - &data->keys, 0, data->shared_secret, - data->shared_secret_len, - data->i_nonce, data->i_nonce_len, - data->key_pad, data->key_pad_len, - wpabuf_put(msg, prf->hash_len)) < 0) { - wpa_printf(MSG_INFO, "IKEV2: Could not derive AUTH data"); - return -1; - } - wpabuf_free(data->r_sign_msg); - data->r_sign_msg = NULL; - - plen = (u8 *) wpabuf_put(msg, 0) - (u8 *) phdr; - WPA_PUT_BE16(phdr->payload_length, plen); - return 0; -} - - -static int ikev2_build_notification(struct ikev2_responder_data *data, - struct wpabuf *msg, u8 next_payload) -{ - struct ikev2_payload_hdr *phdr; - size_t plen; - - wpa_printf(MSG_DEBUG, "IKEV2: Adding Notification payload"); - - if (data->error_type == 0) { - wpa_printf(MSG_INFO, "IKEV2: No Notify Message Type " - "available"); - return -1; - } - - /* Notify - RFC 4306, Sect. 3.10 */ - phdr = wpabuf_put(msg, sizeof(*phdr)); - phdr->next_payload = next_payload; - phdr->flags = 0; -#ifdef CCNS_PL - wpabuf_put_u8(msg, 1); /* Protocol ID: IKE_SA notification */ -#else /* CCNS_PL */ - wpabuf_put_u8(msg, 0); /* Protocol ID: no existing SA */ -#endif /* CCNS_PL */ - wpabuf_put_u8(msg, 0); /* SPI Size */ - wpabuf_put_be16(msg, data->error_type); - - switch (data->error_type) { - case INVALID_KE_PAYLOAD: - if (data->proposal.dh == -1) { - wpa_printf(MSG_INFO, "IKEV2: No DH Group selected for " - "INVALID_KE_PAYLOAD notifications"); - return -1; - } - wpabuf_put_be16(msg, data->proposal.dh); - wpa_printf(MSG_DEBUG, "IKEV2: INVALID_KE_PAYLOAD - request " - "DH Group #%d", data->proposal.dh); - break; - case AUTHENTICATION_FAILED: - /* no associated data */ - break; - default: - wpa_printf(MSG_INFO, "IKEV2: Unsupported Notify Message Type " - "%d", data->error_type); - return -1; - } - - plen = (u8 *) wpabuf_put(msg, 0) - (u8 *) phdr; - WPA_PUT_BE16(phdr->payload_length, plen); - return 0; -} - - -static struct wpabuf * ikev2_build_sa_init(struct ikev2_responder_data *data) -{ - struct wpabuf *msg; - - /* build IKE_SA_INIT: HDR, SAr1, KEr, Nr, [CERTREQ], [SK{IDr}] */ - - if (os_get_random(data->r_spi, IKEV2_SPI_LEN)) - return NULL; - wpa_hexdump(MSG_DEBUG, "IKEV2: IKE_SA Responder's SPI", - data->r_spi, IKEV2_SPI_LEN); - - data->r_nonce_len = IKEV2_NONCE_MIN_LEN; - if (random_get_bytes(data->r_nonce, data->r_nonce_len)) - return NULL; -#ifdef CCNS_PL - /* Zeros are removed incorrectly from the beginning of the nonces in - * key derivation; as a workaround, make sure Nr does not start with - * zero.. */ - if (data->r_nonce[0] == 0) - data->r_nonce[0] = 1; -#endif /* CCNS_PL */ - wpa_hexdump(MSG_DEBUG, "IKEV2: Nr", data->r_nonce, data->r_nonce_len); - - msg = wpabuf_alloc(sizeof(struct ikev2_hdr) + data->IDr_len + 1500); - if (msg == NULL) - return NULL; - - ikev2_build_hdr(data, msg, IKE_SA_INIT, IKEV2_PAYLOAD_SA, 0); - if (ikev2_build_sar1(data, msg, IKEV2_PAYLOAD_KEY_EXCHANGE) || - ikev2_build_ker(data, msg, IKEV2_PAYLOAD_NONCE) || - ikev2_build_nr(data, msg, data->peer_auth == PEER_AUTH_SECRET ? - IKEV2_PAYLOAD_ENCRYPTED : - IKEV2_PAYLOAD_NO_NEXT_PAYLOAD)) { - wpabuf_free(msg); - return NULL; - } - - if (ikev2_derive_keys(data)) { - wpabuf_free(msg); - return NULL; - } - - if (data->peer_auth == PEER_AUTH_CERT) { - /* TODO: CERTREQ with SHA-1 hashes of Subject Public Key Info - * for trust agents */ - } - - if (data->peer_auth == PEER_AUTH_SECRET) { - struct wpabuf *plain = wpabuf_alloc(data->IDr_len + 1000); - if (plain == NULL) { - wpabuf_free(msg); - return NULL; - } - if (ikev2_build_idr(data, plain, - IKEV2_PAYLOAD_NO_NEXT_PAYLOAD) || - ikev2_build_encrypted(data->proposal.encr, - data->proposal.integ, - &data->keys, 0, msg, plain, - IKEV2_PAYLOAD_IDr)) { - wpabuf_free(plain); - wpabuf_free(msg); - return NULL; - } - wpabuf_free(plain); - } - - ikev2_update_hdr(msg); - - wpa_hexdump_buf(MSG_MSGDUMP, "IKEV2: Sending message (SA_INIT)", msg); - - data->state = SA_AUTH; - - wpabuf_free(data->r_sign_msg); - data->r_sign_msg = wpabuf_dup(msg); - - return msg; -} - - -static struct wpabuf * ikev2_build_sa_auth(struct ikev2_responder_data *data) -{ - struct wpabuf *msg, *plain; - - /* build IKE_SA_AUTH: HDR, SK {IDr, [CERT,] AUTH} */ - - msg = wpabuf_alloc(sizeof(struct ikev2_hdr) + data->IDr_len + 1000); - if (msg == NULL) - return NULL; - ikev2_build_hdr(data, msg, IKE_SA_AUTH, IKEV2_PAYLOAD_ENCRYPTED, 1); - - plain = wpabuf_alloc(data->IDr_len + 1000); - if (plain == NULL) { - wpabuf_free(msg); - return NULL; - } - - if (ikev2_build_idr(data, plain, IKEV2_PAYLOAD_AUTHENTICATION) || - ikev2_build_auth(data, plain, IKEV2_PAYLOAD_NO_NEXT_PAYLOAD) || - ikev2_build_encrypted(data->proposal.encr, data->proposal.integ, - &data->keys, 0, msg, plain, - IKEV2_PAYLOAD_IDr)) { - wpabuf_free(plain); - wpabuf_free(msg); - return NULL; - } - wpabuf_free(plain); - - wpa_hexdump_buf(MSG_MSGDUMP, "IKEV2: Sending message (SA_AUTH)", msg); - - data->state = IKEV2_DONE; - - return msg; -} - - -static struct wpabuf * ikev2_build_notify(struct ikev2_responder_data *data) -{ - struct wpabuf *msg; - - msg = wpabuf_alloc(sizeof(struct ikev2_hdr) + 1000); - if (msg == NULL) - return NULL; - if (data->last_msg == LAST_MSG_SA_AUTH) { - /* HDR, SK{N} */ - struct wpabuf *plain = wpabuf_alloc(100); - if (plain == NULL) { - wpabuf_free(msg); - return NULL; - } - ikev2_build_hdr(data, msg, IKE_SA_AUTH, - IKEV2_PAYLOAD_ENCRYPTED, 1); - if (ikev2_build_notification(data, plain, - IKEV2_PAYLOAD_NO_NEXT_PAYLOAD) || - ikev2_build_encrypted(data->proposal.encr, - data->proposal.integ, - &data->keys, 0, msg, plain, - IKEV2_PAYLOAD_NOTIFICATION)) { - wpabuf_free(plain); - wpabuf_free(msg); - return NULL; - } - data->state = IKEV2_FAILED; - } else { - /* HDR, N */ - ikev2_build_hdr(data, msg, IKE_SA_INIT, - IKEV2_PAYLOAD_NOTIFICATION, 0); - if (ikev2_build_notification(data, msg, - IKEV2_PAYLOAD_NO_NEXT_PAYLOAD)) { - wpabuf_free(msg); - return NULL; - } - data->state = SA_INIT; - } - - ikev2_update_hdr(msg); - - wpa_hexdump_buf(MSG_MSGDUMP, "IKEV2: Sending message (Notification)", - msg); - - return msg; -} - - -struct wpabuf * ikev2_responder_build(struct ikev2_responder_data *data) -{ - switch (data->state) { - case SA_INIT: - return ikev2_build_sa_init(data); - case SA_AUTH: - return ikev2_build_sa_auth(data); - case CHILD_SA: - return NULL; - case NOTIFY: - return ikev2_build_notify(data); - case IKEV2_DONE: - case IKEV2_FAILED: - return NULL; - } - return NULL; -} diff --git a/hostapd-0.8/src/eap_peer/ikev2.h b/hostapd-0.8/src/eap_peer/ikev2.h deleted file mode 100644 index 9ca0ca5..0000000 --- a/hostapd-0.8/src/eap_peer/ikev2.h +++ /dev/null @@ -1,65 +0,0 @@ -/* - * IKEv2 responder (RFC 4306) for EAP-IKEV2 - * Copyright (c) 2007, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#ifndef IKEV2_H -#define IKEV2_H - -#include "eap_common/ikev2_common.h" - -struct ikev2_proposal_data { - u8 proposal_num; - int integ; - int prf; - int encr; - int dh; -}; - - -struct ikev2_responder_data { - enum { SA_INIT, SA_AUTH, CHILD_SA, NOTIFY, IKEV2_DONE, IKEV2_FAILED } - state; - u8 i_spi[IKEV2_SPI_LEN]; - u8 r_spi[IKEV2_SPI_LEN]; - u8 i_nonce[IKEV2_NONCE_MAX_LEN]; - size_t i_nonce_len; - u8 r_nonce[IKEV2_NONCE_MAX_LEN]; - size_t r_nonce_len; - struct wpabuf *i_dh_public; - struct wpabuf *r_dh_private; - struct ikev2_proposal_data proposal; - const struct dh_group *dh; - struct ikev2_keys keys; - u8 *IDi; - size_t IDi_len; - u8 IDi_type; - u8 *IDr; - size_t IDr_len; - struct wpabuf *r_sign_msg; - struct wpabuf *i_sign_msg; - u8 *shared_secret; - size_t shared_secret_len; - enum { PEER_AUTH_CERT, PEER_AUTH_SECRET } peer_auth; - u8 *key_pad; - size_t key_pad_len; - u16 error_type; - enum { LAST_MSG_SA_INIT, LAST_MSG_SA_AUTH } last_msg; -}; - - -void ikev2_responder_deinit(struct ikev2_responder_data *data); -int ikev2_responder_process(struct ikev2_responder_data *data, - const struct wpabuf *buf); -struct wpabuf * ikev2_responder_build(struct ikev2_responder_data *data); - -#endif /* IKEV2_H */ diff --git a/hostapd-0.8/src/eap_peer/mschapv2.c b/hostapd-0.8/src/eap_peer/mschapv2.c deleted file mode 100644 index b8fb075..0000000 --- a/hostapd-0.8/src/eap_peer/mschapv2.c +++ /dev/null @@ -1,123 +0,0 @@ -/* - * MSCHAPV2 (RFC 2759) - * Copyright (c) 2004-2008, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#include "includes.h" - -#include "common.h" -#include "crypto/ms_funcs.h" -#include "mschapv2.h" - -const u8 * mschapv2_remove_domain(const u8 *username, size_t *len) -{ - size_t i; - - /* - * MSCHAPv2 does not include optional domain name in the - * challenge-response calculation, so remove domain prefix - * (if present). - */ - - for (i = 0; i < *len; i++) { - if (username[i] == '\\') { - *len -= i + 1; - return username + i + 1; - } - } - - return username; -} - - -int mschapv2_derive_response(const u8 *identity, size_t identity_len, - const u8 *password, size_t password_len, - int pwhash, - const u8 *auth_challenge, - const u8 *peer_challenge, - u8 *nt_response, u8 *auth_response, - u8 *master_key) -{ - const u8 *username; - size_t username_len; - u8 password_hash[16], password_hash_hash[16]; - - wpa_hexdump_ascii(MSG_DEBUG, "MSCHAPV2: Identity", - identity, identity_len); - username_len = identity_len; - username = mschapv2_remove_domain(identity, &username_len); - wpa_hexdump_ascii(MSG_DEBUG, "MSCHAPV2: Username", - username, username_len); - - wpa_hexdump(MSG_DEBUG, "MSCHAPV2: auth_challenge", - auth_challenge, MSCHAPV2_CHAL_LEN); - wpa_hexdump(MSG_DEBUG, "MSCHAPV2: peer_challenge", - peer_challenge, MSCHAPV2_CHAL_LEN); - wpa_hexdump_ascii(MSG_DEBUG, "MSCHAPV2: username", - username, username_len); - /* Authenticator response is not really needed yet, but calculate it - * here so that challenges need not be saved. */ - if (pwhash) { - wpa_hexdump_key(MSG_DEBUG, "MSCHAPV2: password hash", - password, password_len); - generate_nt_response_pwhash(auth_challenge, peer_challenge, - username, username_len, - password, nt_response); - generate_authenticator_response_pwhash( - password, peer_challenge, auth_challenge, - username, username_len, nt_response, auth_response); - } else { - wpa_hexdump_ascii_key(MSG_DEBUG, "MSCHAPV2: password", - password, password_len); - generate_nt_response(auth_challenge, peer_challenge, - username, username_len, - password, password_len, nt_response); - generate_authenticator_response(password, password_len, - peer_challenge, auth_challenge, - username, username_len, - nt_response, auth_response); - } - wpa_hexdump(MSG_DEBUG, "MSCHAPV2: NT Response", - nt_response, MSCHAPV2_NT_RESPONSE_LEN); - wpa_hexdump(MSG_DEBUG, "MSCHAPV2: Auth Response", - auth_response, MSCHAPV2_AUTH_RESPONSE_LEN); - - /* Generate master_key here since we have the needed data available. */ - if (pwhash) { - if (hash_nt_password_hash(password, password_hash_hash)) - return -1; - } else { - if (nt_password_hash(password, password_len, password_hash) || - hash_nt_password_hash(password_hash, password_hash_hash)) - return -1; - } - get_master_key(password_hash_hash, nt_response, master_key); - wpa_hexdump_key(MSG_DEBUG, "MSCHAPV2: Master Key", - master_key, MSCHAPV2_MASTER_KEY_LEN); - - return 0; -} - - -int mschapv2_verify_auth_response(const u8 *auth_response, - const u8 *buf, size_t buf_len) -{ - u8 recv_response[MSCHAPV2_AUTH_RESPONSE_LEN]; - if (buf_len < 2 + 2 * MSCHAPV2_AUTH_RESPONSE_LEN || - buf[0] != 'S' || buf[1] != '=' || - hexstr2bin((char *) (buf + 2), recv_response, - MSCHAPV2_AUTH_RESPONSE_LEN) || - os_memcmp(auth_response, recv_response, - MSCHAPV2_AUTH_RESPONSE_LEN) != 0) - return -1; - return 0; -} diff --git a/hostapd-0.8/src/eap_peer/mschapv2.h b/hostapd-0.8/src/eap_peer/mschapv2.h deleted file mode 100644 index 90dad31..0000000 --- a/hostapd-0.8/src/eap_peer/mschapv2.h +++ /dev/null @@ -1,34 +0,0 @@ -/* - * MSCHAPV2 (RFC 2759) - * Copyright (c) 2004-2008, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#ifndef MSCHAPV2_H -#define MSCHAPV2_H - -#define MSCHAPV2_CHAL_LEN 16 -#define MSCHAPV2_NT_RESPONSE_LEN 24 -#define MSCHAPV2_AUTH_RESPONSE_LEN 20 -#define MSCHAPV2_MASTER_KEY_LEN 16 - -const u8 * mschapv2_remove_domain(const u8 *username, size_t *len); -int mschapv2_derive_response(const u8 *username, size_t username_len, - const u8 *password, size_t password_len, - int pwhash, - const u8 *auth_challenge, - const u8 *peer_challenge, - u8 *nt_response, u8 *auth_response, - u8 *master_key); -int mschapv2_verify_auth_response(const u8 *auth_response, - const u8 *buf, size_t buf_len); - -#endif /* MSCHAPV2_H */ diff --git a/hostapd-0.8/src/eap_peer/tncc.c b/hostapd-0.8/src/eap_peer/tncc.c deleted file mode 100644 index a70d70c..0000000 --- a/hostapd-0.8/src/eap_peer/tncc.c +++ /dev/null @@ -1,1369 +0,0 @@ -/* - * EAP-TNC - TNCC (IF-IMC and IF-TNCCS) - * Copyright (c) 2007, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#include "includes.h" -#ifndef CONFIG_NATIVE_WINDOWS -#include -#endif /* CONFIG_NATIVE_WINDOWS */ - -#include "common.h" -#include "base64.h" -#include "tncc.h" -#include "eap_common/eap_tlv_common.h" -#include "eap_common/eap_defs.h" - - -#ifdef UNICODE -#define TSTR "%S" -#else /* UNICODE */ -#define TSTR "%s" -#endif /* UNICODE */ - - -#define TNC_CONFIG_FILE "/etc/tnc_config" -#define TNC_WINREG_PATH TEXT("SOFTWARE\\Trusted Computing Group\\TNC\\IMCs") -#define IF_TNCCS_START \ -"\n" \ -"\n" -#define IF_TNCCS_END "\n" - -/* TNC IF-IMC */ - -typedef unsigned long TNC_UInt32; -typedef unsigned char *TNC_BufferReference; - -typedef TNC_UInt32 TNC_IMCID; -typedef TNC_UInt32 TNC_ConnectionID; -typedef TNC_UInt32 TNC_ConnectionState; -typedef TNC_UInt32 TNC_RetryReason; -typedef TNC_UInt32 TNC_MessageType; -typedef TNC_MessageType *TNC_MessageTypeList; -typedef TNC_UInt32 TNC_VendorID; -typedef TNC_UInt32 TNC_MessageSubtype; -typedef TNC_UInt32 TNC_Version; -typedef TNC_UInt32 TNC_Result; - -typedef TNC_Result (*TNC_TNCC_BindFunctionPointer)( - TNC_IMCID imcID, - char *functionName, - void **pOutfunctionPointer); - -#define TNC_RESULT_SUCCESS 0 -#define TNC_RESULT_NOT_INITIALIZED 1 -#define TNC_RESULT_ALREADY_INITIALIZED 2 -#define TNC_RESULT_NO_COMMON_VERSION 3 -#define TNC_RESULT_CANT_RETRY 4 -#define TNC_RESULT_WONT_RETRY 5 -#define TNC_RESULT_INVALID_PARAMETER 6 -#define TNC_RESULT_CANT_RESPOND 7 -#define TNC_RESULT_ILLEGAL_OPERATION 8 -#define TNC_RESULT_OTHER 9 -#define TNC_RESULT_FATAL 10 - -#define TNC_CONNECTION_STATE_CREATE 0 -#define TNC_CONNECTION_STATE_HANDSHAKE 1 -#define TNC_CONNECTION_STATE_ACCESS_ALLOWED 2 -#define TNC_CONNECTION_STATE_ACCESS_ISOLATED 3 -#define TNC_CONNECTION_STATE_ACCESS_NONE 4 -#define TNC_CONNECTION_STATE_DELETE 5 - -#define TNC_IFIMC_VERSION_1 1 - -#define TNC_VENDORID_ANY ((TNC_VendorID) 0xffffff) -#define TNC_SUBTYPE_ANY ((TNC_MessageSubtype) 0xff) - -/* TNCC-TNCS Message Types */ -#define TNC_TNCCS_RECOMMENDATION 0x00000001 -#define TNC_TNCCS_ERROR 0x00000002 -#define TNC_TNCCS_PREFERREDLANGUAGE 0x00000003 -#define TNC_TNCCS_REASONSTRINGS 0x00000004 - - -/* IF-TNCCS-SOH - SSoH and SSoHR Attributes */ -enum { - SSOH_MS_MACHINE_INVENTORY = 1, - SSOH_MS_QUARANTINE_STATE = 2, - SSOH_MS_PACKET_INFO = 3, - SSOH_MS_SYSTEMGENERATED_IDS = 4, - SSOH_MS_MACHINENAME = 5, - SSOH_MS_CORRELATIONID = 6, - SSOH_MS_INSTALLED_SHVS = 7, - SSOH_MS_MACHINE_INVENTORY_EX = 8 -}; - -struct tnc_if_imc { - struct tnc_if_imc *next; - char *name; - char *path; - void *dlhandle; /* from dlopen() */ - TNC_IMCID imcID; - TNC_ConnectionID connectionID; - TNC_MessageTypeList supported_types; - size_t num_supported_types; - u8 *imc_send; - size_t imc_send_len; - - /* Functions implemented by IMCs (with TNC_IMC_ prefix) */ - TNC_Result (*Initialize)( - TNC_IMCID imcID, - TNC_Version minVersion, - TNC_Version maxVersion, - TNC_Version *pOutActualVersion); - TNC_Result (*NotifyConnectionChange)( - TNC_IMCID imcID, - TNC_ConnectionID connectionID, - TNC_ConnectionState newState); - TNC_Result (*BeginHandshake)( - TNC_IMCID imcID, - TNC_ConnectionID connectionID); - TNC_Result (*ReceiveMessage)( - TNC_IMCID imcID, - TNC_ConnectionID connectionID, - TNC_BufferReference messageBuffer, - TNC_UInt32 messageLength, - TNC_MessageType messageType); - TNC_Result (*BatchEnding)( - TNC_IMCID imcID, - TNC_ConnectionID connectionID); - TNC_Result (*Terminate)(TNC_IMCID imcID); - TNC_Result (*ProvideBindFunction)( - TNC_IMCID imcID, - TNC_TNCC_BindFunctionPointer bindFunction); -}; - -struct tncc_data { - struct tnc_if_imc *imc; - unsigned int last_batchid; -}; - -#define TNC_MAX_IMC_ID 10 -static struct tnc_if_imc *tnc_imc[TNC_MAX_IMC_ID] = { NULL }; - - -/* TNCC functions that IMCs can call */ - -TNC_Result TNC_TNCC_ReportMessageTypes( - TNC_IMCID imcID, - TNC_MessageTypeList supportedTypes, - TNC_UInt32 typeCount) -{ - TNC_UInt32 i; - struct tnc_if_imc *imc; - - wpa_printf(MSG_DEBUG, "TNC: TNC_TNCC_ReportMessageTypes(imcID=%lu " - "typeCount=%lu)", - (unsigned long) imcID, (unsigned long) typeCount); - - for (i = 0; i < typeCount; i++) { - wpa_printf(MSG_DEBUG, "TNC: supportedTypes[%lu] = %lu", - i, supportedTypes[i]); - } - - if (imcID >= TNC_MAX_IMC_ID || tnc_imc[imcID] == NULL) - return TNC_RESULT_INVALID_PARAMETER; - - imc = tnc_imc[imcID]; - os_free(imc->supported_types); - imc->supported_types = - os_malloc(typeCount * sizeof(TNC_MessageType)); - if (imc->supported_types == NULL) - return TNC_RESULT_FATAL; - os_memcpy(imc->supported_types, supportedTypes, - typeCount * sizeof(TNC_MessageType)); - imc->num_supported_types = typeCount; - - return TNC_RESULT_SUCCESS; -} - - -TNC_Result TNC_TNCC_SendMessage( - TNC_IMCID imcID, - TNC_ConnectionID connectionID, - TNC_BufferReference message, - TNC_UInt32 messageLength, - TNC_MessageType messageType) -{ - struct tnc_if_imc *imc; - unsigned char *b64; - size_t b64len; - - wpa_printf(MSG_DEBUG, "TNC: TNC_TNCC_SendMessage(imcID=%lu " - "connectionID=%lu messageType=%lu)", - imcID, connectionID, messageType); - wpa_hexdump_ascii(MSG_DEBUG, "TNC: TNC_TNCC_SendMessage", - message, messageLength); - - if (imcID >= TNC_MAX_IMC_ID || tnc_imc[imcID] == NULL) - return TNC_RESULT_INVALID_PARAMETER; - - b64 = base64_encode(message, messageLength, &b64len); - if (b64 == NULL) - return TNC_RESULT_FATAL; - - imc = tnc_imc[imcID]; - os_free(imc->imc_send); - imc->imc_send_len = 0; - imc->imc_send = os_zalloc(b64len + 100); - if (imc->imc_send == NULL) { - os_free(b64); - return TNC_RESULT_OTHER; - } - - imc->imc_send_len = - os_snprintf((char *) imc->imc_send, b64len + 100, - "%08X" - "%s", - (unsigned int) messageType, b64); - - os_free(b64); - - return TNC_RESULT_SUCCESS; -} - - -TNC_Result TNC_TNCC_RequestHandshakeRetry( - TNC_IMCID imcID, - TNC_ConnectionID connectionID, - TNC_RetryReason reason) -{ - wpa_printf(MSG_DEBUG, "TNC: TNC_TNCC_RequestHandshakeRetry"); - - if (imcID >= TNC_MAX_IMC_ID || tnc_imc[imcID] == NULL) - return TNC_RESULT_INVALID_PARAMETER; - - /* - * TODO: trigger a call to eapol_sm_request_reauth(). This would - * require that the IMC continues to be loaded in memory afer - * authentication.. - */ - - return TNC_RESULT_SUCCESS; -} - - -TNC_Result TNC_9048_LogMessage(TNC_IMCID imcID, TNC_UInt32 severity, - const char *message) -{ - wpa_printf(MSG_DEBUG, "TNC: TNC_9048_LogMessage(imcID=%lu " - "severity==%lu message='%s')", - imcID, severity, message); - return TNC_RESULT_SUCCESS; -} - - -TNC_Result TNC_9048_UserMessage(TNC_IMCID imcID, TNC_ConnectionID connectionID, - const char *message) -{ - wpa_printf(MSG_DEBUG, "TNC: TNC_9048_UserMessage(imcID=%lu " - "connectionID==%lu message='%s')", - imcID, connectionID, message); - return TNC_RESULT_SUCCESS; -} - - -TNC_Result TNC_TNCC_BindFunction( - TNC_IMCID imcID, - char *functionName, - void **pOutfunctionPointer) -{ - wpa_printf(MSG_DEBUG, "TNC: TNC_TNCC_BindFunction(imcID=%lu, " - "functionName='%s')", (unsigned long) imcID, functionName); - - if (imcID >= TNC_MAX_IMC_ID || tnc_imc[imcID] == NULL) - return TNC_RESULT_INVALID_PARAMETER; - - if (pOutfunctionPointer == NULL) - return TNC_RESULT_INVALID_PARAMETER; - - if (os_strcmp(functionName, "TNC_TNCC_ReportMessageTypes") == 0) - *pOutfunctionPointer = TNC_TNCC_ReportMessageTypes; - else if (os_strcmp(functionName, "TNC_TNCC_SendMessage") == 0) - *pOutfunctionPointer = TNC_TNCC_SendMessage; - else if (os_strcmp(functionName, "TNC_TNCC_RequestHandshakeRetry") == - 0) - *pOutfunctionPointer = TNC_TNCC_RequestHandshakeRetry; - else if (os_strcmp(functionName, "TNC_9048_LogMessage") == 0) - *pOutfunctionPointer = TNC_9048_LogMessage; - else if (os_strcmp(functionName, "TNC_9048_UserMessage") == 0) - *pOutfunctionPointer = TNC_9048_UserMessage; - else - *pOutfunctionPointer = NULL; - - return TNC_RESULT_SUCCESS; -} - - -static void * tncc_get_sym(void *handle, char *func) -{ - void *fptr; - -#ifdef CONFIG_NATIVE_WINDOWS -#ifdef _WIN32_WCE - fptr = GetProcAddressA(handle, func); -#else /* _WIN32_WCE */ - fptr = GetProcAddress(handle, func); -#endif /* _WIN32_WCE */ -#else /* CONFIG_NATIVE_WINDOWS */ - fptr = dlsym(handle, func); -#endif /* CONFIG_NATIVE_WINDOWS */ - - return fptr; -} - - -static int tncc_imc_resolve_funcs(struct tnc_if_imc *imc) -{ - void *handle = imc->dlhandle; - - /* Mandatory IMC functions */ - imc->Initialize = tncc_get_sym(handle, "TNC_IMC_Initialize"); - if (imc->Initialize == NULL) { - wpa_printf(MSG_ERROR, "TNC: IMC does not export " - "TNC_IMC_Initialize"); - return -1; - } - - imc->BeginHandshake = tncc_get_sym(handle, "TNC_IMC_BeginHandshake"); - if (imc->BeginHandshake == NULL) { - wpa_printf(MSG_ERROR, "TNC: IMC does not export " - "TNC_IMC_BeginHandshake"); - return -1; - } - - imc->ProvideBindFunction = - tncc_get_sym(handle, "TNC_IMC_ProvideBindFunction"); - if (imc->ProvideBindFunction == NULL) { - wpa_printf(MSG_ERROR, "TNC: IMC does not export " - "TNC_IMC_ProvideBindFunction"); - return -1; - } - - /* Optional IMC functions */ - imc->NotifyConnectionChange = - tncc_get_sym(handle, "TNC_IMC_NotifyConnectionChange"); - imc->ReceiveMessage = tncc_get_sym(handle, "TNC_IMC_ReceiveMessage"); - imc->BatchEnding = tncc_get_sym(handle, "TNC_IMC_BatchEnding"); - imc->Terminate = tncc_get_sym(handle, "TNC_IMC_Terminate"); - - return 0; -} - - -static int tncc_imc_initialize(struct tnc_if_imc *imc) -{ - TNC_Result res; - TNC_Version imc_ver; - - wpa_printf(MSG_DEBUG, "TNC: Calling TNC_IMC_Initialize for IMC '%s'", - imc->name); - res = imc->Initialize(imc->imcID, TNC_IFIMC_VERSION_1, - TNC_IFIMC_VERSION_1, &imc_ver); - wpa_printf(MSG_DEBUG, "TNC: TNC_IMC_Initialize: res=%lu imc_ver=%lu", - (unsigned long) res, (unsigned long) imc_ver); - - return res == TNC_RESULT_SUCCESS ? 0 : -1; -} - - -static int tncc_imc_terminate(struct tnc_if_imc *imc) -{ - TNC_Result res; - - if (imc->Terminate == NULL) - return 0; - - wpa_printf(MSG_DEBUG, "TNC: Calling TNC_IMC_Terminate for IMC '%s'", - imc->name); - res = imc->Terminate(imc->imcID); - wpa_printf(MSG_DEBUG, "TNC: TNC_IMC_Terminate: %lu", - (unsigned long) res); - - return res == TNC_RESULT_SUCCESS ? 0 : -1; -} - - -static int tncc_imc_provide_bind_function(struct tnc_if_imc *imc) -{ - TNC_Result res; - - wpa_printf(MSG_DEBUG, "TNC: Calling TNC_IMC_ProvideBindFunction for " - "IMC '%s'", imc->name); - res = imc->ProvideBindFunction(imc->imcID, TNC_TNCC_BindFunction); - wpa_printf(MSG_DEBUG, "TNC: TNC_IMC_ProvideBindFunction: res=%lu", - (unsigned long) res); - - return res == TNC_RESULT_SUCCESS ? 0 : -1; -} - - -static int tncc_imc_notify_connection_change(struct tnc_if_imc *imc, - TNC_ConnectionState state) -{ - TNC_Result res; - - if (imc->NotifyConnectionChange == NULL) - return 0; - - wpa_printf(MSG_DEBUG, "TNC: Calling TNC_IMC_NotifyConnectionChange(%d)" - " for IMC '%s'", (int) state, imc->name); - res = imc->NotifyConnectionChange(imc->imcID, imc->connectionID, - state); - wpa_printf(MSG_DEBUG, "TNC: TNC_IMC_NotifyConnectionChange: %lu", - (unsigned long) res); - - return res == TNC_RESULT_SUCCESS ? 0 : -1; -} - - -static int tncc_imc_begin_handshake(struct tnc_if_imc *imc) -{ - TNC_Result res; - - wpa_printf(MSG_DEBUG, "TNC: Calling TNC_IMC_BeginHandshake for IMC " - "'%s'", imc->name); - res = imc->BeginHandshake(imc->imcID, imc->connectionID); - wpa_printf(MSG_DEBUG, "TNC: TNC_IMC_BeginHandshake: %lu", - (unsigned long) res); - - return res == TNC_RESULT_SUCCESS ? 0 : -1; -} - - -static int tncc_load_imc(struct tnc_if_imc *imc) -{ - if (imc->path == NULL) { - wpa_printf(MSG_DEBUG, "TNC: No IMC configured"); - return -1; - } - - wpa_printf(MSG_DEBUG, "TNC: Opening IMC: %s (%s)", - imc->name, imc->path); -#ifdef CONFIG_NATIVE_WINDOWS -#ifdef UNICODE - { - TCHAR *lib = wpa_strdup_tchar(imc->path); - if (lib == NULL) - return -1; - imc->dlhandle = LoadLibrary(lib); - os_free(lib); - } -#else /* UNICODE */ - imc->dlhandle = LoadLibrary(imc->path); -#endif /* UNICODE */ - if (imc->dlhandle == NULL) { - wpa_printf(MSG_ERROR, "TNC: Failed to open IMC '%s' (%s): %d", - imc->name, imc->path, (int) GetLastError()); - return -1; - } -#else /* CONFIG_NATIVE_WINDOWS */ - imc->dlhandle = dlopen(imc->path, RTLD_LAZY); - if (imc->dlhandle == NULL) { - wpa_printf(MSG_ERROR, "TNC: Failed to open IMC '%s' (%s): %s", - imc->name, imc->path, dlerror()); - return -1; - } -#endif /* CONFIG_NATIVE_WINDOWS */ - - if (tncc_imc_resolve_funcs(imc) < 0) { - wpa_printf(MSG_ERROR, "TNC: Failed to resolve IMC functions"); - return -1; - } - - if (tncc_imc_initialize(imc) < 0 || - tncc_imc_provide_bind_function(imc) < 0) { - wpa_printf(MSG_ERROR, "TNC: Failed to initialize IMC"); - return -1; - } - - return 0; -} - - -static void tncc_unload_imc(struct tnc_if_imc *imc) -{ - tncc_imc_terminate(imc); - tnc_imc[imc->imcID] = NULL; - - if (imc->dlhandle) { -#ifdef CONFIG_NATIVE_WINDOWS - FreeLibrary(imc->dlhandle); -#else /* CONFIG_NATIVE_WINDOWS */ - dlclose(imc->dlhandle); -#endif /* CONFIG_NATIVE_WINDOWS */ - } - os_free(imc->name); - os_free(imc->path); - os_free(imc->supported_types); - os_free(imc->imc_send); -} - - -static int tncc_supported_type(struct tnc_if_imc *imc, unsigned int type) -{ - size_t i; - unsigned int vendor, subtype; - - if (imc == NULL || imc->supported_types == NULL) - return 0; - - vendor = type >> 8; - subtype = type & 0xff; - - for (i = 0; i < imc->num_supported_types; i++) { - unsigned int svendor, ssubtype; - svendor = imc->supported_types[i] >> 8; - ssubtype = imc->supported_types[i] & 0xff; - if ((vendor == svendor || svendor == TNC_VENDORID_ANY) && - (subtype == ssubtype || ssubtype == TNC_SUBTYPE_ANY)) - return 1; - } - - return 0; -} - - -static void tncc_send_to_imcs(struct tncc_data *tncc, unsigned int type, - const u8 *msg, size_t len) -{ - struct tnc_if_imc *imc; - TNC_Result res; - - wpa_hexdump_ascii(MSG_MSGDUMP, "TNC: Message to IMC(s)", msg, len); - - for (imc = tncc->imc; imc; imc = imc->next) { - if (imc->ReceiveMessage == NULL || - !tncc_supported_type(imc, type)) - continue; - - wpa_printf(MSG_DEBUG, "TNC: Call ReceiveMessage for IMC '%s'", - imc->name); - res = imc->ReceiveMessage(imc->imcID, imc->connectionID, - (TNC_BufferReference) msg, len, - type); - wpa_printf(MSG_DEBUG, "TNC: ReceiveMessage: %lu", - (unsigned long) res); - } -} - - -void tncc_init_connection(struct tncc_data *tncc) -{ - struct tnc_if_imc *imc; - - for (imc = tncc->imc; imc; imc = imc->next) { - tncc_imc_notify_connection_change( - imc, TNC_CONNECTION_STATE_CREATE); - tncc_imc_notify_connection_change( - imc, TNC_CONNECTION_STATE_HANDSHAKE); - - os_free(imc->imc_send); - imc->imc_send = NULL; - imc->imc_send_len = 0; - - tncc_imc_begin_handshake(imc); - } -} - - -size_t tncc_total_send_len(struct tncc_data *tncc) -{ - struct tnc_if_imc *imc; - - size_t len = 0; - for (imc = tncc->imc; imc; imc = imc->next) - len += imc->imc_send_len; - return len; -} - - -u8 * tncc_copy_send_buf(struct tncc_data *tncc, u8 *pos) -{ - struct tnc_if_imc *imc; - - for (imc = tncc->imc; imc; imc = imc->next) { - if (imc->imc_send == NULL) - continue; - - os_memcpy(pos, imc->imc_send, imc->imc_send_len); - pos += imc->imc_send_len; - os_free(imc->imc_send); - imc->imc_send = NULL; - imc->imc_send_len = 0; - } - - return pos; -} - - -char * tncc_if_tnccs_start(struct tncc_data *tncc) -{ - char *buf = os_malloc(1000); - if (buf == NULL) - return NULL; - tncc->last_batchid++; - os_snprintf(buf, 1000, IF_TNCCS_START, tncc->last_batchid); - return buf; -} - - -char * tncc_if_tnccs_end(void) -{ - char *buf = os_malloc(100); - if (buf == NULL) - return NULL; - os_snprintf(buf, 100, IF_TNCCS_END); - return buf; -} - - -static void tncc_notify_recommendation(struct tncc_data *tncc, - enum tncc_process_res res) -{ - TNC_ConnectionState state; - struct tnc_if_imc *imc; - - switch (res) { - case TNCCS_RECOMMENDATION_ALLOW: - state = TNC_CONNECTION_STATE_ACCESS_ALLOWED; - break; - case TNCCS_RECOMMENDATION_NONE: - state = TNC_CONNECTION_STATE_ACCESS_NONE; - break; - case TNCCS_RECOMMENDATION_ISOLATE: - state = TNC_CONNECTION_STATE_ACCESS_ISOLATED; - break; - default: - state = TNC_CONNECTION_STATE_ACCESS_NONE; - break; - } - - for (imc = tncc->imc; imc; imc = imc->next) - tncc_imc_notify_connection_change(imc, state); -} - - -static int tncc_get_type(char *start, unsigned int *type) -{ - char *pos = os_strstr(start, ""); - if (pos == NULL) - return -1; - pos += 6; - *type = strtoul(pos, NULL, 16); - return 0; -} - - -static unsigned char * tncc_get_base64(char *start, size_t *decoded_len) -{ - char *pos, *pos2; - unsigned char *decoded; - - pos = os_strstr(start, ""); - if (pos == NULL) - return NULL; - - pos += 8; - pos2 = os_strstr(pos, ""); - if (pos2 == NULL) - return NULL; - *pos2 = '\0'; - - decoded = base64_decode((unsigned char *) pos, os_strlen(pos), - decoded_len); - *pos2 = '<'; - if (decoded == NULL) { - wpa_printf(MSG_DEBUG, "TNC: Failed to decode Base64 data"); - } - - return decoded; -} - - -static enum tncc_process_res tncc_get_recommendation(char *start) -{ - char *pos, *pos2, saved; - int recom; - - pos = os_strstr(start, ""); - if (start == NULL || end == NULL || start > end) { - os_free(buf); - return TNCCS_PROCESS_ERROR; - } - - start += 13; - while (*start == ' ') - start++; - *end = '\0'; - - pos = os_strstr(start, "BatchId="); - if (pos == NULL) { - os_free(buf); - return TNCCS_PROCESS_ERROR; - } - - pos += 8; - if (*pos == '"') - pos++; - batch_id = atoi(pos); - wpa_printf(MSG_DEBUG, "TNC: Received IF-TNCCS BatchId=%u", - batch_id); - if (batch_id != tncc->last_batchid + 1) { - wpa_printf(MSG_DEBUG, "TNC: Unexpected IF-TNCCS BatchId " - "%u (expected %u)", - batch_id, tncc->last_batchid + 1); - os_free(buf); - return TNCCS_PROCESS_ERROR; - } - tncc->last_batchid = batch_id; - - while (*pos != '\0' && *pos != '>') - pos++; - if (*pos == '\0') { - os_free(buf); - return TNCCS_PROCESS_ERROR; - } - pos++; - payload = start; - - /* - * - * 01234567 - * foo== - * - */ - - while (*start) { - char *endpos; - unsigned int type; - - pos = os_strstr(start, ""); - if (pos == NULL) - break; - start = pos + 17; - end = os_strstr(start, ""); - if (end == NULL) - break; - *end = '\0'; - endpos = end; - end += 18; - - if (tncc_get_type(start, &type) < 0) { - *endpos = '<'; - start = end; - continue; - } - wpa_printf(MSG_DEBUG, "TNC: IMC-IMV-Message Type 0x%x", type); - - decoded = tncc_get_base64(start, &decoded_len); - if (decoded == NULL) { - *endpos = '<'; - start = end; - continue; - } - - tncc_send_to_imcs(tncc, type, decoded, decoded_len); - - os_free(decoded); - - start = end; - } - - /* - * - * 01234567 - * - * foo== - * - */ - - start = payload; - while (*start) { - unsigned int type; - char *xml, *xmlend, *endpos; - - pos = os_strstr(start, ""); - if (pos == NULL) - break; - start = pos + 19; - end = os_strstr(start, ""); - if (end == NULL) - break; - *end = '\0'; - endpos = end; - end += 20; - - if (tncc_get_type(start, &type) < 0) { - *endpos = '<'; - start = end; - continue; - } - wpa_printf(MSG_DEBUG, "TNC: TNCC-TNCS-Message Type 0x%x", - type); - - /* Base64 OR XML */ - decoded = NULL; - xml = NULL; - xmlend = NULL; - pos = os_strstr(start, ""); - if (pos) { - pos += 5; - pos2 = os_strstr(pos, ""); - if (pos2 == NULL) { - *endpos = '<'; - start = end; - continue; - } - xmlend = pos2; - xml = pos; - } else { - decoded = tncc_get_base64(start, &decoded_len); - if (decoded == NULL) { - *endpos = '<'; - start = end; - continue; - } - } - - if (decoded) { - wpa_hexdump_ascii(MSG_MSGDUMP, - "TNC: TNCC-TNCS-Message Base64", - decoded, decoded_len); - os_free(decoded); - } - - if (xml) { - wpa_hexdump_ascii(MSG_MSGDUMP, - "TNC: TNCC-TNCS-Message XML", - (unsigned char *) xml, - xmlend - xml); - } - - if (type == TNC_TNCCS_RECOMMENDATION && xml) { - /* - * - * - */ - *xmlend = '\0'; - res = tncc_get_recommendation(xml); - *xmlend = '<'; - recommendation_msg = 1; - } - - start = end; - } - - os_free(buf); - - if (recommendation_msg) - tncc_notify_recommendation(tncc, res); - - return res; -} - - -#ifdef CONFIG_NATIVE_WINDOWS -static int tncc_read_config_reg(struct tncc_data *tncc, HKEY hive) -{ - HKEY hk, hk2; - LONG ret; - DWORD i; - struct tnc_if_imc *imc, *last; - int j; - - last = tncc->imc; - while (last && last->next) - last = last->next; - - ret = RegOpenKeyEx(hive, TNC_WINREG_PATH, 0, KEY_ENUMERATE_SUB_KEYS, - &hk); - if (ret != ERROR_SUCCESS) - return 0; - - for (i = 0; ; i++) { - TCHAR name[255], *val; - DWORD namelen, buflen; - - namelen = 255; - ret = RegEnumKeyEx(hk, i, name, &namelen, NULL, NULL, NULL, - NULL); - - if (ret == ERROR_NO_MORE_ITEMS) - break; - - if (ret != ERROR_SUCCESS) { - wpa_printf(MSG_DEBUG, "TNC: RegEnumKeyEx failed: 0x%x", - (unsigned int) ret); - break; - } - - if (namelen >= 255) - namelen = 255 - 1; - name[namelen] = '\0'; - - wpa_printf(MSG_DEBUG, "TNC: IMC '" TSTR "'", name); - - ret = RegOpenKeyEx(hk, name, 0, KEY_QUERY_VALUE, &hk2); - if (ret != ERROR_SUCCESS) { - wpa_printf(MSG_DEBUG, "Could not open IMC key '" TSTR - "'", name); - continue; - } - - ret = RegQueryValueEx(hk2, TEXT("Path"), NULL, NULL, NULL, - &buflen); - if (ret != ERROR_SUCCESS) { - wpa_printf(MSG_DEBUG, "TNC: Could not read Path from " - "IMC key '" TSTR "'", name); - RegCloseKey(hk2); - continue; - } - - val = os_malloc(buflen); - if (val == NULL) { - RegCloseKey(hk2); - continue; - } - - ret = RegQueryValueEx(hk2, TEXT("Path"), NULL, NULL, - (LPBYTE) val, &buflen); - if (ret != ERROR_SUCCESS) { - os_free(val); - RegCloseKey(hk2); - continue; - } - - RegCloseKey(hk2); - - wpa_unicode2ascii_inplace(val); - wpa_printf(MSG_DEBUG, "TNC: IMC Path '%s'", (char *) val); - - for (j = 0; j < TNC_MAX_IMC_ID; j++) { - if (tnc_imc[j] == NULL) - break; - } - if (j >= TNC_MAX_IMC_ID) { - wpa_printf(MSG_DEBUG, "TNC: Too many IMCs"); - os_free(val); - continue; - } - - imc = os_zalloc(sizeof(*imc)); - if (imc == NULL) { - os_free(val); - break; - } - - imc->imcID = j; - - wpa_unicode2ascii_inplace(name); - imc->name = os_strdup((char *) name); - imc->path = os_strdup((char *) val); - - os_free(val); - - if (last == NULL) - tncc->imc = imc; - else - last->next = imc; - last = imc; - - tnc_imc[imc->imcID] = imc; - } - - RegCloseKey(hk); - - return 0; -} - - -static int tncc_read_config(struct tncc_data *tncc) -{ - if (tncc_read_config_reg(tncc, HKEY_LOCAL_MACHINE) < 0 || - tncc_read_config_reg(tncc, HKEY_CURRENT_USER) < 0) - return -1; - return 0; -} - -#else /* CONFIG_NATIVE_WINDOWS */ - -static struct tnc_if_imc * tncc_parse_imc(char *start, char *end, int *error) -{ - struct tnc_if_imc *imc; - char *pos, *pos2; - int i; - - for (i = 0; i < TNC_MAX_IMC_ID; i++) { - if (tnc_imc[i] == NULL) - break; - } - if (i >= TNC_MAX_IMC_ID) { - wpa_printf(MSG_DEBUG, "TNC: Too many IMCs"); - return NULL; - } - - imc = os_zalloc(sizeof(*imc)); - if (imc == NULL) { - *error = 1; - return NULL; - } - - imc->imcID = i; - - pos = start; - wpa_printf(MSG_DEBUG, "TNC: Configured IMC: %s", pos); - if (pos + 1 >= end || *pos != '"') { - wpa_printf(MSG_ERROR, "TNC: Ignoring invalid IMC line '%s' " - "(no starting quotation mark)", start); - os_free(imc); - return NULL; - } - - pos++; - pos2 = pos; - while (pos2 < end && *pos2 != '"') - pos2++; - if (pos2 >= end) { - wpa_printf(MSG_ERROR, "TNC: Ignoring invalid IMC line '%s' " - "(no ending quotation mark)", start); - os_free(imc); - return NULL; - } - *pos2 = '\0'; - wpa_printf(MSG_DEBUG, "TNC: Name: '%s'", pos); - imc->name = os_strdup(pos); - - pos = pos2 + 1; - if (pos >= end || *pos != ' ') { - wpa_printf(MSG_ERROR, "TNC: Ignoring invalid IMC line '%s' " - "(no space after name)", start); - os_free(imc->name); - os_free(imc); - return NULL; - } - - pos++; - wpa_printf(MSG_DEBUG, "TNC: IMC file: '%s'", pos); - imc->path = os_strdup(pos); - tnc_imc[imc->imcID] = imc; - - return imc; -} - - -static int tncc_read_config(struct tncc_data *tncc) -{ - char *config, *end, *pos, *line_end; - size_t config_len; - struct tnc_if_imc *imc, *last; - - last = NULL; - - config = os_readfile(TNC_CONFIG_FILE, &config_len); - if (config == NULL) { - wpa_printf(MSG_ERROR, "TNC: Could not open TNC configuration " - "file '%s'", TNC_CONFIG_FILE); - return -1; - } - - end = config + config_len; - for (pos = config; pos < end; pos = line_end + 1) { - line_end = pos; - while (*line_end != '\n' && *line_end != '\r' && - line_end < end) - line_end++; - *line_end = '\0'; - - if (os_strncmp(pos, "IMC ", 4) == 0) { - int error = 0; - - imc = tncc_parse_imc(pos + 4, line_end, &error); - if (error) - return -1; - if (imc) { - if (last == NULL) - tncc->imc = imc; - else - last->next = imc; - last = imc; - } - } - } - - os_free(config); - - return 0; -} - -#endif /* CONFIG_NATIVE_WINDOWS */ - - -struct tncc_data * tncc_init(void) -{ - struct tncc_data *tncc; - struct tnc_if_imc *imc; - - tncc = os_zalloc(sizeof(*tncc)); - if (tncc == NULL) - return NULL; - - /* TODO: - * move loading and Initialize() to a location that is not - * re-initialized for every EAP-TNC session (?) - */ - - if (tncc_read_config(tncc) < 0) { - wpa_printf(MSG_ERROR, "TNC: Failed to read TNC configuration"); - goto failed; - } - - for (imc = tncc->imc; imc; imc = imc->next) { - if (tncc_load_imc(imc)) { - wpa_printf(MSG_ERROR, "TNC: Failed to load IMC '%s'", - imc->name); - goto failed; - } - } - - return tncc; - -failed: - tncc_deinit(tncc); - return NULL; -} - - -void tncc_deinit(struct tncc_data *tncc) -{ - struct tnc_if_imc *imc, *prev; - - imc = tncc->imc; - while (imc) { - tncc_unload_imc(imc); - - prev = imc; - imc = imc->next; - os_free(prev); - } - - os_free(tncc); -} - - -static struct wpabuf * tncc_build_soh(int ver) -{ - struct wpabuf *buf; - u8 *tlv_len, *tlv_len2, *outer_len, *inner_len, *ssoh_len, *end; - u8 correlation_id[24]; - /* TODO: get correct name */ - char *machinename = "wpa_supplicant@w1.fi"; - - if (os_get_random(correlation_id, sizeof(correlation_id))) - return NULL; - wpa_hexdump(MSG_DEBUG, "TNC: SoH Correlation ID", - correlation_id, sizeof(correlation_id)); - - buf = wpabuf_alloc(200); - if (buf == NULL) - return NULL; - - /* Vendor-Specific TLV (Microsoft) - SoH */ - wpabuf_put_be16(buf, EAP_TLV_VENDOR_SPECIFIC_TLV); /* TLV Type */ - tlv_len = wpabuf_put(buf, 2); /* Length */ - wpabuf_put_be32(buf, EAP_VENDOR_MICROSOFT); /* Vendor_Id */ - wpabuf_put_be16(buf, 0x01); /* TLV Type - SoH TLV */ - tlv_len2 = wpabuf_put(buf, 2); /* Length */ - - /* SoH Header */ - wpabuf_put_be16(buf, EAP_TLV_VENDOR_SPECIFIC_TLV); /* Outer Type */ - outer_len = wpabuf_put(buf, 2); - wpabuf_put_be32(buf, EAP_VENDOR_MICROSOFT); /* IANA SMI Code */ - wpabuf_put_be16(buf, ver); /* Inner Type */ - inner_len = wpabuf_put(buf, 2); - - if (ver == 2) { - /* SoH Mode Sub-Header */ - /* Outer Type */ - wpabuf_put_be16(buf, EAP_TLV_VENDOR_SPECIFIC_TLV); - wpabuf_put_be16(buf, 4 + 24 + 1 + 1); /* Length */ - wpabuf_put_be32(buf, EAP_VENDOR_MICROSOFT); /* IANA SMI Code */ - /* Value: */ - wpabuf_put_data(buf, correlation_id, sizeof(correlation_id)); - wpabuf_put_u8(buf, 0x01); /* Intent Flag - Request */ - wpabuf_put_u8(buf, 0x00); /* Content-Type Flag */ - } - - /* SSoH TLV */ - /* System-Health-Id */ - wpabuf_put_be16(buf, 0x0002); /* Type */ - wpabuf_put_be16(buf, 4); /* Length */ - wpabuf_put_be32(buf, 79616); - /* Vendor-Specific Attribute */ - wpabuf_put_be16(buf, EAP_TLV_VENDOR_SPECIFIC_TLV); - ssoh_len = wpabuf_put(buf, 2); - wpabuf_put_be32(buf, EAP_VENDOR_MICROSOFT); /* IANA SMI Code */ - - /* MS-Packet-Info */ - wpabuf_put_u8(buf, SSOH_MS_PACKET_INFO); - /* Note: IF-TNCCS-SOH v1.0 r8 claims this field to be: - * Reserved(4 bits) r(1 bit) Vers(3 bits), but Windows XP - * SP3 seems to be sending 0x11 for SSoH, i.e., r(request/response) bit - * would not be in the specified location. - * [MS-SOH] 4.0.2: Reserved(3 bits) r(1 bit) Vers(4 bits) - */ - wpabuf_put_u8(buf, 0x11); /* r=request, vers=1 */ - - /* MS-Machine-Inventory */ - /* TODO: get correct values; 0 = not applicable for OS */ - wpabuf_put_u8(buf, SSOH_MS_MACHINE_INVENTORY); - wpabuf_put_be32(buf, 0); /* osVersionMajor */ - wpabuf_put_be32(buf, 0); /* osVersionMinor */ - wpabuf_put_be32(buf, 0); /* osVersionBuild */ - wpabuf_put_be16(buf, 0); /* spVersionMajor */ - wpabuf_put_be16(buf, 0); /* spVersionMinor */ - wpabuf_put_be16(buf, 0); /* procArch */ - - /* MS-MachineName */ - wpabuf_put_u8(buf, SSOH_MS_MACHINENAME); - wpabuf_put_be16(buf, os_strlen(machinename) + 1); - wpabuf_put_data(buf, machinename, os_strlen(machinename) + 1); - - /* MS-CorrelationId */ - wpabuf_put_u8(buf, SSOH_MS_CORRELATIONID); - wpabuf_put_data(buf, correlation_id, sizeof(correlation_id)); - - /* MS-Quarantine-State */ - wpabuf_put_u8(buf, SSOH_MS_QUARANTINE_STATE); - wpabuf_put_be16(buf, 1); /* Flags: ExtState=0, f=0, qState=1 */ - wpabuf_put_be32(buf, 0xffffffff); /* ProbTime (hi) */ - wpabuf_put_be32(buf, 0xffffffff); /* ProbTime (lo) */ - wpabuf_put_be16(buf, 1); /* urlLenInBytes */ - wpabuf_put_u8(buf, 0); /* null termination for the url */ - - /* MS-Machine-Inventory-Ex */ - wpabuf_put_u8(buf, SSOH_MS_MACHINE_INVENTORY_EX); - wpabuf_put_be32(buf, 0); /* Reserved - * (note: Windows XP SP3 uses 0xdecafbad) */ - wpabuf_put_u8(buf, 1); /* ProductType: Client */ - - /* Update SSoH Length */ - end = wpabuf_put(buf, 0); - WPA_PUT_BE16(ssoh_len, end - ssoh_len - 2); - - /* TODO: SoHReportEntry TLV (zero or more) */ - - /* Update length fields */ - end = wpabuf_put(buf, 0); - WPA_PUT_BE16(tlv_len, end - tlv_len - 2); - WPA_PUT_BE16(tlv_len2, end - tlv_len2 - 2); - WPA_PUT_BE16(outer_len, end - outer_len - 2); - WPA_PUT_BE16(inner_len, end - inner_len - 2); - - return buf; -} - - -struct wpabuf * tncc_process_soh_request(int ver, const u8 *data, size_t len) -{ - const u8 *pos; - - wpa_hexdump(MSG_DEBUG, "TNC: SoH Request", data, len); - - if (len < 12) - return NULL; - - /* SoH Request */ - pos = data; - - /* TLV Type */ - if (WPA_GET_BE16(pos) != EAP_TLV_VENDOR_SPECIFIC_TLV) - return NULL; - pos += 2; - - /* Length */ - if (WPA_GET_BE16(pos) < 8) - return NULL; - pos += 2; - - /* Vendor_Id */ - if (WPA_GET_BE32(pos) != EAP_VENDOR_MICROSOFT) - return NULL; - pos += 4; - - /* TLV Type */ - if (WPA_GET_BE16(pos) != 0x02 /* SoH request TLV */) - return NULL; - - wpa_printf(MSG_DEBUG, "TNC: SoH Request TLV received"); - - return tncc_build_soh(2); -} diff --git a/hostapd-0.8/src/eap_peer/tncc.h b/hostapd-0.8/src/eap_peer/tncc.h deleted file mode 100644 index 4d42a05..0000000 --- a/hostapd-0.8/src/eap_peer/tncc.h +++ /dev/null @@ -1,42 +0,0 @@ -/* - * EAP-TNC - TNCC (IF-IMC and IF-TNCCS) - * Copyright (c) 2007, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#ifndef TNCC_H -#define TNCC_H - -struct tncc_data; - -struct tncc_data * tncc_init(void); -void tncc_deinit(struct tncc_data *tncc); -void tncc_init_connection(struct tncc_data *tncc); -size_t tncc_total_send_len(struct tncc_data *tncc); -u8 * tncc_copy_send_buf(struct tncc_data *tncc, u8 *pos); -char * tncc_if_tnccs_start(struct tncc_data *tncc); -char * tncc_if_tnccs_end(void); - -enum tncc_process_res { - TNCCS_PROCESS_ERROR = -1, - TNCCS_PROCESS_OK_NO_RECOMMENDATION = 0, - TNCCS_RECOMMENDATION_ERROR, - TNCCS_RECOMMENDATION_ALLOW, - TNCCS_RECOMMENDATION_NONE, - TNCCS_RECOMMENDATION_ISOLATE -}; - -enum tncc_process_res tncc_process_if_tnccs(struct tncc_data *tncc, - const u8 *msg, size_t len); - -struct wpabuf * tncc_process_soh_request(int ver, const u8 *data, size_t len); - -#endif /* TNCC_H */ diff --git a/hostapd-0.8/src/eap_server/Makefile b/hostapd-0.8/src/eap_server/Makefile deleted file mode 100644 index 9c41962..0000000 --- a/hostapd-0.8/src/eap_server/Makefile +++ /dev/null @@ -1,8 +0,0 @@ -all: - @echo Nothing to be made. - -clean: - rm -f *~ *.o *.d - -install: - @echo Nothing to be made. diff --git a/hostapd-0.8/src/eap_server/eap.h b/hostapd-0.8/src/eap_server/eap.h deleted file mode 100644 index 6b29075..0000000 --- a/hostapd-0.8/src/eap_server/eap.h +++ /dev/null @@ -1,128 +0,0 @@ -/* - * hostapd / EAP Full Authenticator state machine (RFC 4137) - * Copyright (c) 2004-2007, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#ifndef EAP_H -#define EAP_H - -#include "common/defs.h" -#include "eap_common/eap_defs.h" -#include "eap_server/eap_methods.h" -#include "wpabuf.h" - -struct eap_sm; - -#define EAP_MAX_METHODS 8 - -#define EAP_TTLS_AUTH_PAP 1 -#define EAP_TTLS_AUTH_CHAP 2 -#define EAP_TTLS_AUTH_MSCHAP 4 -#define EAP_TTLS_AUTH_MSCHAPV2 8 - -struct eap_user { - struct { - int vendor; - u32 method; - } methods[EAP_MAX_METHODS]; - u8 *password; - size_t password_len; - int password_hash; /* whether password is hashed with - * nt_password_hash() */ - int phase2; - int force_version; - int ttls_auth; /* bitfield of - * EAP_TTLS_AUTH_{PAP,CHAP,MSCHAP,MSCHAPV2} */ -}; - -struct eap_eapol_interface { - /* Lower layer to full authenticator variables */ - Boolean eapResp; /* shared with EAPOL Backend Authentication */ - struct wpabuf *eapRespData; - Boolean portEnabled; - int retransWhile; - Boolean eapRestart; /* shared with EAPOL Authenticator PAE */ - int eapSRTT; - int eapRTTVAR; - - /* Full authenticator to lower layer variables */ - Boolean eapReq; /* shared with EAPOL Backend Authentication */ - Boolean eapNoReq; /* shared with EAPOL Backend Authentication */ - Boolean eapSuccess; - Boolean eapFail; - Boolean eapTimeout; - struct wpabuf *eapReqData; - u8 *eapKeyData; - size_t eapKeyDataLen; - Boolean eapKeyAvailable; /* called keyAvailable in IEEE 802.1X-2004 */ - - /* AAA interface to full authenticator variables */ - Boolean aaaEapReq; - Boolean aaaEapNoReq; - Boolean aaaSuccess; - Boolean aaaFail; - struct wpabuf *aaaEapReqData; - u8 *aaaEapKeyData; - size_t aaaEapKeyDataLen; - Boolean aaaEapKeyAvailable; - int aaaMethodTimeout; - - /* Full authenticator to AAA interface variables */ - Boolean aaaEapResp; - struct wpabuf *aaaEapRespData; - /* aaaIdentity -> eap_get_identity() */ - Boolean aaaTimeout; -}; - -struct eapol_callbacks { - int (*get_eap_user)(void *ctx, const u8 *identity, size_t identity_len, - int phase2, struct eap_user *user); - const char * (*get_eap_req_id_text)(void *ctx, size_t *len); -}; - -struct eap_config { - void *ssl_ctx; - void *msg_ctx; - void *eap_sim_db_priv; - Boolean backend_auth; - int eap_server; - u16 pwd_group; - u8 *pac_opaque_encr_key; - u8 *eap_fast_a_id; - size_t eap_fast_a_id_len; - char *eap_fast_a_id_info; - int eap_fast_prov; - int pac_key_lifetime; - int pac_key_refresh_time; - int eap_sim_aka_result_ind; - int tnc; - struct wps_context *wps; - const struct wpabuf *assoc_wps_ie; - const struct wpabuf *assoc_p2p_ie; - const u8 *peer_addr; - int fragment_size; -}; - - -struct eap_sm * eap_server_sm_init(void *eapol_ctx, - struct eapol_callbacks *eapol_cb, - struct eap_config *eap_conf); -void eap_server_sm_deinit(struct eap_sm *sm); -int eap_server_sm_step(struct eap_sm *sm); -void eap_sm_notify_cached(struct eap_sm *sm); -void eap_sm_pending_cb(struct eap_sm *sm); -int eap_sm_method_pending(struct eap_sm *sm); -const u8 * eap_get_identity(struct eap_sm *sm, size_t *len); -struct eap_eapol_interface * eap_get_interface(struct eap_sm *sm); -void eap_server_clear_identity(struct eap_sm *sm); - -#endif /* EAP_H */ diff --git a/hostapd-0.8/src/eap_server/eap_i.h b/hostapd-0.8/src/eap_server/eap_i.h deleted file mode 100644 index daac746..0000000 --- a/hostapd-0.8/src/eap_server/eap_i.h +++ /dev/null @@ -1,201 +0,0 @@ -/* - * hostapd / EAP Authenticator state machine internal structures (RFC 4137) - * Copyright (c) 2004-2007, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#ifndef EAP_I_H -#define EAP_I_H - -#include "wpabuf.h" -#include "eap_server/eap.h" -#include "eap_common/eap_common.h" - -/* RFC 4137 - EAP Standalone Authenticator */ - -/** - * struct eap_method - EAP method interface - * This structure defines the EAP method interface. Each method will need to - * register its own EAP type, EAP name, and set of function pointers for method - * specific operations. This interface is based on section 5.4 of RFC 4137. - */ -struct eap_method { - int vendor; - EapType method; - const char *name; - - void * (*init)(struct eap_sm *sm); - void * (*initPickUp)(struct eap_sm *sm); - void (*reset)(struct eap_sm *sm, void *priv); - - struct wpabuf * (*buildReq)(struct eap_sm *sm, void *priv, u8 id); - int (*getTimeout)(struct eap_sm *sm, void *priv); - Boolean (*check)(struct eap_sm *sm, void *priv, - struct wpabuf *respData); - void (*process)(struct eap_sm *sm, void *priv, - struct wpabuf *respData); - Boolean (*isDone)(struct eap_sm *sm, void *priv); - u8 * (*getKey)(struct eap_sm *sm, void *priv, size_t *len); - /* isSuccess is not specified in draft-ietf-eap-statemachine-05.txt, - * but it is useful in implementing Policy.getDecision() */ - Boolean (*isSuccess)(struct eap_sm *sm, void *priv); - - /** - * free - Free EAP method data - * @method: Pointer to the method data registered with - * eap_server_method_register(). - * - * This function will be called when the EAP method is being - * unregistered. If the EAP method allocated resources during - * registration (e.g., allocated struct eap_method), they should be - * freed in this function. No other method functions will be called - * after this call. If this function is not defined (i.e., function - * pointer is %NULL), a default handler is used to release the method - * data with free(method). This is suitable for most cases. - */ - void (*free)(struct eap_method *method); - -#define EAP_SERVER_METHOD_INTERFACE_VERSION 1 - /** - * version - Version of the EAP server method interface - * - * The EAP server method implementation should set this variable to - * EAP_SERVER_METHOD_INTERFACE_VERSION. This is used to verify that the - * EAP method is using supported API version when using dynamically - * loadable EAP methods. - */ - int version; - - /** - * next - Pointer to the next EAP method - * - * This variable is used internally in the EAP method registration code - * to create a linked list of registered EAP methods. - */ - struct eap_method *next; - - /** - * get_emsk - Get EAP method specific keying extended material (EMSK) - * @sm: Pointer to EAP state machine allocated with eap_sm_init() - * @priv: Pointer to private EAP method data from eap_method::init() - * @len: Pointer to a variable to store EMSK length - * Returns: EMSK or %NULL if not available - * - * This function can be used to get the extended keying material from - * the EAP method. The key may already be stored in the method-specific - * private data or this function may derive the key. - */ - u8 * (*get_emsk)(struct eap_sm *sm, void *priv, size_t *len); -}; - -/** - * struct eap_sm - EAP server state machine data - */ -struct eap_sm { - enum { - EAP_DISABLED, EAP_INITIALIZE, EAP_IDLE, EAP_RECEIVED, - EAP_INTEGRITY_CHECK, EAP_METHOD_RESPONSE, EAP_METHOD_REQUEST, - EAP_PROPOSE_METHOD, EAP_SELECT_ACTION, EAP_SEND_REQUEST, - EAP_DISCARD, EAP_NAK, EAP_RETRANSMIT, EAP_SUCCESS, EAP_FAILURE, - EAP_TIMEOUT_FAILURE, EAP_PICK_UP_METHOD, - EAP_INITIALIZE_PASSTHROUGH, EAP_IDLE2, EAP_RETRANSMIT2, - EAP_RECEIVED2, EAP_DISCARD2, EAP_SEND_REQUEST2, - EAP_AAA_REQUEST, EAP_AAA_RESPONSE, EAP_AAA_IDLE, - EAP_TIMEOUT_FAILURE2, EAP_FAILURE2, EAP_SUCCESS2 - } EAP_state; - - /* Constants */ - int MaxRetrans; - - struct eap_eapol_interface eap_if; - - /* Full authenticator state machine local variables */ - - /* Long-term (maintained betwen packets) */ - EapType currentMethod; - int currentId; - enum { - METHOD_PROPOSED, METHOD_CONTINUE, METHOD_END - } methodState; - int retransCount; - struct wpabuf *lastReqData; - int methodTimeout; - - /* Short-term (not maintained between packets) */ - Boolean rxResp; - int respId; - EapType respMethod; - int respVendor; - u32 respVendorMethod; - Boolean ignore; - enum { - DECISION_SUCCESS, DECISION_FAILURE, DECISION_CONTINUE, - DECISION_PASSTHROUGH - } decision; - - /* Miscellaneous variables */ - const struct eap_method *m; /* selected EAP method */ - /* not defined in RFC 4137 */ - Boolean changed; - void *eapol_ctx, *msg_ctx; - struct eapol_callbacks *eapol_cb; - void *eap_method_priv; - u8 *identity; - size_t identity_len; - /* Whether Phase 2 method should validate identity match */ - int require_identity_match; - int lastId; /* Identifier used in the last EAP-Packet */ - struct eap_user *user; - int user_eap_method_index; - int init_phase2; - void *ssl_ctx; - void *eap_sim_db_priv; - Boolean backend_auth; - Boolean update_user; - int eap_server; - - int num_rounds; - enum { - METHOD_PENDING_NONE, METHOD_PENDING_WAIT, METHOD_PENDING_CONT - } method_pending; - - u8 *auth_challenge; - u8 *peer_challenge; - - u8 *pac_opaque_encr_key; - u8 *eap_fast_a_id; - size_t eap_fast_a_id_len; - char *eap_fast_a_id_info; - enum { - NO_PROV, ANON_PROV, AUTH_PROV, BOTH_PROV - } eap_fast_prov; - int pac_key_lifetime; - int pac_key_refresh_time; - int eap_sim_aka_result_ind; - int tnc; - u16 pwd_group; - struct wps_context *wps; - struct wpabuf *assoc_wps_ie; - struct wpabuf *assoc_p2p_ie; - - Boolean start_reauth; - - u8 peer_addr[ETH_ALEN]; - - /* Fragmentation size for EAP method init() handler */ - int fragment_size; -}; - -int eap_user_get(struct eap_sm *sm, const u8 *identity, size_t identity_len, - int phase2); -void eap_sm_process_nak(struct eap_sm *sm, const u8 *nak_list, size_t len); - -#endif /* EAP_I_H */ diff --git a/hostapd-0.8/src/eap_server/eap_methods.h b/hostapd-0.8/src/eap_server/eap_methods.h deleted file mode 100644 index 4a5296e..0000000 --- a/hostapd-0.8/src/eap_server/eap_methods.h +++ /dev/null @@ -1,54 +0,0 @@ -/* - * EAP server method registration - * Copyright (c) 2004-2009, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#ifndef EAP_SERVER_METHODS_H -#define EAP_SERVER_METHODS_H - -#include "eap_common/eap_defs.h" - -const struct eap_method * eap_server_get_eap_method(int vendor, - EapType method); -struct eap_method * eap_server_method_alloc(int version, int vendor, - EapType method, const char *name); -void eap_server_method_free(struct eap_method *method); -int eap_server_method_register(struct eap_method *method); - -EapType eap_server_get_type(const char *name, int *vendor); -void eap_server_unregister_methods(void); -const char * eap_server_get_name(int vendor, EapType type); - -/* EAP server method registration calls for statically linked in methods */ -int eap_server_identity_register(void); -int eap_server_md5_register(void); -int eap_server_tls_register(void); -int eap_server_mschapv2_register(void); -int eap_server_peap_register(void); -int eap_server_tlv_register(void); -int eap_server_gtc_register(void); -int eap_server_ttls_register(void); -int eap_server_sim_register(void); -int eap_server_aka_register(void); -int eap_server_aka_prime_register(void); -int eap_server_pax_register(void); -int eap_server_psk_register(void); -int eap_server_sake_register(void); -int eap_server_gpsk_register(void); -int eap_server_vendor_test_register(void); -int eap_server_fast_register(void); -int eap_server_wsc_register(void); -int eap_server_ikev2_register(void); -int eap_server_tnc_register(void); -int eap_server_pwd_register(void); - -#endif /* EAP_SERVER_METHODS_H */ diff --git a/hostapd-0.8/src/eap_server/eap_server.c b/hostapd-0.8/src/eap_server/eap_server.c deleted file mode 100644 index 41416b1..0000000 --- a/hostapd-0.8/src/eap_server/eap_server.c +++ /dev/null @@ -1,1384 +0,0 @@ -/* - * hostapd / EAP Full Authenticator state machine (RFC 4137) - * Copyright (c) 2004-2007, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - * - * This state machine is based on the full authenticator state machine defined - * in RFC 4137. However, to support backend authentication in RADIUS - * authentication server functionality, parts of backend authenticator (also - * from RFC 4137) are mixed in. This functionality is enabled by setting - * backend_auth configuration variable to TRUE. - */ - -#include "includes.h" - -#include "common.h" -#include "eap_i.h" -#include "state_machine.h" -#include "common/wpa_ctrl.h" - -#define STATE_MACHINE_DATA struct eap_sm -#define STATE_MACHINE_DEBUG_PREFIX "EAP" - -#define EAP_MAX_AUTH_ROUNDS 50 - -static void eap_user_free(struct eap_user *user); - - -/* EAP state machines are described in RFC 4137 */ - -static int eap_sm_calculateTimeout(struct eap_sm *sm, int retransCount, - int eapSRTT, int eapRTTVAR, - int methodTimeout); -static void eap_sm_parseEapResp(struct eap_sm *sm, const struct wpabuf *resp); -static int eap_sm_getId(const struct wpabuf *data); -static struct wpabuf * eap_sm_buildSuccess(struct eap_sm *sm, u8 id); -static struct wpabuf * eap_sm_buildFailure(struct eap_sm *sm, u8 id); -static int eap_sm_nextId(struct eap_sm *sm, int id); -static void eap_sm_Policy_update(struct eap_sm *sm, const u8 *nak_list, - size_t len); -static EapType eap_sm_Policy_getNextMethod(struct eap_sm *sm, int *vendor); -static int eap_sm_Policy_getDecision(struct eap_sm *sm); -static Boolean eap_sm_Policy_doPickUp(struct eap_sm *sm, EapType method); - - -static int eap_copy_buf(struct wpabuf **dst, const struct wpabuf *src) -{ - if (src == NULL) - return -1; - - wpabuf_free(*dst); - *dst = wpabuf_dup(src); - return *dst ? 0 : -1; -} - - -static int eap_copy_data(u8 **dst, size_t *dst_len, - const u8 *src, size_t src_len) -{ - if (src == NULL) - return -1; - - os_free(*dst); - *dst = os_malloc(src_len); - if (*dst) { - os_memcpy(*dst, src, src_len); - *dst_len = src_len; - return 0; - } else { - *dst_len = 0; - return -1; - } -} - -#define EAP_COPY(dst, src) \ - eap_copy_data((dst), (dst ## Len), (src), (src ## Len)) - - -/** - * eap_user_get - Fetch user information from the database - * @sm: Pointer to EAP state machine allocated with eap_server_sm_init() - * @identity: Identity (User-Name) of the user - * @identity_len: Length of identity in bytes - * @phase2: 0 = EAP phase1 user, 1 = EAP phase2 (tunneled) user - * Returns: 0 on success, or -1 on failure - * - * This function is used to fetch user information for EAP. The user will be - * selected based on the specified identity. sm->user and - * sm->user_eap_method_index are updated for the new user when a matching user - * is found. sm->user can be used to get user information (e.g., password). - */ -int eap_user_get(struct eap_sm *sm, const u8 *identity, size_t identity_len, - int phase2) -{ - struct eap_user *user; - - if (sm == NULL || sm->eapol_cb == NULL || - sm->eapol_cb->get_eap_user == NULL) - return -1; - - eap_user_free(sm->user); - sm->user = NULL; - - user = os_zalloc(sizeof(*user)); - if (user == NULL) - return -1; - - if (sm->eapol_cb->get_eap_user(sm->eapol_ctx, identity, - identity_len, phase2, user) != 0) { - eap_user_free(user); - return -1; - } - - sm->user = user; - sm->user_eap_method_index = 0; - - return 0; -} - - -SM_STATE(EAP, DISABLED) -{ - SM_ENTRY(EAP, DISABLED); - sm->num_rounds = 0; -} - - -SM_STATE(EAP, INITIALIZE) -{ - SM_ENTRY(EAP, INITIALIZE); - - sm->currentId = -1; - sm->eap_if.eapSuccess = FALSE; - sm->eap_if.eapFail = FALSE; - sm->eap_if.eapTimeout = FALSE; - os_free(sm->eap_if.eapKeyData); - sm->eap_if.eapKeyData = NULL; - sm->eap_if.eapKeyDataLen = 0; - sm->eap_if.eapKeyAvailable = FALSE; - sm->eap_if.eapRestart = FALSE; - - /* - * This is not defined in RFC 4137, but method state needs to be - * reseted here so that it does not remain in success state when - * re-authentication starts. - */ - if (sm->m && sm->eap_method_priv) { - sm->m->reset(sm, sm->eap_method_priv); - sm->eap_method_priv = NULL; - } - sm->m = NULL; - sm->user_eap_method_index = 0; - - if (sm->backend_auth) { - sm->currentMethod = EAP_TYPE_NONE; - /* parse rxResp, respId, respMethod */ - eap_sm_parseEapResp(sm, sm->eap_if.eapRespData); - if (sm->rxResp) { - sm->currentId = sm->respId; - } - } - sm->num_rounds = 0; - sm->method_pending = METHOD_PENDING_NONE; - - wpa_msg(sm->msg_ctx, MSG_INFO, WPA_EVENT_EAP_STARTED - MACSTR, MAC2STR(sm->peer_addr)); -} - - -SM_STATE(EAP, PICK_UP_METHOD) -{ - SM_ENTRY(EAP, PICK_UP_METHOD); - - if (eap_sm_Policy_doPickUp(sm, sm->respMethod)) { - sm->currentMethod = sm->respMethod; - if (sm->m && sm->eap_method_priv) { - sm->m->reset(sm, sm->eap_method_priv); - sm->eap_method_priv = NULL; - } - sm->m = eap_server_get_eap_method(EAP_VENDOR_IETF, - sm->currentMethod); - if (sm->m && sm->m->initPickUp) { - sm->eap_method_priv = sm->m->initPickUp(sm); - if (sm->eap_method_priv == NULL) { - wpa_printf(MSG_DEBUG, "EAP: Failed to " - "initialize EAP method %d", - sm->currentMethod); - sm->m = NULL; - sm->currentMethod = EAP_TYPE_NONE; - } - } else { - sm->m = NULL; - sm->currentMethod = EAP_TYPE_NONE; - } - } - - wpa_msg(sm->msg_ctx, MSG_INFO, WPA_EVENT_EAP_PROPOSED_METHOD - "method=%u", sm->currentMethod); -} - - -SM_STATE(EAP, IDLE) -{ - SM_ENTRY(EAP, IDLE); - - sm->eap_if.retransWhile = eap_sm_calculateTimeout( - sm, sm->retransCount, sm->eap_if.eapSRTT, sm->eap_if.eapRTTVAR, - sm->methodTimeout); -} - - -SM_STATE(EAP, RETRANSMIT) -{ - SM_ENTRY(EAP, RETRANSMIT); - - sm->retransCount++; - if (sm->retransCount <= sm->MaxRetrans && sm->lastReqData) { - if (eap_copy_buf(&sm->eap_if.eapReqData, sm->lastReqData) == 0) - sm->eap_if.eapReq = TRUE; - } -} - - -SM_STATE(EAP, RECEIVED) -{ - SM_ENTRY(EAP, RECEIVED); - - /* parse rxResp, respId, respMethod */ - eap_sm_parseEapResp(sm, sm->eap_if.eapRespData); - sm->num_rounds++; -} - - -SM_STATE(EAP, DISCARD) -{ - SM_ENTRY(EAP, DISCARD); - sm->eap_if.eapResp = FALSE; - sm->eap_if.eapNoReq = TRUE; -} - - -SM_STATE(EAP, SEND_REQUEST) -{ - SM_ENTRY(EAP, SEND_REQUEST); - - sm->retransCount = 0; - if (sm->eap_if.eapReqData) { - if (eap_copy_buf(&sm->lastReqData, sm->eap_if.eapReqData) == 0) - { - sm->eap_if.eapResp = FALSE; - sm->eap_if.eapReq = TRUE; - } else { - sm->eap_if.eapResp = FALSE; - sm->eap_if.eapReq = FALSE; - } - } else { - wpa_printf(MSG_INFO, "EAP: SEND_REQUEST - no eapReqData"); - sm->eap_if.eapResp = FALSE; - sm->eap_if.eapReq = FALSE; - sm->eap_if.eapNoReq = TRUE; - } -} - - -SM_STATE(EAP, INTEGRITY_CHECK) -{ - SM_ENTRY(EAP, INTEGRITY_CHECK); - - if (sm->m->check) { - sm->ignore = sm->m->check(sm, sm->eap_method_priv, - sm->eap_if.eapRespData); - } -} - - -SM_STATE(EAP, METHOD_REQUEST) -{ - SM_ENTRY(EAP, METHOD_REQUEST); - - if (sm->m == NULL) { - wpa_printf(MSG_DEBUG, "EAP: method not initialized"); - return; - } - - sm->currentId = eap_sm_nextId(sm, sm->currentId); - wpa_printf(MSG_DEBUG, "EAP: building EAP-Request: Identifier %d", - sm->currentId); - sm->lastId = sm->currentId; - wpabuf_free(sm->eap_if.eapReqData); - sm->eap_if.eapReqData = sm->m->buildReq(sm, sm->eap_method_priv, - sm->currentId); - if (sm->m->getTimeout) - sm->methodTimeout = sm->m->getTimeout(sm, sm->eap_method_priv); - else - sm->methodTimeout = 0; -} - - -SM_STATE(EAP, METHOD_RESPONSE) -{ - SM_ENTRY(EAP, METHOD_RESPONSE); - - sm->m->process(sm, sm->eap_method_priv, sm->eap_if.eapRespData); - if (sm->m->isDone(sm, sm->eap_method_priv)) { - eap_sm_Policy_update(sm, NULL, 0); - os_free(sm->eap_if.eapKeyData); - if (sm->m->getKey) { - sm->eap_if.eapKeyData = sm->m->getKey( - sm, sm->eap_method_priv, - &sm->eap_if.eapKeyDataLen); - } else { - sm->eap_if.eapKeyData = NULL; - sm->eap_if.eapKeyDataLen = 0; - } - sm->methodState = METHOD_END; - } else { - sm->methodState = METHOD_CONTINUE; - } -} - - -SM_STATE(EAP, PROPOSE_METHOD) -{ - int vendor; - EapType type; - - SM_ENTRY(EAP, PROPOSE_METHOD); - - type = eap_sm_Policy_getNextMethod(sm, &vendor); - if (vendor == EAP_VENDOR_IETF) - sm->currentMethod = type; - else - sm->currentMethod = EAP_TYPE_EXPANDED; - if (sm->m && sm->eap_method_priv) { - sm->m->reset(sm, sm->eap_method_priv); - sm->eap_method_priv = NULL; - } - sm->m = eap_server_get_eap_method(vendor, type); - if (sm->m) { - sm->eap_method_priv = sm->m->init(sm); - if (sm->eap_method_priv == NULL) { - wpa_printf(MSG_DEBUG, "EAP: Failed to initialize EAP " - "method %d", sm->currentMethod); - sm->m = NULL; - sm->currentMethod = EAP_TYPE_NONE; - } - } - if (sm->currentMethod == EAP_TYPE_IDENTITY || - sm->currentMethod == EAP_TYPE_NOTIFICATION) - sm->methodState = METHOD_CONTINUE; - else - sm->methodState = METHOD_PROPOSED; - - wpa_msg(sm->msg_ctx, MSG_INFO, WPA_EVENT_EAP_PROPOSED_METHOD - "vendor=%u method=%u", vendor, sm->currentMethod); -} - - -SM_STATE(EAP, NAK) -{ - const struct eap_hdr *nak; - size_t len = 0; - const u8 *pos; - const u8 *nak_list = NULL; - - SM_ENTRY(EAP, NAK); - - if (sm->eap_method_priv) { - sm->m->reset(sm, sm->eap_method_priv); - sm->eap_method_priv = NULL; - } - sm->m = NULL; - - nak = wpabuf_head(sm->eap_if.eapRespData); - if (nak && wpabuf_len(sm->eap_if.eapRespData) > sizeof(*nak)) { - len = be_to_host16(nak->length); - if (len > wpabuf_len(sm->eap_if.eapRespData)) - len = wpabuf_len(sm->eap_if.eapRespData); - pos = (const u8 *) (nak + 1); - len -= sizeof(*nak); - if (*pos == EAP_TYPE_NAK) { - pos++; - len--; - nak_list = pos; - } - } - eap_sm_Policy_update(sm, nak_list, len); -} - - -SM_STATE(EAP, SELECT_ACTION) -{ - SM_ENTRY(EAP, SELECT_ACTION); - - sm->decision = eap_sm_Policy_getDecision(sm); -} - - -SM_STATE(EAP, TIMEOUT_FAILURE) -{ - SM_ENTRY(EAP, TIMEOUT_FAILURE); - - sm->eap_if.eapTimeout = TRUE; -} - - -SM_STATE(EAP, FAILURE) -{ - SM_ENTRY(EAP, FAILURE); - - wpabuf_free(sm->eap_if.eapReqData); - sm->eap_if.eapReqData = eap_sm_buildFailure(sm, sm->currentId); - wpabuf_free(sm->lastReqData); - sm->lastReqData = NULL; - sm->eap_if.eapFail = TRUE; - - wpa_msg(sm->msg_ctx, MSG_INFO, WPA_EVENT_EAP_FAILURE - MACSTR, MAC2STR(sm->peer_addr)); -} - - -SM_STATE(EAP, SUCCESS) -{ - SM_ENTRY(EAP, SUCCESS); - - wpabuf_free(sm->eap_if.eapReqData); - sm->eap_if.eapReqData = eap_sm_buildSuccess(sm, sm->currentId); - wpabuf_free(sm->lastReqData); - sm->lastReqData = NULL; - if (sm->eap_if.eapKeyData) - sm->eap_if.eapKeyAvailable = TRUE; - sm->eap_if.eapSuccess = TRUE; - - wpa_msg(sm->msg_ctx, MSG_INFO, WPA_EVENT_EAP_SUCCESS - MACSTR, MAC2STR(sm->peer_addr)); -} - - -SM_STATE(EAP, INITIALIZE_PASSTHROUGH) -{ - SM_ENTRY(EAP, INITIALIZE_PASSTHROUGH); - - wpabuf_free(sm->eap_if.aaaEapRespData); - sm->eap_if.aaaEapRespData = NULL; -} - - -SM_STATE(EAP, IDLE2) -{ - SM_ENTRY(EAP, IDLE2); - - sm->eap_if.retransWhile = eap_sm_calculateTimeout( - sm, sm->retransCount, sm->eap_if.eapSRTT, sm->eap_if.eapRTTVAR, - sm->methodTimeout); -} - - -SM_STATE(EAP, RETRANSMIT2) -{ - SM_ENTRY(EAP, RETRANSMIT2); - - sm->retransCount++; - if (sm->retransCount <= sm->MaxRetrans && sm->lastReqData) { - if (eap_copy_buf(&sm->eap_if.eapReqData, sm->lastReqData) == 0) - sm->eap_if.eapReq = TRUE; - } -} - - -SM_STATE(EAP, RECEIVED2) -{ - SM_ENTRY(EAP, RECEIVED2); - - /* parse rxResp, respId, respMethod */ - eap_sm_parseEapResp(sm, sm->eap_if.eapRespData); -} - - -SM_STATE(EAP, DISCARD2) -{ - SM_ENTRY(EAP, DISCARD2); - sm->eap_if.eapResp = FALSE; - sm->eap_if.eapNoReq = TRUE; -} - - -SM_STATE(EAP, SEND_REQUEST2) -{ - SM_ENTRY(EAP, SEND_REQUEST2); - - sm->retransCount = 0; - if (sm->eap_if.eapReqData) { - if (eap_copy_buf(&sm->lastReqData, sm->eap_if.eapReqData) == 0) - { - sm->eap_if.eapResp = FALSE; - sm->eap_if.eapReq = TRUE; - } else { - sm->eap_if.eapResp = FALSE; - sm->eap_if.eapReq = FALSE; - } - } else { - wpa_printf(MSG_INFO, "EAP: SEND_REQUEST2 - no eapReqData"); - sm->eap_if.eapResp = FALSE; - sm->eap_if.eapReq = FALSE; - sm->eap_if.eapNoReq = TRUE; - } -} - - -SM_STATE(EAP, AAA_REQUEST) -{ - SM_ENTRY(EAP, AAA_REQUEST); - - if (sm->eap_if.eapRespData == NULL) { - wpa_printf(MSG_INFO, "EAP: AAA_REQUEST - no eapRespData"); - return; - } - - /* - * if (respMethod == IDENTITY) - * aaaIdentity = eapRespData - * This is already taken care of by the EAP-Identity method which - * stores the identity into sm->identity. - */ - - eap_copy_buf(&sm->eap_if.aaaEapRespData, sm->eap_if.eapRespData); -} - - -SM_STATE(EAP, AAA_RESPONSE) -{ - SM_ENTRY(EAP, AAA_RESPONSE); - - eap_copy_buf(&sm->eap_if.eapReqData, sm->eap_if.aaaEapReqData); - sm->currentId = eap_sm_getId(sm->eap_if.eapReqData); - sm->methodTimeout = sm->eap_if.aaaMethodTimeout; -} - - -SM_STATE(EAP, AAA_IDLE) -{ - SM_ENTRY(EAP, AAA_IDLE); - - sm->eap_if.aaaFail = FALSE; - sm->eap_if.aaaSuccess = FALSE; - sm->eap_if.aaaEapReq = FALSE; - sm->eap_if.aaaEapNoReq = FALSE; - sm->eap_if.aaaEapResp = TRUE; -} - - -SM_STATE(EAP, TIMEOUT_FAILURE2) -{ - SM_ENTRY(EAP, TIMEOUT_FAILURE2); - - sm->eap_if.eapTimeout = TRUE; -} - - -SM_STATE(EAP, FAILURE2) -{ - SM_ENTRY(EAP, FAILURE2); - - eap_copy_buf(&sm->eap_if.eapReqData, sm->eap_if.aaaEapReqData); - sm->eap_if.eapFail = TRUE; -} - - -SM_STATE(EAP, SUCCESS2) -{ - SM_ENTRY(EAP, SUCCESS2); - - eap_copy_buf(&sm->eap_if.eapReqData, sm->eap_if.aaaEapReqData); - - sm->eap_if.eapKeyAvailable = sm->eap_if.aaaEapKeyAvailable; - if (sm->eap_if.aaaEapKeyAvailable) { - EAP_COPY(&sm->eap_if.eapKeyData, sm->eap_if.aaaEapKeyData); - } else { - os_free(sm->eap_if.eapKeyData); - sm->eap_if.eapKeyData = NULL; - sm->eap_if.eapKeyDataLen = 0; - } - - sm->eap_if.eapSuccess = TRUE; - - /* - * Start reauthentication with identity request even though we know the - * previously used identity. This is needed to get reauthentication - * started properly. - */ - sm->start_reauth = TRUE; -} - - -SM_STEP(EAP) -{ - if (sm->eap_if.eapRestart && sm->eap_if.portEnabled) - SM_ENTER_GLOBAL(EAP, INITIALIZE); - else if (!sm->eap_if.portEnabled) - SM_ENTER_GLOBAL(EAP, DISABLED); - else if (sm->num_rounds > EAP_MAX_AUTH_ROUNDS) { - if (sm->num_rounds == EAP_MAX_AUTH_ROUNDS + 1) { - wpa_printf(MSG_DEBUG, "EAP: more than %d " - "authentication rounds - abort", - EAP_MAX_AUTH_ROUNDS); - sm->num_rounds++; - SM_ENTER_GLOBAL(EAP, FAILURE); - } - } else switch (sm->EAP_state) { - case EAP_INITIALIZE: - if (sm->backend_auth) { - if (!sm->rxResp) - SM_ENTER(EAP, SELECT_ACTION); - else if (sm->rxResp && - (sm->respMethod == EAP_TYPE_NAK || - (sm->respMethod == EAP_TYPE_EXPANDED && - sm->respVendor == EAP_VENDOR_IETF && - sm->respVendorMethod == EAP_TYPE_NAK))) - SM_ENTER(EAP, NAK); - else - SM_ENTER(EAP, PICK_UP_METHOD); - } else { - SM_ENTER(EAP, SELECT_ACTION); - } - break; - case EAP_PICK_UP_METHOD: - if (sm->currentMethod == EAP_TYPE_NONE) { - SM_ENTER(EAP, SELECT_ACTION); - } else { - SM_ENTER(EAP, METHOD_RESPONSE); - } - break; - case EAP_DISABLED: - if (sm->eap_if.portEnabled) - SM_ENTER(EAP, INITIALIZE); - break; - case EAP_IDLE: - if (sm->eap_if.retransWhile == 0) - SM_ENTER(EAP, RETRANSMIT); - else if (sm->eap_if.eapResp) - SM_ENTER(EAP, RECEIVED); - break; - case EAP_RETRANSMIT: - if (sm->retransCount > sm->MaxRetrans) - SM_ENTER(EAP, TIMEOUT_FAILURE); - else - SM_ENTER(EAP, IDLE); - break; - case EAP_RECEIVED: - if (sm->rxResp && (sm->respId == sm->currentId) && - (sm->respMethod == EAP_TYPE_NAK || - (sm->respMethod == EAP_TYPE_EXPANDED && - sm->respVendor == EAP_VENDOR_IETF && - sm->respVendorMethod == EAP_TYPE_NAK)) - && (sm->methodState == METHOD_PROPOSED)) - SM_ENTER(EAP, NAK); - else if (sm->rxResp && (sm->respId == sm->currentId) && - ((sm->respMethod == sm->currentMethod) || - (sm->respMethod == EAP_TYPE_EXPANDED && - sm->respVendor == EAP_VENDOR_IETF && - sm->respVendorMethod == sm->currentMethod))) - SM_ENTER(EAP, INTEGRITY_CHECK); - else { - wpa_printf(MSG_DEBUG, "EAP: RECEIVED->DISCARD: " - "rxResp=%d respId=%d currentId=%d " - "respMethod=%d currentMethod=%d", - sm->rxResp, sm->respId, sm->currentId, - sm->respMethod, sm->currentMethod); - SM_ENTER(EAP, DISCARD); - } - break; - case EAP_DISCARD: - SM_ENTER(EAP, IDLE); - break; - case EAP_SEND_REQUEST: - SM_ENTER(EAP, IDLE); - break; - case EAP_INTEGRITY_CHECK: - if (sm->ignore) - SM_ENTER(EAP, DISCARD); - else - SM_ENTER(EAP, METHOD_RESPONSE); - break; - case EAP_METHOD_REQUEST: - SM_ENTER(EAP, SEND_REQUEST); - break; - case EAP_METHOD_RESPONSE: - /* - * Note: Mechanism to allow EAP methods to wait while going - * through pending processing is an extension to RFC 4137 - * which only defines the transits to SELECT_ACTION and - * METHOD_REQUEST from this METHOD_RESPONSE state. - */ - if (sm->methodState == METHOD_END) - SM_ENTER(EAP, SELECT_ACTION); - else if (sm->method_pending == METHOD_PENDING_WAIT) { - wpa_printf(MSG_DEBUG, "EAP: Method has pending " - "processing - wait before proceeding to " - "METHOD_REQUEST state"); - } else if (sm->method_pending == METHOD_PENDING_CONT) { - wpa_printf(MSG_DEBUG, "EAP: Method has completed " - "pending processing - reprocess pending " - "EAP message"); - sm->method_pending = METHOD_PENDING_NONE; - SM_ENTER(EAP, METHOD_RESPONSE); - } else - SM_ENTER(EAP, METHOD_REQUEST); - break; - case EAP_PROPOSE_METHOD: - /* - * Note: Mechanism to allow EAP methods to wait while going - * through pending processing is an extension to RFC 4137 - * which only defines the transit to METHOD_REQUEST from this - * PROPOSE_METHOD state. - */ - if (sm->method_pending == METHOD_PENDING_WAIT) { - wpa_printf(MSG_DEBUG, "EAP: Method has pending " - "processing - wait before proceeding to " - "METHOD_REQUEST state"); - if (sm->user_eap_method_index > 0) - sm->user_eap_method_index--; - } else if (sm->method_pending == METHOD_PENDING_CONT) { - wpa_printf(MSG_DEBUG, "EAP: Method has completed " - "pending processing - reprocess pending " - "EAP message"); - sm->method_pending = METHOD_PENDING_NONE; - SM_ENTER(EAP, PROPOSE_METHOD); - } else - SM_ENTER(EAP, METHOD_REQUEST); - break; - case EAP_NAK: - SM_ENTER(EAP, SELECT_ACTION); - break; - case EAP_SELECT_ACTION: - if (sm->decision == DECISION_FAILURE) - SM_ENTER(EAP, FAILURE); - else if (sm->decision == DECISION_SUCCESS) - SM_ENTER(EAP, SUCCESS); - else if (sm->decision == DECISION_PASSTHROUGH) - SM_ENTER(EAP, INITIALIZE_PASSTHROUGH); - else - SM_ENTER(EAP, PROPOSE_METHOD); - break; - case EAP_TIMEOUT_FAILURE: - break; - case EAP_FAILURE: - break; - case EAP_SUCCESS: - break; - - case EAP_INITIALIZE_PASSTHROUGH: - if (sm->currentId == -1) - SM_ENTER(EAP, AAA_IDLE); - else - SM_ENTER(EAP, AAA_REQUEST); - break; - case EAP_IDLE2: - if (sm->eap_if.eapResp) - SM_ENTER(EAP, RECEIVED2); - else if (sm->eap_if.retransWhile == 0) - SM_ENTER(EAP, RETRANSMIT2); - break; - case EAP_RETRANSMIT2: - if (sm->retransCount > sm->MaxRetrans) - SM_ENTER(EAP, TIMEOUT_FAILURE2); - else - SM_ENTER(EAP, IDLE2); - break; - case EAP_RECEIVED2: - if (sm->rxResp && (sm->respId == sm->currentId)) - SM_ENTER(EAP, AAA_REQUEST); - else - SM_ENTER(EAP, DISCARD2); - break; - case EAP_DISCARD2: - SM_ENTER(EAP, IDLE2); - break; - case EAP_SEND_REQUEST2: - SM_ENTER(EAP, IDLE2); - break; - case EAP_AAA_REQUEST: - SM_ENTER(EAP, AAA_IDLE); - break; - case EAP_AAA_RESPONSE: - SM_ENTER(EAP, SEND_REQUEST2); - break; - case EAP_AAA_IDLE: - if (sm->eap_if.aaaFail) - SM_ENTER(EAP, FAILURE2); - else if (sm->eap_if.aaaSuccess) - SM_ENTER(EAP, SUCCESS2); - else if (sm->eap_if.aaaEapReq) - SM_ENTER(EAP, AAA_RESPONSE); - else if (sm->eap_if.aaaTimeout) - SM_ENTER(EAP, TIMEOUT_FAILURE2); - break; - case EAP_TIMEOUT_FAILURE2: - break; - case EAP_FAILURE2: - break; - case EAP_SUCCESS2: - break; - } -} - - -static int eap_sm_calculateTimeout(struct eap_sm *sm, int retransCount, - int eapSRTT, int eapRTTVAR, - int methodTimeout) -{ - int rto, i; - - if (methodTimeout) { - /* - * EAP method (either internal or through AAA server, provided - * timeout hint. Use that as-is as a timeout for retransmitting - * the EAP request if no response is received. - */ - wpa_printf(MSG_DEBUG, "EAP: retransmit timeout %d seconds " - "(from EAP method hint)", methodTimeout); - return methodTimeout; - } - - /* - * RFC 3748 recommends algorithms described in RFC 2988 for estimation - * of the retransmission timeout. This should be implemented once - * round-trip time measurements are available. For nowm a simple - * backoff mechanism is used instead if there are no EAP method - * specific hints. - * - * SRTT = smoothed round-trip time - * RTTVAR = round-trip time variation - * RTO = retransmission timeout - */ - - /* - * RFC 2988, 2.1: before RTT measurement, set RTO to 3 seconds for - * initial retransmission and then double the RTO to provide back off - * per 5.5. Limit the maximum RTO to 20 seconds per RFC 3748, 4.3 - * modified RTOmax. - */ - rto = 3; - for (i = 0; i < retransCount; i++) { - rto *= 2; - if (rto >= 20) { - rto = 20; - break; - } - } - - wpa_printf(MSG_DEBUG, "EAP: retransmit timeout %d seconds " - "(from dynamic back off; retransCount=%d)", - rto, retransCount); - - return rto; -} - - -static void eap_sm_parseEapResp(struct eap_sm *sm, const struct wpabuf *resp) -{ - const struct eap_hdr *hdr; - size_t plen; - - /* parse rxResp, respId, respMethod */ - sm->rxResp = FALSE; - sm->respId = -1; - sm->respMethod = EAP_TYPE_NONE; - sm->respVendor = EAP_VENDOR_IETF; - sm->respVendorMethod = EAP_TYPE_NONE; - - if (resp == NULL || wpabuf_len(resp) < sizeof(*hdr)) { - wpa_printf(MSG_DEBUG, "EAP: parseEapResp: invalid resp=%p " - "len=%lu", resp, - resp ? (unsigned long) wpabuf_len(resp) : 0); - return; - } - - hdr = wpabuf_head(resp); - plen = be_to_host16(hdr->length); - if (plen > wpabuf_len(resp)) { - wpa_printf(MSG_DEBUG, "EAP: Ignored truncated EAP-Packet " - "(len=%lu plen=%lu)", - (unsigned long) wpabuf_len(resp), - (unsigned long) plen); - return; - } - - sm->respId = hdr->identifier; - - if (hdr->code == EAP_CODE_RESPONSE) - sm->rxResp = TRUE; - - if (plen > sizeof(*hdr)) { - u8 *pos = (u8 *) (hdr + 1); - sm->respMethod = *pos++; - if (sm->respMethod == EAP_TYPE_EXPANDED) { - if (plen < sizeof(*hdr) + 8) { - wpa_printf(MSG_DEBUG, "EAP: Ignored truncated " - "expanded EAP-Packet (plen=%lu)", - (unsigned long) plen); - return; - } - sm->respVendor = WPA_GET_BE24(pos); - pos += 3; - sm->respVendorMethod = WPA_GET_BE32(pos); - } - } - - wpa_printf(MSG_DEBUG, "EAP: parseEapResp: rxResp=%d respId=%d " - "respMethod=%u respVendor=%u respVendorMethod=%u", - sm->rxResp, sm->respId, sm->respMethod, sm->respVendor, - sm->respVendorMethod); -} - - -static int eap_sm_getId(const struct wpabuf *data) -{ - const struct eap_hdr *hdr; - - if (data == NULL || wpabuf_len(data) < sizeof(*hdr)) - return -1; - - hdr = wpabuf_head(data); - wpa_printf(MSG_DEBUG, "EAP: getId: id=%d", hdr->identifier); - return hdr->identifier; -} - - -static struct wpabuf * eap_sm_buildSuccess(struct eap_sm *sm, u8 id) -{ - struct wpabuf *msg; - struct eap_hdr *resp; - wpa_printf(MSG_DEBUG, "EAP: Building EAP-Success (id=%d)", id); - - msg = wpabuf_alloc(sizeof(*resp)); - if (msg == NULL) - return NULL; - resp = wpabuf_put(msg, sizeof(*resp)); - resp->code = EAP_CODE_SUCCESS; - resp->identifier = id; - resp->length = host_to_be16(sizeof(*resp)); - - return msg; -} - - -static struct wpabuf * eap_sm_buildFailure(struct eap_sm *sm, u8 id) -{ - struct wpabuf *msg; - struct eap_hdr *resp; - wpa_printf(MSG_DEBUG, "EAP: Building EAP-Failure (id=%d)", id); - - msg = wpabuf_alloc(sizeof(*resp)); - if (msg == NULL) - return NULL; - resp = wpabuf_put(msg, sizeof(*resp)); - resp->code = EAP_CODE_FAILURE; - resp->identifier = id; - resp->length = host_to_be16(sizeof(*resp)); - - return msg; -} - - -static int eap_sm_nextId(struct eap_sm *sm, int id) -{ - if (id < 0) { - /* RFC 3748 Ch 4.1: recommended to initialize Identifier with a - * random number */ - id = rand() & 0xff; - if (id != sm->lastId) - return id; - } - return (id + 1) & 0xff; -} - - -/** - * eap_sm_process_nak - Process EAP-Response/Nak - * @sm: Pointer to EAP state machine allocated with eap_server_sm_init() - * @nak_list: Nak list (allowed methods) from the supplicant - * @len: Length of nak_list in bytes - * - * This function is called when EAP-Response/Nak is received from the - * supplicant. This can happen for both phase 1 and phase 2 authentications. - */ -void eap_sm_process_nak(struct eap_sm *sm, const u8 *nak_list, size_t len) -{ - int i; - size_t j; - - if (sm->user == NULL) - return; - - wpa_printf(MSG_MSGDUMP, "EAP: processing NAK (current EAP method " - "index %d)", sm->user_eap_method_index); - - wpa_hexdump(MSG_MSGDUMP, "EAP: configured methods", - (u8 *) sm->user->methods, - EAP_MAX_METHODS * sizeof(sm->user->methods[0])); - wpa_hexdump(MSG_MSGDUMP, "EAP: list of methods supported by the peer", - nak_list, len); - - i = sm->user_eap_method_index; - while (i < EAP_MAX_METHODS && - (sm->user->methods[i].vendor != EAP_VENDOR_IETF || - sm->user->methods[i].method != EAP_TYPE_NONE)) { - if (sm->user->methods[i].vendor != EAP_VENDOR_IETF) - goto not_found; - for (j = 0; j < len; j++) { - if (nak_list[j] == sm->user->methods[i].method) { - break; - } - } - - if (j < len) { - /* found */ - i++; - continue; - } - - not_found: - /* not found - remove from the list */ - os_memmove(&sm->user->methods[i], &sm->user->methods[i + 1], - (EAP_MAX_METHODS - i - 1) * - sizeof(sm->user->methods[0])); - sm->user->methods[EAP_MAX_METHODS - 1].vendor = - EAP_VENDOR_IETF; - sm->user->methods[EAP_MAX_METHODS - 1].method = EAP_TYPE_NONE; - } - - wpa_hexdump(MSG_MSGDUMP, "EAP: new list of configured methods", - (u8 *) sm->user->methods, EAP_MAX_METHODS * - sizeof(sm->user->methods[0])); -} - - -static void eap_sm_Policy_update(struct eap_sm *sm, const u8 *nak_list, - size_t len) -{ - if (nak_list == NULL || sm == NULL || sm->user == NULL) - return; - - if (sm->user->phase2) { - wpa_printf(MSG_DEBUG, "EAP: EAP-Nak received after Phase2 user" - " info was selected - reject"); - sm->decision = DECISION_FAILURE; - return; - } - - eap_sm_process_nak(sm, nak_list, len); -} - - -static EapType eap_sm_Policy_getNextMethod(struct eap_sm *sm, int *vendor) -{ - EapType next; - int idx = sm->user_eap_method_index; - - /* In theory, there should be no problems with starting - * re-authentication with something else than EAP-Request/Identity and - * this does indeed work with wpa_supplicant. However, at least Funk - * Supplicant seemed to ignore re-auth if it skipped - * EAP-Request/Identity. - * Re-auth sets currentId == -1, so that can be used here to select - * whether Identity needs to be requested again. */ - if (sm->identity == NULL || sm->currentId == -1) { - *vendor = EAP_VENDOR_IETF; - next = EAP_TYPE_IDENTITY; - sm->update_user = TRUE; - } else if (sm->user && idx < EAP_MAX_METHODS && - (sm->user->methods[idx].vendor != EAP_VENDOR_IETF || - sm->user->methods[idx].method != EAP_TYPE_NONE)) { - *vendor = sm->user->methods[idx].vendor; - next = sm->user->methods[idx].method; - sm->user_eap_method_index++; - } else { - *vendor = EAP_VENDOR_IETF; - next = EAP_TYPE_NONE; - } - wpa_printf(MSG_DEBUG, "EAP: getNextMethod: vendor %d type %d", - *vendor, next); - return next; -} - - -static int eap_sm_Policy_getDecision(struct eap_sm *sm) -{ - if (!sm->eap_server && sm->identity && !sm->start_reauth) { - wpa_printf(MSG_DEBUG, "EAP: getDecision: -> PASSTHROUGH"); - return DECISION_PASSTHROUGH; - } - - if (sm->m && sm->currentMethod != EAP_TYPE_IDENTITY && - sm->m->isSuccess(sm, sm->eap_method_priv)) { - wpa_printf(MSG_DEBUG, "EAP: getDecision: method succeeded -> " - "SUCCESS"); - sm->update_user = TRUE; - return DECISION_SUCCESS; - } - - if (sm->m && sm->m->isDone(sm, sm->eap_method_priv) && - !sm->m->isSuccess(sm, sm->eap_method_priv)) { - wpa_printf(MSG_DEBUG, "EAP: getDecision: method failed -> " - "FAILURE"); - sm->update_user = TRUE; - return DECISION_FAILURE; - } - - if ((sm->user == NULL || sm->update_user) && sm->identity && - !sm->start_reauth) { - /* - * Allow Identity method to be started once to allow identity - * selection hint to be sent from the authentication server, - * but prevent a loop of Identity requests by only allowing - * this to happen once. - */ - int id_req = 0; - if (sm->user && sm->currentMethod == EAP_TYPE_IDENTITY && - sm->user->methods[0].vendor == EAP_VENDOR_IETF && - sm->user->methods[0].method == EAP_TYPE_IDENTITY) - id_req = 1; - if (eap_user_get(sm, sm->identity, sm->identity_len, 0) != 0) { - wpa_printf(MSG_DEBUG, "EAP: getDecision: user not " - "found from database -> FAILURE"); - return DECISION_FAILURE; - } - if (id_req && sm->user && - sm->user->methods[0].vendor == EAP_VENDOR_IETF && - sm->user->methods[0].method == EAP_TYPE_IDENTITY) { - wpa_printf(MSG_DEBUG, "EAP: getDecision: stop " - "identity request loop -> FAILURE"); - sm->update_user = TRUE; - return DECISION_FAILURE; - } - sm->update_user = FALSE; - } - sm->start_reauth = FALSE; - - if (sm->user && sm->user_eap_method_index < EAP_MAX_METHODS && - (sm->user->methods[sm->user_eap_method_index].vendor != - EAP_VENDOR_IETF || - sm->user->methods[sm->user_eap_method_index].method != - EAP_TYPE_NONE)) { - wpa_printf(MSG_DEBUG, "EAP: getDecision: another method " - "available -> CONTINUE"); - return DECISION_CONTINUE; - } - - if (sm->identity == NULL || sm->currentId == -1) { - wpa_printf(MSG_DEBUG, "EAP: getDecision: no identity known " - "yet -> CONTINUE"); - return DECISION_CONTINUE; - } - - wpa_printf(MSG_DEBUG, "EAP: getDecision: no more methods available -> " - "FAILURE"); - return DECISION_FAILURE; -} - - -static Boolean eap_sm_Policy_doPickUp(struct eap_sm *sm, EapType method) -{ - return method == EAP_TYPE_IDENTITY ? TRUE : FALSE; -} - - -/** - * eap_server_sm_step - Step EAP server state machine - * @sm: Pointer to EAP state machine allocated with eap_server_sm_init() - * Returns: 1 if EAP state was changed or 0 if not - * - * This function advances EAP state machine to a new state to match with the - * current variables. This should be called whenever variables used by the EAP - * state machine have changed. - */ -int eap_server_sm_step(struct eap_sm *sm) -{ - int res = 0; - do { - sm->changed = FALSE; - SM_STEP_RUN(EAP); - if (sm->changed) - res = 1; - } while (sm->changed); - return res; -} - - -static void eap_user_free(struct eap_user *user) -{ - if (user == NULL) - return; - os_free(user->password); - user->password = NULL; - os_free(user); -} - - -/** - * eap_server_sm_init - Allocate and initialize EAP server state machine - * @eapol_ctx: Context data to be used with eapol_cb calls - * @eapol_cb: Pointer to EAPOL callback functions - * @conf: EAP configuration - * Returns: Pointer to the allocated EAP state machine or %NULL on failure - * - * This function allocates and initializes an EAP state machine. - */ -struct eap_sm * eap_server_sm_init(void *eapol_ctx, - struct eapol_callbacks *eapol_cb, - struct eap_config *conf) -{ - struct eap_sm *sm; - - sm = os_zalloc(sizeof(*sm)); - if (sm == NULL) - return NULL; - sm->eapol_ctx = eapol_ctx; - sm->eapol_cb = eapol_cb; - sm->MaxRetrans = 5; /* RFC 3748: max 3-5 retransmissions suggested */ - sm->ssl_ctx = conf->ssl_ctx; - sm->msg_ctx = conf->msg_ctx; - sm->eap_sim_db_priv = conf->eap_sim_db_priv; - sm->backend_auth = conf->backend_auth; - sm->eap_server = conf->eap_server; - if (conf->pac_opaque_encr_key) { - sm->pac_opaque_encr_key = os_malloc(16); - if (sm->pac_opaque_encr_key) { - os_memcpy(sm->pac_opaque_encr_key, - conf->pac_opaque_encr_key, 16); - } - } - if (conf->eap_fast_a_id) { - sm->eap_fast_a_id = os_malloc(conf->eap_fast_a_id_len); - if (sm->eap_fast_a_id) { - os_memcpy(sm->eap_fast_a_id, conf->eap_fast_a_id, - conf->eap_fast_a_id_len); - sm->eap_fast_a_id_len = conf->eap_fast_a_id_len; - } - } - if (conf->eap_fast_a_id_info) - sm->eap_fast_a_id_info = os_strdup(conf->eap_fast_a_id_info); - sm->eap_fast_prov = conf->eap_fast_prov; - sm->pac_key_lifetime = conf->pac_key_lifetime; - sm->pac_key_refresh_time = conf->pac_key_refresh_time; - sm->eap_sim_aka_result_ind = conf->eap_sim_aka_result_ind; - sm->tnc = conf->tnc; - sm->wps = conf->wps; - if (conf->assoc_wps_ie) - sm->assoc_wps_ie = wpabuf_dup(conf->assoc_wps_ie); - if (conf->assoc_p2p_ie) - sm->assoc_p2p_ie = wpabuf_dup(conf->assoc_p2p_ie); - if (conf->peer_addr) - os_memcpy(sm->peer_addr, conf->peer_addr, ETH_ALEN); - sm->fragment_size = conf->fragment_size; - sm->pwd_group = conf->pwd_group; - - wpa_printf(MSG_DEBUG, "EAP: Server state machine created"); - - return sm; -} - - -/** - * eap_server_sm_deinit - Deinitialize and free an EAP server state machine - * @sm: Pointer to EAP state machine allocated with eap_server_sm_init() - * - * This function deinitializes EAP state machine and frees all allocated - * resources. - */ -void eap_server_sm_deinit(struct eap_sm *sm) -{ - if (sm == NULL) - return; - wpa_printf(MSG_DEBUG, "EAP: Server state machine removed"); - if (sm->m && sm->eap_method_priv) - sm->m->reset(sm, sm->eap_method_priv); - wpabuf_free(sm->eap_if.eapReqData); - os_free(sm->eap_if.eapKeyData); - wpabuf_free(sm->lastReqData); - wpabuf_free(sm->eap_if.eapRespData); - os_free(sm->identity); - os_free(sm->pac_opaque_encr_key); - os_free(sm->eap_fast_a_id); - os_free(sm->eap_fast_a_id_info); - wpabuf_free(sm->eap_if.aaaEapReqData); - wpabuf_free(sm->eap_if.aaaEapRespData); - os_free(sm->eap_if.aaaEapKeyData); - eap_user_free(sm->user); - wpabuf_free(sm->assoc_wps_ie); - wpabuf_free(sm->assoc_p2p_ie); - os_free(sm); -} - - -/** - * eap_sm_notify_cached - Notify EAP state machine of cached PMK - * @sm: Pointer to EAP state machine allocated with eap_server_sm_init() - * - * This function is called when PMKSA caching is used to skip EAP - * authentication. - */ -void eap_sm_notify_cached(struct eap_sm *sm) -{ - if (sm == NULL) - return; - - sm->EAP_state = EAP_SUCCESS; -} - - -/** - * eap_sm_pending_cb - EAP state machine callback for a pending EAP request - * @sm: Pointer to EAP state machine allocated with eap_server_sm_init() - * - * This function is called when data for a pending EAP-Request is received. - */ -void eap_sm_pending_cb(struct eap_sm *sm) -{ - if (sm == NULL) - return; - wpa_printf(MSG_DEBUG, "EAP: Callback for pending request received"); - if (sm->method_pending == METHOD_PENDING_WAIT) - sm->method_pending = METHOD_PENDING_CONT; -} - - -/** - * eap_sm_method_pending - Query whether EAP method is waiting for pending data - * @sm: Pointer to EAP state machine allocated with eap_server_sm_init() - * Returns: 1 if method is waiting for pending data or 0 if not - */ -int eap_sm_method_pending(struct eap_sm *sm) -{ - if (sm == NULL) - return 0; - return sm->method_pending == METHOD_PENDING_WAIT; -} - - -/** - * eap_get_identity - Get the user identity (from EAP-Response/Identity) - * @sm: Pointer to EAP state machine allocated with eap_server_sm_init() - * @len: Buffer for returning identity length - * Returns: Pointer to the user identity or %NULL if not available - */ -const u8 * eap_get_identity(struct eap_sm *sm, size_t *len) -{ - *len = sm->identity_len; - return sm->identity; -} - - -/** - * eap_get_interface - Get pointer to EAP-EAPOL interface data - * @sm: Pointer to EAP state machine allocated with eap_server_sm_init() - * Returns: Pointer to the EAP-EAPOL interface data - */ -struct eap_eapol_interface * eap_get_interface(struct eap_sm *sm) -{ - return &sm->eap_if; -} - - -/** - * eap_server_clear_identity - Clear EAP identity information - * @sm: Pointer to EAP state machine allocated with eap_server_sm_init() - * - * This function can be used to clear the EAP identity information in the EAP - * server context. This allows the EAP/Identity method to be used again after - * EAPOL-Start or EAPOL-Logoff. - */ -void eap_server_clear_identity(struct eap_sm *sm) -{ - os_free(sm->identity); - sm->identity = NULL; -} diff --git a/hostapd-0.8/src/eap_server/eap_server_aka.c b/hostapd-0.8/src/eap_server/eap_server_aka.c deleted file mode 100644 index 42cbdce..0000000 --- a/hostapd-0.8/src/eap_server/eap_server_aka.c +++ /dev/null @@ -1,1278 +0,0 @@ -/* - * hostapd / EAP-AKA (RFC 4187) and EAP-AKA' (draft-arkko-eap-aka-kdf) - * Copyright (c) 2005-2008, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#include "includes.h" - -#include "common.h" -#include "crypto/sha256.h" -#include "crypto/crypto.h" -#include "crypto/random.h" -#include "eap_common/eap_sim_common.h" -#include "eap_server/eap_i.h" -#include "eap_server/eap_sim_db.h" - - -struct eap_aka_data { - u8 mk[EAP_SIM_MK_LEN]; - u8 nonce_s[EAP_SIM_NONCE_S_LEN]; - u8 k_aut[EAP_AKA_PRIME_K_AUT_LEN]; - u8 k_encr[EAP_SIM_K_ENCR_LEN]; - u8 k_re[EAP_AKA_PRIME_K_RE_LEN]; /* EAP-AKA' only */ - u8 msk[EAP_SIM_KEYING_DATA_LEN]; - u8 emsk[EAP_EMSK_LEN]; - u8 rand[EAP_AKA_RAND_LEN]; - u8 autn[EAP_AKA_AUTN_LEN]; - u8 ck[EAP_AKA_CK_LEN]; - u8 ik[EAP_AKA_IK_LEN]; - u8 res[EAP_AKA_RES_MAX_LEN]; - size_t res_len; - enum { - IDENTITY, CHALLENGE, REAUTH, NOTIFICATION, SUCCESS, FAILURE - } state; - char *next_pseudonym; - char *next_reauth_id; - u16 counter; - struct eap_sim_reauth *reauth; - int auts_reported; /* whether the current AUTS has been reported to the - * eap_sim_db */ - u16 notification; - int use_result_ind; - - struct wpabuf *id_msgs; - int pending_id; - u8 eap_method; - u8 *network_name; - size_t network_name_len; - u16 kdf; -}; - - -static void eap_aka_determine_identity(struct eap_sm *sm, - struct eap_aka_data *data, - int before_identity, int after_reauth); - - -static const char * eap_aka_state_txt(int state) -{ - switch (state) { - case IDENTITY: - return "IDENTITY"; - case CHALLENGE: - return "CHALLENGE"; - case REAUTH: - return "REAUTH"; - case SUCCESS: - return "SUCCESS"; - case FAILURE: - return "FAILURE"; - case NOTIFICATION: - return "NOTIFICATION"; - default: - return "Unknown?!"; - } -} - - -static void eap_aka_state(struct eap_aka_data *data, int state) -{ - wpa_printf(MSG_DEBUG, "EAP-AKA: %s -> %s", - eap_aka_state_txt(data->state), - eap_aka_state_txt(state)); - data->state = state; -} - - -static void * eap_aka_init(struct eap_sm *sm) -{ - struct eap_aka_data *data; - - if (sm->eap_sim_db_priv == NULL) { - wpa_printf(MSG_WARNING, "EAP-AKA: eap_sim_db not configured"); - return NULL; - } - - data = os_zalloc(sizeof(*data)); - if (data == NULL) - return NULL; - - data->eap_method = EAP_TYPE_AKA; - - data->state = IDENTITY; - eap_aka_determine_identity(sm, data, 1, 0); - data->pending_id = -1; - - return data; -} - - -#ifdef EAP_SERVER_AKA_PRIME -static void * eap_aka_prime_init(struct eap_sm *sm) -{ - struct eap_aka_data *data; - /* TODO: make ANID configurable; see 3GPP TS 24.302 */ - char *network_name = "WLAN"; - - if (sm->eap_sim_db_priv == NULL) { - wpa_printf(MSG_WARNING, "EAP-AKA: eap_sim_db not configured"); - return NULL; - } - - data = os_zalloc(sizeof(*data)); - if (data == NULL) - return NULL; - - data->eap_method = EAP_TYPE_AKA_PRIME; - data->network_name = os_malloc(os_strlen(network_name)); - if (data->network_name == NULL) { - os_free(data); - return NULL; - } - - data->network_name_len = os_strlen(network_name); - os_memcpy(data->network_name, network_name, data->network_name_len); - - data->state = IDENTITY; - eap_aka_determine_identity(sm, data, 1, 0); - data->pending_id = -1; - - return data; -} -#endif /* EAP_SERVER_AKA_PRIME */ - - -static void eap_aka_reset(struct eap_sm *sm, void *priv) -{ - struct eap_aka_data *data = priv; - os_free(data->next_pseudonym); - os_free(data->next_reauth_id); - wpabuf_free(data->id_msgs); - os_free(data->network_name); - os_free(data); -} - - -static int eap_aka_add_id_msg(struct eap_aka_data *data, - const struct wpabuf *msg) -{ - if (msg == NULL) - return -1; - - if (data->id_msgs == NULL) { - data->id_msgs = wpabuf_dup(msg); - return data->id_msgs == NULL ? -1 : 0; - } - - if (wpabuf_resize(&data->id_msgs, wpabuf_len(msg)) < 0) - return -1; - wpabuf_put_buf(data->id_msgs, msg); - - return 0; -} - - -static void eap_aka_add_checkcode(struct eap_aka_data *data, - struct eap_sim_msg *msg) -{ - const u8 *addr; - size_t len; - u8 hash[SHA256_MAC_LEN]; - - wpa_printf(MSG_DEBUG, " AT_CHECKCODE"); - - if (data->id_msgs == NULL) { - /* - * No EAP-AKA/Identity packets were exchanged - send empty - * checkcode. - */ - eap_sim_msg_add(msg, EAP_SIM_AT_CHECKCODE, 0, NULL, 0); - return; - } - - /* Checkcode is SHA1 hash over all EAP-AKA/Identity packets. */ - addr = wpabuf_head(data->id_msgs); - len = wpabuf_len(data->id_msgs); - wpa_hexdump(MSG_MSGDUMP, "EAP-AKA: AT_CHECKCODE data", addr, len); - if (data->eap_method == EAP_TYPE_AKA_PRIME) - sha256_vector(1, &addr, &len, hash); - else - sha1_vector(1, &addr, &len, hash); - - eap_sim_msg_add(msg, EAP_SIM_AT_CHECKCODE, 0, hash, - data->eap_method == EAP_TYPE_AKA_PRIME ? - EAP_AKA_PRIME_CHECKCODE_LEN : EAP_AKA_CHECKCODE_LEN); -} - - -static int eap_aka_verify_checkcode(struct eap_aka_data *data, - const u8 *checkcode, size_t checkcode_len) -{ - const u8 *addr; - size_t len; - u8 hash[SHA256_MAC_LEN]; - size_t hash_len; - - if (checkcode == NULL) - return -1; - - if (data->id_msgs == NULL) { - if (checkcode_len != 0) { - wpa_printf(MSG_DEBUG, "EAP-AKA: Checkcode from peer " - "indicates that AKA/Identity messages were " - "used, but they were not"); - return -1; - } - return 0; - } - - hash_len = data->eap_method == EAP_TYPE_AKA_PRIME ? - EAP_AKA_PRIME_CHECKCODE_LEN : EAP_AKA_CHECKCODE_LEN; - - if (checkcode_len != hash_len) { - wpa_printf(MSG_DEBUG, "EAP-AKA: Checkcode from peer indicates " - "that AKA/Identity message were not used, but they " - "were"); - return -1; - } - - /* Checkcode is SHA1 hash over all EAP-AKA/Identity packets. */ - addr = wpabuf_head(data->id_msgs); - len = wpabuf_len(data->id_msgs); - if (data->eap_method == EAP_TYPE_AKA_PRIME) - sha256_vector(1, &addr, &len, hash); - else - sha1_vector(1, &addr, &len, hash); - - if (os_memcmp(hash, checkcode, hash_len) != 0) { - wpa_printf(MSG_DEBUG, "EAP-AKA: Mismatch in AT_CHECKCODE"); - return -1; - } - - return 0; -} - - -static struct wpabuf * eap_aka_build_identity(struct eap_sm *sm, - struct eap_aka_data *data, u8 id) -{ - struct eap_sim_msg *msg; - struct wpabuf *buf; - - wpa_printf(MSG_DEBUG, "EAP-AKA: Generating Identity"); - msg = eap_sim_msg_init(EAP_CODE_REQUEST, id, data->eap_method, - EAP_AKA_SUBTYPE_IDENTITY); - if (eap_sim_db_identity_known(sm->eap_sim_db_priv, sm->identity, - sm->identity_len)) { - wpa_printf(MSG_DEBUG, " AT_PERMANENT_ID_REQ"); - eap_sim_msg_add(msg, EAP_SIM_AT_PERMANENT_ID_REQ, 0, NULL, 0); - } else { - /* - * RFC 4187, Chap. 4.1.4 recommends that identity from EAP is - * ignored and the AKA/Identity is used to request the - * identity. - */ - wpa_printf(MSG_DEBUG, " AT_ANY_ID_REQ"); - eap_sim_msg_add(msg, EAP_SIM_AT_ANY_ID_REQ, 0, NULL, 0); - } - buf = eap_sim_msg_finish(msg, NULL, NULL, 0); - if (eap_aka_add_id_msg(data, buf) < 0) { - wpabuf_free(buf); - return NULL; - } - data->pending_id = id; - return buf; -} - - -static int eap_aka_build_encr(struct eap_sm *sm, struct eap_aka_data *data, - struct eap_sim_msg *msg, u16 counter, - const u8 *nonce_s) -{ - os_free(data->next_pseudonym); - data->next_pseudonym = - eap_sim_db_get_next_pseudonym(sm->eap_sim_db_priv, 1); - os_free(data->next_reauth_id); - if (data->counter <= EAP_AKA_MAX_FAST_REAUTHS) { - data->next_reauth_id = - eap_sim_db_get_next_reauth_id(sm->eap_sim_db_priv, 1); - } else { - wpa_printf(MSG_DEBUG, "EAP-AKA: Max fast re-authentication " - "count exceeded - force full authentication"); - data->next_reauth_id = NULL; - } - - if (data->next_pseudonym == NULL && data->next_reauth_id == NULL && - counter == 0 && nonce_s == NULL) - return 0; - - wpa_printf(MSG_DEBUG, " AT_IV"); - wpa_printf(MSG_DEBUG, " AT_ENCR_DATA"); - eap_sim_msg_add_encr_start(msg, EAP_SIM_AT_IV, EAP_SIM_AT_ENCR_DATA); - - if (counter > 0) { - wpa_printf(MSG_DEBUG, " *AT_COUNTER (%u)", counter); - eap_sim_msg_add(msg, EAP_SIM_AT_COUNTER, counter, NULL, 0); - } - - if (nonce_s) { - wpa_printf(MSG_DEBUG, " *AT_NONCE_S"); - eap_sim_msg_add(msg, EAP_SIM_AT_NONCE_S, 0, nonce_s, - EAP_SIM_NONCE_S_LEN); - } - - if (data->next_pseudonym) { - wpa_printf(MSG_DEBUG, " *AT_NEXT_PSEUDONYM (%s)", - data->next_pseudonym); - eap_sim_msg_add(msg, EAP_SIM_AT_NEXT_PSEUDONYM, - os_strlen(data->next_pseudonym), - (u8 *) data->next_pseudonym, - os_strlen(data->next_pseudonym)); - } - - if (data->next_reauth_id) { - wpa_printf(MSG_DEBUG, " *AT_NEXT_REAUTH_ID (%s)", - data->next_reauth_id); - eap_sim_msg_add(msg, EAP_SIM_AT_NEXT_REAUTH_ID, - os_strlen(data->next_reauth_id), - (u8 *) data->next_reauth_id, - os_strlen(data->next_reauth_id)); - } - - if (eap_sim_msg_add_encr_end(msg, data->k_encr, EAP_SIM_AT_PADDING)) { - wpa_printf(MSG_WARNING, "EAP-AKA: Failed to encrypt " - "AT_ENCR_DATA"); - return -1; - } - - return 0; -} - - -static struct wpabuf * eap_aka_build_challenge(struct eap_sm *sm, - struct eap_aka_data *data, - u8 id) -{ - struct eap_sim_msg *msg; - - wpa_printf(MSG_DEBUG, "EAP-AKA: Generating Challenge"); - msg = eap_sim_msg_init(EAP_CODE_REQUEST, id, data->eap_method, - EAP_AKA_SUBTYPE_CHALLENGE); - wpa_printf(MSG_DEBUG, " AT_RAND"); - eap_sim_msg_add(msg, EAP_SIM_AT_RAND, 0, data->rand, EAP_AKA_RAND_LEN); - wpa_printf(MSG_DEBUG, " AT_AUTN"); - eap_sim_msg_add(msg, EAP_SIM_AT_AUTN, 0, data->autn, EAP_AKA_AUTN_LEN); - if (data->eap_method == EAP_TYPE_AKA_PRIME) { - if (data->kdf) { - /* Add the selected KDF into the beginning */ - wpa_printf(MSG_DEBUG, " AT_KDF"); - eap_sim_msg_add(msg, EAP_SIM_AT_KDF, data->kdf, - NULL, 0); - } - wpa_printf(MSG_DEBUG, " AT_KDF"); - eap_sim_msg_add(msg, EAP_SIM_AT_KDF, EAP_AKA_PRIME_KDF, - NULL, 0); - wpa_printf(MSG_DEBUG, " AT_KDF_INPUT"); - eap_sim_msg_add(msg, EAP_SIM_AT_KDF_INPUT, - data->network_name_len, - data->network_name, data->network_name_len); - } - - if (eap_aka_build_encr(sm, data, msg, 0, NULL)) { - eap_sim_msg_free(msg); - return NULL; - } - - eap_aka_add_checkcode(data, msg); - - if (sm->eap_sim_aka_result_ind) { - wpa_printf(MSG_DEBUG, " AT_RESULT_IND"); - eap_sim_msg_add(msg, EAP_SIM_AT_RESULT_IND, 0, NULL, 0); - } - -#ifdef EAP_SERVER_AKA_PRIME - if (data->eap_method == EAP_TYPE_AKA) { - u16 flags = 0; - int i; - int aka_prime_preferred = 0; - - i = 0; - while (sm->user && i < EAP_MAX_METHODS && - (sm->user->methods[i].vendor != EAP_VENDOR_IETF || - sm->user->methods[i].method != EAP_TYPE_NONE)) { - if (sm->user->methods[i].vendor == EAP_VENDOR_IETF) { - if (sm->user->methods[i].method == - EAP_TYPE_AKA) - break; - if (sm->user->methods[i].method == - EAP_TYPE_AKA_PRIME) { - aka_prime_preferred = 1; - break; - } - } - i++; - } - - if (aka_prime_preferred) - flags |= EAP_AKA_BIDDING_FLAG_D; - eap_sim_msg_add(msg, EAP_SIM_AT_BIDDING, flags, NULL, 0); - } -#endif /* EAP_SERVER_AKA_PRIME */ - - wpa_printf(MSG_DEBUG, " AT_MAC"); - eap_sim_msg_add_mac(msg, EAP_SIM_AT_MAC); - return eap_sim_msg_finish(msg, data->k_aut, NULL, 0); -} - - -static struct wpabuf * eap_aka_build_reauth(struct eap_sm *sm, - struct eap_aka_data *data, u8 id) -{ - struct eap_sim_msg *msg; - - wpa_printf(MSG_DEBUG, "EAP-AKA: Generating Re-authentication"); - - if (random_get_bytes(data->nonce_s, EAP_SIM_NONCE_S_LEN)) - return NULL; - wpa_hexdump_key(MSG_MSGDUMP, "EAP-AKA: NONCE_S", - data->nonce_s, EAP_SIM_NONCE_S_LEN); - - if (data->eap_method == EAP_TYPE_AKA_PRIME) { - eap_aka_prime_derive_keys_reauth(data->k_re, data->counter, - sm->identity, - sm->identity_len, - data->nonce_s, - data->msk, data->emsk); - } else { - eap_sim_derive_keys(data->mk, data->k_encr, data->k_aut, - data->msk, data->emsk); - eap_sim_derive_keys_reauth(data->counter, sm->identity, - sm->identity_len, data->nonce_s, - data->mk, data->msk, data->emsk); - } - - msg = eap_sim_msg_init(EAP_CODE_REQUEST, id, data->eap_method, - EAP_AKA_SUBTYPE_REAUTHENTICATION); - - if (eap_aka_build_encr(sm, data, msg, data->counter, data->nonce_s)) { - eap_sim_msg_free(msg); - return NULL; - } - - eap_aka_add_checkcode(data, msg); - - if (sm->eap_sim_aka_result_ind) { - wpa_printf(MSG_DEBUG, " AT_RESULT_IND"); - eap_sim_msg_add(msg, EAP_SIM_AT_RESULT_IND, 0, NULL, 0); - } - - wpa_printf(MSG_DEBUG, " AT_MAC"); - eap_sim_msg_add_mac(msg, EAP_SIM_AT_MAC); - return eap_sim_msg_finish(msg, data->k_aut, NULL, 0); -} - - -static struct wpabuf * eap_aka_build_notification(struct eap_sm *sm, - struct eap_aka_data *data, - u8 id) -{ - struct eap_sim_msg *msg; - - wpa_printf(MSG_DEBUG, "EAP-AKA: Generating Notification"); - msg = eap_sim_msg_init(EAP_CODE_REQUEST, id, data->eap_method, - EAP_AKA_SUBTYPE_NOTIFICATION); - wpa_printf(MSG_DEBUG, " AT_NOTIFICATION (%d)", data->notification); - eap_sim_msg_add(msg, EAP_SIM_AT_NOTIFICATION, data->notification, - NULL, 0); - if (data->use_result_ind) { - if (data->reauth) { - wpa_printf(MSG_DEBUG, " AT_IV"); - wpa_printf(MSG_DEBUG, " AT_ENCR_DATA"); - eap_sim_msg_add_encr_start(msg, EAP_SIM_AT_IV, - EAP_SIM_AT_ENCR_DATA); - wpa_printf(MSG_DEBUG, " *AT_COUNTER (%u)", - data->counter); - eap_sim_msg_add(msg, EAP_SIM_AT_COUNTER, data->counter, - NULL, 0); - - if (eap_sim_msg_add_encr_end(msg, data->k_encr, - EAP_SIM_AT_PADDING)) { - wpa_printf(MSG_WARNING, "EAP-AKA: Failed to " - "encrypt AT_ENCR_DATA"); - eap_sim_msg_free(msg); - return NULL; - } - } - - wpa_printf(MSG_DEBUG, " AT_MAC"); - eap_sim_msg_add_mac(msg, EAP_SIM_AT_MAC); - } - return eap_sim_msg_finish(msg, data->k_aut, NULL, 0); -} - - -static struct wpabuf * eap_aka_buildReq(struct eap_sm *sm, void *priv, u8 id) -{ - struct eap_aka_data *data = priv; - - data->auts_reported = 0; - switch (data->state) { - case IDENTITY: - return eap_aka_build_identity(sm, data, id); - case CHALLENGE: - return eap_aka_build_challenge(sm, data, id); - case REAUTH: - return eap_aka_build_reauth(sm, data, id); - case NOTIFICATION: - return eap_aka_build_notification(sm, data, id); - default: - wpa_printf(MSG_DEBUG, "EAP-AKA: Unknown state %d in " - "buildReq", data->state); - break; - } - return NULL; -} - - -static Boolean eap_aka_check(struct eap_sm *sm, void *priv, - struct wpabuf *respData) -{ - struct eap_aka_data *data = priv; - const u8 *pos; - size_t len; - - pos = eap_hdr_validate(EAP_VENDOR_IETF, data->eap_method, respData, - &len); - if (pos == NULL || len < 3) { - wpa_printf(MSG_INFO, "EAP-AKA: Invalid frame"); - return TRUE; - } - - return FALSE; -} - - -static Boolean eap_aka_subtype_ok(struct eap_aka_data *data, u8 subtype) -{ - if (subtype == EAP_AKA_SUBTYPE_CLIENT_ERROR || - subtype == EAP_AKA_SUBTYPE_AUTHENTICATION_REJECT) - return FALSE; - - switch (data->state) { - case IDENTITY: - if (subtype != EAP_AKA_SUBTYPE_IDENTITY) { - wpa_printf(MSG_INFO, "EAP-AKA: Unexpected response " - "subtype %d", subtype); - return TRUE; - } - break; - case CHALLENGE: - if (subtype != EAP_AKA_SUBTYPE_CHALLENGE && - subtype != EAP_AKA_SUBTYPE_SYNCHRONIZATION_FAILURE) { - wpa_printf(MSG_INFO, "EAP-AKA: Unexpected response " - "subtype %d", subtype); - return TRUE; - } - break; - case REAUTH: - if (subtype != EAP_AKA_SUBTYPE_REAUTHENTICATION) { - wpa_printf(MSG_INFO, "EAP-AKA: Unexpected response " - "subtype %d", subtype); - return TRUE; - } - break; - case NOTIFICATION: - if (subtype != EAP_AKA_SUBTYPE_NOTIFICATION) { - wpa_printf(MSG_INFO, "EAP-AKA: Unexpected response " - "subtype %d", subtype); - return TRUE; - } - break; - default: - wpa_printf(MSG_INFO, "EAP-AKA: Unexpected state (%d) for " - "processing a response", data->state); - return TRUE; - } - - return FALSE; -} - - -static void eap_aka_determine_identity(struct eap_sm *sm, - struct eap_aka_data *data, - int before_identity, int after_reauth) -{ - const u8 *identity; - size_t identity_len; - int res; - - identity = NULL; - identity_len = 0; - - if (after_reauth && data->reauth) { - identity = data->reauth->identity; - identity_len = data->reauth->identity_len; - } else if (sm->identity && sm->identity_len > 0 && - sm->identity[0] == EAP_AKA_PERMANENT_PREFIX) { - identity = sm->identity; - identity_len = sm->identity_len; - } else { - identity = eap_sim_db_get_permanent(sm->eap_sim_db_priv, - sm->identity, - sm->identity_len, - &identity_len); - if (identity == NULL) { - data->reauth = eap_sim_db_get_reauth_entry( - sm->eap_sim_db_priv, sm->identity, - sm->identity_len); - if (data->reauth && - data->reauth->aka_prime != - (data->eap_method == EAP_TYPE_AKA_PRIME)) { - wpa_printf(MSG_DEBUG, "EAP-AKA: Reauth data " - "was for different AKA version"); - data->reauth = NULL; - } - if (data->reauth) { - wpa_printf(MSG_DEBUG, "EAP-AKA: Using fast " - "re-authentication"); - identity = data->reauth->identity; - identity_len = data->reauth->identity_len; - data->counter = data->reauth->counter; - if (data->eap_method == EAP_TYPE_AKA_PRIME) { - os_memcpy(data->k_encr, - data->reauth->k_encr, - EAP_SIM_K_ENCR_LEN); - os_memcpy(data->k_aut, - data->reauth->k_aut, - EAP_AKA_PRIME_K_AUT_LEN); - os_memcpy(data->k_re, - data->reauth->k_re, - EAP_AKA_PRIME_K_RE_LEN); - } else { - os_memcpy(data->mk, data->reauth->mk, - EAP_SIM_MK_LEN); - } - } - } - } - - if (identity == NULL || - eap_sim_db_identity_known(sm->eap_sim_db_priv, sm->identity, - sm->identity_len) < 0) { - if (before_identity) { - wpa_printf(MSG_DEBUG, "EAP-AKA: Permanent user name " - "not known - send AKA-Identity request"); - eap_aka_state(data, IDENTITY); - return; - } else { - wpa_printf(MSG_DEBUG, "EAP-AKA: Unknown whether the " - "permanent user name is known; try to use " - "it"); - /* eap_sim_db_get_aka_auth() will report failure, if - * this identity is not known. */ - } - } - - wpa_hexdump_ascii(MSG_DEBUG, "EAP-AKA: Identity", - identity, identity_len); - - if (!after_reauth && data->reauth) { - eap_aka_state(data, REAUTH); - return; - } - - res = eap_sim_db_get_aka_auth(sm->eap_sim_db_priv, identity, - identity_len, data->rand, data->autn, - data->ik, data->ck, data->res, - &data->res_len, sm); - if (res == EAP_SIM_DB_PENDING) { - wpa_printf(MSG_DEBUG, "EAP-AKA: AKA authentication data " - "not yet available - pending request"); - sm->method_pending = METHOD_PENDING_WAIT; - return; - } - -#ifdef EAP_SERVER_AKA_PRIME - if (data->eap_method == EAP_TYPE_AKA_PRIME) { - /* Note: AUTN = (SQN ^ AK) || AMF || MAC which gives us the - * needed 6-octet SQN ^AK for CK',IK' derivation */ - eap_aka_prime_derive_ck_ik_prime(data->ck, data->ik, - data->autn, - data->network_name, - data->network_name_len); - } -#endif /* EAP_SERVER_AKA_PRIME */ - - data->reauth = NULL; - data->counter = 0; /* reset re-auth counter since this is full auth */ - - if (res != 0) { - wpa_printf(MSG_INFO, "EAP-AKA: Failed to get AKA " - "authentication data for the peer"); - data->notification = EAP_SIM_GENERAL_FAILURE_BEFORE_AUTH; - eap_aka_state(data, NOTIFICATION); - return; - } - if (sm->method_pending == METHOD_PENDING_WAIT) { - wpa_printf(MSG_DEBUG, "EAP-AKA: AKA authentication data " - "available - abort pending wait"); - sm->method_pending = METHOD_PENDING_NONE; - } - - identity_len = sm->identity_len; - while (identity_len > 0 && sm->identity[identity_len - 1] == '\0') { - wpa_printf(MSG_DEBUG, "EAP-AKA: Workaround - drop last null " - "character from identity"); - identity_len--; - } - wpa_hexdump_ascii(MSG_DEBUG, "EAP-AKA: Identity for MK derivation", - sm->identity, identity_len); - - if (data->eap_method == EAP_TYPE_AKA_PRIME) { - eap_aka_prime_derive_keys(identity, identity_len, data->ik, - data->ck, data->k_encr, data->k_aut, - data->k_re, data->msk, data->emsk); - } else { - eap_aka_derive_mk(sm->identity, identity_len, data->ik, - data->ck, data->mk); - eap_sim_derive_keys(data->mk, data->k_encr, data->k_aut, - data->msk, data->emsk); - } - - eap_aka_state(data, CHALLENGE); -} - - -static void eap_aka_process_identity(struct eap_sm *sm, - struct eap_aka_data *data, - struct wpabuf *respData, - struct eap_sim_attrs *attr) -{ - wpa_printf(MSG_DEBUG, "EAP-AKA: Processing Identity"); - - if (attr->mac || attr->iv || attr->encr_data) { - wpa_printf(MSG_WARNING, "EAP-AKA: Unexpected attribute " - "received in EAP-Response/AKA-Identity"); - data->notification = EAP_SIM_GENERAL_FAILURE_BEFORE_AUTH; - eap_aka_state(data, NOTIFICATION); - return; - } - - if (attr->identity) { - os_free(sm->identity); - sm->identity = os_malloc(attr->identity_len); - if (sm->identity) { - os_memcpy(sm->identity, attr->identity, - attr->identity_len); - sm->identity_len = attr->identity_len; - } - } - - eap_aka_determine_identity(sm, data, 0, 0); - if (eap_get_id(respData) == data->pending_id) { - data->pending_id = -1; - eap_aka_add_id_msg(data, respData); - } -} - - -static int eap_aka_verify_mac(struct eap_aka_data *data, - const struct wpabuf *req, - const u8 *mac, const u8 *extra, - size_t extra_len) -{ - if (data->eap_method == EAP_TYPE_AKA_PRIME) - return eap_sim_verify_mac_sha256(data->k_aut, req, mac, extra, - extra_len); - return eap_sim_verify_mac(data->k_aut, req, mac, extra, extra_len); -} - - -static void eap_aka_process_challenge(struct eap_sm *sm, - struct eap_aka_data *data, - struct wpabuf *respData, - struct eap_sim_attrs *attr) -{ - const u8 *identity; - size_t identity_len; - - wpa_printf(MSG_DEBUG, "EAP-AKA: Processing Challenge"); - -#ifdef EAP_SERVER_AKA_PRIME -#if 0 - /* KDF negotiation; to be enabled only after more than one KDF is - * supported */ - if (data->eap_method == EAP_TYPE_AKA_PRIME && - attr->kdf_count == 1 && attr->mac == NULL) { - if (attr->kdf[0] != EAP_AKA_PRIME_KDF) { - wpa_printf(MSG_WARNING, "EAP-AKA': Peer selected " - "unknown KDF"); - data->notification = - EAP_SIM_GENERAL_FAILURE_BEFORE_AUTH; - eap_aka_state(data, NOTIFICATION); - return; - } - - data->kdf = attr->kdf[0]; - - /* Allow negotiation to continue with the selected KDF by - * sending another Challenge message */ - wpa_printf(MSG_DEBUG, "EAP-AKA': KDF %d selected", data->kdf); - return; - } -#endif -#endif /* EAP_SERVER_AKA_PRIME */ - - if (attr->checkcode && - eap_aka_verify_checkcode(data, attr->checkcode, - attr->checkcode_len)) { - wpa_printf(MSG_WARNING, "EAP-AKA: Invalid AT_CHECKCODE in the " - "message"); - data->notification = EAP_SIM_GENERAL_FAILURE_BEFORE_AUTH; - eap_aka_state(data, NOTIFICATION); - return; - } - if (attr->mac == NULL || - eap_aka_verify_mac(data, respData, attr->mac, NULL, 0)) { - wpa_printf(MSG_WARNING, "EAP-AKA: Challenge message " - "did not include valid AT_MAC"); - data->notification = EAP_SIM_GENERAL_FAILURE_BEFORE_AUTH; - eap_aka_state(data, NOTIFICATION); - return; - } - - /* - * AT_RES is padded, so verify that there is enough room for RES and - * that the RES length in bits matches with the expected RES. - */ - if (attr->res == NULL || attr->res_len < data->res_len || - attr->res_len_bits != data->res_len * 8 || - os_memcmp(attr->res, data->res, data->res_len) != 0) { - wpa_printf(MSG_WARNING, "EAP-AKA: Challenge message did not " - "include valid AT_RES (attr len=%lu, res len=%lu " - "bits, expected %lu bits)", - (unsigned long) attr->res_len, - (unsigned long) attr->res_len_bits, - (unsigned long) data->res_len * 8); - data->notification = EAP_SIM_GENERAL_FAILURE_BEFORE_AUTH; - eap_aka_state(data, NOTIFICATION); - return; - } - - wpa_printf(MSG_DEBUG, "EAP-AKA: Challenge response includes the " - "correct AT_MAC"); - if (sm->eap_sim_aka_result_ind && attr->result_ind) { - data->use_result_ind = 1; - data->notification = EAP_SIM_SUCCESS; - eap_aka_state(data, NOTIFICATION); - } else - eap_aka_state(data, SUCCESS); - - identity = eap_sim_db_get_permanent(sm->eap_sim_db_priv, sm->identity, - sm->identity_len, &identity_len); - if (identity == NULL) { - identity = sm->identity; - identity_len = sm->identity_len; - } - - if (data->next_pseudonym) { - eap_sim_db_add_pseudonym(sm->eap_sim_db_priv, identity, - identity_len, - data->next_pseudonym); - data->next_pseudonym = NULL; - } - if (data->next_reauth_id) { - if (data->eap_method == EAP_TYPE_AKA_PRIME) { -#ifdef EAP_SERVER_AKA_PRIME - eap_sim_db_add_reauth_prime(sm->eap_sim_db_priv, - identity, - identity_len, - data->next_reauth_id, - data->counter + 1, - data->k_encr, data->k_aut, - data->k_re); -#endif /* EAP_SERVER_AKA_PRIME */ - } else { - eap_sim_db_add_reauth(sm->eap_sim_db_priv, identity, - identity_len, - data->next_reauth_id, - data->counter + 1, - data->mk); - } - data->next_reauth_id = NULL; - } -} - - -static void eap_aka_process_sync_failure(struct eap_sm *sm, - struct eap_aka_data *data, - struct wpabuf *respData, - struct eap_sim_attrs *attr) -{ - wpa_printf(MSG_DEBUG, "EAP-AKA: Processing Synchronization-Failure"); - - if (attr->auts == NULL) { - wpa_printf(MSG_WARNING, "EAP-AKA: Synchronization-Failure " - "message did not include valid AT_AUTS"); - data->notification = EAP_SIM_GENERAL_FAILURE_BEFORE_AUTH; - eap_aka_state(data, NOTIFICATION); - return; - } - - /* Avoid re-reporting AUTS when processing pending EAP packet by - * maintaining a local flag stating whether this AUTS has already been - * reported. */ - if (!data->auts_reported && - eap_sim_db_resynchronize(sm->eap_sim_db_priv, sm->identity, - sm->identity_len, attr->auts, - data->rand)) { - wpa_printf(MSG_WARNING, "EAP-AKA: Resynchronization failed"); - data->notification = EAP_SIM_GENERAL_FAILURE_BEFORE_AUTH; - eap_aka_state(data, NOTIFICATION); - return; - } - data->auts_reported = 1; - - /* Try again after resynchronization */ - eap_aka_determine_identity(sm, data, 0, 0); -} - - -static void eap_aka_process_reauth(struct eap_sm *sm, - struct eap_aka_data *data, - struct wpabuf *respData, - struct eap_sim_attrs *attr) -{ - struct eap_sim_attrs eattr; - u8 *decrypted = NULL; - const u8 *identity, *id2; - size_t identity_len, id2_len; - - wpa_printf(MSG_DEBUG, "EAP-AKA: Processing Reauthentication"); - - if (attr->mac == NULL || - eap_aka_verify_mac(data, respData, attr->mac, data->nonce_s, - EAP_SIM_NONCE_S_LEN)) { - wpa_printf(MSG_WARNING, "EAP-AKA: Re-authentication message " - "did not include valid AT_MAC"); - goto fail; - } - - if (attr->encr_data == NULL || attr->iv == NULL) { - wpa_printf(MSG_WARNING, "EAP-AKA: Reauthentication " - "message did not include encrypted data"); - goto fail; - } - - decrypted = eap_sim_parse_encr(data->k_encr, attr->encr_data, - attr->encr_data_len, attr->iv, &eattr, - 0); - if (decrypted == NULL) { - wpa_printf(MSG_WARNING, "EAP-AKA: Failed to parse encrypted " - "data from reauthentication message"); - goto fail; - } - - if (eattr.counter != data->counter) { - wpa_printf(MSG_WARNING, "EAP-AKA: Re-authentication message " - "used incorrect counter %u, expected %u", - eattr.counter, data->counter); - goto fail; - } - os_free(decrypted); - decrypted = NULL; - - wpa_printf(MSG_DEBUG, "EAP-AKA: Re-authentication response includes " - "the correct AT_MAC"); - - if (eattr.counter_too_small) { - wpa_printf(MSG_DEBUG, "EAP-AKA: Re-authentication response " - "included AT_COUNTER_TOO_SMALL - starting full " - "authentication"); - eap_aka_determine_identity(sm, data, 0, 1); - return; - } - - if (sm->eap_sim_aka_result_ind && attr->result_ind) { - data->use_result_ind = 1; - data->notification = EAP_SIM_SUCCESS; - eap_aka_state(data, NOTIFICATION); - } else - eap_aka_state(data, SUCCESS); - - if (data->reauth) { - identity = data->reauth->identity; - identity_len = data->reauth->identity_len; - } else { - identity = sm->identity; - identity_len = sm->identity_len; - } - - id2 = eap_sim_db_get_permanent(sm->eap_sim_db_priv, identity, - identity_len, &id2_len); - if (id2) { - identity = id2; - identity_len = id2_len; - } - - if (data->next_pseudonym) { - eap_sim_db_add_pseudonym(sm->eap_sim_db_priv, identity, - identity_len, data->next_pseudonym); - data->next_pseudonym = NULL; - } - if (data->next_reauth_id) { - if (data->eap_method == EAP_TYPE_AKA_PRIME) { -#ifdef EAP_SERVER_AKA_PRIME - eap_sim_db_add_reauth_prime(sm->eap_sim_db_priv, - identity, - identity_len, - data->next_reauth_id, - data->counter + 1, - data->k_encr, data->k_aut, - data->k_re); -#endif /* EAP_SERVER_AKA_PRIME */ - } else { - eap_sim_db_add_reauth(sm->eap_sim_db_priv, identity, - identity_len, - data->next_reauth_id, - data->counter + 1, - data->mk); - } - data->next_reauth_id = NULL; - } else { - eap_sim_db_remove_reauth(sm->eap_sim_db_priv, data->reauth); - data->reauth = NULL; - } - - return; - -fail: - data->notification = EAP_SIM_GENERAL_FAILURE_BEFORE_AUTH; - eap_aka_state(data, NOTIFICATION); - eap_sim_db_remove_reauth(sm->eap_sim_db_priv, data->reauth); - data->reauth = NULL; - os_free(decrypted); -} - - -static void eap_aka_process_client_error(struct eap_sm *sm, - struct eap_aka_data *data, - struct wpabuf *respData, - struct eap_sim_attrs *attr) -{ - wpa_printf(MSG_DEBUG, "EAP-AKA: Client reported error %d", - attr->client_error_code); - if (data->notification == EAP_SIM_SUCCESS && data->use_result_ind) - eap_aka_state(data, SUCCESS); - else - eap_aka_state(data, FAILURE); -} - - -static void eap_aka_process_authentication_reject( - struct eap_sm *sm, struct eap_aka_data *data, - struct wpabuf *respData, struct eap_sim_attrs *attr) -{ - wpa_printf(MSG_DEBUG, "EAP-AKA: Client rejected authentication"); - eap_aka_state(data, FAILURE); -} - - -static void eap_aka_process_notification(struct eap_sm *sm, - struct eap_aka_data *data, - struct wpabuf *respData, - struct eap_sim_attrs *attr) -{ - wpa_printf(MSG_DEBUG, "EAP-AKA: Client replied to notification"); - if (data->notification == EAP_SIM_SUCCESS && data->use_result_ind) - eap_aka_state(data, SUCCESS); - else - eap_aka_state(data, FAILURE); -} - - -static void eap_aka_process(struct eap_sm *sm, void *priv, - struct wpabuf *respData) -{ - struct eap_aka_data *data = priv; - const u8 *pos, *end; - u8 subtype; - size_t len; - struct eap_sim_attrs attr; - - pos = eap_hdr_validate(EAP_VENDOR_IETF, data->eap_method, respData, - &len); - if (pos == NULL || len < 3) - return; - - end = pos + len; - subtype = *pos; - pos += 3; - - if (eap_aka_subtype_ok(data, subtype)) { - wpa_printf(MSG_DEBUG, "EAP-AKA: Unrecognized or unexpected " - "EAP-AKA Subtype in EAP Response"); - data->notification = EAP_SIM_GENERAL_FAILURE_BEFORE_AUTH; - eap_aka_state(data, NOTIFICATION); - return; - } - - if (eap_sim_parse_attr(pos, end, &attr, - data->eap_method == EAP_TYPE_AKA_PRIME ? 2 : 1, - 0)) { - wpa_printf(MSG_DEBUG, "EAP-AKA: Failed to parse attributes"); - data->notification = EAP_SIM_GENERAL_FAILURE_BEFORE_AUTH; - eap_aka_state(data, NOTIFICATION); - return; - } - - if (subtype == EAP_AKA_SUBTYPE_CLIENT_ERROR) { - eap_aka_process_client_error(sm, data, respData, &attr); - return; - } - - if (subtype == EAP_AKA_SUBTYPE_AUTHENTICATION_REJECT) { - eap_aka_process_authentication_reject(sm, data, respData, - &attr); - return; - } - - switch (data->state) { - case IDENTITY: - eap_aka_process_identity(sm, data, respData, &attr); - break; - case CHALLENGE: - if (subtype == EAP_AKA_SUBTYPE_SYNCHRONIZATION_FAILURE) { - eap_aka_process_sync_failure(sm, data, respData, - &attr); - } else { - eap_aka_process_challenge(sm, data, respData, &attr); - } - break; - case REAUTH: - eap_aka_process_reauth(sm, data, respData, &attr); - break; - case NOTIFICATION: - eap_aka_process_notification(sm, data, respData, &attr); - break; - default: - wpa_printf(MSG_DEBUG, "EAP-AKA: Unknown state %d in " - "process", data->state); - break; - } -} - - -static Boolean eap_aka_isDone(struct eap_sm *sm, void *priv) -{ - struct eap_aka_data *data = priv; - return data->state == SUCCESS || data->state == FAILURE; -} - - -static u8 * eap_aka_getKey(struct eap_sm *sm, void *priv, size_t *len) -{ - struct eap_aka_data *data = priv; - u8 *key; - - if (data->state != SUCCESS) - return NULL; - - key = os_malloc(EAP_SIM_KEYING_DATA_LEN); - if (key == NULL) - return NULL; - os_memcpy(key, data->msk, EAP_SIM_KEYING_DATA_LEN); - *len = EAP_SIM_KEYING_DATA_LEN; - return key; -} - - -static u8 * eap_aka_get_emsk(struct eap_sm *sm, void *priv, size_t *len) -{ - struct eap_aka_data *data = priv; - u8 *key; - - if (data->state != SUCCESS) - return NULL; - - key = os_malloc(EAP_EMSK_LEN); - if (key == NULL) - return NULL; - os_memcpy(key, data->emsk, EAP_EMSK_LEN); - *len = EAP_EMSK_LEN; - return key; -} - - -static Boolean eap_aka_isSuccess(struct eap_sm *sm, void *priv) -{ - struct eap_aka_data *data = priv; - return data->state == SUCCESS; -} - - -int eap_server_aka_register(void) -{ - struct eap_method *eap; - int ret; - - eap = eap_server_method_alloc(EAP_SERVER_METHOD_INTERFACE_VERSION, - EAP_VENDOR_IETF, EAP_TYPE_AKA, "AKA"); - if (eap == NULL) - return -1; - - eap->init = eap_aka_init; - eap->reset = eap_aka_reset; - eap->buildReq = eap_aka_buildReq; - eap->check = eap_aka_check; - eap->process = eap_aka_process; - eap->isDone = eap_aka_isDone; - eap->getKey = eap_aka_getKey; - eap->isSuccess = eap_aka_isSuccess; - eap->get_emsk = eap_aka_get_emsk; - - ret = eap_server_method_register(eap); - if (ret) - eap_server_method_free(eap); - return ret; -} - - -#ifdef EAP_SERVER_AKA_PRIME -int eap_server_aka_prime_register(void) -{ - struct eap_method *eap; - int ret; - - eap = eap_server_method_alloc(EAP_SERVER_METHOD_INTERFACE_VERSION, - EAP_VENDOR_IETF, EAP_TYPE_AKA_PRIME, - "AKA'"); - if (eap == NULL) - return -1; - - eap->init = eap_aka_prime_init; - eap->reset = eap_aka_reset; - eap->buildReq = eap_aka_buildReq; - eap->check = eap_aka_check; - eap->process = eap_aka_process; - eap->isDone = eap_aka_isDone; - eap->getKey = eap_aka_getKey; - eap->isSuccess = eap_aka_isSuccess; - eap->get_emsk = eap_aka_get_emsk; - - ret = eap_server_method_register(eap); - if (ret) - eap_server_method_free(eap); - - return ret; -} -#endif /* EAP_SERVER_AKA_PRIME */ diff --git a/hostapd-0.8/src/eap_server/eap_server_fast.c b/hostapd-0.8/src/eap_server/eap_server_fast.c deleted file mode 100644 index ba17e98..0000000 --- a/hostapd-0.8/src/eap_server/eap_server_fast.c +++ /dev/null @@ -1,1620 +0,0 @@ -/* - * EAP-FAST server (RFC 4851) - * Copyright (c) 2004-2008, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#include "includes.h" - -#include "common.h" -#include "crypto/aes_wrap.h" -#include "crypto/sha1.h" -#include "crypto/tls.h" -#include "crypto/random.h" -#include "eap_common/eap_tlv_common.h" -#include "eap_common/eap_fast_common.h" -#include "eap_i.h" -#include "eap_tls_common.h" - - -static void eap_fast_reset(struct eap_sm *sm, void *priv); - - -/* Private PAC-Opaque TLV types */ -#define PAC_OPAQUE_TYPE_PAD 0 -#define PAC_OPAQUE_TYPE_KEY 1 -#define PAC_OPAQUE_TYPE_LIFETIME 2 -#define PAC_OPAQUE_TYPE_IDENTITY 3 - -struct eap_fast_data { - struct eap_ssl_data ssl; - enum { - START, PHASE1, PHASE2_START, PHASE2_ID, PHASE2_METHOD, - CRYPTO_BINDING, REQUEST_PAC, SUCCESS, FAILURE - } state; - - int fast_version; - const struct eap_method *phase2_method; - void *phase2_priv; - int force_version; - int peer_version; - - u8 crypto_binding_nonce[32]; - int final_result; - - struct eap_fast_key_block_provisioning *key_block_p; - - u8 simck[EAP_FAST_SIMCK_LEN]; - u8 cmk[EAP_FAST_CMK_LEN]; - int simck_idx; - - u8 pac_opaque_encr[16]; - u8 *srv_id; - size_t srv_id_len; - char *srv_id_info; - - int anon_provisioning; - int send_new_pac; /* server triggered re-keying of Tunnel PAC */ - struct wpabuf *pending_phase2_resp; - u8 *identity; /* from PAC-Opaque */ - size_t identity_len; - int eap_seq; - int tnc_started; - - int pac_key_lifetime; - int pac_key_refresh_time; -}; - - -static int eap_fast_process_phase2_start(struct eap_sm *sm, - struct eap_fast_data *data); - - -static const char * eap_fast_state_txt(int state) -{ - switch (state) { - case START: - return "START"; - case PHASE1: - return "PHASE1"; - case PHASE2_START: - return "PHASE2_START"; - case PHASE2_ID: - return "PHASE2_ID"; - case PHASE2_METHOD: - return "PHASE2_METHOD"; - case CRYPTO_BINDING: - return "CRYPTO_BINDING"; - case REQUEST_PAC: - return "REQUEST_PAC"; - case SUCCESS: - return "SUCCESS"; - case FAILURE: - return "FAILURE"; - default: - return "Unknown?!"; - } -} - - -static void eap_fast_state(struct eap_fast_data *data, int state) -{ - wpa_printf(MSG_DEBUG, "EAP-FAST: %s -> %s", - eap_fast_state_txt(data->state), - eap_fast_state_txt(state)); - data->state = state; -} - - -static EapType eap_fast_req_failure(struct eap_sm *sm, - struct eap_fast_data *data) -{ - /* TODO: send Result TLV(FAILURE) */ - eap_fast_state(data, FAILURE); - return EAP_TYPE_NONE; -} - - -static int eap_fast_session_ticket_cb(void *ctx, const u8 *ticket, size_t len, - const u8 *client_random, - const u8 *server_random, - u8 *master_secret) -{ - struct eap_fast_data *data = ctx; - const u8 *pac_opaque; - size_t pac_opaque_len; - u8 *buf, *pos, *end, *pac_key = NULL; - os_time_t lifetime = 0; - struct os_time now; - u8 *identity = NULL; - size_t identity_len = 0; - - wpa_printf(MSG_DEBUG, "EAP-FAST: SessionTicket callback"); - wpa_hexdump(MSG_DEBUG, "EAP-FAST: SessionTicket (PAC-Opaque)", - ticket, len); - - if (len < 4 || WPA_GET_BE16(ticket) != PAC_TYPE_PAC_OPAQUE) { - wpa_printf(MSG_DEBUG, "EAP-FAST: Ignore invalid " - "SessionTicket"); - return 0; - } - - pac_opaque_len = WPA_GET_BE16(ticket + 2); - pac_opaque = ticket + 4; - if (pac_opaque_len < 8 || pac_opaque_len % 8 || - pac_opaque_len > len - 4) { - wpa_printf(MSG_DEBUG, "EAP-FAST: Ignore invalid PAC-Opaque " - "(len=%lu left=%lu)", - (unsigned long) pac_opaque_len, - (unsigned long) len); - return 0; - } - wpa_hexdump(MSG_DEBUG, "EAP-FAST: Received PAC-Opaque", - pac_opaque, pac_opaque_len); - - buf = os_malloc(pac_opaque_len - 8); - if (buf == NULL) { - wpa_printf(MSG_DEBUG, "EAP-FAST: Failed to allocate memory " - "for decrypting PAC-Opaque"); - return 0; - } - - if (aes_unwrap(data->pac_opaque_encr, (pac_opaque_len - 8) / 8, - pac_opaque, buf) < 0) { - wpa_printf(MSG_DEBUG, "EAP-FAST: Failed to decrypt " - "PAC-Opaque"); - os_free(buf); - /* - * This may have been caused by server changing the PAC-Opaque - * encryption key, so just ignore this PAC-Opaque instead of - * failing the authentication completely. Provisioning can now - * be used to provision a new PAC. - */ - return 0; - } - - end = buf + pac_opaque_len - 8; - wpa_hexdump_key(MSG_DEBUG, "EAP-FAST: Decrypted PAC-Opaque", - buf, end - buf); - - pos = buf; - while (pos + 1 < end) { - if (pos + 2 + pos[1] > end) - break; - - switch (*pos) { - case PAC_OPAQUE_TYPE_PAD: - pos = end; - break; - case PAC_OPAQUE_TYPE_KEY: - if (pos[1] != EAP_FAST_PAC_KEY_LEN) { - wpa_printf(MSG_DEBUG, "EAP-FAST: Invalid " - "PAC-Key length %d", pos[1]); - os_free(buf); - return -1; - } - pac_key = pos + 2; - wpa_hexdump_key(MSG_DEBUG, "EAP-FAST: PAC-Key from " - "decrypted PAC-Opaque", - pac_key, EAP_FAST_PAC_KEY_LEN); - break; - case PAC_OPAQUE_TYPE_LIFETIME: - if (pos[1] != 4) { - wpa_printf(MSG_DEBUG, "EAP-FAST: Invalid " - "PAC-Key lifetime length %d", - pos[1]); - os_free(buf); - return -1; - } - lifetime = WPA_GET_BE32(pos + 2); - break; - case PAC_OPAQUE_TYPE_IDENTITY: - identity = pos + 2; - identity_len = pos[1]; - break; - } - - pos += 2 + pos[1]; - } - - if (pac_key == NULL) { - wpa_printf(MSG_DEBUG, "EAP-FAST: No PAC-Key included in " - "PAC-Opaque"); - os_free(buf); - return -1; - } - - if (identity) { - wpa_hexdump_ascii(MSG_DEBUG, "EAP-FAST: Identity from " - "PAC-Opaque", identity, identity_len); - os_free(data->identity); - data->identity = os_malloc(identity_len); - if (data->identity) { - os_memcpy(data->identity, identity, identity_len); - data->identity_len = identity_len; - } - } - - if (os_get_time(&now) < 0 || lifetime <= 0 || now.sec > lifetime) { - wpa_printf(MSG_DEBUG, "EAP-FAST: PAC-Key not valid anymore " - "(lifetime=%ld now=%ld)", lifetime, now.sec); - data->send_new_pac = 2; - /* - * Allow PAC to be used to allow a PAC update with some level - * of server authentication (i.e., do not fall back to full TLS - * handshake since we cannot be sure that the peer would be - * able to validate server certificate now). However, reject - * the authentication since the PAC was not valid anymore. Peer - * can connect again with the newly provisioned PAC after this. - */ - } else if (lifetime - now.sec < data->pac_key_refresh_time) { - wpa_printf(MSG_DEBUG, "EAP-FAST: PAC-Key soft timeout; send " - "an update if authentication succeeds"); - data->send_new_pac = 1; - } - - eap_fast_derive_master_secret(pac_key, server_random, client_random, - master_secret); - - os_free(buf); - - return 1; -} - - -static void eap_fast_derive_key_auth(struct eap_sm *sm, - struct eap_fast_data *data) -{ - u8 *sks; - - /* RFC 4851, Section 5.1: - * Extra key material after TLS key_block: session_key_seed[40] - */ - - sks = eap_fast_derive_key(sm->ssl_ctx, data->ssl.conn, "key expansion", - EAP_FAST_SKS_LEN); - if (sks == NULL) { - wpa_printf(MSG_DEBUG, "EAP-FAST: Failed to derive " - "session_key_seed"); - return; - } - - /* - * RFC 4851, Section 5.2: - * S-IMCK[0] = session_key_seed - */ - wpa_hexdump_key(MSG_DEBUG, - "EAP-FAST: session_key_seed (SKS = S-IMCK[0])", - sks, EAP_FAST_SKS_LEN); - data->simck_idx = 0; - os_memcpy(data->simck, sks, EAP_FAST_SIMCK_LEN); - os_free(sks); -} - - -static void eap_fast_derive_key_provisioning(struct eap_sm *sm, - struct eap_fast_data *data) -{ - os_free(data->key_block_p); - data->key_block_p = (struct eap_fast_key_block_provisioning *) - eap_fast_derive_key(sm->ssl_ctx, data->ssl.conn, - "key expansion", - sizeof(*data->key_block_p)); - if (data->key_block_p == NULL) { - wpa_printf(MSG_DEBUG, "EAP-FAST: Failed to derive key block"); - return; - } - /* - * RFC 4851, Section 5.2: - * S-IMCK[0] = session_key_seed - */ - wpa_hexdump_key(MSG_DEBUG, - "EAP-FAST: session_key_seed (SKS = S-IMCK[0])", - data->key_block_p->session_key_seed, - sizeof(data->key_block_p->session_key_seed)); - data->simck_idx = 0; - os_memcpy(data->simck, data->key_block_p->session_key_seed, - EAP_FAST_SIMCK_LEN); - wpa_hexdump_key(MSG_DEBUG, "EAP-FAST: server_challenge", - data->key_block_p->server_challenge, - sizeof(data->key_block_p->server_challenge)); - wpa_hexdump_key(MSG_DEBUG, "EAP-FAST: client_challenge", - data->key_block_p->client_challenge, - sizeof(data->key_block_p->client_challenge)); -} - - -static int eap_fast_get_phase2_key(struct eap_sm *sm, - struct eap_fast_data *data, - u8 *isk, size_t isk_len) -{ - u8 *key; - size_t key_len; - - os_memset(isk, 0, isk_len); - - if (data->phase2_method == NULL || data->phase2_priv == NULL) { - wpa_printf(MSG_DEBUG, "EAP-FAST: Phase 2 method not " - "available"); - return -1; - } - - if (data->phase2_method->getKey == NULL) - return 0; - - if ((key = data->phase2_method->getKey(sm, data->phase2_priv, - &key_len)) == NULL) { - wpa_printf(MSG_DEBUG, "EAP-FAST: Could not get key material " - "from Phase 2"); - return -1; - } - - if (key_len > isk_len) - key_len = isk_len; - if (key_len == 32 && - data->phase2_method->vendor == EAP_VENDOR_IETF && - data->phase2_method->method == EAP_TYPE_MSCHAPV2) { - /* - * EAP-FAST uses reverse order for MS-MPPE keys when deriving - * MSK from EAP-MSCHAPv2. Swap the keys here to get the correct - * ISK for EAP-FAST cryptobinding. - */ - os_memcpy(isk, key + 16, 16); - os_memcpy(isk + 16, key, 16); - } else - os_memcpy(isk, key, key_len); - os_free(key); - - return 0; -} - - -static int eap_fast_update_icmk(struct eap_sm *sm, struct eap_fast_data *data) -{ - u8 isk[32], imck[60]; - - wpa_printf(MSG_DEBUG, "EAP-FAST: Deriving ICMK[%d] (S-IMCK and CMK)", - data->simck_idx + 1); - - /* - * RFC 4851, Section 5.2: - * IMCK[j] = T-PRF(S-IMCK[j-1], "Inner Methods Compound Keys", - * MSK[j], 60) - * S-IMCK[j] = first 40 octets of IMCK[j] - * CMK[j] = last 20 octets of IMCK[j] - */ - - if (eap_fast_get_phase2_key(sm, data, isk, sizeof(isk)) < 0) - return -1; - wpa_hexdump_key(MSG_MSGDUMP, "EAP-FAST: ISK[j]", isk, sizeof(isk)); - sha1_t_prf(data->simck, EAP_FAST_SIMCK_LEN, - "Inner Methods Compound Keys", - isk, sizeof(isk), imck, sizeof(imck)); - data->simck_idx++; - os_memcpy(data->simck, imck, EAP_FAST_SIMCK_LEN); - wpa_hexdump_key(MSG_MSGDUMP, "EAP-FAST: S-IMCK[j]", - data->simck, EAP_FAST_SIMCK_LEN); - os_memcpy(data->cmk, imck + EAP_FAST_SIMCK_LEN, EAP_FAST_CMK_LEN); - wpa_hexdump_key(MSG_MSGDUMP, "EAP-FAST: CMK[j]", - data->cmk, EAP_FAST_CMK_LEN); - - return 0; -} - - -static void * eap_fast_init(struct eap_sm *sm) -{ - struct eap_fast_data *data; - u8 ciphers[5] = { - TLS_CIPHER_ANON_DH_AES128_SHA, - TLS_CIPHER_AES128_SHA, - TLS_CIPHER_RSA_DHE_AES128_SHA, - TLS_CIPHER_RC4_SHA, - TLS_CIPHER_NONE - }; - - data = os_zalloc(sizeof(*data)); - if (data == NULL) - return NULL; - data->fast_version = EAP_FAST_VERSION; - data->force_version = -1; - if (sm->user && sm->user->force_version >= 0) { - data->force_version = sm->user->force_version; - wpa_printf(MSG_DEBUG, "EAP-FAST: forcing version %d", - data->force_version); - data->fast_version = data->force_version; - } - data->state = START; - - if (eap_server_tls_ssl_init(sm, &data->ssl, 0)) { - wpa_printf(MSG_INFO, "EAP-FAST: Failed to initialize SSL."); - eap_fast_reset(sm, data); - return NULL; - } - - if (tls_connection_set_cipher_list(sm->ssl_ctx, data->ssl.conn, - ciphers) < 0) { - wpa_printf(MSG_INFO, "EAP-FAST: Failed to set TLS cipher " - "suites"); - eap_fast_reset(sm, data); - return NULL; - } - - if (tls_connection_set_session_ticket_cb(sm->ssl_ctx, data->ssl.conn, - eap_fast_session_ticket_cb, - data) < 0) { - wpa_printf(MSG_INFO, "EAP-FAST: Failed to set SessionTicket " - "callback"); - eap_fast_reset(sm, data); - return NULL; - } - - if (sm->pac_opaque_encr_key == NULL) { - wpa_printf(MSG_INFO, "EAP-FAST: No PAC-Opaque encryption key " - "configured"); - eap_fast_reset(sm, data); - return NULL; - } - os_memcpy(data->pac_opaque_encr, sm->pac_opaque_encr_key, - sizeof(data->pac_opaque_encr)); - - if (sm->eap_fast_a_id == NULL) { - wpa_printf(MSG_INFO, "EAP-FAST: No A-ID configured"); - eap_fast_reset(sm, data); - return NULL; - } - data->srv_id = os_malloc(sm->eap_fast_a_id_len); - if (data->srv_id == NULL) { - eap_fast_reset(sm, data); - return NULL; - } - os_memcpy(data->srv_id, sm->eap_fast_a_id, sm->eap_fast_a_id_len); - data->srv_id_len = sm->eap_fast_a_id_len; - - if (sm->eap_fast_a_id_info == NULL) { - wpa_printf(MSG_INFO, "EAP-FAST: No A-ID-Info configured"); - eap_fast_reset(sm, data); - return NULL; - } - data->srv_id_info = os_strdup(sm->eap_fast_a_id_info); - if (data->srv_id_info == NULL) { - eap_fast_reset(sm, data); - return NULL; - } - - /* PAC-Key lifetime in seconds (hard limit) */ - data->pac_key_lifetime = sm->pac_key_lifetime; - - /* - * PAC-Key refresh time in seconds (soft limit on remaining hard - * limit). The server will generate a new PAC-Key when this number of - * seconds (or fewer) of the lifetime remains. - */ - data->pac_key_refresh_time = sm->pac_key_refresh_time; - - return data; -} - - -static void eap_fast_reset(struct eap_sm *sm, void *priv) -{ - struct eap_fast_data *data = priv; - if (data == NULL) - return; - if (data->phase2_priv && data->phase2_method) - data->phase2_method->reset(sm, data->phase2_priv); - eap_server_tls_ssl_deinit(sm, &data->ssl); - os_free(data->srv_id); - os_free(data->srv_id_info); - os_free(data->key_block_p); - wpabuf_free(data->pending_phase2_resp); - os_free(data->identity); - os_free(data); -} - - -static struct wpabuf * eap_fast_build_start(struct eap_sm *sm, - struct eap_fast_data *data, u8 id) -{ - struct wpabuf *req; - - req = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_FAST, - 1 + sizeof(struct pac_tlv_hdr) + data->srv_id_len, - EAP_CODE_REQUEST, id); - if (req == NULL) { - wpa_printf(MSG_ERROR, "EAP-FAST: Failed to allocate memory for" - " request"); - eap_fast_state(data, FAILURE); - return NULL; - } - - wpabuf_put_u8(req, EAP_TLS_FLAGS_START | data->fast_version); - - /* RFC 4851, 4.1.1. Authority ID Data */ - eap_fast_put_tlv(req, PAC_TYPE_A_ID, data->srv_id, data->srv_id_len); - - eap_fast_state(data, PHASE1); - - return req; -} - - -static int eap_fast_phase1_done(struct eap_sm *sm, struct eap_fast_data *data) -{ - char cipher[64]; - - wpa_printf(MSG_DEBUG, "EAP-FAST: Phase1 done, starting Phase2"); - - if (tls_get_cipher(sm->ssl_ctx, data->ssl.conn, cipher, sizeof(cipher)) - < 0) { - wpa_printf(MSG_DEBUG, "EAP-FAST: Failed to get cipher " - "information"); - eap_fast_state(data, FAILURE); - return -1; - } - data->anon_provisioning = os_strstr(cipher, "ADH") != NULL; - - if (data->anon_provisioning) { - wpa_printf(MSG_DEBUG, "EAP-FAST: Anonymous provisioning"); - eap_fast_derive_key_provisioning(sm, data); - } else - eap_fast_derive_key_auth(sm, data); - - eap_fast_state(data, PHASE2_START); - - return 0; -} - - -static struct wpabuf * eap_fast_build_phase2_req(struct eap_sm *sm, - struct eap_fast_data *data, - u8 id) -{ - struct wpabuf *req; - - if (data->phase2_priv == NULL) { - wpa_printf(MSG_DEBUG, "EAP-FAST: Phase 2 method not " - "initialized"); - return NULL; - } - req = data->phase2_method->buildReq(sm, data->phase2_priv, id); - if (req == NULL) - return NULL; - - wpa_hexdump_buf_key(MSG_MSGDUMP, "EAP-FAST: Phase 2 EAP-Request", req); - return eap_fast_tlv_eap_payload(req); -} - - -static struct wpabuf * eap_fast_build_crypto_binding( - struct eap_sm *sm, struct eap_fast_data *data) -{ - struct wpabuf *buf; - struct eap_tlv_result_tlv *result; - struct eap_tlv_crypto_binding_tlv *binding; - - buf = wpabuf_alloc(2 * sizeof(*result) + sizeof(*binding)); - if (buf == NULL) - return NULL; - - if (data->send_new_pac || data->anon_provisioning || - data->phase2_method) - data->final_result = 0; - else - data->final_result = 1; - - if (!data->final_result || data->eap_seq > 1) { - /* Intermediate-Result */ - wpa_printf(MSG_DEBUG, "EAP-FAST: Add Intermediate-Result TLV " - "(status=SUCCESS)"); - result = wpabuf_put(buf, sizeof(*result)); - result->tlv_type = host_to_be16( - EAP_TLV_TYPE_MANDATORY | - EAP_TLV_INTERMEDIATE_RESULT_TLV); - result->length = host_to_be16(2); - result->status = host_to_be16(EAP_TLV_RESULT_SUCCESS); - } - - if (data->final_result) { - /* Result TLV */ - wpa_printf(MSG_DEBUG, "EAP-FAST: Add Result TLV " - "(status=SUCCESS)"); - result = wpabuf_put(buf, sizeof(*result)); - result->tlv_type = host_to_be16(EAP_TLV_TYPE_MANDATORY | - EAP_TLV_RESULT_TLV); - result->length = host_to_be16(2); - result->status = host_to_be16(EAP_TLV_RESULT_SUCCESS); - } - - /* Crypto-Binding TLV */ - binding = wpabuf_put(buf, sizeof(*binding)); - binding->tlv_type = host_to_be16(EAP_TLV_TYPE_MANDATORY | - EAP_TLV_CRYPTO_BINDING_TLV); - binding->length = host_to_be16(sizeof(*binding) - - sizeof(struct eap_tlv_hdr)); - binding->version = EAP_FAST_VERSION; - binding->received_version = data->peer_version; - binding->subtype = EAP_TLV_CRYPTO_BINDING_SUBTYPE_REQUEST; - if (random_get_bytes(binding->nonce, sizeof(binding->nonce)) < 0) { - wpabuf_free(buf); - return NULL; - } - - /* - * RFC 4851, Section 4.2.8: - * The nonce in a request MUST have its least significant bit set to 0. - */ - binding->nonce[sizeof(binding->nonce) - 1] &= ~0x01; - - os_memcpy(data->crypto_binding_nonce, binding->nonce, - sizeof(binding->nonce)); - - /* - * RFC 4851, Section 5.3: - * CMK = CMK[j] - * Compound-MAC = HMAC-SHA1( CMK, Crypto-Binding TLV ) - */ - - hmac_sha1(data->cmk, EAP_FAST_CMK_LEN, - (u8 *) binding, sizeof(*binding), - binding->compound_mac); - - wpa_printf(MSG_DEBUG, "EAP-FAST: Add Crypto-Binding TLV: Version %d " - "Received Version %d SubType %d", - binding->version, binding->received_version, - binding->subtype); - wpa_hexdump(MSG_MSGDUMP, "EAP-FAST: NONCE", - binding->nonce, sizeof(binding->nonce)); - wpa_hexdump(MSG_MSGDUMP, "EAP-FAST: Compound MAC", - binding->compound_mac, sizeof(binding->compound_mac)); - - return buf; -} - - -static struct wpabuf * eap_fast_build_pac(struct eap_sm *sm, - struct eap_fast_data *data) -{ - u8 pac_key[EAP_FAST_PAC_KEY_LEN]; - u8 *pac_buf, *pac_opaque; - struct wpabuf *buf; - u8 *pos; - size_t buf_len, srv_id_info_len, pac_len; - struct eap_tlv_hdr *pac_tlv; - struct pac_tlv_hdr *pac_info; - struct eap_tlv_result_tlv *result; - struct os_time now; - - if (random_get_bytes(pac_key, EAP_FAST_PAC_KEY_LEN) < 0 || - os_get_time(&now) < 0) - return NULL; - wpa_hexdump_key(MSG_DEBUG, "EAP-FAST: Generated PAC-Key", - pac_key, EAP_FAST_PAC_KEY_LEN); - - pac_len = (2 + EAP_FAST_PAC_KEY_LEN) + (2 + 4) + - (2 + sm->identity_len) + 8; - pac_buf = os_malloc(pac_len); - if (pac_buf == NULL) - return NULL; - - srv_id_info_len = os_strlen(data->srv_id_info); - - pos = pac_buf; - *pos++ = PAC_OPAQUE_TYPE_KEY; - *pos++ = EAP_FAST_PAC_KEY_LEN; - os_memcpy(pos, pac_key, EAP_FAST_PAC_KEY_LEN); - pos += EAP_FAST_PAC_KEY_LEN; - - *pos++ = PAC_OPAQUE_TYPE_LIFETIME; - *pos++ = 4; - WPA_PUT_BE32(pos, now.sec + data->pac_key_lifetime); - pos += 4; - - if (sm->identity) { - *pos++ = PAC_OPAQUE_TYPE_IDENTITY; - *pos++ = sm->identity_len; - os_memcpy(pos, sm->identity, sm->identity_len); - pos += sm->identity_len; - } - - pac_len = pos - pac_buf; - while (pac_len % 8) { - *pos++ = PAC_OPAQUE_TYPE_PAD; - pac_len++; - } - - pac_opaque = os_malloc(pac_len + 8); - if (pac_opaque == NULL) { - os_free(pac_buf); - return NULL; - } - if (aes_wrap(data->pac_opaque_encr, pac_len / 8, pac_buf, - pac_opaque) < 0) { - os_free(pac_buf); - os_free(pac_opaque); - return NULL; - } - os_free(pac_buf); - - pac_len += 8; - wpa_hexdump(MSG_DEBUG, "EAP-FAST: PAC-Opaque", - pac_opaque, pac_len); - - buf_len = sizeof(*pac_tlv) + - sizeof(struct pac_tlv_hdr) + EAP_FAST_PAC_KEY_LEN + - sizeof(struct pac_tlv_hdr) + pac_len + - data->srv_id_len + srv_id_info_len + 100 + sizeof(*result); - buf = wpabuf_alloc(buf_len); - if (buf == NULL) { - os_free(pac_opaque); - return NULL; - } - - /* Result TLV */ - wpa_printf(MSG_DEBUG, "EAP-FAST: Add Result TLV (status=SUCCESS)"); - result = wpabuf_put(buf, sizeof(*result)); - WPA_PUT_BE16((u8 *) &result->tlv_type, - EAP_TLV_TYPE_MANDATORY | EAP_TLV_RESULT_TLV); - WPA_PUT_BE16((u8 *) &result->length, 2); - WPA_PUT_BE16((u8 *) &result->status, EAP_TLV_RESULT_SUCCESS); - - /* PAC TLV */ - wpa_printf(MSG_DEBUG, "EAP-FAST: Add PAC TLV"); - pac_tlv = wpabuf_put(buf, sizeof(*pac_tlv)); - pac_tlv->tlv_type = host_to_be16(EAP_TLV_TYPE_MANDATORY | - EAP_TLV_PAC_TLV); - - /* PAC-Key */ - eap_fast_put_tlv(buf, PAC_TYPE_PAC_KEY, pac_key, EAP_FAST_PAC_KEY_LEN); - - /* PAC-Opaque */ - eap_fast_put_tlv(buf, PAC_TYPE_PAC_OPAQUE, pac_opaque, pac_len); - os_free(pac_opaque); - - /* PAC-Info */ - pac_info = wpabuf_put(buf, sizeof(*pac_info)); - pac_info->type = host_to_be16(PAC_TYPE_PAC_INFO); - - /* PAC-Lifetime (inside PAC-Info) */ - eap_fast_put_tlv_hdr(buf, PAC_TYPE_CRED_LIFETIME, 4); - wpabuf_put_be32(buf, now.sec + data->pac_key_lifetime); - - /* A-ID (inside PAC-Info) */ - eap_fast_put_tlv(buf, PAC_TYPE_A_ID, data->srv_id, data->srv_id_len); - - /* Note: headers may be misaligned after A-ID */ - - if (sm->identity) { - eap_fast_put_tlv(buf, PAC_TYPE_I_ID, sm->identity, - sm->identity_len); - } - - /* A-ID-Info (inside PAC-Info) */ - eap_fast_put_tlv(buf, PAC_TYPE_A_ID_INFO, data->srv_id_info, - srv_id_info_len); - - /* PAC-Type (inside PAC-Info) */ - eap_fast_put_tlv_hdr(buf, PAC_TYPE_PAC_TYPE, 2); - wpabuf_put_be16(buf, PAC_TYPE_TUNNEL_PAC); - - /* Update PAC-Info and PAC TLV Length fields */ - pos = wpabuf_put(buf, 0); - pac_info->len = host_to_be16(pos - (u8 *) (pac_info + 1)); - pac_tlv->length = host_to_be16(pos - (u8 *) (pac_tlv + 1)); - - return buf; -} - - -static int eap_fast_encrypt_phase2(struct eap_sm *sm, - struct eap_fast_data *data, - struct wpabuf *plain, int piggyback) -{ - struct wpabuf *encr; - - wpa_hexdump_buf_key(MSG_DEBUG, "EAP-FAST: Encrypting Phase 2 TLVs", - plain); - encr = eap_server_tls_encrypt(sm, &data->ssl, plain); - wpabuf_free(plain); - - if (data->ssl.tls_out && piggyback) { - wpa_printf(MSG_DEBUG, "EAP-FAST: Piggyback Phase 2 data " - "(len=%d) with last Phase 1 Message (len=%d " - "used=%d)", - (int) wpabuf_len(encr), - (int) wpabuf_len(data->ssl.tls_out), - (int) data->ssl.tls_out_pos); - if (wpabuf_resize(&data->ssl.tls_out, wpabuf_len(encr)) < 0) { - wpa_printf(MSG_WARNING, "EAP-FAST: Failed to resize " - "output buffer"); - wpabuf_free(encr); - return -1; - } - wpabuf_put_buf(data->ssl.tls_out, encr); - wpabuf_free(encr); - } else { - wpabuf_free(data->ssl.tls_out); - data->ssl.tls_out_pos = 0; - data->ssl.tls_out = encr; - } - - return 0; -} - - -static struct wpabuf * eap_fast_buildReq(struct eap_sm *sm, void *priv, u8 id) -{ - struct eap_fast_data *data = priv; - struct wpabuf *req = NULL; - int piggyback = 0; - - if (data->ssl.state == FRAG_ACK) { - return eap_server_tls_build_ack(id, EAP_TYPE_FAST, - data->fast_version); - } - - if (data->ssl.state == WAIT_FRAG_ACK) { - return eap_server_tls_build_msg(&data->ssl, EAP_TYPE_FAST, - data->fast_version, id); - } - - switch (data->state) { - case START: - return eap_fast_build_start(sm, data, id); - case PHASE1: - if (tls_connection_established(sm->ssl_ctx, data->ssl.conn)) { - if (eap_fast_phase1_done(sm, data) < 0) - return NULL; - if (data->state == PHASE2_START) { - /* - * Try to generate Phase 2 data to piggyback - * with the end of Phase 1 to avoid extra - * roundtrip. - */ - wpa_printf(MSG_DEBUG, "EAP-FAST: Try to start " - "Phase 2"); - if (eap_fast_process_phase2_start(sm, data)) - break; - req = eap_fast_build_phase2_req(sm, data, id); - piggyback = 1; - } - } - break; - case PHASE2_ID: - case PHASE2_METHOD: - req = eap_fast_build_phase2_req(sm, data, id); - break; - case CRYPTO_BINDING: - req = eap_fast_build_crypto_binding(sm, data); - if (data->phase2_method) { - /* - * Include the start of the next EAP method in the - * sequence in the same message with Crypto-Binding to - * save a round-trip. - */ - struct wpabuf *eap; - eap = eap_fast_build_phase2_req(sm, data, id); - req = wpabuf_concat(req, eap); - eap_fast_state(data, PHASE2_METHOD); - } - break; - case REQUEST_PAC: - req = eap_fast_build_pac(sm, data); - break; - default: - wpa_printf(MSG_DEBUG, "EAP-FAST: %s - unexpected state %d", - __func__, data->state); - return NULL; - } - - if (req && - eap_fast_encrypt_phase2(sm, data, req, piggyback) < 0) - return NULL; - - return eap_server_tls_build_msg(&data->ssl, EAP_TYPE_FAST, - data->fast_version, id); -} - - -static Boolean eap_fast_check(struct eap_sm *sm, void *priv, - struct wpabuf *respData) -{ - const u8 *pos; - size_t len; - - pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_FAST, respData, &len); - if (pos == NULL || len < 1) { - wpa_printf(MSG_INFO, "EAP-FAST: Invalid frame"); - return TRUE; - } - - return FALSE; -} - - -static int eap_fast_phase2_init(struct eap_sm *sm, struct eap_fast_data *data, - EapType eap_type) -{ - if (data->phase2_priv && data->phase2_method) { - data->phase2_method->reset(sm, data->phase2_priv); - data->phase2_method = NULL; - data->phase2_priv = NULL; - } - data->phase2_method = eap_server_get_eap_method(EAP_VENDOR_IETF, - eap_type); - if (!data->phase2_method) - return -1; - - if (data->key_block_p) { - sm->auth_challenge = data->key_block_p->server_challenge; - sm->peer_challenge = data->key_block_p->client_challenge; - } - sm->init_phase2 = 1; - data->phase2_priv = data->phase2_method->init(sm); - sm->init_phase2 = 0; - sm->auth_challenge = NULL; - sm->peer_challenge = NULL; - - return data->phase2_priv == NULL ? -1 : 0; -} - - -static void eap_fast_process_phase2_response(struct eap_sm *sm, - struct eap_fast_data *data, - u8 *in_data, size_t in_len) -{ - u8 next_type = EAP_TYPE_NONE; - struct eap_hdr *hdr; - u8 *pos; - size_t left; - struct wpabuf buf; - const struct eap_method *m = data->phase2_method; - void *priv = data->phase2_priv; - - if (priv == NULL) { - wpa_printf(MSG_DEBUG, "EAP-FAST: %s - Phase2 not " - "initialized?!", __func__); - return; - } - - hdr = (struct eap_hdr *) in_data; - pos = (u8 *) (hdr + 1); - - if (in_len > sizeof(*hdr) && *pos == EAP_TYPE_NAK) { - left = in_len - sizeof(*hdr); - wpa_hexdump(MSG_DEBUG, "EAP-FAST: Phase2 type Nak'ed; " - "allowed types", pos + 1, left - 1); -#ifdef EAP_SERVER_TNC - if (m && m->vendor == EAP_VENDOR_IETF && - m->method == EAP_TYPE_TNC) { - wpa_printf(MSG_DEBUG, "EAP-FAST: Peer Nak'ed required " - "TNC negotiation"); - next_type = eap_fast_req_failure(sm, data); - eap_fast_phase2_init(sm, data, next_type); - return; - } -#endif /* EAP_SERVER_TNC */ - eap_sm_process_nak(sm, pos + 1, left - 1); - if (sm->user && sm->user_eap_method_index < EAP_MAX_METHODS && - sm->user->methods[sm->user_eap_method_index].method != - EAP_TYPE_NONE) { - next_type = sm->user->methods[ - sm->user_eap_method_index++].method; - wpa_printf(MSG_DEBUG, "EAP-FAST: try EAP type %d", - next_type); - } else { - next_type = eap_fast_req_failure(sm, data); - } - eap_fast_phase2_init(sm, data, next_type); - return; - } - - wpabuf_set(&buf, in_data, in_len); - - if (m->check(sm, priv, &buf)) { - wpa_printf(MSG_DEBUG, "EAP-FAST: Phase2 check() asked to " - "ignore the packet"); - next_type = eap_fast_req_failure(sm, data); - return; - } - - m->process(sm, priv, &buf); - - if (!m->isDone(sm, priv)) - return; - - if (!m->isSuccess(sm, priv)) { - wpa_printf(MSG_DEBUG, "EAP-FAST: Phase2 method failed"); - next_type = eap_fast_req_failure(sm, data); - eap_fast_phase2_init(sm, data, next_type); - return; - } - - switch (data->state) { - case PHASE2_ID: - if (eap_user_get(sm, sm->identity, sm->identity_len, 1) != 0) { - wpa_hexdump_ascii(MSG_DEBUG, "EAP-FAST: Phase2 " - "Identity not found in the user " - "database", - sm->identity, sm->identity_len); - next_type = eap_fast_req_failure(sm, data); - break; - } - - eap_fast_state(data, PHASE2_METHOD); - if (data->anon_provisioning) { - /* - * Only EAP-MSCHAPv2 is allowed for anonymous - * provisioning. - */ - next_type = EAP_TYPE_MSCHAPV2; - sm->user_eap_method_index = 0; - } else { - next_type = sm->user->methods[0].method; - sm->user_eap_method_index = 1; - } - wpa_printf(MSG_DEBUG, "EAP-FAST: try EAP type %d", next_type); - break; - case PHASE2_METHOD: - case CRYPTO_BINDING: - eap_fast_update_icmk(sm, data); - eap_fast_state(data, CRYPTO_BINDING); - data->eap_seq++; - next_type = EAP_TYPE_NONE; -#ifdef EAP_SERVER_TNC - if (sm->tnc && !data->tnc_started) { - wpa_printf(MSG_DEBUG, "EAP-FAST: Initialize TNC"); - next_type = EAP_TYPE_TNC; - data->tnc_started = 1; - } -#endif /* EAP_SERVER_TNC */ - break; - case FAILURE: - break; - default: - wpa_printf(MSG_DEBUG, "EAP-FAST: %s - unexpected state %d", - __func__, data->state); - break; - } - - eap_fast_phase2_init(sm, data, next_type); -} - - -static void eap_fast_process_phase2_eap(struct eap_sm *sm, - struct eap_fast_data *data, - u8 *in_data, size_t in_len) -{ - struct eap_hdr *hdr; - size_t len; - - hdr = (struct eap_hdr *) in_data; - if (in_len < (int) sizeof(*hdr)) { - wpa_printf(MSG_INFO, "EAP-FAST: Too short Phase 2 " - "EAP frame (len=%lu)", (unsigned long) in_len); - eap_fast_req_failure(sm, data); - return; - } - len = be_to_host16(hdr->length); - if (len > in_len) { - wpa_printf(MSG_INFO, "EAP-FAST: Length mismatch in " - "Phase 2 EAP frame (len=%lu hdr->length=%lu)", - (unsigned long) in_len, (unsigned long) len); - eap_fast_req_failure(sm, data); - return; - } - wpa_printf(MSG_DEBUG, "EAP-FAST: Received Phase 2: code=%d " - "identifier=%d length=%lu", hdr->code, hdr->identifier, - (unsigned long) len); - switch (hdr->code) { - case EAP_CODE_RESPONSE: - eap_fast_process_phase2_response(sm, data, (u8 *) hdr, len); - break; - default: - wpa_printf(MSG_INFO, "EAP-FAST: Unexpected code=%d in " - "Phase 2 EAP header", hdr->code); - break; - } -} - - -static int eap_fast_parse_tlvs(struct wpabuf *data, - struct eap_fast_tlv_parse *tlv) -{ - int mandatory, tlv_type, len, res; - u8 *pos, *end; - - os_memset(tlv, 0, sizeof(*tlv)); - - pos = wpabuf_mhead(data); - end = pos + wpabuf_len(data); - while (pos + 4 < end) { - mandatory = pos[0] & 0x80; - tlv_type = WPA_GET_BE16(pos) & 0x3fff; - pos += 2; - len = WPA_GET_BE16(pos); - pos += 2; - if (pos + len > end) { - wpa_printf(MSG_INFO, "EAP-FAST: TLV overflow"); - return -1; - } - wpa_printf(MSG_DEBUG, "EAP-FAST: Received Phase 2: " - "TLV type %d length %d%s", - tlv_type, len, mandatory ? " (mandatory)" : ""); - - res = eap_fast_parse_tlv(tlv, tlv_type, pos, len); - if (res == -2) - break; - if (res < 0) { - if (mandatory) { - wpa_printf(MSG_DEBUG, "EAP-FAST: Nak unknown " - "mandatory TLV type %d", tlv_type); - /* TODO: generate Nak TLV */ - break; - } else { - wpa_printf(MSG_DEBUG, "EAP-FAST: Ignored " - "unknown optional TLV type %d", - tlv_type); - } - } - - pos += len; - } - - return 0; -} - - -static int eap_fast_validate_crypto_binding( - struct eap_fast_data *data, struct eap_tlv_crypto_binding_tlv *b, - size_t bind_len) -{ - u8 cmac[SHA1_MAC_LEN]; - - wpa_printf(MSG_DEBUG, "EAP-FAST: Reply Crypto-Binding TLV: " - "Version %d Received Version %d SubType %d", - b->version, b->received_version, b->subtype); - wpa_hexdump(MSG_MSGDUMP, "EAP-FAST: NONCE", - b->nonce, sizeof(b->nonce)); - wpa_hexdump(MSG_MSGDUMP, "EAP-FAST: Compound MAC", - b->compound_mac, sizeof(b->compound_mac)); - - if (b->version != EAP_FAST_VERSION || - b->received_version != EAP_FAST_VERSION) { - wpa_printf(MSG_DEBUG, "EAP-FAST: Unexpected version " - "in Crypto-Binding: version %d " - "received_version %d", b->version, - b->received_version); - return -1; - } - - if (b->subtype != EAP_TLV_CRYPTO_BINDING_SUBTYPE_RESPONSE) { - wpa_printf(MSG_DEBUG, "EAP-FAST: Unexpected subtype in " - "Crypto-Binding: %d", b->subtype); - return -1; - } - - if (os_memcmp(data->crypto_binding_nonce, b->nonce, 31) != 0 || - (data->crypto_binding_nonce[31] | 1) != b->nonce[31]) { - wpa_printf(MSG_DEBUG, "EAP-FAST: Invalid nonce in " - "Crypto-Binding"); - return -1; - } - - os_memcpy(cmac, b->compound_mac, sizeof(cmac)); - os_memset(b->compound_mac, 0, sizeof(cmac)); - wpa_hexdump(MSG_MSGDUMP, "EAP-FAST: Crypto-Binding TLV for " - "Compound MAC calculation", - (u8 *) b, bind_len); - hmac_sha1(data->cmk, EAP_FAST_CMK_LEN, (u8 *) b, bind_len, - b->compound_mac); - if (os_memcmp(cmac, b->compound_mac, sizeof(cmac)) != 0) { - wpa_hexdump(MSG_MSGDUMP, - "EAP-FAST: Calculated Compound MAC", - b->compound_mac, sizeof(cmac)); - wpa_printf(MSG_INFO, "EAP-FAST: Compound MAC did not " - "match"); - return -1; - } - - return 0; -} - - -static int eap_fast_pac_type(u8 *pac, size_t len, u16 type) -{ - struct eap_tlv_pac_type_tlv *tlv; - - if (pac == NULL || len != sizeof(*tlv)) - return 0; - - tlv = (struct eap_tlv_pac_type_tlv *) pac; - - return be_to_host16(tlv->tlv_type) == PAC_TYPE_PAC_TYPE && - be_to_host16(tlv->length) == 2 && - be_to_host16(tlv->pac_type) == type; -} - - -static void eap_fast_process_phase2_tlvs(struct eap_sm *sm, - struct eap_fast_data *data, - struct wpabuf *in_data) -{ - struct eap_fast_tlv_parse tlv; - int check_crypto_binding = data->state == CRYPTO_BINDING; - - if (eap_fast_parse_tlvs(in_data, &tlv) < 0) { - wpa_printf(MSG_DEBUG, "EAP-FAST: Failed to parse received " - "Phase 2 TLVs"); - return; - } - - if (tlv.result == EAP_TLV_RESULT_FAILURE) { - wpa_printf(MSG_DEBUG, "EAP-FAST: Result TLV indicated " - "failure"); - eap_fast_state(data, FAILURE); - return; - } - - if (data->state == REQUEST_PAC) { - u16 type, len, res; - if (tlv.pac == NULL || tlv.pac_len < 6) { - wpa_printf(MSG_DEBUG, "EAP-FAST: No PAC " - "Acknowledgement received"); - eap_fast_state(data, FAILURE); - return; - } - - type = WPA_GET_BE16(tlv.pac); - len = WPA_GET_BE16(tlv.pac + 2); - res = WPA_GET_BE16(tlv.pac + 4); - - if (type != PAC_TYPE_PAC_ACKNOWLEDGEMENT || len != 2 || - res != EAP_TLV_RESULT_SUCCESS) { - wpa_printf(MSG_DEBUG, "EAP-FAST: PAC TLV did not " - "contain acknowledgement"); - eap_fast_state(data, FAILURE); - return; - } - - wpa_printf(MSG_DEBUG, "EAP-FAST: PAC-Acknowledgement received " - "- PAC provisioning succeeded"); - eap_fast_state(data, (data->anon_provisioning || - data->send_new_pac == 2) ? - FAILURE : SUCCESS); - return; - } - - if (check_crypto_binding) { - if (tlv.crypto_binding == NULL) { - wpa_printf(MSG_DEBUG, "EAP-FAST: No Crypto-Binding " - "TLV received"); - eap_fast_state(data, FAILURE); - return; - } - - if (data->final_result && - tlv.result != EAP_TLV_RESULT_SUCCESS) { - wpa_printf(MSG_DEBUG, "EAP-FAST: Crypto-Binding TLV " - "without Success Result"); - eap_fast_state(data, FAILURE); - return; - } - - if (!data->final_result && - tlv.iresult != EAP_TLV_RESULT_SUCCESS) { - wpa_printf(MSG_DEBUG, "EAP-FAST: Crypto-Binding TLV " - "without intermediate Success Result"); - eap_fast_state(data, FAILURE); - return; - } - - if (eap_fast_validate_crypto_binding(data, tlv.crypto_binding, - tlv.crypto_binding_len)) { - eap_fast_state(data, FAILURE); - return; - } - - wpa_printf(MSG_DEBUG, "EAP-FAST: Valid Crypto-Binding TLV " - "received"); - if (data->final_result) { - wpa_printf(MSG_DEBUG, "EAP-FAST: Authentication " - "completed successfully"); - } - - if (data->anon_provisioning && - sm->eap_fast_prov != ANON_PROV && - sm->eap_fast_prov != BOTH_PROV) { - wpa_printf(MSG_DEBUG, "EAP-FAST: Client is trying to " - "use unauthenticated provisioning which is " - "disabled"); - eap_fast_state(data, FAILURE); - return; - } - - if (sm->eap_fast_prov != AUTH_PROV && - sm->eap_fast_prov != BOTH_PROV && - tlv.request_action == EAP_TLV_ACTION_PROCESS_TLV && - eap_fast_pac_type(tlv.pac, tlv.pac_len, - PAC_TYPE_TUNNEL_PAC)) { - wpa_printf(MSG_DEBUG, "EAP-FAST: Client is trying to " - "use authenticated provisioning which is " - "disabled"); - eap_fast_state(data, FAILURE); - return; - } - - if (data->anon_provisioning || - (tlv.request_action == EAP_TLV_ACTION_PROCESS_TLV && - eap_fast_pac_type(tlv.pac, tlv.pac_len, - PAC_TYPE_TUNNEL_PAC))) { - wpa_printf(MSG_DEBUG, "EAP-FAST: Requested a new " - "Tunnel PAC"); - eap_fast_state(data, REQUEST_PAC); - } else if (data->send_new_pac) { - wpa_printf(MSG_DEBUG, "EAP-FAST: Server triggered " - "re-keying of Tunnel PAC"); - eap_fast_state(data, REQUEST_PAC); - } else if (data->final_result) - eap_fast_state(data, SUCCESS); - } - - if (tlv.eap_payload_tlv) { - eap_fast_process_phase2_eap(sm, data, tlv.eap_payload_tlv, - tlv.eap_payload_tlv_len); - } -} - - -static void eap_fast_process_phase2(struct eap_sm *sm, - struct eap_fast_data *data, - struct wpabuf *in_buf) -{ - struct wpabuf *in_decrypted; - - wpa_printf(MSG_DEBUG, "EAP-FAST: Received %lu bytes encrypted data for" - " Phase 2", (unsigned long) wpabuf_len(in_buf)); - - if (data->pending_phase2_resp) { - wpa_printf(MSG_DEBUG, "EAP-PEAP: Pending Phase 2 response - " - "skip decryption and use old data"); - eap_fast_process_phase2_tlvs(sm, data, - data->pending_phase2_resp); - wpabuf_free(data->pending_phase2_resp); - data->pending_phase2_resp = NULL; - return; - } - - in_decrypted = tls_connection_decrypt(sm->ssl_ctx, data->ssl.conn, - in_buf); - if (in_decrypted == NULL) { - wpa_printf(MSG_INFO, "EAP-FAST: Failed to decrypt Phase 2 " - "data"); - eap_fast_state(data, FAILURE); - return; - } - - wpa_hexdump_buf_key(MSG_DEBUG, "EAP-FAST: Decrypted Phase 2 TLVs", - in_decrypted); - - eap_fast_process_phase2_tlvs(sm, data, in_decrypted); - - if (sm->method_pending == METHOD_PENDING_WAIT) { - wpa_printf(MSG_DEBUG, "EAP-FAST: Phase2 method is in " - "pending wait state - save decrypted response"); - wpabuf_free(data->pending_phase2_resp); - data->pending_phase2_resp = in_decrypted; - return; - } - - wpabuf_free(in_decrypted); -} - - -static int eap_fast_process_version(struct eap_sm *sm, void *priv, - int peer_version) -{ - struct eap_fast_data *data = priv; - - data->peer_version = peer_version; - - if (data->force_version >= 0 && peer_version != data->force_version) { - wpa_printf(MSG_INFO, "EAP-FAST: peer did not select the forced" - " version (forced=%d peer=%d) - reject", - data->force_version, peer_version); - return -1; - } - - if (peer_version < data->fast_version) { - wpa_printf(MSG_DEBUG, "EAP-FAST: peer ver=%d, own ver=%d; " - "use version %d", - peer_version, data->fast_version, peer_version); - data->fast_version = peer_version; - } - - return 0; -} - - -static int eap_fast_process_phase1(struct eap_sm *sm, - struct eap_fast_data *data) -{ - if (eap_server_tls_phase1(sm, &data->ssl) < 0) { - wpa_printf(MSG_INFO, "EAP-FAST: TLS processing failed"); - eap_fast_state(data, FAILURE); - return -1; - } - - if (!tls_connection_established(sm->ssl_ctx, data->ssl.conn) || - wpabuf_len(data->ssl.tls_out) > 0) - return 1; - - /* - * Phase 1 was completed with the received message (e.g., when using - * abbreviated handshake), so Phase 2 can be started immediately - * without having to send through an empty message to the peer. - */ - - return eap_fast_phase1_done(sm, data); -} - - -static int eap_fast_process_phase2_start(struct eap_sm *sm, - struct eap_fast_data *data) -{ - u8 next_type; - - if (data->identity) { - os_free(sm->identity); - sm->identity = data->identity; - data->identity = NULL; - sm->identity_len = data->identity_len; - data->identity_len = 0; - sm->require_identity_match = 1; - if (eap_user_get(sm, sm->identity, sm->identity_len, 1) != 0) { - wpa_hexdump_ascii(MSG_DEBUG, "EAP-FAST: " - "Phase2 Identity not found " - "in the user database", - sm->identity, sm->identity_len); - next_type = eap_fast_req_failure(sm, data); - } else { - wpa_printf(MSG_DEBUG, "EAP-FAST: Identity already " - "known - skip Phase 2 Identity Request"); - next_type = sm->user->methods[0].method; - sm->user_eap_method_index = 1; - } - - eap_fast_state(data, PHASE2_METHOD); - } else { - eap_fast_state(data, PHASE2_ID); - next_type = EAP_TYPE_IDENTITY; - } - - return eap_fast_phase2_init(sm, data, next_type); -} - - -static void eap_fast_process_msg(struct eap_sm *sm, void *priv, - const struct wpabuf *respData) -{ - struct eap_fast_data *data = priv; - - switch (data->state) { - case PHASE1: - if (eap_fast_process_phase1(sm, data)) - break; - - /* fall through to PHASE2_START */ - case PHASE2_START: - eap_fast_process_phase2_start(sm, data); - break; - case PHASE2_ID: - case PHASE2_METHOD: - case CRYPTO_BINDING: - case REQUEST_PAC: - eap_fast_process_phase2(sm, data, data->ssl.tls_in); - break; - default: - wpa_printf(MSG_DEBUG, "EAP-FAST: Unexpected state %d in %s", - data->state, __func__); - break; - } -} - - -static void eap_fast_process(struct eap_sm *sm, void *priv, - struct wpabuf *respData) -{ - struct eap_fast_data *data = priv; - if (eap_server_tls_process(sm, &data->ssl, respData, data, - EAP_TYPE_FAST, eap_fast_process_version, - eap_fast_process_msg) < 0) - eap_fast_state(data, FAILURE); -} - - -static Boolean eap_fast_isDone(struct eap_sm *sm, void *priv) -{ - struct eap_fast_data *data = priv; - return data->state == SUCCESS || data->state == FAILURE; -} - - -static u8 * eap_fast_getKey(struct eap_sm *sm, void *priv, size_t *len) -{ - struct eap_fast_data *data = priv; - u8 *eapKeyData; - - if (data->state != SUCCESS) - return NULL; - - eapKeyData = os_malloc(EAP_FAST_KEY_LEN); - if (eapKeyData == NULL) - return NULL; - - eap_fast_derive_eap_msk(data->simck, eapKeyData); - *len = EAP_FAST_KEY_LEN; - - return eapKeyData; -} - - -static u8 * eap_fast_get_emsk(struct eap_sm *sm, void *priv, size_t *len) -{ - struct eap_fast_data *data = priv; - u8 *eapKeyData; - - if (data->state != SUCCESS) - return NULL; - - eapKeyData = os_malloc(EAP_EMSK_LEN); - if (eapKeyData == NULL) - return NULL; - - eap_fast_derive_eap_emsk(data->simck, eapKeyData); - *len = EAP_EMSK_LEN; - - return eapKeyData; -} - - -static Boolean eap_fast_isSuccess(struct eap_sm *sm, void *priv) -{ - struct eap_fast_data *data = priv; - return data->state == SUCCESS; -} - - -int eap_server_fast_register(void) -{ - struct eap_method *eap; - int ret; - - eap = eap_server_method_alloc(EAP_SERVER_METHOD_INTERFACE_VERSION, - EAP_VENDOR_IETF, EAP_TYPE_FAST, "FAST"); - if (eap == NULL) - return -1; - - eap->init = eap_fast_init; - eap->reset = eap_fast_reset; - eap->buildReq = eap_fast_buildReq; - eap->check = eap_fast_check; - eap->process = eap_fast_process; - eap->isDone = eap_fast_isDone; - eap->getKey = eap_fast_getKey; - eap->get_emsk = eap_fast_get_emsk; - eap->isSuccess = eap_fast_isSuccess; - - ret = eap_server_method_register(eap); - if (ret) - eap_server_method_free(eap); - return ret; -} diff --git a/hostapd-0.8/src/eap_server/eap_server_gpsk.c b/hostapd-0.8/src/eap_server/eap_server_gpsk.c deleted file mode 100644 index a794806..0000000 --- a/hostapd-0.8/src/eap_server/eap_server_gpsk.c +++ /dev/null @@ -1,634 +0,0 @@ -/* - * hostapd / EAP-GPSK (RFC 5433) server - * Copyright (c) 2006-2007, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#include "includes.h" - -#include "common.h" -#include "crypto/random.h" -#include "eap_server/eap_i.h" -#include "eap_common/eap_gpsk_common.h" - - -struct eap_gpsk_data { - enum { GPSK_1, GPSK_3, SUCCESS, FAILURE } state; - u8 rand_server[EAP_GPSK_RAND_LEN]; - u8 rand_peer[EAP_GPSK_RAND_LEN]; - u8 msk[EAP_MSK_LEN]; - u8 emsk[EAP_EMSK_LEN]; - u8 sk[EAP_GPSK_MAX_SK_LEN]; - size_t sk_len; - u8 pk[EAP_GPSK_MAX_PK_LEN]; - size_t pk_len; - u8 *id_peer; - size_t id_peer_len; - u8 *id_server; - size_t id_server_len; -#define MAX_NUM_CSUITES 2 - struct eap_gpsk_csuite csuite_list[MAX_NUM_CSUITES]; - size_t csuite_count; - int vendor; /* CSuite/Vendor */ - int specifier; /* CSuite/Specifier */ -}; - - -static const char * eap_gpsk_state_txt(int state) -{ - switch (state) { - case GPSK_1: - return "GPSK-1"; - case GPSK_3: - return "GPSK-3"; - case SUCCESS: - return "SUCCESS"; - case FAILURE: - return "FAILURE"; - default: - return "?"; - } -} - - -static void eap_gpsk_state(struct eap_gpsk_data *data, int state) -{ - wpa_printf(MSG_DEBUG, "EAP-GPSK: %s -> %s", - eap_gpsk_state_txt(data->state), - eap_gpsk_state_txt(state)); - data->state = state; -} - - -static void * eap_gpsk_init(struct eap_sm *sm) -{ - struct eap_gpsk_data *data; - - data = os_zalloc(sizeof(*data)); - if (data == NULL) - return NULL; - data->state = GPSK_1; - - /* TODO: add support for configuring ID_Server */ - data->id_server = (u8 *) os_strdup("hostapd"); - if (data->id_server) - data->id_server_len = os_strlen((char *) data->id_server); - - data->csuite_count = 0; - if (eap_gpsk_supported_ciphersuite(EAP_GPSK_VENDOR_IETF, - EAP_GPSK_CIPHER_AES)) { - WPA_PUT_BE32(data->csuite_list[data->csuite_count].vendor, - EAP_GPSK_VENDOR_IETF); - WPA_PUT_BE16(data->csuite_list[data->csuite_count].specifier, - EAP_GPSK_CIPHER_AES); - data->csuite_count++; - } - if (eap_gpsk_supported_ciphersuite(EAP_GPSK_VENDOR_IETF, - EAP_GPSK_CIPHER_SHA256)) { - WPA_PUT_BE32(data->csuite_list[data->csuite_count].vendor, - EAP_GPSK_VENDOR_IETF); - WPA_PUT_BE16(data->csuite_list[data->csuite_count].specifier, - EAP_GPSK_CIPHER_SHA256); - data->csuite_count++; - } - - return data; -} - - -static void eap_gpsk_reset(struct eap_sm *sm, void *priv) -{ - struct eap_gpsk_data *data = priv; - os_free(data->id_server); - os_free(data->id_peer); - os_free(data); -} - - -static struct wpabuf * eap_gpsk_build_gpsk_1(struct eap_sm *sm, - struct eap_gpsk_data *data, u8 id) -{ - size_t len; - struct wpabuf *req; - - wpa_printf(MSG_DEBUG, "EAP-GPSK: Request/GPSK-1"); - - if (random_get_bytes(data->rand_server, EAP_GPSK_RAND_LEN)) { - wpa_printf(MSG_ERROR, "EAP-GPSK: Failed to get random data"); - eap_gpsk_state(data, FAILURE); - return NULL; - } - wpa_hexdump(MSG_MSGDUMP, "EAP-GPSK: RAND_Server", - data->rand_server, EAP_GPSK_RAND_LEN); - - len = 1 + 2 + data->id_server_len + EAP_GPSK_RAND_LEN + 2 + - data->csuite_count * sizeof(struct eap_gpsk_csuite); - req = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_GPSK, len, - EAP_CODE_REQUEST, id); - if (req == NULL) { - wpa_printf(MSG_ERROR, "EAP-GPSK: Failed to allocate memory " - "for request/GPSK-1"); - eap_gpsk_state(data, FAILURE); - return NULL; - } - - wpabuf_put_u8(req, EAP_GPSK_OPCODE_GPSK_1); - wpabuf_put_be16(req, data->id_server_len); - wpabuf_put_data(req, data->id_server, data->id_server_len); - wpabuf_put_data(req, data->rand_server, EAP_GPSK_RAND_LEN); - wpabuf_put_be16(req, - data->csuite_count * sizeof(struct eap_gpsk_csuite)); - wpabuf_put_data(req, data->csuite_list, - data->csuite_count * sizeof(struct eap_gpsk_csuite)); - - return req; -} - - -static struct wpabuf * eap_gpsk_build_gpsk_3(struct eap_sm *sm, - struct eap_gpsk_data *data, u8 id) -{ - u8 *pos, *start; - size_t len, miclen; - struct eap_gpsk_csuite *csuite; - struct wpabuf *req; - - wpa_printf(MSG_DEBUG, "EAP-GPSK: Request/GPSK-3"); - - miclen = eap_gpsk_mic_len(data->vendor, data->specifier); - len = 1 + 2 * EAP_GPSK_RAND_LEN + 2 + data->id_server_len + - sizeof(struct eap_gpsk_csuite) + 2 + miclen; - req = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_GPSK, len, - EAP_CODE_REQUEST, id); - if (req == NULL) { - wpa_printf(MSG_ERROR, "EAP-GPSK: Failed to allocate memory " - "for request/GPSK-3"); - eap_gpsk_state(data, FAILURE); - return NULL; - } - - wpabuf_put_u8(req, EAP_GPSK_OPCODE_GPSK_3); - start = wpabuf_put(req, 0); - - wpabuf_put_data(req, data->rand_peer, EAP_GPSK_RAND_LEN); - wpabuf_put_data(req, data->rand_server, EAP_GPSK_RAND_LEN); - wpabuf_put_be16(req, data->id_server_len); - wpabuf_put_data(req, data->id_server, data->id_server_len); - csuite = wpabuf_put(req, sizeof(*csuite)); - WPA_PUT_BE32(csuite->vendor, data->vendor); - WPA_PUT_BE16(csuite->specifier, data->specifier); - - /* no PD_Payload_2 */ - wpabuf_put_be16(req, 0); - - pos = wpabuf_put(req, miclen); - if (eap_gpsk_compute_mic(data->sk, data->sk_len, data->vendor, - data->specifier, start, pos - start, pos) < 0) - { - os_free(req); - eap_gpsk_state(data, FAILURE); - return NULL; - } - - return req; -} - - -static struct wpabuf * eap_gpsk_buildReq(struct eap_sm *sm, void *priv, u8 id) -{ - struct eap_gpsk_data *data = priv; - - switch (data->state) { - case GPSK_1: - return eap_gpsk_build_gpsk_1(sm, data, id); - case GPSK_3: - return eap_gpsk_build_gpsk_3(sm, data, id); - default: - wpa_printf(MSG_DEBUG, "EAP-GPSK: Unknown state %d in buildReq", - data->state); - break; - } - return NULL; -} - - -static Boolean eap_gpsk_check(struct eap_sm *sm, void *priv, - struct wpabuf *respData) -{ - struct eap_gpsk_data *data = priv; - const u8 *pos; - size_t len; - - pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_GPSK, respData, &len); - if (pos == NULL || len < 1) { - wpa_printf(MSG_INFO, "EAP-GPSK: Invalid frame"); - return TRUE; - } - - wpa_printf(MSG_DEBUG, "EAP-GPSK: Received frame: opcode=%d", *pos); - - if (data->state == GPSK_1 && *pos == EAP_GPSK_OPCODE_GPSK_2) - return FALSE; - - if (data->state == GPSK_3 && *pos == EAP_GPSK_OPCODE_GPSK_4) - return FALSE; - - wpa_printf(MSG_INFO, "EAP-GPSK: Unexpected opcode=%d in state=%d", - *pos, data->state); - - return TRUE; -} - - -static void eap_gpsk_process_gpsk_2(struct eap_sm *sm, - struct eap_gpsk_data *data, - const u8 *payload, size_t payloadlen) -{ - const u8 *pos, *end; - u16 alen; - const struct eap_gpsk_csuite *csuite; - size_t i, miclen; - u8 mic[EAP_GPSK_MAX_MIC_LEN]; - - if (data->state != GPSK_1) - return; - - wpa_printf(MSG_DEBUG, "EAP-GPSK: Received Response/GPSK-2"); - - pos = payload; - end = payload + payloadlen; - - if (end - pos < 2) { - wpa_printf(MSG_DEBUG, "EAP-GPSK: Too short message for " - "ID_Peer length"); - eap_gpsk_state(data, FAILURE); - return; - } - alen = WPA_GET_BE16(pos); - pos += 2; - if (end - pos < alen) { - wpa_printf(MSG_DEBUG, "EAP-GPSK: Too short message for " - "ID_Peer"); - eap_gpsk_state(data, FAILURE); - return; - } - os_free(data->id_peer); - data->id_peer = os_malloc(alen); - if (data->id_peer == NULL) { - wpa_printf(MSG_DEBUG, "EAP-GPSK: Not enough memory to store " - "%d-octet ID_Peer", alen); - return; - } - os_memcpy(data->id_peer, pos, alen); - data->id_peer_len = alen; - wpa_hexdump_ascii(MSG_DEBUG, "EAP-GPSK: ID_Peer", - data->id_peer, data->id_peer_len); - pos += alen; - - if (end - pos < 2) { - wpa_printf(MSG_DEBUG, "EAP-GPSK: Too short message for " - "ID_Server length"); - eap_gpsk_state(data, FAILURE); - return; - } - alen = WPA_GET_BE16(pos); - pos += 2; - if (end - pos < alen) { - wpa_printf(MSG_DEBUG, "EAP-GPSK: Too short message for " - "ID_Server"); - eap_gpsk_state(data, FAILURE); - return; - } - if (alen != data->id_server_len || - os_memcmp(pos, data->id_server, alen) != 0) { - wpa_printf(MSG_DEBUG, "EAP-GPSK: ID_Server in GPSK-1 and " - "GPSK-2 did not match"); - eap_gpsk_state(data, FAILURE); - return; - } - pos += alen; - - if (end - pos < EAP_GPSK_RAND_LEN) { - wpa_printf(MSG_DEBUG, "EAP-GPSK: Too short message for " - "RAND_Peer"); - eap_gpsk_state(data, FAILURE); - return; - } - os_memcpy(data->rand_peer, pos, EAP_GPSK_RAND_LEN); - wpa_hexdump(MSG_DEBUG, "EAP-GPSK: RAND_Peer", - data->rand_peer, EAP_GPSK_RAND_LEN); - pos += EAP_GPSK_RAND_LEN; - - if (end - pos < EAP_GPSK_RAND_LEN) { - wpa_printf(MSG_DEBUG, "EAP-GPSK: Too short message for " - "RAND_Server"); - eap_gpsk_state(data, FAILURE); - return; - } - if (os_memcmp(data->rand_server, pos, EAP_GPSK_RAND_LEN) != 0) { - wpa_printf(MSG_DEBUG, "EAP-GPSK: RAND_Server in GPSK-1 and " - "GPSK-2 did not match"); - wpa_hexdump(MSG_DEBUG, "EAP-GPSK: RAND_Server in GPSK-1", - data->rand_server, EAP_GPSK_RAND_LEN); - wpa_hexdump(MSG_DEBUG, "EAP-GPSK: RAND_Server in GPSK-2", - pos, EAP_GPSK_RAND_LEN); - eap_gpsk_state(data, FAILURE); - return; - } - pos += EAP_GPSK_RAND_LEN; - - if (end - pos < 2) { - wpa_printf(MSG_DEBUG, "EAP-GPSK: Too short message for " - "CSuite_List length"); - eap_gpsk_state(data, FAILURE); - return; - } - alen = WPA_GET_BE16(pos); - pos += 2; - if (end - pos < alen) { - wpa_printf(MSG_DEBUG, "EAP-GPSK: Too short message for " - "CSuite_List"); - eap_gpsk_state(data, FAILURE); - return; - } - if (alen != data->csuite_count * sizeof(struct eap_gpsk_csuite) || - os_memcmp(pos, data->csuite_list, alen) != 0) { - wpa_printf(MSG_DEBUG, "EAP-GPSK: CSuite_List in GPSK-1 and " - "GPSK-2 did not match"); - eap_gpsk_state(data, FAILURE); - return; - } - pos += alen; - - if (end - pos < (int) sizeof(*csuite)) { - wpa_printf(MSG_DEBUG, "EAP-GPSK: Too short message for " - "CSuite_Sel"); - eap_gpsk_state(data, FAILURE); - return; - } - csuite = (const struct eap_gpsk_csuite *) pos; - for (i = 0; i < data->csuite_count; i++) { - if (os_memcmp(csuite, &data->csuite_list[i], sizeof(*csuite)) - == 0) - break; - } - if (i == data->csuite_count) { - wpa_printf(MSG_DEBUG, "EAP-GPSK: Peer selected unsupported " - "ciphersuite %d:%d", - WPA_GET_BE32(csuite->vendor), - WPA_GET_BE16(csuite->specifier)); - eap_gpsk_state(data, FAILURE); - return; - } - data->vendor = WPA_GET_BE32(csuite->vendor); - data->specifier = WPA_GET_BE16(csuite->specifier); - wpa_printf(MSG_DEBUG, "EAP-GPSK: CSuite_Sel %d:%d", - data->vendor, data->specifier); - pos += sizeof(*csuite); - - if (end - pos < 2) { - wpa_printf(MSG_DEBUG, "EAP-GPSK: Too short message for " - "PD_Payload_1 length"); - eap_gpsk_state(data, FAILURE); - return; - } - alen = WPA_GET_BE16(pos); - pos += 2; - if (end - pos < alen) { - wpa_printf(MSG_DEBUG, "EAP-GPSK: Too short message for " - "PD_Payload_1"); - eap_gpsk_state(data, FAILURE); - return; - } - wpa_hexdump(MSG_DEBUG, "EAP-GPSK: PD_Payload_1", pos, alen); - pos += alen; - - if (sm->user == NULL || sm->user->password == NULL) { - wpa_printf(MSG_INFO, "EAP-GPSK: No PSK/password configured " - "for the user"); - eap_gpsk_state(data, FAILURE); - return; - } - - if (eap_gpsk_derive_keys(sm->user->password, sm->user->password_len, - data->vendor, data->specifier, - data->rand_peer, data->rand_server, - data->id_peer, data->id_peer_len, - data->id_server, data->id_server_len, - data->msk, data->emsk, - data->sk, &data->sk_len, - data->pk, &data->pk_len) < 0) { - wpa_printf(MSG_DEBUG, "EAP-GPSK: Failed to derive keys"); - eap_gpsk_state(data, FAILURE); - return; - } - - miclen = eap_gpsk_mic_len(data->vendor, data->specifier); - if (end - pos < (int) miclen) { - wpa_printf(MSG_DEBUG, "EAP-GPSK: Message too short for MIC " - "(left=%lu miclen=%lu)", - (unsigned long) (end - pos), - (unsigned long) miclen); - eap_gpsk_state(data, FAILURE); - return; - } - if (eap_gpsk_compute_mic(data->sk, data->sk_len, data->vendor, - data->specifier, payload, pos - payload, mic) - < 0) { - wpa_printf(MSG_DEBUG, "EAP-GPSK: Failed to compute MIC"); - eap_gpsk_state(data, FAILURE); - return; - } - if (os_memcmp(mic, pos, miclen) != 0) { - wpa_printf(MSG_INFO, "EAP-GPSK: Incorrect MIC in GPSK-2"); - wpa_hexdump(MSG_DEBUG, "EAP-GPSK: Received MIC", pos, miclen); - wpa_hexdump(MSG_DEBUG, "EAP-GPSK: Computed MIC", mic, miclen); - eap_gpsk_state(data, FAILURE); - return; - } - pos += miclen; - - if (pos != end) { - wpa_printf(MSG_DEBUG, "EAP-GPSK: Ignored %lu bytes of extra " - "data in the end of GPSK-2", - (unsigned long) (end - pos)); - } - - eap_gpsk_state(data, GPSK_3); -} - - -static void eap_gpsk_process_gpsk_4(struct eap_sm *sm, - struct eap_gpsk_data *data, - const u8 *payload, size_t payloadlen) -{ - const u8 *pos, *end; - u16 alen; - size_t miclen; - u8 mic[EAP_GPSK_MAX_MIC_LEN]; - - if (data->state != GPSK_3) - return; - - wpa_printf(MSG_DEBUG, "EAP-GPSK: Received Response/GPSK-4"); - - pos = payload; - end = payload + payloadlen; - - if (end - pos < 2) { - wpa_printf(MSG_DEBUG, "EAP-GPSK: Too short message for " - "PD_Payload_1 length"); - eap_gpsk_state(data, FAILURE); - return; - } - alen = WPA_GET_BE16(pos); - pos += 2; - if (end - pos < alen) { - wpa_printf(MSG_DEBUG, "EAP-GPSK: Too short message for " - "PD_Payload_1"); - eap_gpsk_state(data, FAILURE); - return; - } - wpa_hexdump(MSG_DEBUG, "EAP-GPSK: PD_Payload_1", pos, alen); - pos += alen; - - miclen = eap_gpsk_mic_len(data->vendor, data->specifier); - if (end - pos < (int) miclen) { - wpa_printf(MSG_DEBUG, "EAP-GPSK: Message too short for MIC " - "(left=%lu miclen=%lu)", - (unsigned long) (end - pos), - (unsigned long) miclen); - eap_gpsk_state(data, FAILURE); - return; - } - if (eap_gpsk_compute_mic(data->sk, data->sk_len, data->vendor, - data->specifier, payload, pos - payload, mic) - < 0) { - wpa_printf(MSG_DEBUG, "EAP-GPSK: Failed to compute MIC"); - eap_gpsk_state(data, FAILURE); - return; - } - if (os_memcmp(mic, pos, miclen) != 0) { - wpa_printf(MSG_INFO, "EAP-GPSK: Incorrect MIC in GPSK-4"); - wpa_hexdump(MSG_DEBUG, "EAP-GPSK: Received MIC", pos, miclen); - wpa_hexdump(MSG_DEBUG, "EAP-GPSK: Computed MIC", mic, miclen); - eap_gpsk_state(data, FAILURE); - return; - } - pos += miclen; - - if (pos != end) { - wpa_printf(MSG_DEBUG, "EAP-GPSK: Ignored %lu bytes of extra " - "data in the end of GPSK-4", - (unsigned long) (end - pos)); - } - - eap_gpsk_state(data, SUCCESS); -} - - -static void eap_gpsk_process(struct eap_sm *sm, void *priv, - struct wpabuf *respData) -{ - struct eap_gpsk_data *data = priv; - const u8 *pos; - size_t len; - - pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_GPSK, respData, &len); - if (pos == NULL || len < 1) - return; - - switch (*pos) { - case EAP_GPSK_OPCODE_GPSK_2: - eap_gpsk_process_gpsk_2(sm, data, pos + 1, len - 1); - break; - case EAP_GPSK_OPCODE_GPSK_4: - eap_gpsk_process_gpsk_4(sm, data, pos + 1, len - 1); - break; - } -} - - -static Boolean eap_gpsk_isDone(struct eap_sm *sm, void *priv) -{ - struct eap_gpsk_data *data = priv; - return data->state == SUCCESS || data->state == FAILURE; -} - - -static u8 * eap_gpsk_getKey(struct eap_sm *sm, void *priv, size_t *len) -{ - struct eap_gpsk_data *data = priv; - u8 *key; - - if (data->state != SUCCESS) - return NULL; - - key = os_malloc(EAP_MSK_LEN); - if (key == NULL) - return NULL; - os_memcpy(key, data->msk, EAP_MSK_LEN); - *len = EAP_MSK_LEN; - - return key; -} - - -static u8 * eap_gpsk_get_emsk(struct eap_sm *sm, void *priv, size_t *len) -{ - struct eap_gpsk_data *data = priv; - u8 *key; - - if (data->state != SUCCESS) - return NULL; - - key = os_malloc(EAP_EMSK_LEN); - if (key == NULL) - return NULL; - os_memcpy(key, data->emsk, EAP_EMSK_LEN); - *len = EAP_EMSK_LEN; - - return key; -} - - -static Boolean eap_gpsk_isSuccess(struct eap_sm *sm, void *priv) -{ - struct eap_gpsk_data *data = priv; - return data->state == SUCCESS; -} - - -int eap_server_gpsk_register(void) -{ - struct eap_method *eap; - int ret; - - eap = eap_server_method_alloc(EAP_SERVER_METHOD_INTERFACE_VERSION, - EAP_VENDOR_IETF, EAP_TYPE_GPSK, "GPSK"); - if (eap == NULL) - return -1; - - eap->init = eap_gpsk_init; - eap->reset = eap_gpsk_reset; - eap->buildReq = eap_gpsk_buildReq; - eap->check = eap_gpsk_check; - eap->process = eap_gpsk_process; - eap->isDone = eap_gpsk_isDone; - eap->getKey = eap_gpsk_getKey; - eap->isSuccess = eap_gpsk_isSuccess; - eap->get_emsk = eap_gpsk_get_emsk; - - ret = eap_server_method_register(eap); - if (ret) - eap_server_method_free(eap); - return ret; -} diff --git a/hostapd-0.8/src/eap_server/eap_server_gtc.c b/hostapd-0.8/src/eap_server/eap_server_gtc.c deleted file mode 100644 index 79b9696..0000000 --- a/hostapd-0.8/src/eap_server/eap_server_gtc.c +++ /dev/null @@ -1,230 +0,0 @@ -/* - * hostapd / EAP-GTC (RFC 3748) - * Copyright (c) 2004-2006, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#include "includes.h" - -#include "common.h" -#include "eap_i.h" - - -struct eap_gtc_data { - enum { CONTINUE, SUCCESS, FAILURE } state; - int prefix; -}; - - -static void * eap_gtc_init(struct eap_sm *sm) -{ - struct eap_gtc_data *data; - - data = os_zalloc(sizeof(*data)); - if (data == NULL) - return NULL; - data->state = CONTINUE; - -#ifdef EAP_SERVER_FAST - if (sm->m && sm->m->vendor == EAP_VENDOR_IETF && - sm->m->method == EAP_TYPE_FAST) { - wpa_printf(MSG_DEBUG, "EAP-GTC: EAP-FAST tunnel - use prefix " - "with challenge/response"); - data->prefix = 1; - } -#endif /* EAP_SERVER_FAST */ - - return data; -} - - -static void eap_gtc_reset(struct eap_sm *sm, void *priv) -{ - struct eap_gtc_data *data = priv; - os_free(data); -} - - -static struct wpabuf * eap_gtc_buildReq(struct eap_sm *sm, void *priv, u8 id) -{ - struct eap_gtc_data *data = priv; - struct wpabuf *req; - char *msg; - size_t msg_len; - - msg = data->prefix ? "CHALLENGE=Password" : "Password"; - - msg_len = os_strlen(msg); - req = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_GTC, msg_len, - EAP_CODE_REQUEST, id); - if (req == NULL) { - wpa_printf(MSG_ERROR, "EAP-GTC: Failed to allocate memory for " - "request"); - data->state = FAILURE; - return NULL; - } - - wpabuf_put_data(req, msg, msg_len); - - data->state = CONTINUE; - - return req; -} - - -static Boolean eap_gtc_check(struct eap_sm *sm, void *priv, - struct wpabuf *respData) -{ - const u8 *pos; - size_t len; - - pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_GTC, respData, &len); - if (pos == NULL || len < 1) { - wpa_printf(MSG_INFO, "EAP-GTC: Invalid frame"); - return TRUE; - } - - return FALSE; -} - - -static void eap_gtc_process(struct eap_sm *sm, void *priv, - struct wpabuf *respData) -{ - struct eap_gtc_data *data = priv; - const u8 *pos; - size_t rlen; - - pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_GTC, respData, &rlen); - if (pos == NULL || rlen < 1) - return; /* Should not happen - frame already validated */ - - wpa_hexdump_ascii_key(MSG_MSGDUMP, "EAP-GTC: Response", pos, rlen); - -#ifdef EAP_SERVER_FAST - if (data->prefix) { - const u8 *pos2, *end; - /* "RESPONSE=\0" */ - if (rlen < 10) { - wpa_printf(MSG_DEBUG, "EAP-GTC: Too short response " - "for EAP-FAST prefix"); - data->state = FAILURE; - return; - } - - end = pos + rlen; - pos += 9; - pos2 = pos; - while (pos2 < end && *pos2) - pos2++; - if (pos2 == end) { - wpa_printf(MSG_DEBUG, "EAP-GTC: No password in " - "response to EAP-FAST prefix"); - data->state = FAILURE; - return; - } - - wpa_hexdump_ascii(MSG_MSGDUMP, "EAP-GTC: Response user", - pos, pos2 - pos); - if (sm->identity && sm->require_identity_match && - (pos2 - pos != (int) sm->identity_len || - os_memcmp(pos, sm->identity, sm->identity_len))) { - wpa_printf(MSG_DEBUG, "EAP-GTC: Phase 2 Identity did " - "not match with required Identity"); - wpa_hexdump_ascii(MSG_MSGDUMP, "EAP-GTC: Expected " - "identity", - sm->identity, sm->identity_len); - data->state = FAILURE; - return; - } else { - os_free(sm->identity); - sm->identity_len = pos2 - pos; - sm->identity = os_malloc(sm->identity_len); - if (sm->identity == NULL) { - data->state = FAILURE; - return; - } - os_memcpy(sm->identity, pos, sm->identity_len); - } - - if (eap_user_get(sm, sm->identity, sm->identity_len, 1) != 0) { - wpa_hexdump_ascii(MSG_DEBUG, "EAP-GTC: Phase2 " - "Identity not found in the user " - "database", - sm->identity, sm->identity_len); - data->state = FAILURE; - return; - } - - pos = pos2 + 1; - rlen = end - pos; - wpa_hexdump_ascii_key(MSG_MSGDUMP, - "EAP-GTC: Response password", - pos, rlen); - } -#endif /* EAP_SERVER_FAST */ - - if (sm->user == NULL || sm->user->password == NULL || - sm->user->password_hash) { - wpa_printf(MSG_INFO, "EAP-GTC: Plaintext password not " - "configured"); - data->state = FAILURE; - return; - } - - if (rlen != sm->user->password_len || - os_memcmp(pos, sm->user->password, rlen) != 0) { - wpa_printf(MSG_DEBUG, "EAP-GTC: Done - Failure"); - data->state = FAILURE; - } else { - wpa_printf(MSG_DEBUG, "EAP-GTC: Done - Success"); - data->state = SUCCESS; - } -} - - -static Boolean eap_gtc_isDone(struct eap_sm *sm, void *priv) -{ - struct eap_gtc_data *data = priv; - return data->state != CONTINUE; -} - - -static Boolean eap_gtc_isSuccess(struct eap_sm *sm, void *priv) -{ - struct eap_gtc_data *data = priv; - return data->state == SUCCESS; -} - - -int eap_server_gtc_register(void) -{ - struct eap_method *eap; - int ret; - - eap = eap_server_method_alloc(EAP_SERVER_METHOD_INTERFACE_VERSION, - EAP_VENDOR_IETF, EAP_TYPE_GTC, "GTC"); - if (eap == NULL) - return -1; - - eap->init = eap_gtc_init; - eap->reset = eap_gtc_reset; - eap->buildReq = eap_gtc_buildReq; - eap->check = eap_gtc_check; - eap->process = eap_gtc_process; - eap->isDone = eap_gtc_isDone; - eap->isSuccess = eap_gtc_isSuccess; - - ret = eap_server_method_register(eap); - if (ret) - eap_server_method_free(eap); - return ret; -} diff --git a/hostapd-0.8/src/eap_server/eap_server_identity.c b/hostapd-0.8/src/eap_server/eap_server_identity.c deleted file mode 100644 index cd8da2a..0000000 --- a/hostapd-0.8/src/eap_server/eap_server_identity.c +++ /dev/null @@ -1,180 +0,0 @@ -/* - * hostapd / EAP-Identity - * Copyright (c) 2004-2006, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#include "includes.h" - -#include "common.h" -#include "eap_i.h" - - -struct eap_identity_data { - enum { CONTINUE, SUCCESS, FAILURE } state; - int pick_up; -}; - - -static void * eap_identity_init(struct eap_sm *sm) -{ - struct eap_identity_data *data; - - data = os_zalloc(sizeof(*data)); - if (data == NULL) - return NULL; - data->state = CONTINUE; - - return data; -} - - -static void * eap_identity_initPickUp(struct eap_sm *sm) -{ - struct eap_identity_data *data; - data = eap_identity_init(sm); - if (data) { - data->pick_up = 1; - } - return data; -} - - -static void eap_identity_reset(struct eap_sm *sm, void *priv) -{ - struct eap_identity_data *data = priv; - os_free(data); -} - - -static struct wpabuf * eap_identity_buildReq(struct eap_sm *sm, void *priv, - u8 id) -{ - struct eap_identity_data *data = priv; - struct wpabuf *req; - const char *req_data; - size_t req_data_len; - - if (sm->eapol_cb->get_eap_req_id_text) { - req_data = sm->eapol_cb->get_eap_req_id_text(sm->eapol_ctx, - &req_data_len); - } else { - req_data = NULL; - req_data_len = 0; - } - req = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_IDENTITY, req_data_len, - EAP_CODE_REQUEST, id); - if (req == NULL) { - wpa_printf(MSG_ERROR, "EAP-Identity: Failed to allocate " - "memory for request"); - data->state = FAILURE; - return NULL; - } - - wpabuf_put_data(req, req_data, req_data_len); - - return req; -} - - -static Boolean eap_identity_check(struct eap_sm *sm, void *priv, - struct wpabuf *respData) -{ - const u8 *pos; - size_t len; - - pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_IDENTITY, - respData, &len); - if (pos == NULL) { - wpa_printf(MSG_INFO, "EAP-Identity: Invalid frame"); - return TRUE; - } - - return FALSE; -} - - -static void eap_identity_process(struct eap_sm *sm, void *priv, - struct wpabuf *respData) -{ - struct eap_identity_data *data = priv; - const u8 *pos; - size_t len; - - if (data->pick_up) { - if (eap_identity_check(sm, data, respData)) { - wpa_printf(MSG_DEBUG, "EAP-Identity: failed to pick " - "up already started negotiation"); - data->state = FAILURE; - return; - } - data->pick_up = 0; - } - - pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_IDENTITY, - respData, &len); - if (pos == NULL) - return; /* Should not happen - frame already validated */ - - wpa_hexdump_ascii(MSG_DEBUG, "EAP-Identity: Peer identity", pos, len); - if (sm->identity) - sm->update_user = TRUE; - os_free(sm->identity); - sm->identity = os_malloc(len ? len : 1); - if (sm->identity == NULL) { - data->state = FAILURE; - } else { - os_memcpy(sm->identity, pos, len); - sm->identity_len = len; - data->state = SUCCESS; - } -} - - -static Boolean eap_identity_isDone(struct eap_sm *sm, void *priv) -{ - struct eap_identity_data *data = priv; - return data->state != CONTINUE; -} - - -static Boolean eap_identity_isSuccess(struct eap_sm *sm, void *priv) -{ - struct eap_identity_data *data = priv; - return data->state == SUCCESS; -} - - -int eap_server_identity_register(void) -{ - struct eap_method *eap; - int ret; - - eap = eap_server_method_alloc(EAP_SERVER_METHOD_INTERFACE_VERSION, - EAP_VENDOR_IETF, EAP_TYPE_IDENTITY, - "Identity"); - if (eap == NULL) - return -1; - - eap->init = eap_identity_init; - eap->initPickUp = eap_identity_initPickUp; - eap->reset = eap_identity_reset; - eap->buildReq = eap_identity_buildReq; - eap->check = eap_identity_check; - eap->process = eap_identity_process; - eap->isDone = eap_identity_isDone; - eap->isSuccess = eap_identity_isSuccess; - - ret = eap_server_method_register(eap); - if (ret) - eap_server_method_free(eap); - return ret; -} diff --git a/hostapd-0.8/src/eap_server/eap_server_ikev2.c b/hostapd-0.8/src/eap_server/eap_server_ikev2.c deleted file mode 100644 index ec4fa87..0000000 --- a/hostapd-0.8/src/eap_server/eap_server_ikev2.c +++ /dev/null @@ -1,539 +0,0 @@ -/* - * EAP-IKEv2 server (RFC 5106) - * Copyright (c) 2007, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#include "includes.h" - -#include "common.h" -#include "eap_i.h" -#include "eap_common/eap_ikev2_common.h" -#include "ikev2.h" - - -struct eap_ikev2_data { - struct ikev2_initiator_data ikev2; - enum { MSG, FRAG_ACK, WAIT_FRAG_ACK, DONE, FAIL } state; - struct wpabuf *in_buf; - struct wpabuf *out_buf; - size_t out_used; - size_t fragment_size; - int keys_ready; - u8 keymat[EAP_MSK_LEN + EAP_EMSK_LEN]; - int keymat_ok; -}; - - -static const u8 * eap_ikev2_get_shared_secret(void *ctx, const u8 *IDr, - size_t IDr_len, - size_t *secret_len) -{ - struct eap_sm *sm = ctx; - - if (IDr == NULL) { - wpa_printf(MSG_DEBUG, "EAP-IKEV2: No IDr received - default " - "to user identity from EAP-Identity"); - IDr = sm->identity; - IDr_len = sm->identity_len; - } - - if (eap_user_get(sm, IDr, IDr_len, 0) < 0 || sm->user == NULL || - sm->user->password == NULL) { - wpa_printf(MSG_DEBUG, "EAP-IKEV2: No user entry found"); - return NULL; - } - - *secret_len = sm->user->password_len; - return sm->user->password; -} - - -static const char * eap_ikev2_state_txt(int state) -{ - switch (state) { - case MSG: - return "MSG"; - case FRAG_ACK: - return "FRAG_ACK"; - case WAIT_FRAG_ACK: - return "WAIT_FRAG_ACK"; - case DONE: - return "DONE"; - case FAIL: - return "FAIL"; - default: - return "?"; - } -} - - -static void eap_ikev2_state(struct eap_ikev2_data *data, int state) -{ - wpa_printf(MSG_DEBUG, "EAP-IKEV2: %s -> %s", - eap_ikev2_state_txt(data->state), - eap_ikev2_state_txt(state)); - data->state = state; -} - - -static void * eap_ikev2_init(struct eap_sm *sm) -{ - struct eap_ikev2_data *data; - - data = os_zalloc(sizeof(*data)); - if (data == NULL) - return NULL; - data->state = MSG; - data->fragment_size = sm->fragment_size > 0 ? sm->fragment_size : - IKEV2_FRAGMENT_SIZE; - data->ikev2.state = SA_INIT; - data->ikev2.peer_auth = PEER_AUTH_SECRET; - data->ikev2.key_pad = (u8 *) os_strdup("Key Pad for EAP-IKEv2"); - if (data->ikev2.key_pad == NULL) - goto failed; - data->ikev2.key_pad_len = 21; - - /* TODO: make proposals configurable */ - data->ikev2.proposal.proposal_num = 1; - data->ikev2.proposal.integ = AUTH_HMAC_SHA1_96; - data->ikev2.proposal.prf = PRF_HMAC_SHA1; - data->ikev2.proposal.encr = ENCR_AES_CBC; - data->ikev2.proposal.dh = DH_GROUP2_1024BIT_MODP; - - data->ikev2.IDi = (u8 *) os_strdup("hostapd"); - data->ikev2.IDi_len = 7; - - data->ikev2.get_shared_secret = eap_ikev2_get_shared_secret; - data->ikev2.cb_ctx = sm; - - return data; - -failed: - ikev2_initiator_deinit(&data->ikev2); - os_free(data); - return NULL; -} - - -static void eap_ikev2_reset(struct eap_sm *sm, void *priv) -{ - struct eap_ikev2_data *data = priv; - wpabuf_free(data->in_buf); - wpabuf_free(data->out_buf); - ikev2_initiator_deinit(&data->ikev2); - os_free(data); -} - - -static struct wpabuf * eap_ikev2_build_msg(struct eap_ikev2_data *data, u8 id) -{ - struct wpabuf *req; - u8 flags; - size_t send_len, plen, icv_len = 0; - - wpa_printf(MSG_DEBUG, "EAP-IKEV2: Generating Request"); - - flags = 0; - send_len = wpabuf_len(data->out_buf) - data->out_used; - if (1 + send_len > data->fragment_size) { - send_len = data->fragment_size - 1; - flags |= IKEV2_FLAGS_MORE_FRAGMENTS; - if (data->out_used == 0) { - flags |= IKEV2_FLAGS_LENGTH_INCLUDED; - send_len -= 4; - } - } - - plen = 1 + send_len; - if (flags & IKEV2_FLAGS_LENGTH_INCLUDED) - plen += 4; - if (data->keys_ready) { - const struct ikev2_integ_alg *integ; - wpa_printf(MSG_DEBUG, "EAP-IKEV2: Add Integrity Checksum " - "Data"); - flags |= IKEV2_FLAGS_ICV_INCLUDED; - integ = ikev2_get_integ(data->ikev2.proposal.integ); - if (integ == NULL) { - wpa_printf(MSG_DEBUG, "EAP-IKEV2: Unknown INTEG " - "transform / cannot generate ICV"); - return NULL; - } - icv_len = integ->hash_len; - - plen += icv_len; - } - req = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_IKEV2, plen, - EAP_CODE_REQUEST, id); - if (req == NULL) - return NULL; - - wpabuf_put_u8(req, flags); /* Flags */ - if (flags & IKEV2_FLAGS_LENGTH_INCLUDED) - wpabuf_put_be32(req, wpabuf_len(data->out_buf)); - - wpabuf_put_data(req, wpabuf_head_u8(data->out_buf) + data->out_used, - send_len); - data->out_used += send_len; - - if (flags & IKEV2_FLAGS_ICV_INCLUDED) { - const u8 *msg = wpabuf_head(req); - size_t len = wpabuf_len(req); - ikev2_integ_hash(data->ikev2.proposal.integ, - data->ikev2.keys.SK_ai, - data->ikev2.keys.SK_integ_len, - msg, len, wpabuf_put(req, icv_len)); - } - - if (data->out_used == wpabuf_len(data->out_buf)) { - wpa_printf(MSG_DEBUG, "EAP-IKEV2: Sending out %lu bytes " - "(message sent completely)", - (unsigned long) send_len); - wpabuf_free(data->out_buf); - data->out_buf = NULL; - data->out_used = 0; - } else { - wpa_printf(MSG_DEBUG, "EAP-IKEV2: Sending out %lu bytes " - "(%lu more to send)", (unsigned long) send_len, - (unsigned long) wpabuf_len(data->out_buf) - - data->out_used); - eap_ikev2_state(data, WAIT_FRAG_ACK); - } - - return req; -} - - -static struct wpabuf * eap_ikev2_buildReq(struct eap_sm *sm, void *priv, u8 id) -{ - struct eap_ikev2_data *data = priv; - - switch (data->state) { - case MSG: - if (data->out_buf == NULL) { - data->out_buf = ikev2_initiator_build(&data->ikev2); - if (data->out_buf == NULL) { - wpa_printf(MSG_DEBUG, "EAP-IKEV2: Failed to " - "generate IKEv2 message"); - return NULL; - } - data->out_used = 0; - } - /* pass through */ - case WAIT_FRAG_ACK: - return eap_ikev2_build_msg(data, id); - case FRAG_ACK: - return eap_ikev2_build_frag_ack(id, EAP_CODE_REQUEST); - default: - wpa_printf(MSG_DEBUG, "EAP-IKEV2: Unexpected state %d in " - "buildReq", data->state); - return NULL; - } -} - - -static Boolean eap_ikev2_check(struct eap_sm *sm, void *priv, - struct wpabuf *respData) -{ - const u8 *pos; - size_t len; - - pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_IKEV2, respData, - &len); - if (pos == NULL) { - wpa_printf(MSG_INFO, "EAP-IKEV2: Invalid frame"); - return TRUE; - } - - return FALSE; -} - - -static int eap_ikev2_process_icv(struct eap_ikev2_data *data, - const struct wpabuf *respData, - u8 flags, const u8 *pos, const u8 **end) -{ - if (flags & IKEV2_FLAGS_ICV_INCLUDED) { - int icv_len = eap_ikev2_validate_icv( - data->ikev2.proposal.integ, &data->ikev2.keys, 0, - respData, pos, *end); - if (icv_len < 0) - return -1; - /* Hide Integrity Checksum Data from further processing */ - *end -= icv_len; - } else if (data->keys_ready) { - wpa_printf(MSG_INFO, "EAP-IKEV2: The message should have " - "included integrity checksum"); - return -1; - } - - return 0; -} - - -static int eap_ikev2_process_cont(struct eap_ikev2_data *data, - const u8 *buf, size_t len) -{ - /* Process continuation of a pending message */ - if (len > wpabuf_tailroom(data->in_buf)) { - wpa_printf(MSG_DEBUG, "EAP-IKEV2: Fragment overflow"); - eap_ikev2_state(data, FAIL); - return -1; - } - - wpabuf_put_data(data->in_buf, buf, len); - wpa_printf(MSG_DEBUG, "EAP-IKEV2: Received %lu bytes, waiting for %lu " - "bytes more", (unsigned long) len, - (unsigned long) wpabuf_tailroom(data->in_buf)); - - return 0; -} - - -static int eap_ikev2_process_fragment(struct eap_ikev2_data *data, - u8 flags, u32 message_length, - const u8 *buf, size_t len) -{ - /* Process a fragment that is not the last one of the message */ - if (data->in_buf == NULL && !(flags & IKEV2_FLAGS_LENGTH_INCLUDED)) { - wpa_printf(MSG_DEBUG, "EAP-IKEV2: No Message Length field in " - "a fragmented packet"); - return -1; - } - - if (data->in_buf == NULL) { - /* First fragment of the message */ - data->in_buf = wpabuf_alloc(message_length); - if (data->in_buf == NULL) { - wpa_printf(MSG_DEBUG, "EAP-IKEV2: No memory for " - "message"); - return -1; - } - wpabuf_put_data(data->in_buf, buf, len); - wpa_printf(MSG_DEBUG, "EAP-IKEV2: Received %lu bytes in first " - "fragment, waiting for %lu bytes more", - (unsigned long) len, - (unsigned long) wpabuf_tailroom(data->in_buf)); - } - - return 0; -} - - -static int eap_ikev2_server_keymat(struct eap_ikev2_data *data) -{ - if (eap_ikev2_derive_keymat( - data->ikev2.proposal.prf, &data->ikev2.keys, - data->ikev2.i_nonce, data->ikev2.i_nonce_len, - data->ikev2.r_nonce, data->ikev2.r_nonce_len, - data->keymat) < 0) { - wpa_printf(MSG_DEBUG, "EAP-IKEV2: Failed to derive " - "key material"); - return -1; - } - data->keymat_ok = 1; - return 0; -} - - -static void eap_ikev2_process(struct eap_sm *sm, void *priv, - struct wpabuf *respData) -{ - struct eap_ikev2_data *data = priv; - const u8 *start, *pos, *end; - size_t len; - u8 flags; - u32 message_length = 0; - struct wpabuf tmpbuf; - - pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_IKEV2, respData, - &len); - if (pos == NULL) - return; /* Should not happen; message already verified */ - - start = pos; - end = start + len; - - if (len == 0) { - /* fragment ack */ - flags = 0; - } else - flags = *pos++; - - if (eap_ikev2_process_icv(data, respData, flags, pos, &end) < 0) { - eap_ikev2_state(data, FAIL); - return; - } - - if (flags & IKEV2_FLAGS_LENGTH_INCLUDED) { - if (end - pos < 4) { - wpa_printf(MSG_DEBUG, "EAP-IKEV2: Message underflow"); - eap_ikev2_state(data, FAIL); - return; - } - message_length = WPA_GET_BE32(pos); - pos += 4; - - if (message_length < (u32) (end - pos)) { - wpa_printf(MSG_DEBUG, "EAP-IKEV2: Invalid Message " - "Length (%d; %ld remaining in this msg)", - message_length, (long) (end - pos)); - eap_ikev2_state(data, FAIL); - return; - } - } - wpa_printf(MSG_DEBUG, "EAP-IKEV2: Received packet: Flags 0x%x " - "Message Length %u", flags, message_length); - - if (data->state == WAIT_FRAG_ACK) { - if (len != 0) { - wpa_printf(MSG_DEBUG, "EAP-IKEV2: Unexpected payload " - "in WAIT_FRAG_ACK state"); - eap_ikev2_state(data, FAIL); - return; - } - wpa_printf(MSG_DEBUG, "EAP-IKEV2: Fragment acknowledged"); - eap_ikev2_state(data, MSG); - return; - } - - if (data->in_buf && eap_ikev2_process_cont(data, pos, end - pos) < 0) { - eap_ikev2_state(data, FAIL); - return; - } - - if (flags & IKEV2_FLAGS_MORE_FRAGMENTS) { - if (eap_ikev2_process_fragment(data, flags, message_length, - pos, end - pos) < 0) - eap_ikev2_state(data, FAIL); - else - eap_ikev2_state(data, FRAG_ACK); - return; - } else if (data->state == FRAG_ACK) { - wpa_printf(MSG_DEBUG, "EAP-TNC: All fragments received"); - data->state = MSG; - } - - if (data->in_buf == NULL) { - /* Wrap unfragmented messages as wpabuf without extra copy */ - wpabuf_set(&tmpbuf, pos, end - pos); - data->in_buf = &tmpbuf; - } - - if (ikev2_initiator_process(&data->ikev2, data->in_buf) < 0) { - if (data->in_buf == &tmpbuf) - data->in_buf = NULL; - eap_ikev2_state(data, FAIL); - return; - } - - switch (data->ikev2.state) { - case SA_AUTH: - /* SA_INIT was sent out, so message have to be - * integrity protected from now on. */ - data->keys_ready = 1; - break; - case IKEV2_DONE: - if (data->state == FAIL) - break; - wpa_printf(MSG_DEBUG, "EAP-IKEV2: Authentication completed " - "successfully"); - if (eap_ikev2_server_keymat(data)) - break; - eap_ikev2_state(data, DONE); - break; - default: - break; - } - - if (data->in_buf != &tmpbuf) - wpabuf_free(data->in_buf); - data->in_buf = NULL; -} - - -static Boolean eap_ikev2_isDone(struct eap_sm *sm, void *priv) -{ - struct eap_ikev2_data *data = priv; - return data->state == DONE || data->state == FAIL; -} - - -static Boolean eap_ikev2_isSuccess(struct eap_sm *sm, void *priv) -{ - struct eap_ikev2_data *data = priv; - return data->state == DONE && data->ikev2.state == IKEV2_DONE && - data->keymat_ok; -} - - -static u8 * eap_ikev2_getKey(struct eap_sm *sm, void *priv, size_t *len) -{ - struct eap_ikev2_data *data = priv; - u8 *key; - - if (data->state != DONE || !data->keymat_ok) - return NULL; - - key = os_malloc(EAP_MSK_LEN); - if (key) { - os_memcpy(key, data->keymat, EAP_MSK_LEN); - *len = EAP_MSK_LEN; - } - - return key; -} - - -static u8 * eap_ikev2_get_emsk(struct eap_sm *sm, void *priv, size_t *len) -{ - struct eap_ikev2_data *data = priv; - u8 *key; - - if (data->state != DONE || !data->keymat_ok) - return NULL; - - key = os_malloc(EAP_EMSK_LEN); - if (key) { - os_memcpy(key, data->keymat + EAP_MSK_LEN, EAP_EMSK_LEN); - *len = EAP_EMSK_LEN; - } - - return key; -} - - -int eap_server_ikev2_register(void) -{ - struct eap_method *eap; - int ret; - - eap = eap_server_method_alloc(EAP_SERVER_METHOD_INTERFACE_VERSION, - EAP_VENDOR_IETF, EAP_TYPE_IKEV2, - "IKEV2"); - if (eap == NULL) - return -1; - - eap->init = eap_ikev2_init; - eap->reset = eap_ikev2_reset; - eap->buildReq = eap_ikev2_buildReq; - eap->check = eap_ikev2_check; - eap->process = eap_ikev2_process; - eap->isDone = eap_ikev2_isDone; - eap->getKey = eap_ikev2_getKey; - eap->isSuccess = eap_ikev2_isSuccess; - eap->get_emsk = eap_ikev2_get_emsk; - - ret = eap_server_method_register(eap); - if (ret) - eap_server_method_free(eap); - return ret; -} diff --git a/hostapd-0.8/src/eap_server/eap_server_md5.c b/hostapd-0.8/src/eap_server/eap_server_md5.c deleted file mode 100644 index d03ec53..0000000 --- a/hostapd-0.8/src/eap_server/eap_server_md5.c +++ /dev/null @@ -1,177 +0,0 @@ -/* - * hostapd / EAP-MD5 server - * Copyright (c) 2004-2007, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#include "includes.h" - -#include "common.h" -#include "crypto/random.h" -#include "eap_i.h" -#include "eap_common/chap.h" - - -#define CHALLENGE_LEN 16 - -struct eap_md5_data { - u8 challenge[CHALLENGE_LEN]; - enum { CONTINUE, SUCCESS, FAILURE } state; -}; - - -static void * eap_md5_init(struct eap_sm *sm) -{ - struct eap_md5_data *data; - - data = os_zalloc(sizeof(*data)); - if (data == NULL) - return NULL; - data->state = CONTINUE; - - return data; -} - - -static void eap_md5_reset(struct eap_sm *sm, void *priv) -{ - struct eap_md5_data *data = priv; - os_free(data); -} - - -static struct wpabuf * eap_md5_buildReq(struct eap_sm *sm, void *priv, u8 id) -{ - struct eap_md5_data *data = priv; - struct wpabuf *req; - - if (random_get_bytes(data->challenge, CHALLENGE_LEN)) { - wpa_printf(MSG_ERROR, "EAP-MD5: Failed to get random data"); - data->state = FAILURE; - return NULL; - } - - req = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_MD5, 1 + CHALLENGE_LEN, - EAP_CODE_REQUEST, id); - if (req == NULL) { - wpa_printf(MSG_ERROR, "EAP-MD5: Failed to allocate memory for " - "request"); - data->state = FAILURE; - return NULL; - } - - wpabuf_put_u8(req, CHALLENGE_LEN); - wpabuf_put_data(req, data->challenge, CHALLENGE_LEN); - wpa_hexdump(MSG_MSGDUMP, "EAP-MD5: Challenge", data->challenge, - CHALLENGE_LEN); - - data->state = CONTINUE; - - return req; -} - - -static Boolean eap_md5_check(struct eap_sm *sm, void *priv, - struct wpabuf *respData) -{ - const u8 *pos; - size_t len; - - pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_MD5, respData, &len); - if (pos == NULL || len < 1) { - wpa_printf(MSG_INFO, "EAP-MD5: Invalid frame"); - return TRUE; - } - if (*pos != CHAP_MD5_LEN || 1 + CHAP_MD5_LEN > len) { - wpa_printf(MSG_INFO, "EAP-MD5: Invalid response " - "(response_len=%d payload_len=%lu", - *pos, (unsigned long) len); - return TRUE; - } - - return FALSE; -} - - -static void eap_md5_process(struct eap_sm *sm, void *priv, - struct wpabuf *respData) -{ - struct eap_md5_data *data = priv; - const u8 *pos; - size_t plen; - u8 hash[CHAP_MD5_LEN], id; - - if (sm->user == NULL || sm->user->password == NULL || - sm->user->password_hash) { - wpa_printf(MSG_INFO, "EAP-MD5: Plaintext password not " - "configured"); - data->state = FAILURE; - return; - } - - pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_MD5, respData, &plen); - if (pos == NULL || *pos != CHAP_MD5_LEN || plen < 1 + CHAP_MD5_LEN) - return; /* Should not happen - frame already validated */ - - pos++; /* Skip response len */ - wpa_hexdump(MSG_MSGDUMP, "EAP-MD5: Response", pos, CHAP_MD5_LEN); - - id = eap_get_id(respData); - chap_md5(id, sm->user->password, sm->user->password_len, - data->challenge, CHALLENGE_LEN, hash); - - if (os_memcmp(hash, pos, CHAP_MD5_LEN) == 0) { - wpa_printf(MSG_DEBUG, "EAP-MD5: Done - Success"); - data->state = SUCCESS; - } else { - wpa_printf(MSG_DEBUG, "EAP-MD5: Done - Failure"); - data->state = FAILURE; - } -} - - -static Boolean eap_md5_isDone(struct eap_sm *sm, void *priv) -{ - struct eap_md5_data *data = priv; - return data->state != CONTINUE; -} - - -static Boolean eap_md5_isSuccess(struct eap_sm *sm, void *priv) -{ - struct eap_md5_data *data = priv; - return data->state == SUCCESS; -} - - -int eap_server_md5_register(void) -{ - struct eap_method *eap; - int ret; - - eap = eap_server_method_alloc(EAP_SERVER_METHOD_INTERFACE_VERSION, - EAP_VENDOR_IETF, EAP_TYPE_MD5, "MD5"); - if (eap == NULL) - return -1; - - eap->init = eap_md5_init; - eap->reset = eap_md5_reset; - eap->buildReq = eap_md5_buildReq; - eap->check = eap_md5_check; - eap->process = eap_md5_process; - eap->isDone = eap_md5_isDone; - eap->isSuccess = eap_md5_isSuccess; - - ret = eap_server_method_register(eap); - if (ret) - eap_server_method_free(eap); - return ret; -} diff --git a/hostapd-0.8/src/eap_server/eap_server_methods.c b/hostapd-0.8/src/eap_server/eap_server_methods.c deleted file mode 100644 index 900a5dd..0000000 --- a/hostapd-0.8/src/eap_server/eap_server_methods.c +++ /dev/null @@ -1,175 +0,0 @@ -/* - * EAP server method registration - * Copyright (c) 2004-2009, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#include "includes.h" - -#include "common.h" -#include "eap_i.h" -#include "eap_methods.h" - - -static struct eap_method *eap_methods; - - -/** - * eap_server_get_eap_method - Get EAP method based on type number - * @vendor: EAP Vendor-Id (0 = IETF) - * @method: EAP type number - * Returns: Pointer to EAP method or %NULL if not found - */ -const struct eap_method * eap_server_get_eap_method(int vendor, EapType method) -{ - struct eap_method *m; - for (m = eap_methods; m; m = m->next) { - if (m->vendor == vendor && m->method == method) - return m; - } - return NULL; -} - - -/** - * eap_server_get_type - Get EAP type for the given EAP method name - * @name: EAP method name, e.g., TLS - * @vendor: Buffer for returning EAP Vendor-Id - * Returns: EAP method type or %EAP_TYPE_NONE if not found - * - * This function maps EAP type names into EAP type numbers based on the list of - * EAP methods included in the build. - */ -EapType eap_server_get_type(const char *name, int *vendor) -{ - struct eap_method *m; - for (m = eap_methods; m; m = m->next) { - if (os_strcmp(m->name, name) == 0) { - *vendor = m->vendor; - return m->method; - } - } - *vendor = EAP_VENDOR_IETF; - return EAP_TYPE_NONE; -} - - -/** - * eap_server_method_alloc - Allocate EAP server method structure - * @version: Version of the EAP server method interface (set to - * EAP_SERVER_METHOD_INTERFACE_VERSION) - * @vendor: EAP Vendor-ID (EAP_VENDOR_*) (0 = IETF) - * @method: EAP type number (EAP_TYPE_*) - * @name: Name of the method (e.g., "TLS") - * Returns: Allocated EAP method structure or %NULL on failure - * - * The returned structure should be freed with eap_server_method_free() when it - * is not needed anymore. - */ -struct eap_method * eap_server_method_alloc(int version, int vendor, - EapType method, const char *name) -{ - struct eap_method *eap; - eap = os_zalloc(sizeof(*eap)); - if (eap == NULL) - return NULL; - eap->version = version; - eap->vendor = vendor; - eap->method = method; - eap->name = name; - return eap; -} - - -/** - * eap_server_method_free - Free EAP server method structure - * @method: Method structure allocated with eap_server_method_alloc() - */ -void eap_server_method_free(struct eap_method *method) -{ - os_free(method); -} - - -/** - * eap_server_method_register - Register an EAP server method - * @method: EAP method to register - * Returns: 0 on success, -1 on invalid method, or -2 if a matching EAP method - * has already been registered - * - * Each EAP server method needs to call this function to register itself as a - * supported EAP method. - */ -int eap_server_method_register(struct eap_method *method) -{ - struct eap_method *m, *last = NULL; - - if (method == NULL || method->name == NULL || - method->version != EAP_SERVER_METHOD_INTERFACE_VERSION) - return -1; - - for (m = eap_methods; m; m = m->next) { - if ((m->vendor == method->vendor && - m->method == method->method) || - os_strcmp(m->name, method->name) == 0) - return -2; - last = m; - } - - if (last) - last->next = method; - else - eap_methods = method; - - return 0; -} - - -/** - * eap_server_unregister_methods - Unregister EAP server methods - * - * This function is called at program termination to unregister all EAP server - * methods. - */ -void eap_server_unregister_methods(void) -{ - struct eap_method *m; - - while (eap_methods) { - m = eap_methods; - eap_methods = eap_methods->next; - - if (m->free) - m->free(m); - else - eap_server_method_free(m); - } -} - - -/** - * eap_server_get_name - Get EAP method name for the given EAP type - * @vendor: EAP Vendor-Id (0 = IETF) - * @type: EAP method type - * Returns: EAP method name, e.g., TLS, or %NULL if not found - * - * This function maps EAP type numbers into EAP type names based on the list of - * EAP methods included in the build. - */ -const char * eap_server_get_name(int vendor, EapType type) -{ - struct eap_method *m; - for (m = eap_methods; m; m = m->next) { - if (m->vendor == vendor && m->method == type) - return m->name; - } - return NULL; -} diff --git a/hostapd-0.8/src/eap_server/eap_server_mschapv2.c b/hostapd-0.8/src/eap_server/eap_server_mschapv2.c deleted file mode 100644 index 64120a4..0000000 --- a/hostapd-0.8/src/eap_server/eap_server_mschapv2.c +++ /dev/null @@ -1,575 +0,0 @@ -/* - * hostapd / EAP-MSCHAPv2 (draft-kamath-pppext-eap-mschapv2-00.txt) server - * Copyright (c) 2004-2007, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#include "includes.h" - -#include "common.h" -#include "crypto/ms_funcs.h" -#include "crypto/random.h" -#include "eap_i.h" - - -struct eap_mschapv2_hdr { - u8 op_code; /* MSCHAPV2_OP_* */ - u8 mschapv2_id; /* must be changed for challenges, but not for - * success/failure */ - u8 ms_length[2]; /* Note: misaligned; length - 5 */ - /* followed by data */ -} STRUCT_PACKED; - -#define MSCHAPV2_OP_CHALLENGE 1 -#define MSCHAPV2_OP_RESPONSE 2 -#define MSCHAPV2_OP_SUCCESS 3 -#define MSCHAPV2_OP_FAILURE 4 -#define MSCHAPV2_OP_CHANGE_PASSWORD 7 - -#define MSCHAPV2_RESP_LEN 49 - -#define ERROR_RESTRICTED_LOGON_HOURS 646 -#define ERROR_ACCT_DISABLED 647 -#define ERROR_PASSWD_EXPIRED 648 -#define ERROR_NO_DIALIN_PERMISSION 649 -#define ERROR_AUTHENTICATION_FAILURE 691 -#define ERROR_CHANGING_PASSWORD 709 - -#define PASSWD_CHANGE_CHAL_LEN 16 -#define MSCHAPV2_KEY_LEN 16 - - -#define CHALLENGE_LEN 16 - -struct eap_mschapv2_data { - u8 auth_challenge[CHALLENGE_LEN]; - int auth_challenge_from_tls; - u8 *peer_challenge; - u8 auth_response[20]; - enum { CHALLENGE, SUCCESS_REQ, FAILURE_REQ, SUCCESS, FAILURE } state; - u8 resp_mschapv2_id; - u8 master_key[16]; - int master_key_valid; -}; - - -static void * eap_mschapv2_init(struct eap_sm *sm) -{ - struct eap_mschapv2_data *data; - - data = os_zalloc(sizeof(*data)); - if (data == NULL) - return NULL; - data->state = CHALLENGE; - - if (sm->auth_challenge) { - os_memcpy(data->auth_challenge, sm->auth_challenge, - CHALLENGE_LEN); - data->auth_challenge_from_tls = 1; - } - - if (sm->peer_challenge) { - data->peer_challenge = os_malloc(CHALLENGE_LEN); - if (data->peer_challenge == NULL) { - os_free(data); - return NULL; - } - os_memcpy(data->peer_challenge, sm->peer_challenge, - CHALLENGE_LEN); - } - - return data; -} - - -static void eap_mschapv2_reset(struct eap_sm *sm, void *priv) -{ - struct eap_mschapv2_data *data = priv; - if (data == NULL) - return; - - os_free(data->peer_challenge); - os_free(data); -} - - -static struct wpabuf * eap_mschapv2_build_challenge( - struct eap_sm *sm, struct eap_mschapv2_data *data, u8 id) -{ - struct wpabuf *req; - struct eap_mschapv2_hdr *ms; - char *name = "hostapd"; /* TODO: make this configurable */ - size_t ms_len; - - if (!data->auth_challenge_from_tls && - random_get_bytes(data->auth_challenge, CHALLENGE_LEN)) { - wpa_printf(MSG_ERROR, "EAP-MSCHAPV2: Failed to get random " - "data"); - data->state = FAILURE; - return NULL; - } - - ms_len = sizeof(*ms) + 1 + CHALLENGE_LEN + os_strlen(name); - req = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_MSCHAPV2, ms_len, - EAP_CODE_REQUEST, id); - if (req == NULL) { - wpa_printf(MSG_ERROR, "EAP-MSCHAPV2: Failed to allocate memory" - " for request"); - data->state = FAILURE; - return NULL; - } - - ms = wpabuf_put(req, sizeof(*ms)); - ms->op_code = MSCHAPV2_OP_CHALLENGE; - ms->mschapv2_id = id; - WPA_PUT_BE16(ms->ms_length, ms_len); - - wpabuf_put_u8(req, CHALLENGE_LEN); - if (!data->auth_challenge_from_tls) - wpabuf_put_data(req, data->auth_challenge, CHALLENGE_LEN); - else - wpabuf_put(req, CHALLENGE_LEN); - wpa_hexdump(MSG_MSGDUMP, "EAP-MSCHAPV2: Challenge", - data->auth_challenge, CHALLENGE_LEN); - wpabuf_put_data(req, name, os_strlen(name)); - - return req; -} - - -static struct wpabuf * eap_mschapv2_build_success_req( - struct eap_sm *sm, struct eap_mschapv2_data *data, u8 id) -{ - struct wpabuf *req; - struct eap_mschapv2_hdr *ms; - u8 *msg; - char *message = "OK"; - size_t ms_len; - - ms_len = sizeof(*ms) + 2 + 2 * sizeof(data->auth_response) + 1 + 2 + - os_strlen(message); - req = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_MSCHAPV2, ms_len, - EAP_CODE_REQUEST, id); - if (req == NULL) { - wpa_printf(MSG_ERROR, "EAP-MSCHAPV2: Failed to allocate memory" - " for request"); - data->state = FAILURE; - return NULL; - } - - ms = wpabuf_put(req, sizeof(*ms)); - ms->op_code = MSCHAPV2_OP_SUCCESS; - ms->mschapv2_id = data->resp_mschapv2_id; - WPA_PUT_BE16(ms->ms_length, ms_len); - msg = (u8 *) (ms + 1); - - wpabuf_put_u8(req, 'S'); - wpabuf_put_u8(req, '='); - wpa_snprintf_hex_uppercase( - wpabuf_put(req, sizeof(data->auth_response) * 2), - sizeof(data->auth_response) * 2 + 1, - data->auth_response, sizeof(data->auth_response)); - wpabuf_put_u8(req, ' '); - wpabuf_put_u8(req, 'M'); - wpabuf_put_u8(req, '='); - wpabuf_put_data(req, message, os_strlen(message)); - - wpa_hexdump_ascii(MSG_MSGDUMP, "EAP-MSCHAPV2: Success Request Message", - msg, ms_len - sizeof(*ms)); - - return req; -} - - -static struct wpabuf * eap_mschapv2_build_failure_req( - struct eap_sm *sm, struct eap_mschapv2_data *data, u8 id) -{ - struct wpabuf *req; - struct eap_mschapv2_hdr *ms; - char *message = "E=691 R=0 C=00000000000000000000000000000000 V=3 " - "M=FAILED"; - size_t ms_len; - - ms_len = sizeof(*ms) + os_strlen(message); - req = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_MSCHAPV2, ms_len, - EAP_CODE_REQUEST, id); - if (req == NULL) { - wpa_printf(MSG_ERROR, "EAP-MSCHAPV2: Failed to allocate memory" - " for request"); - data->state = FAILURE; - return NULL; - } - - ms = wpabuf_put(req, sizeof(*ms)); - ms->op_code = MSCHAPV2_OP_FAILURE; - ms->mschapv2_id = data->resp_mschapv2_id; - WPA_PUT_BE16(ms->ms_length, ms_len); - - wpabuf_put_data(req, message, os_strlen(message)); - - wpa_hexdump_ascii(MSG_MSGDUMP, "EAP-MSCHAPV2: Failure Request Message", - (u8 *) message, os_strlen(message)); - - return req; -} - - -static struct wpabuf * eap_mschapv2_buildReq(struct eap_sm *sm, void *priv, - u8 id) -{ - struct eap_mschapv2_data *data = priv; - - switch (data->state) { - case CHALLENGE: - return eap_mschapv2_build_challenge(sm, data, id); - case SUCCESS_REQ: - return eap_mschapv2_build_success_req(sm, data, id); - case FAILURE_REQ: - return eap_mschapv2_build_failure_req(sm, data, id); - default: - wpa_printf(MSG_DEBUG, "EAP-MSCHAPV2: Unknown state %d in " - "buildReq", data->state); - break; - } - return NULL; -} - - -static Boolean eap_mschapv2_check(struct eap_sm *sm, void *priv, - struct wpabuf *respData) -{ - struct eap_mschapv2_data *data = priv; - struct eap_mschapv2_hdr *resp; - const u8 *pos; - size_t len; - - pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_MSCHAPV2, respData, - &len); - if (pos == NULL || len < 1) { - wpa_printf(MSG_INFO, "EAP-MSCHAPV2: Invalid frame"); - return TRUE; - } - - resp = (struct eap_mschapv2_hdr *) pos; - if (data->state == CHALLENGE && - resp->op_code != MSCHAPV2_OP_RESPONSE) { - wpa_printf(MSG_DEBUG, "EAP-MSCHAPV2: Expected Response - " - "ignore op %d", resp->op_code); - return TRUE; - } - - if (data->state == SUCCESS_REQ && - resp->op_code != MSCHAPV2_OP_SUCCESS && - resp->op_code != MSCHAPV2_OP_FAILURE) { - wpa_printf(MSG_DEBUG, "EAP-MSCHAPV2: Expected Success or " - "Failure - ignore op %d", resp->op_code); - return TRUE; - } - - if (data->state == FAILURE_REQ && - resp->op_code != MSCHAPV2_OP_FAILURE) { - wpa_printf(MSG_DEBUG, "EAP-MSCHAPV2: Expected Failure " - "- ignore op %d", resp->op_code); - return TRUE; - } - - return FALSE; -} - - -static void eap_mschapv2_process_response(struct eap_sm *sm, - struct eap_mschapv2_data *data, - struct wpabuf *respData) -{ - struct eap_mschapv2_hdr *resp; - const u8 *pos, *end, *peer_challenge, *nt_response, *name; - u8 flags; - size_t len, name_len, i; - u8 expected[24]; - const u8 *username, *user; - size_t username_len, user_len; - int res; - - pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_MSCHAPV2, respData, - &len); - if (pos == NULL || len < 1) - return; /* Should not happen - frame already validated */ - - end = pos + len; - resp = (struct eap_mschapv2_hdr *) pos; - pos = (u8 *) (resp + 1); - - if (len < sizeof(*resp) + 1 + 49 || - resp->op_code != MSCHAPV2_OP_RESPONSE || - pos[0] != 49) { - wpa_hexdump_buf(MSG_DEBUG, "EAP-MSCHAPV2: Invalid response", - respData); - data->state = FAILURE; - return; - } - data->resp_mschapv2_id = resp->mschapv2_id; - pos++; - peer_challenge = pos; - pos += 16 + 8; - nt_response = pos; - pos += 24; - flags = *pos++; - name = pos; - name_len = end - name; - - if (data->peer_challenge) { - wpa_printf(MSG_DEBUG, "EAP-MSCHAPV2: Using pre-configured " - "Peer-Challenge"); - peer_challenge = data->peer_challenge; - } - wpa_hexdump(MSG_MSGDUMP, "EAP-MSCHAPV2: Peer-Challenge", - peer_challenge, 16); - wpa_hexdump(MSG_MSGDUMP, "EAP-MSCHAPV2: NT-Response", nt_response, 24); - wpa_printf(MSG_MSGDUMP, "EAP-MSCHAPV2: Flags 0x%x", flags); - wpa_hexdump_ascii(MSG_MSGDUMP, "EAP-MSCHAPV2: Name", name, name_len); - - /* MSCHAPv2 does not include optional domain name in the - * challenge-response calculation, so remove domain prefix - * (if present). */ - username = sm->identity; - username_len = sm->identity_len; - for (i = 0; i < username_len; i++) { - if (username[i] == '\\') { - username_len -= i + 1; - username += i + 1; - break; - } - } - - user = name; - user_len = name_len; - for (i = 0; i < user_len; i++) { - if (user[i] == '\\') { - user_len -= i + 1; - user += i + 1; - break; - } - } - - if (username_len != user_len || - os_memcmp(username, user, username_len) != 0) { - wpa_printf(MSG_DEBUG, "EAP-MSCHAPV2: Mismatch in user names"); - wpa_hexdump_ascii(MSG_DEBUG, "EAP-MSCHAPV2: Expected user " - "name", username, username_len); - wpa_hexdump_ascii(MSG_DEBUG, "EAP-MSCHAPV2: Received user " - "name", user, user_len); - data->state = FAILURE; - return; - } - - wpa_hexdump_ascii(MSG_MSGDUMP, "EAP-MSCHAPV2: User name", - username, username_len); - - if (sm->user->password_hash) { - res = generate_nt_response_pwhash(data->auth_challenge, - peer_challenge, - username, username_len, - sm->user->password, - expected); - } else { - res = generate_nt_response(data->auth_challenge, - peer_challenge, - username, username_len, - sm->user->password, - sm->user->password_len, - expected); - } - if (res) { - data->state = FAILURE; - return; - } - - if (os_memcmp(nt_response, expected, 24) == 0) { - const u8 *pw_hash; - u8 pw_hash_buf[16], pw_hash_hash[16]; - - wpa_printf(MSG_DEBUG, "EAP-MSCHAPV2: Correct NT-Response"); - data->state = SUCCESS_REQ; - - /* Authenticator response is not really needed yet, but - * calculate it here so that peer_challenge and username need - * not be saved. */ - if (sm->user->password_hash) { - pw_hash = sm->user->password; - } else { - nt_password_hash(sm->user->password, - sm->user->password_len, - pw_hash_buf); - pw_hash = pw_hash_buf; - } - generate_authenticator_response_pwhash( - pw_hash, peer_challenge, data->auth_challenge, - username, username_len, nt_response, - data->auth_response); - - hash_nt_password_hash(pw_hash, pw_hash_hash); - get_master_key(pw_hash_hash, nt_response, data->master_key); - data->master_key_valid = 1; - wpa_hexdump_key(MSG_DEBUG, "EAP-MSCHAPV2: Derived Master Key", - data->master_key, MSCHAPV2_KEY_LEN); - } else { - wpa_hexdump(MSG_MSGDUMP, "EAP-MSCHAPV2: Expected NT-Response", - expected, 24); - wpa_printf(MSG_DEBUG, "EAP-MSCHAPV2: Invalid NT-Response"); - data->state = FAILURE_REQ; - } -} - - -static void eap_mschapv2_process_success_resp(struct eap_sm *sm, - struct eap_mschapv2_data *data, - struct wpabuf *respData) -{ - struct eap_mschapv2_hdr *resp; - const u8 *pos; - size_t len; - - pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_MSCHAPV2, respData, - &len); - if (pos == NULL || len < 1) - return; /* Should not happen - frame already validated */ - - resp = (struct eap_mschapv2_hdr *) pos; - - if (resp->op_code == MSCHAPV2_OP_SUCCESS) { - wpa_printf(MSG_DEBUG, "EAP-MSCHAPV2: Received Success Response" - " - authentication completed successfully"); - data->state = SUCCESS; - } else { - wpa_printf(MSG_DEBUG, "EAP-MSCHAPV2: Did not receive Success " - "Response - peer rejected authentication"); - data->state = FAILURE; - } -} - - -static void eap_mschapv2_process_failure_resp(struct eap_sm *sm, - struct eap_mschapv2_data *data, - struct wpabuf *respData) -{ - struct eap_mschapv2_hdr *resp; - const u8 *pos; - size_t len; - - pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_MSCHAPV2, respData, - &len); - if (pos == NULL || len < 1) - return; /* Should not happen - frame already validated */ - - resp = (struct eap_mschapv2_hdr *) pos; - - if (resp->op_code == MSCHAPV2_OP_FAILURE) { - wpa_printf(MSG_DEBUG, "EAP-MSCHAPV2: Received Failure Response" - " - authentication failed"); - } else { - wpa_printf(MSG_DEBUG, "EAP-MSCHAPV2: Did not receive Failure " - "Response - authentication failed"); - } - - data->state = FAILURE; -} - - -static void eap_mschapv2_process(struct eap_sm *sm, void *priv, - struct wpabuf *respData) -{ - struct eap_mschapv2_data *data = priv; - - if (sm->user == NULL || sm->user->password == NULL) { - wpa_printf(MSG_INFO, "EAP-MSCHAPV2: Password not configured"); - data->state = FAILURE; - return; - } - - switch (data->state) { - case CHALLENGE: - eap_mschapv2_process_response(sm, data, respData); - break; - case SUCCESS_REQ: - eap_mschapv2_process_success_resp(sm, data, respData); - break; - case FAILURE_REQ: - eap_mschapv2_process_failure_resp(sm, data, respData); - break; - default: - wpa_printf(MSG_DEBUG, "EAP-MSCHAPV2: Unknown state %d in " - "process", data->state); - break; - } -} - - -static Boolean eap_mschapv2_isDone(struct eap_sm *sm, void *priv) -{ - struct eap_mschapv2_data *data = priv; - return data->state == SUCCESS || data->state == FAILURE; -} - - -static u8 * eap_mschapv2_getKey(struct eap_sm *sm, void *priv, size_t *len) -{ - struct eap_mschapv2_data *data = priv; - u8 *key; - - if (data->state != SUCCESS || !data->master_key_valid) - return NULL; - - *len = 2 * MSCHAPV2_KEY_LEN; - key = os_malloc(*len); - if (key == NULL) - return NULL; - /* MSK = server MS-MPPE-Recv-Key | MS-MPPE-Send-Key */ - get_asymetric_start_key(data->master_key, key, MSCHAPV2_KEY_LEN, 0, 1); - get_asymetric_start_key(data->master_key, key + MSCHAPV2_KEY_LEN, - MSCHAPV2_KEY_LEN, 1, 1); - wpa_hexdump_key(MSG_DEBUG, "EAP-MSCHAPV2: Derived key", key, *len); - - return key; -} - - -static Boolean eap_mschapv2_isSuccess(struct eap_sm *sm, void *priv) -{ - struct eap_mschapv2_data *data = priv; - return data->state == SUCCESS; -} - - -int eap_server_mschapv2_register(void) -{ - struct eap_method *eap; - int ret; - - eap = eap_server_method_alloc(EAP_SERVER_METHOD_INTERFACE_VERSION, - EAP_VENDOR_IETF, EAP_TYPE_MSCHAPV2, - "MSCHAPV2"); - if (eap == NULL) - return -1; - - eap->init = eap_mschapv2_init; - eap->reset = eap_mschapv2_reset; - eap->buildReq = eap_mschapv2_buildReq; - eap->check = eap_mschapv2_check; - eap->process = eap_mschapv2_process; - eap->isDone = eap_mschapv2_isDone; - eap->getKey = eap_mschapv2_getKey; - eap->isSuccess = eap_mschapv2_isSuccess; - - ret = eap_server_method_register(eap); - if (ret) - eap_server_method_free(eap); - return ret; -} diff --git a/hostapd-0.8/src/eap_server/eap_server_pax.c b/hostapd-0.8/src/eap_server/eap_server_pax.c deleted file mode 100644 index 4d64269..0000000 --- a/hostapd-0.8/src/eap_server/eap_server_pax.c +++ /dev/null @@ -1,570 +0,0 @@ -/* - * hostapd / EAP-PAX (RFC 4746) server - * Copyright (c) 2005-2007, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#include "includes.h" - -#include "common.h" -#include "crypto/random.h" -#include "eap_server/eap_i.h" -#include "eap_common/eap_pax_common.h" - -/* - * Note: only PAX_STD subprotocol is currently supported - * - * TODO: Add support with PAX_SEC with the mandatory to implement ciphersuite - * (HMAC_SHA1_128, IANA DH Group 14 (2048 bits), RSA-PKCS1-V1_5) and - * recommended ciphersuite (HMAC_SHA256_128, IANA DH Group 15 (3072 bits), - * RSAES-OAEP). - */ - -struct eap_pax_data { - enum { PAX_STD_1, PAX_STD_3, SUCCESS, FAILURE } state; - u8 mac_id; - union { - u8 e[2 * EAP_PAX_RAND_LEN]; - struct { - u8 x[EAP_PAX_RAND_LEN]; /* server rand */ - u8 y[EAP_PAX_RAND_LEN]; /* client rand */ - } r; - } rand; - u8 ak[EAP_PAX_AK_LEN]; - u8 mk[EAP_PAX_MK_LEN]; - u8 ck[EAP_PAX_CK_LEN]; - u8 ick[EAP_PAX_ICK_LEN]; - int keys_set; - char *cid; - size_t cid_len; -}; - - -static void * eap_pax_init(struct eap_sm *sm) -{ - struct eap_pax_data *data; - - data = os_zalloc(sizeof(*data)); - if (data == NULL) - return NULL; - data->state = PAX_STD_1; - /* - * TODO: make this configurable once EAP_PAX_HMAC_SHA256_128 is - * supported - */ - data->mac_id = EAP_PAX_MAC_HMAC_SHA1_128; - - return data; -} - - -static void eap_pax_reset(struct eap_sm *sm, void *priv) -{ - struct eap_pax_data *data = priv; - os_free(data->cid); - os_free(data); -} - - -static struct wpabuf * eap_pax_build_std_1(struct eap_sm *sm, - struct eap_pax_data *data, u8 id) -{ - struct wpabuf *req; - struct eap_pax_hdr *pax; - u8 *pos; - - wpa_printf(MSG_DEBUG, "EAP-PAX: PAX_STD-1 (sending)"); - - if (random_get_bytes(data->rand.r.x, EAP_PAX_RAND_LEN)) { - wpa_printf(MSG_ERROR, "EAP-PAX: Failed to get random data"); - data->state = FAILURE; - return NULL; - } - - req = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_PAX, - sizeof(*pax) + 2 + EAP_PAX_RAND_LEN + - EAP_PAX_ICV_LEN, EAP_CODE_REQUEST, id); - if (req == NULL) { - wpa_printf(MSG_ERROR, "EAP-PAX: Failed to allocate memory " - "request"); - data->state = FAILURE; - return NULL; - } - - pax = wpabuf_put(req, sizeof(*pax)); - pax->op_code = EAP_PAX_OP_STD_1; - pax->flags = 0; - pax->mac_id = data->mac_id; - pax->dh_group_id = EAP_PAX_DH_GROUP_NONE; - pax->public_key_id = EAP_PAX_PUBLIC_KEY_NONE; - - wpabuf_put_be16(req, EAP_PAX_RAND_LEN); - wpabuf_put_data(req, data->rand.r.x, EAP_PAX_RAND_LEN); - wpa_hexdump(MSG_MSGDUMP, "EAP-PAX: A = X (server rand)", - data->rand.r.x, EAP_PAX_RAND_LEN); - - pos = wpabuf_put(req, EAP_PAX_MAC_LEN); - eap_pax_mac(data->mac_id, (u8 *) "", 0, - wpabuf_mhead(req), wpabuf_len(req) - EAP_PAX_ICV_LEN, - NULL, 0, NULL, 0, pos); - wpa_hexdump(MSG_MSGDUMP, "EAP-PAX: ICV", pos, EAP_PAX_ICV_LEN); - - return req; -} - - -static struct wpabuf * eap_pax_build_std_3(struct eap_sm *sm, - struct eap_pax_data *data, u8 id) -{ - struct wpabuf *req; - struct eap_pax_hdr *pax; - u8 *pos; - - wpa_printf(MSG_DEBUG, "EAP-PAX: PAX_STD-3 (sending)"); - - req = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_PAX, - sizeof(*pax) + 2 + EAP_PAX_MAC_LEN + - EAP_PAX_ICV_LEN, EAP_CODE_REQUEST, id); - if (req == NULL) { - wpa_printf(MSG_ERROR, "EAP-PAX: Failed to allocate memory " - "request"); - data->state = FAILURE; - return NULL; - } - - pax = wpabuf_put(req, sizeof(*pax)); - pax->op_code = EAP_PAX_OP_STD_3; - pax->flags = 0; - pax->mac_id = data->mac_id; - pax->dh_group_id = EAP_PAX_DH_GROUP_NONE; - pax->public_key_id = EAP_PAX_PUBLIC_KEY_NONE; - - wpabuf_put_be16(req, EAP_PAX_MAC_LEN); - pos = wpabuf_put(req, EAP_PAX_MAC_LEN); - eap_pax_mac(data->mac_id, data->ck, EAP_PAX_CK_LEN, - data->rand.r.y, EAP_PAX_RAND_LEN, - (u8 *) data->cid, data->cid_len, NULL, 0, pos); - wpa_hexdump(MSG_MSGDUMP, "EAP-PAX: MAC_CK(B, CID)", - pos, EAP_PAX_MAC_LEN); - pos += EAP_PAX_MAC_LEN; - - /* Optional ADE could be added here, if needed */ - - pos = wpabuf_put(req, EAP_PAX_MAC_LEN); - eap_pax_mac(data->mac_id, data->ick, EAP_PAX_ICK_LEN, - wpabuf_mhead(req), wpabuf_len(req) - EAP_PAX_ICV_LEN, - NULL, 0, NULL, 0, pos); - wpa_hexdump(MSG_MSGDUMP, "EAP-PAX: ICV", pos, EAP_PAX_ICV_LEN); - - return req; -} - - -static struct wpabuf * eap_pax_buildReq(struct eap_sm *sm, void *priv, u8 id) -{ - struct eap_pax_data *data = priv; - - switch (data->state) { - case PAX_STD_1: - return eap_pax_build_std_1(sm, data, id); - case PAX_STD_3: - return eap_pax_build_std_3(sm, data, id); - default: - wpa_printf(MSG_DEBUG, "EAP-PAX: Unknown state %d in buildReq", - data->state); - break; - } - return NULL; -} - - -static Boolean eap_pax_check(struct eap_sm *sm, void *priv, - struct wpabuf *respData) -{ - struct eap_pax_data *data = priv; - struct eap_pax_hdr *resp; - const u8 *pos; - size_t len, mlen; - u8 icvbuf[EAP_PAX_ICV_LEN], *icv; - - pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_PAX, respData, &len); - if (pos == NULL || len < sizeof(*resp)) { - wpa_printf(MSG_INFO, "EAP-PAX: Invalid frame"); - return TRUE; - } - - mlen = sizeof(struct eap_hdr) + 1 + len; - resp = (struct eap_pax_hdr *) pos; - - wpa_printf(MSG_DEBUG, "EAP-PAX: received frame: op_code 0x%x " - "flags 0x%x mac_id 0x%x dh_group_id 0x%x " - "public_key_id 0x%x", - resp->op_code, resp->flags, resp->mac_id, resp->dh_group_id, - resp->public_key_id); - wpa_hexdump(MSG_MSGDUMP, "EAP-PAX: received payload", - (u8 *) (resp + 1), len - sizeof(*resp) - EAP_PAX_ICV_LEN); - - if (data->state == PAX_STD_1 && - resp->op_code != EAP_PAX_OP_STD_2) { - wpa_printf(MSG_DEBUG, "EAP-PAX: Expected PAX_STD-2 - " - "ignore op %d", resp->op_code); - return TRUE; - } - - if (data->state == PAX_STD_3 && - resp->op_code != EAP_PAX_OP_ACK) { - wpa_printf(MSG_DEBUG, "EAP-PAX: Expected PAX-ACK - " - "ignore op %d", resp->op_code); - return TRUE; - } - - if (resp->op_code != EAP_PAX_OP_STD_2 && - resp->op_code != EAP_PAX_OP_ACK) { - wpa_printf(MSG_DEBUG, "EAP-PAX: Unknown op_code 0x%x", - resp->op_code); - } - - if (data->mac_id != resp->mac_id) { - wpa_printf(MSG_DEBUG, "EAP-PAX: Expected MAC ID 0x%x, " - "received 0x%x", data->mac_id, resp->mac_id); - return TRUE; - } - - if (resp->dh_group_id != EAP_PAX_DH_GROUP_NONE) { - wpa_printf(MSG_INFO, "EAP-PAX: Expected DH Group ID 0x%x, " - "received 0x%x", EAP_PAX_DH_GROUP_NONE, - resp->dh_group_id); - return TRUE; - } - - if (resp->public_key_id != EAP_PAX_PUBLIC_KEY_NONE) { - wpa_printf(MSG_INFO, "EAP-PAX: Expected Public Key ID 0x%x, " - "received 0x%x", EAP_PAX_PUBLIC_KEY_NONE, - resp->public_key_id); - return TRUE; - } - - if (resp->flags & EAP_PAX_FLAGS_MF) { - /* TODO: add support for reassembling fragments */ - wpa_printf(MSG_INFO, "EAP-PAX: fragmentation not supported"); - return TRUE; - } - - if (resp->flags & EAP_PAX_FLAGS_CE) { - wpa_printf(MSG_INFO, "EAP-PAX: Unexpected CE flag"); - return TRUE; - } - - if (data->keys_set) { - if (len - sizeof(*resp) < EAP_PAX_ICV_LEN) { - wpa_printf(MSG_INFO, "EAP-PAX: No ICV in the packet"); - return TRUE; - } - icv = wpabuf_mhead_u8(respData) + mlen - EAP_PAX_ICV_LEN; - wpa_hexdump(MSG_MSGDUMP, "EAP-PAX: ICV", icv, EAP_PAX_ICV_LEN); - eap_pax_mac(data->mac_id, data->ick, EAP_PAX_ICK_LEN, - wpabuf_mhead(respData), - wpabuf_len(respData) - EAP_PAX_ICV_LEN, - NULL, 0, NULL, 0, icvbuf); - if (os_memcmp(icvbuf, icv, EAP_PAX_ICV_LEN) != 0) { - wpa_printf(MSG_INFO, "EAP-PAX: Invalid ICV"); - wpa_hexdump(MSG_MSGDUMP, "EAP-PAX: Expected ICV", - icvbuf, EAP_PAX_ICV_LEN); - return TRUE; - } - } - - return FALSE; -} - - -static void eap_pax_process_std_2(struct eap_sm *sm, - struct eap_pax_data *data, - struct wpabuf *respData) -{ - struct eap_pax_hdr *resp; - u8 mac[EAP_PAX_MAC_LEN], icvbuf[EAP_PAX_ICV_LEN]; - const u8 *pos; - size_t len, left; - int i; - - if (data->state != PAX_STD_1) - return; - - wpa_printf(MSG_DEBUG, "EAP-PAX: Received PAX_STD-2"); - - pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_PAX, respData, &len); - if (pos == NULL || len < sizeof(*resp) + EAP_PAX_ICV_LEN) - return; - - resp = (struct eap_pax_hdr *) pos; - pos = (u8 *) (resp + 1); - left = len - sizeof(*resp); - - if (left < 2 + EAP_PAX_RAND_LEN || - WPA_GET_BE16(pos) != EAP_PAX_RAND_LEN) { - wpa_printf(MSG_INFO, "EAP-PAX: Too short PAX_STD-2 (B)"); - return; - } - pos += 2; - left -= 2; - os_memcpy(data->rand.r.y, pos, EAP_PAX_RAND_LEN); - wpa_hexdump(MSG_MSGDUMP, "EAP-PAX: Y (client rand)", - data->rand.r.y, EAP_PAX_RAND_LEN); - pos += EAP_PAX_RAND_LEN; - left -= EAP_PAX_RAND_LEN; - - if (left < 2 || (size_t) 2 + WPA_GET_BE16(pos) > left) { - wpa_printf(MSG_INFO, "EAP-PAX: Too short PAX_STD-2 (CID)"); - return; - } - data->cid_len = WPA_GET_BE16(pos); - os_free(data->cid); - data->cid = os_malloc(data->cid_len); - if (data->cid == NULL) { - wpa_printf(MSG_INFO, "EAP-PAX: Failed to allocate memory for " - "CID"); - return; - } - os_memcpy(data->cid, pos + 2, data->cid_len); - pos += 2 + data->cid_len; - left -= 2 + data->cid_len; - wpa_hexdump_ascii(MSG_MSGDUMP, "EAP-PAX: CID", - (u8 *) data->cid, data->cid_len); - - if (left < 2 + EAP_PAX_MAC_LEN || - WPA_GET_BE16(pos) != EAP_PAX_MAC_LEN) { - wpa_printf(MSG_INFO, "EAP-PAX: Too short PAX_STD-2 (MAC_CK)"); - return; - } - pos += 2; - left -= 2; - wpa_hexdump(MSG_MSGDUMP, "EAP-PAX: MAC_CK(A, B, CID)", - pos, EAP_PAX_MAC_LEN); - - if (eap_user_get(sm, (u8 *) data->cid, data->cid_len, 0) < 0) { - wpa_hexdump_ascii(MSG_DEBUG, "EAP-PAX: unknown CID", - (u8 *) data->cid, data->cid_len); - data->state = FAILURE; - return; - } - - for (i = 0; - i < EAP_MAX_METHODS && - (sm->user->methods[i].vendor != EAP_VENDOR_IETF || - sm->user->methods[i].method != EAP_TYPE_NONE); - i++) { - if (sm->user->methods[i].vendor == EAP_VENDOR_IETF && - sm->user->methods[i].method == EAP_TYPE_PAX) - break; - } - - if (i >= EAP_MAX_METHODS || - sm->user->methods[i].vendor != EAP_VENDOR_IETF || - sm->user->methods[i].method != EAP_TYPE_PAX) { - wpa_hexdump_ascii(MSG_DEBUG, - "EAP-PAX: EAP-PAX not enabled for CID", - (u8 *) data->cid, data->cid_len); - data->state = FAILURE; - return; - } - - if (sm->user->password == NULL || - sm->user->password_len != EAP_PAX_AK_LEN) { - wpa_hexdump_ascii(MSG_DEBUG, "EAP-PAX: invalid password in " - "user database for CID", - (u8 *) data->cid, data->cid_len); - data->state = FAILURE; - return; - } - os_memcpy(data->ak, sm->user->password, EAP_PAX_AK_LEN); - - if (eap_pax_initial_key_derivation(data->mac_id, data->ak, - data->rand.e, data->mk, data->ck, - data->ick) < 0) { - wpa_printf(MSG_INFO, "EAP-PAX: Failed to complete initial " - "key derivation"); - data->state = FAILURE; - return; - } - data->keys_set = 1; - - eap_pax_mac(data->mac_id, data->ck, EAP_PAX_CK_LEN, - data->rand.r.x, EAP_PAX_RAND_LEN, - data->rand.r.y, EAP_PAX_RAND_LEN, - (u8 *) data->cid, data->cid_len, mac); - if (os_memcmp(mac, pos, EAP_PAX_MAC_LEN) != 0) { - wpa_printf(MSG_INFO, "EAP-PAX: Invalid MAC_CK(A, B, CID) in " - "PAX_STD-2"); - wpa_hexdump(MSG_MSGDUMP, "EAP-PAX: Expected MAC_CK(A, B, CID)", - mac, EAP_PAX_MAC_LEN); - data->state = FAILURE; - return; - } - - pos += EAP_PAX_MAC_LEN; - left -= EAP_PAX_MAC_LEN; - - if (left < EAP_PAX_ICV_LEN) { - wpa_printf(MSG_INFO, "EAP-PAX: Too short ICV (%lu) in " - "PAX_STD-2", (unsigned long) left); - return; - } - wpa_hexdump(MSG_MSGDUMP, "EAP-PAX: ICV", pos, EAP_PAX_ICV_LEN); - eap_pax_mac(data->mac_id, data->ick, EAP_PAX_ICK_LEN, - wpabuf_head(respData), - wpabuf_len(respData) - EAP_PAX_ICV_LEN, NULL, 0, NULL, 0, - icvbuf); - if (os_memcmp(icvbuf, pos, EAP_PAX_ICV_LEN) != 0) { - wpa_printf(MSG_INFO, "EAP-PAX: Invalid ICV in PAX_STD-2"); - wpa_hexdump(MSG_MSGDUMP, "EAP-PAX: Expected ICV", - icvbuf, EAP_PAX_ICV_LEN); - return; - } - pos += EAP_PAX_ICV_LEN; - left -= EAP_PAX_ICV_LEN; - - if (left > 0) { - wpa_hexdump(MSG_MSGDUMP, "EAP-PAX: ignored extra payload", - pos, left); - } - - data->state = PAX_STD_3; -} - - -static void eap_pax_process_ack(struct eap_sm *sm, - struct eap_pax_data *data, - struct wpabuf *respData) -{ - if (data->state != PAX_STD_3) - return; - - wpa_printf(MSG_DEBUG, "EAP-PAX: Received PAX-ACK - authentication " - "completed successfully"); - data->state = SUCCESS; -} - - -static void eap_pax_process(struct eap_sm *sm, void *priv, - struct wpabuf *respData) -{ - struct eap_pax_data *data = priv; - struct eap_pax_hdr *resp; - const u8 *pos; - size_t len; - - if (sm->user == NULL || sm->user->password == NULL) { - wpa_printf(MSG_INFO, "EAP-PAX: Plaintext password not " - "configured"); - data->state = FAILURE; - return; - } - - pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_PAX, respData, &len); - if (pos == NULL || len < sizeof(*resp)) - return; - - resp = (struct eap_pax_hdr *) pos; - - switch (resp->op_code) { - case EAP_PAX_OP_STD_2: - eap_pax_process_std_2(sm, data, respData); - break; - case EAP_PAX_OP_ACK: - eap_pax_process_ack(sm, data, respData); - break; - } -} - - -static Boolean eap_pax_isDone(struct eap_sm *sm, void *priv) -{ - struct eap_pax_data *data = priv; - return data->state == SUCCESS || data->state == FAILURE; -} - - -static u8 * eap_pax_getKey(struct eap_sm *sm, void *priv, size_t *len) -{ - struct eap_pax_data *data = priv; - u8 *key; - - if (data->state != SUCCESS) - return NULL; - - key = os_malloc(EAP_MSK_LEN); - if (key == NULL) - return NULL; - - *len = EAP_MSK_LEN; - eap_pax_kdf(data->mac_id, data->mk, EAP_PAX_MK_LEN, - "Master Session Key", data->rand.e, 2 * EAP_PAX_RAND_LEN, - EAP_MSK_LEN, key); - - return key; -} - - -static u8 * eap_pax_get_emsk(struct eap_sm *sm, void *priv, size_t *len) -{ - struct eap_pax_data *data = priv; - u8 *key; - - if (data->state != SUCCESS) - return NULL; - - key = os_malloc(EAP_EMSK_LEN); - if (key == NULL) - return NULL; - - *len = EAP_EMSK_LEN; - eap_pax_kdf(data->mac_id, data->mk, EAP_PAX_MK_LEN, - "Extended Master Session Key", - data->rand.e, 2 * EAP_PAX_RAND_LEN, - EAP_EMSK_LEN, key); - - return key; -} - - -static Boolean eap_pax_isSuccess(struct eap_sm *sm, void *priv) -{ - struct eap_pax_data *data = priv; - return data->state == SUCCESS; -} - - -int eap_server_pax_register(void) -{ - struct eap_method *eap; - int ret; - - eap = eap_server_method_alloc(EAP_SERVER_METHOD_INTERFACE_VERSION, - EAP_VENDOR_IETF, EAP_TYPE_PAX, "PAX"); - if (eap == NULL) - return -1; - - eap->init = eap_pax_init; - eap->reset = eap_pax_reset; - eap->buildReq = eap_pax_buildReq; - eap->check = eap_pax_check; - eap->process = eap_pax_process; - eap->isDone = eap_pax_isDone; - eap->getKey = eap_pax_getKey; - eap->isSuccess = eap_pax_isSuccess; - eap->get_emsk = eap_pax_get_emsk; - - ret = eap_server_method_register(eap); - if (ret) - eap_server_method_free(eap); - return ret; -} diff --git a/hostapd-0.8/src/eap_server/eap_server_peap.c b/hostapd-0.8/src/eap_server/eap_server_peap.c deleted file mode 100644 index 8a7d626..0000000 --- a/hostapd-0.8/src/eap_server/eap_server_peap.c +++ /dev/null @@ -1,1387 +0,0 @@ -/* - * hostapd / EAP-PEAP (draft-josefsson-pppext-eap-tls-eap-10.txt) - * Copyright (c) 2004-2008, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#include "includes.h" - -#include "common.h" -#include "crypto/sha1.h" -#include "crypto/tls.h" -#include "crypto/random.h" -#include "eap_i.h" -#include "eap_tls_common.h" -#include "eap_common/eap_tlv_common.h" -#include "eap_common/eap_peap_common.h" -#include "tncs.h" - - -/* Maximum supported PEAP version - * 0 = Microsoft's PEAP version 0; draft-kamath-pppext-peapv0-00.txt - * 1 = draft-josefsson-ppext-eap-tls-eap-05.txt - * 2 = draft-josefsson-ppext-eap-tls-eap-10.txt - */ -#define EAP_PEAP_VERSION 1 - - -static void eap_peap_reset(struct eap_sm *sm, void *priv); - - -struct eap_peap_data { - struct eap_ssl_data ssl; - enum { - START, PHASE1, PHASE1_ID2, PHASE2_START, PHASE2_ID, - PHASE2_METHOD, PHASE2_SOH, - PHASE2_TLV, SUCCESS_REQ, FAILURE_REQ, SUCCESS, FAILURE - } state; - - int peap_version; - int recv_version; - const struct eap_method *phase2_method; - void *phase2_priv; - int force_version; - struct wpabuf *pending_phase2_resp; - enum { TLV_REQ_NONE, TLV_REQ_SUCCESS, TLV_REQ_FAILURE } tlv_request; - int crypto_binding_sent; - int crypto_binding_used; - enum { NO_BINDING, OPTIONAL_BINDING, REQUIRE_BINDING } crypto_binding; - u8 binding_nonce[32]; - u8 ipmk[40]; - u8 cmk[20]; - u8 *phase2_key; - size_t phase2_key_len; - struct wpabuf *soh_response; -}; - - -static const char * eap_peap_state_txt(int state) -{ - switch (state) { - case START: - return "START"; - case PHASE1: - return "PHASE1"; - case PHASE1_ID2: - return "PHASE1_ID2"; - case PHASE2_START: - return "PHASE2_START"; - case PHASE2_ID: - return "PHASE2_ID"; - case PHASE2_METHOD: - return "PHASE2_METHOD"; - case PHASE2_SOH: - return "PHASE2_SOH"; - case PHASE2_TLV: - return "PHASE2_TLV"; - case SUCCESS_REQ: - return "SUCCESS_REQ"; - case FAILURE_REQ: - return "FAILURE_REQ"; - case SUCCESS: - return "SUCCESS"; - case FAILURE: - return "FAILURE"; - default: - return "Unknown?!"; - } -} - - -static void eap_peap_state(struct eap_peap_data *data, int state) -{ - wpa_printf(MSG_DEBUG, "EAP-PEAP: %s -> %s", - eap_peap_state_txt(data->state), - eap_peap_state_txt(state)); - data->state = state; -} - - -static struct wpabuf * eap_peapv2_tlv_eap_payload(struct wpabuf *buf) -{ - struct wpabuf *e; - struct eap_tlv_hdr *tlv; - - if (buf == NULL) - return NULL; - - /* Encapsulate EAP packet in EAP-Payload TLV */ - wpa_printf(MSG_DEBUG, "EAP-PEAPv2: Add EAP-Payload TLV"); - e = wpabuf_alloc(sizeof(*tlv) + wpabuf_len(buf)); - if (e == NULL) { - wpa_printf(MSG_DEBUG, "EAP-PEAPv2: Failed to allocate memory " - "for TLV encapsulation"); - wpabuf_free(buf); - return NULL; - } - tlv = wpabuf_put(e, sizeof(*tlv)); - tlv->tlv_type = host_to_be16(EAP_TLV_TYPE_MANDATORY | - EAP_TLV_EAP_PAYLOAD_TLV); - tlv->length = host_to_be16(wpabuf_len(buf)); - wpabuf_put_buf(e, buf); - wpabuf_free(buf); - return e; -} - - -static void eap_peap_req_success(struct eap_sm *sm, - struct eap_peap_data *data) -{ - if (data->state == FAILURE || data->state == FAILURE_REQ) { - eap_peap_state(data, FAILURE); - return; - } - - if (data->peap_version == 0) { - data->tlv_request = TLV_REQ_SUCCESS; - eap_peap_state(data, PHASE2_TLV); - } else { - eap_peap_state(data, SUCCESS_REQ); - } -} - - -static void eap_peap_req_failure(struct eap_sm *sm, - struct eap_peap_data *data) -{ - if (data->state == FAILURE || data->state == FAILURE_REQ || - data->state == SUCCESS_REQ || data->tlv_request != TLV_REQ_NONE) { - eap_peap_state(data, FAILURE); - return; - } - - if (data->peap_version == 0) { - data->tlv_request = TLV_REQ_FAILURE; - eap_peap_state(data, PHASE2_TLV); - } else { - eap_peap_state(data, FAILURE_REQ); - } -} - - -static void * eap_peap_init(struct eap_sm *sm) -{ - struct eap_peap_data *data; - - data = os_zalloc(sizeof(*data)); - if (data == NULL) - return NULL; - data->peap_version = EAP_PEAP_VERSION; - data->force_version = -1; - if (sm->user && sm->user->force_version >= 0) { - data->force_version = sm->user->force_version; - wpa_printf(MSG_DEBUG, "EAP-PEAP: forcing version %d", - data->force_version); - data->peap_version = data->force_version; - } - data->state = START; - data->crypto_binding = OPTIONAL_BINDING; - - if (eap_server_tls_ssl_init(sm, &data->ssl, 0)) { - wpa_printf(MSG_INFO, "EAP-PEAP: Failed to initialize SSL."); - eap_peap_reset(sm, data); - return NULL; - } - - return data; -} - - -static void eap_peap_reset(struct eap_sm *sm, void *priv) -{ - struct eap_peap_data *data = priv; - if (data == NULL) - return; - if (data->phase2_priv && data->phase2_method) - data->phase2_method->reset(sm, data->phase2_priv); - eap_server_tls_ssl_deinit(sm, &data->ssl); - wpabuf_free(data->pending_phase2_resp); - os_free(data->phase2_key); - wpabuf_free(data->soh_response); - os_free(data); -} - - -static struct wpabuf * eap_peap_build_start(struct eap_sm *sm, - struct eap_peap_data *data, u8 id) -{ - struct wpabuf *req; - - req = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_PEAP, 1, - EAP_CODE_REQUEST, id); - if (req == NULL) { - wpa_printf(MSG_ERROR, "EAP-PEAP: Failed to allocate memory for" - " request"); - eap_peap_state(data, FAILURE); - return NULL; - } - - wpabuf_put_u8(req, EAP_TLS_FLAGS_START | data->peap_version); - - eap_peap_state(data, PHASE1); - - return req; -} - - -static struct wpabuf * eap_peap_build_phase2_req(struct eap_sm *sm, - struct eap_peap_data *data, - u8 id) -{ - struct wpabuf *buf, *encr_req, msgbuf; - const u8 *req; - size_t req_len; - - if (data->phase2_method == NULL || data->phase2_priv == NULL) { - wpa_printf(MSG_DEBUG, "EAP-PEAP: Phase 2 method not ready"); - return NULL; - } - buf = data->phase2_method->buildReq(sm, data->phase2_priv, id); - if (data->peap_version >= 2 && buf) - buf = eap_peapv2_tlv_eap_payload(buf); - if (buf == NULL) - return NULL; - - req = wpabuf_head(buf); - req_len = wpabuf_len(buf); - wpa_hexdump_key(MSG_DEBUG, "EAP-PEAP: Encrypting Phase 2 data", - req, req_len); - - if (data->peap_version == 0 && - data->phase2_method->method != EAP_TYPE_TLV) { - req += sizeof(struct eap_hdr); - req_len -= sizeof(struct eap_hdr); - } - - wpabuf_set(&msgbuf, req, req_len); - encr_req = eap_server_tls_encrypt(sm, &data->ssl, &msgbuf); - wpabuf_free(buf); - - return encr_req; -} - - -#ifdef EAP_SERVER_TNC -static struct wpabuf * eap_peap_build_phase2_soh(struct eap_sm *sm, - struct eap_peap_data *data, - u8 id) -{ - struct wpabuf *buf1, *buf, *encr_req, msgbuf; - const u8 *req; - size_t req_len; - - buf1 = tncs_build_soh_request(); - if (buf1 == NULL) - return NULL; - - buf = eap_msg_alloc(EAP_VENDOR_MICROSOFT, 0x21, wpabuf_len(buf1), - EAP_CODE_REQUEST, id); - if (buf == NULL) { - wpabuf_free(buf1); - return NULL; - } - wpabuf_put_buf(buf, buf1); - wpabuf_free(buf1); - - req = wpabuf_head(buf); - req_len = wpabuf_len(buf); - - wpa_hexdump_key(MSG_DEBUG, "EAP-PEAP: Encrypting Phase 2 SOH data", - req, req_len); - - req += sizeof(struct eap_hdr); - req_len -= sizeof(struct eap_hdr); - wpabuf_set(&msgbuf, req, req_len); - - encr_req = eap_server_tls_encrypt(sm, &data->ssl, &msgbuf); - wpabuf_free(buf); - - return encr_req; -} -#endif /* EAP_SERVER_TNC */ - - -static void eap_peap_get_isk(struct eap_peap_data *data, - u8 *isk, size_t isk_len) -{ - size_t key_len; - - os_memset(isk, 0, isk_len); - if (data->phase2_key == NULL) - return; - - key_len = data->phase2_key_len; - if (key_len > isk_len) - key_len = isk_len; - os_memcpy(isk, data->phase2_key, key_len); -} - - -static int eap_peap_derive_cmk(struct eap_sm *sm, struct eap_peap_data *data) -{ - u8 *tk; - u8 isk[32], imck[60]; - - /* - * Tunnel key (TK) is the first 60 octets of the key generated by - * phase 1 of PEAP (based on TLS). - */ - tk = eap_server_tls_derive_key(sm, &data->ssl, "client EAP encryption", - EAP_TLS_KEY_LEN); - if (tk == NULL) - return -1; - wpa_hexdump_key(MSG_DEBUG, "EAP-PEAP: TK", tk, 60); - - eap_peap_get_isk(data, isk, sizeof(isk)); - wpa_hexdump_key(MSG_DEBUG, "EAP-PEAP: ISK", isk, sizeof(isk)); - - /* - * IPMK Seed = "Inner Methods Compound Keys" | ISK - * TempKey = First 40 octets of TK - * IPMK|CMK = PRF+(TempKey, IPMK Seed, 60) - * (note: draft-josefsson-pppext-eap-tls-eap-10.txt includes a space - * in the end of the label just before ISK; is that just a typo?) - */ - wpa_hexdump_key(MSG_DEBUG, "EAP-PEAP: TempKey", tk, 40); - peap_prfplus(data->peap_version, tk, 40, "Inner Methods Compound Keys", - isk, sizeof(isk), imck, sizeof(imck)); - wpa_hexdump_key(MSG_DEBUG, "EAP-PEAP: IMCK (IPMKj)", - imck, sizeof(imck)); - - os_free(tk); - - /* TODO: fast-connect: IPMK|CMK = TK */ - os_memcpy(data->ipmk, imck, 40); - wpa_hexdump_key(MSG_DEBUG, "EAP-PEAP: IPMK (S-IPMKj)", data->ipmk, 40); - os_memcpy(data->cmk, imck + 40, 20); - wpa_hexdump_key(MSG_DEBUG, "EAP-PEAP: CMK (CMKj)", data->cmk, 20); - - return 0; -} - - -static struct wpabuf * eap_peap_build_phase2_tlv(struct eap_sm *sm, - struct eap_peap_data *data, - u8 id) -{ - struct wpabuf *buf, *encr_req; - size_t mlen; - - mlen = 6; /* Result TLV */ - if (data->crypto_binding != NO_BINDING) - mlen += 60; /* Cryptobinding TLV */ -#ifdef EAP_SERVER_TNC - if (data->soh_response) - mlen += wpabuf_len(data->soh_response); -#endif /* EAP_SERVER_TNC */ - - buf = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_TLV, mlen, - EAP_CODE_REQUEST, id); - if (buf == NULL) - return NULL; - - wpabuf_put_u8(buf, 0x80); /* Mandatory */ - wpabuf_put_u8(buf, EAP_TLV_RESULT_TLV); - /* Length */ - wpabuf_put_be16(buf, 2); - /* Status */ - wpabuf_put_be16(buf, data->tlv_request == TLV_REQ_SUCCESS ? - EAP_TLV_RESULT_SUCCESS : EAP_TLV_RESULT_FAILURE); - - if (data->peap_version == 0 && data->tlv_request == TLV_REQ_SUCCESS && - data->crypto_binding != NO_BINDING) { - u8 *mac; - u8 eap_type = EAP_TYPE_PEAP; - const u8 *addr[2]; - size_t len[2]; - u16 tlv_type; - -#ifdef EAP_SERVER_TNC - if (data->soh_response) { - wpa_printf(MSG_DEBUG, "EAP-PEAP: Adding MS-SOH " - "Response TLV"); - wpabuf_put_buf(buf, data->soh_response); - wpabuf_free(data->soh_response); - data->soh_response = NULL; - } -#endif /* EAP_SERVER_TNC */ - - if (eap_peap_derive_cmk(sm, data) < 0 || - random_get_bytes(data->binding_nonce, 32)) { - wpabuf_free(buf); - return NULL; - } - - /* Compound_MAC: HMAC-SHA1-160(cryptobinding TLV | EAP type) */ - addr[0] = wpabuf_put(buf, 0); - len[0] = 60; - addr[1] = &eap_type; - len[1] = 1; - - tlv_type = EAP_TLV_CRYPTO_BINDING_TLV; - if (data->peap_version >= 2) - tlv_type |= EAP_TLV_TYPE_MANDATORY; - wpabuf_put_be16(buf, tlv_type); - wpabuf_put_be16(buf, 56); - - wpabuf_put_u8(buf, 0); /* Reserved */ - wpabuf_put_u8(buf, data->peap_version); /* Version */ - wpabuf_put_u8(buf, data->recv_version); /* RecvVersion */ - wpabuf_put_u8(buf, 0); /* SubType: 0 = Request, 1 = Response */ - wpabuf_put_data(buf, data->binding_nonce, 32); /* Nonce */ - mac = wpabuf_put(buf, 20); /* Compound_MAC */ - wpa_hexdump(MSG_MSGDUMP, "EAP-PEAP: Compound_MAC CMK", - data->cmk, 20); - wpa_hexdump(MSG_MSGDUMP, "EAP-PEAP: Compound_MAC data 1", - addr[0], len[0]); - wpa_hexdump(MSG_MSGDUMP, "EAP-PEAP: Compound_MAC data 2", - addr[1], len[1]); - hmac_sha1_vector(data->cmk, 20, 2, addr, len, mac); - wpa_hexdump(MSG_MSGDUMP, "EAP-PEAP: Compound_MAC", - mac, SHA1_MAC_LEN); - data->crypto_binding_sent = 1; - } - - wpa_hexdump_buf_key(MSG_DEBUG, "EAP-PEAP: Encrypting Phase 2 TLV data", - buf); - - encr_req = eap_server_tls_encrypt(sm, &data->ssl, buf); - wpabuf_free(buf); - - return encr_req; -} - - -static struct wpabuf * eap_peap_build_phase2_term(struct eap_sm *sm, - struct eap_peap_data *data, - u8 id, int success) -{ - struct wpabuf *encr_req, msgbuf; - size_t req_len; - struct eap_hdr *hdr; - - req_len = sizeof(*hdr); - hdr = os_zalloc(req_len); - if (hdr == NULL) - return NULL; - - hdr->code = success ? EAP_CODE_SUCCESS : EAP_CODE_FAILURE; - hdr->identifier = id; - hdr->length = host_to_be16(req_len); - - wpa_hexdump_key(MSG_DEBUG, "EAP-PEAP: Encrypting Phase 2 data", - (u8 *) hdr, req_len); - - wpabuf_set(&msgbuf, hdr, req_len); - encr_req = eap_server_tls_encrypt(sm, &data->ssl, &msgbuf); - os_free(hdr); - - return encr_req; -} - - -static struct wpabuf * eap_peap_buildReq(struct eap_sm *sm, void *priv, u8 id) -{ - struct eap_peap_data *data = priv; - - if (data->ssl.state == FRAG_ACK) { - return eap_server_tls_build_ack(id, EAP_TYPE_PEAP, - data->peap_version); - } - - if (data->ssl.state == WAIT_FRAG_ACK) { - return eap_server_tls_build_msg(&data->ssl, EAP_TYPE_PEAP, - data->peap_version, id); - } - - switch (data->state) { - case START: - return eap_peap_build_start(sm, data, id); - case PHASE1: - case PHASE1_ID2: - if (data->peap_version < 2 && - tls_connection_established(sm->ssl_ctx, data->ssl.conn)) { - wpa_printf(MSG_DEBUG, "EAP-PEAP: Phase1 done, " - "starting Phase2"); - eap_peap_state(data, PHASE2_START); - } - break; - case PHASE2_ID: - case PHASE2_METHOD: - wpabuf_free(data->ssl.tls_out); - data->ssl.tls_out_pos = 0; - data->ssl.tls_out = eap_peap_build_phase2_req(sm, data, id); - break; -#ifdef EAP_SERVER_TNC - case PHASE2_SOH: - wpabuf_free(data->ssl.tls_out); - data->ssl.tls_out_pos = 0; - data->ssl.tls_out = eap_peap_build_phase2_soh(sm, data, id); - break; -#endif /* EAP_SERVER_TNC */ - case PHASE2_TLV: - wpabuf_free(data->ssl.tls_out); - data->ssl.tls_out_pos = 0; - data->ssl.tls_out = eap_peap_build_phase2_tlv(sm, data, id); - break; - case SUCCESS_REQ: - wpabuf_free(data->ssl.tls_out); - data->ssl.tls_out_pos = 0; - data->ssl.tls_out = eap_peap_build_phase2_term(sm, data, id, - 1); - break; - case FAILURE_REQ: - wpabuf_free(data->ssl.tls_out); - data->ssl.tls_out_pos = 0; - data->ssl.tls_out = eap_peap_build_phase2_term(sm, data, id, - 0); - break; - default: - wpa_printf(MSG_DEBUG, "EAP-PEAP: %s - unexpected state %d", - __func__, data->state); - return NULL; - } - - return eap_server_tls_build_msg(&data->ssl, EAP_TYPE_PEAP, - data->peap_version, id); -} - - -static Boolean eap_peap_check(struct eap_sm *sm, void *priv, - struct wpabuf *respData) -{ - const u8 *pos; - size_t len; - - pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_PEAP, respData, &len); - if (pos == NULL || len < 1) { - wpa_printf(MSG_INFO, "EAP-PEAP: Invalid frame"); - return TRUE; - } - - return FALSE; -} - - -static int eap_peap_phase2_init(struct eap_sm *sm, struct eap_peap_data *data, - EapType eap_type) -{ - if (data->phase2_priv && data->phase2_method) { - data->phase2_method->reset(sm, data->phase2_priv); - data->phase2_method = NULL; - data->phase2_priv = NULL; - } - data->phase2_method = eap_server_get_eap_method(EAP_VENDOR_IETF, - eap_type); - if (!data->phase2_method) - return -1; - - sm->init_phase2 = 1; - data->phase2_priv = data->phase2_method->init(sm); - sm->init_phase2 = 0; - return 0; -} - - -static int eap_tlv_validate_cryptobinding(struct eap_sm *sm, - struct eap_peap_data *data, - const u8 *crypto_tlv, - size_t crypto_tlv_len) -{ - u8 buf[61], mac[SHA1_MAC_LEN]; - const u8 *pos; - - if (crypto_tlv_len != 4 + 56) { - wpa_printf(MSG_DEBUG, "EAP-PEAP: Invalid cryptobinding TLV " - "length %d", (int) crypto_tlv_len); - return -1; - } - - pos = crypto_tlv; - pos += 4; /* TLV header */ - if (pos[1] != data->peap_version) { - wpa_printf(MSG_DEBUG, "EAP-PEAP: Cryptobinding TLV Version " - "mismatch (was %d; expected %d)", - pos[1], data->peap_version); - return -1; - } - - if (pos[3] != 1) { - wpa_printf(MSG_DEBUG, "EAP-PEAP: Unexpected Cryptobinding TLV " - "SubType %d", pos[3]); - return -1; - } - pos += 4; - pos += 32; /* Nonce */ - - /* Compound_MAC: HMAC-SHA1-160(cryptobinding TLV | EAP type) */ - os_memcpy(buf, crypto_tlv, 60); - os_memset(buf + 4 + 4 + 32, 0, 20); /* Compound_MAC */ - buf[60] = EAP_TYPE_PEAP; - hmac_sha1(data->cmk, 20, buf, sizeof(buf), mac); - - if (os_memcmp(mac, pos, SHA1_MAC_LEN) != 0) { - wpa_printf(MSG_DEBUG, "EAP-PEAP: Invalid Compound_MAC in " - "cryptobinding TLV"); - wpa_hexdump_key(MSG_DEBUG, "EAP-PEAP: CMK", data->cmk, 20); - wpa_hexdump(MSG_DEBUG, "EAP-PEAP: Cryptobinding seed data", - buf, 61); - return -1; - } - - wpa_printf(MSG_DEBUG, "EAP-PEAP: Valid cryptobinding TLV received"); - - return 0; -} - - -static void eap_peap_process_phase2_tlv(struct eap_sm *sm, - struct eap_peap_data *data, - struct wpabuf *in_data) -{ - const u8 *pos; - size_t left; - const u8 *result_tlv = NULL, *crypto_tlv = NULL; - size_t result_tlv_len = 0, crypto_tlv_len = 0; - int tlv_type, mandatory, tlv_len; - - pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_TLV, in_data, &left); - if (pos == NULL) { - wpa_printf(MSG_DEBUG, "EAP-PEAP: Invalid EAP-TLV header"); - return; - } - - /* Parse TLVs */ - wpa_hexdump(MSG_DEBUG, "EAP-PEAP: Received TLVs", pos, left); - while (left >= 4) { - mandatory = !!(pos[0] & 0x80); - tlv_type = pos[0] & 0x3f; - tlv_type = (tlv_type << 8) | pos[1]; - tlv_len = ((int) pos[2] << 8) | pos[3]; - pos += 4; - left -= 4; - if ((size_t) tlv_len > left) { - wpa_printf(MSG_DEBUG, "EAP-PEAP: TLV underrun " - "(tlv_len=%d left=%lu)", tlv_len, - (unsigned long) left); - eap_peap_state(data, FAILURE); - return; - } - switch (tlv_type) { - case EAP_TLV_RESULT_TLV: - result_tlv = pos; - result_tlv_len = tlv_len; - break; - case EAP_TLV_CRYPTO_BINDING_TLV: - crypto_tlv = pos; - crypto_tlv_len = tlv_len; - break; - default: - wpa_printf(MSG_DEBUG, "EAP-PEAP: Unsupported TLV Type " - "%d%s", tlv_type, - mandatory ? " (mandatory)" : ""); - if (mandatory) { - eap_peap_state(data, FAILURE); - return; - } - /* Ignore this TLV, but process other TLVs */ - break; - } - - pos += tlv_len; - left -= tlv_len; - } - if (left) { - wpa_printf(MSG_DEBUG, "EAP-PEAP: Last TLV too short in " - "Request (left=%lu)", (unsigned long) left); - eap_peap_state(data, FAILURE); - return; - } - - /* Process supported TLVs */ - if (crypto_tlv && data->crypto_binding_sent) { - wpa_hexdump(MSG_DEBUG, "EAP-PEAP: Cryptobinding TLV", - crypto_tlv, crypto_tlv_len); - if (eap_tlv_validate_cryptobinding(sm, data, crypto_tlv - 4, - crypto_tlv_len + 4) < 0) { - eap_peap_state(data, FAILURE); - return; - } - data->crypto_binding_used = 1; - } else if (!crypto_tlv && data->crypto_binding_sent && - data->crypto_binding == REQUIRE_BINDING) { - wpa_printf(MSG_DEBUG, "EAP-PEAP: No cryptobinding TLV"); - eap_peap_state(data, FAILURE); - return; - } - - if (result_tlv) { - int status; - const char *requested; - - wpa_hexdump(MSG_DEBUG, "EAP-PEAP: Result TLV", - result_tlv, result_tlv_len); - if (result_tlv_len < 2) { - wpa_printf(MSG_INFO, "EAP-PEAP: Too short Result TLV " - "(len=%lu)", - (unsigned long) result_tlv_len); - eap_peap_state(data, FAILURE); - return; - } - requested = data->tlv_request == TLV_REQ_SUCCESS ? "Success" : - "Failure"; - status = WPA_GET_BE16(result_tlv); - if (status == EAP_TLV_RESULT_SUCCESS) { - wpa_printf(MSG_INFO, "EAP-PEAP: TLV Result - Success " - "- requested %s", requested); - if (data->tlv_request == TLV_REQ_SUCCESS) - eap_peap_state(data, SUCCESS); - else - eap_peap_state(data, FAILURE); - - } else if (status == EAP_TLV_RESULT_FAILURE) { - wpa_printf(MSG_INFO, "EAP-PEAP: TLV Result - Failure " - "- requested %s", requested); - eap_peap_state(data, FAILURE); - } else { - wpa_printf(MSG_INFO, "EAP-PEAP: Unknown TLV Result " - "Status %d", status); - eap_peap_state(data, FAILURE); - } - } -} - - -#ifdef EAP_SERVER_TNC -static void eap_peap_process_phase2_soh(struct eap_sm *sm, - struct eap_peap_data *data, - struct wpabuf *in_data) -{ - const u8 *pos, *vpos; - size_t left; - const u8 *soh_tlv = NULL; - size_t soh_tlv_len = 0; - int tlv_type, mandatory, tlv_len, vtlv_len; - u8 next_type; - u32 vendor_id; - - pos = eap_hdr_validate(EAP_VENDOR_MICROSOFT, 0x21, in_data, &left); - if (pos == NULL) { - wpa_printf(MSG_DEBUG, "EAP-PEAP: Not a valid SoH EAP " - "Extensions Method header - skip TNC"); - goto auth_method; - } - - /* Parse TLVs */ - wpa_hexdump(MSG_DEBUG, "EAP-PEAP: Received TLVs (SoH)", pos, left); - while (left >= 4) { - mandatory = !!(pos[0] & 0x80); - tlv_type = pos[0] & 0x3f; - tlv_type = (tlv_type << 8) | pos[1]; - tlv_len = ((int) pos[2] << 8) | pos[3]; - pos += 4; - left -= 4; - if ((size_t) tlv_len > left) { - wpa_printf(MSG_DEBUG, "EAP-PEAP: TLV underrun " - "(tlv_len=%d left=%lu)", tlv_len, - (unsigned long) left); - eap_peap_state(data, FAILURE); - return; - } - switch (tlv_type) { - case EAP_TLV_VENDOR_SPECIFIC_TLV: - if (tlv_len < 4) { - wpa_printf(MSG_DEBUG, "EAP-PEAP: Too short " - "vendor specific TLV (len=%d)", - (int) tlv_len); - eap_peap_state(data, FAILURE); - return; - } - - vendor_id = WPA_GET_BE32(pos); - if (vendor_id != EAP_VENDOR_MICROSOFT) { - if (mandatory) { - eap_peap_state(data, FAILURE); - return; - } - break; - } - - vpos = pos + 4; - mandatory = !!(vpos[0] & 0x80); - tlv_type = vpos[0] & 0x3f; - tlv_type = (tlv_type << 8) | vpos[1]; - vtlv_len = ((int) vpos[2] << 8) | vpos[3]; - vpos += 4; - if (vpos + vtlv_len > pos + left) { - wpa_printf(MSG_DEBUG, "EAP-PEAP: Vendor TLV " - "underrun"); - eap_peap_state(data, FAILURE); - return; - } - - if (tlv_type == 1) { - soh_tlv = vpos; - soh_tlv_len = vtlv_len; - break; - } - - wpa_printf(MSG_DEBUG, "EAP-PEAP: Unsupported MS-TLV " - "Type %d%s", tlv_type, - mandatory ? " (mandatory)" : ""); - if (mandatory) { - eap_peap_state(data, FAILURE); - return; - } - /* Ignore this TLV, but process other TLVs */ - break; - default: - wpa_printf(MSG_DEBUG, "EAP-PEAP: Unsupported TLV Type " - "%d%s", tlv_type, - mandatory ? " (mandatory)" : ""); - if (mandatory) { - eap_peap_state(data, FAILURE); - return; - } - /* Ignore this TLV, but process other TLVs */ - break; - } - - pos += tlv_len; - left -= tlv_len; - } - if (left) { - wpa_printf(MSG_DEBUG, "EAP-PEAP: Last TLV too short in " - "Request (left=%lu)", (unsigned long) left); - eap_peap_state(data, FAILURE); - return; - } - - /* Process supported TLVs */ - if (soh_tlv) { - int failure = 0; - wpabuf_free(data->soh_response); - data->soh_response = tncs_process_soh(soh_tlv, soh_tlv_len, - &failure); - if (failure) { - eap_peap_state(data, FAILURE); - return; - } - } else { - wpa_printf(MSG_DEBUG, "EAP-PEAP: No SoH TLV received"); - eap_peap_state(data, FAILURE); - return; - } - -auth_method: - eap_peap_state(data, PHASE2_METHOD); - next_type = sm->user->methods[0].method; - sm->user_eap_method_index = 1; - wpa_printf(MSG_DEBUG, "EAP-PEAP: try EAP type %d", next_type); - eap_peap_phase2_init(sm, data, next_type); -} -#endif /* EAP_SERVER_TNC */ - - -static void eap_peap_process_phase2_response(struct eap_sm *sm, - struct eap_peap_data *data, - struct wpabuf *in_data) -{ - u8 next_type = EAP_TYPE_NONE; - const struct eap_hdr *hdr; - const u8 *pos; - size_t left; - - if (data->state == PHASE2_TLV) { - eap_peap_process_phase2_tlv(sm, data, in_data); - return; - } - -#ifdef EAP_SERVER_TNC - if (data->state == PHASE2_SOH) { - eap_peap_process_phase2_soh(sm, data, in_data); - return; - } -#endif /* EAP_SERVER_TNC */ - - if (data->phase2_priv == NULL) { - wpa_printf(MSG_DEBUG, "EAP-PEAP: %s - Phase2 not " - "initialized?!", __func__); - return; - } - - hdr = wpabuf_head(in_data); - pos = (const u8 *) (hdr + 1); - - if (wpabuf_len(in_data) > sizeof(*hdr) && *pos == EAP_TYPE_NAK) { - left = wpabuf_len(in_data) - sizeof(*hdr); - wpa_hexdump(MSG_DEBUG, "EAP-PEAP: Phase2 type Nak'ed; " - "allowed types", pos + 1, left - 1); - eap_sm_process_nak(sm, pos + 1, left - 1); - if (sm->user && sm->user_eap_method_index < EAP_MAX_METHODS && - sm->user->methods[sm->user_eap_method_index].method != - EAP_TYPE_NONE) { - next_type = sm->user->methods[ - sm->user_eap_method_index++].method; - wpa_printf(MSG_DEBUG, "EAP-PEAP: try EAP type %d", - next_type); - } else { - eap_peap_req_failure(sm, data); - next_type = EAP_TYPE_NONE; - } - eap_peap_phase2_init(sm, data, next_type); - return; - } - - if (data->phase2_method->check(sm, data->phase2_priv, in_data)) { - wpa_printf(MSG_DEBUG, "EAP-PEAP: Phase2 check() asked to " - "ignore the packet"); - return; - } - - data->phase2_method->process(sm, data->phase2_priv, in_data); - - if (sm->method_pending == METHOD_PENDING_WAIT) { - wpa_printf(MSG_DEBUG, "EAP-PEAP: Phase2 method is in " - "pending wait state - save decrypted response"); - wpabuf_free(data->pending_phase2_resp); - data->pending_phase2_resp = wpabuf_dup(in_data); - } - - if (!data->phase2_method->isDone(sm, data->phase2_priv)) - return; - - if (!data->phase2_method->isSuccess(sm, data->phase2_priv)) { - wpa_printf(MSG_DEBUG, "EAP-PEAP: Phase2 method failed"); - eap_peap_req_failure(sm, data); - next_type = EAP_TYPE_NONE; - eap_peap_phase2_init(sm, data, next_type); - return; - } - - os_free(data->phase2_key); - if (data->phase2_method->getKey) { - data->phase2_key = data->phase2_method->getKey( - sm, data->phase2_priv, &data->phase2_key_len); - if (data->phase2_key == NULL) { - wpa_printf(MSG_DEBUG, "EAP-PEAP: Phase2 getKey " - "failed"); - eap_peap_req_failure(sm, data); - eap_peap_phase2_init(sm, data, EAP_TYPE_NONE); - return; - } - } - - switch (data->state) { - case PHASE1_ID2: - case PHASE2_ID: - case PHASE2_SOH: - if (eap_user_get(sm, sm->identity, sm->identity_len, 1) != 0) { - wpa_hexdump_ascii(MSG_DEBUG, "EAP_PEAP: Phase2 " - "Identity not found in the user " - "database", - sm->identity, sm->identity_len); - eap_peap_req_failure(sm, data); - next_type = EAP_TYPE_NONE; - break; - } - -#ifdef EAP_SERVER_TNC - if (data->state != PHASE2_SOH && sm->tnc && - data->peap_version == 0) { - eap_peap_state(data, PHASE2_SOH); - wpa_printf(MSG_DEBUG, "EAP-PEAP: Try to initialize " - "TNC (NAP SOH)"); - next_type = EAP_TYPE_NONE; - break; - } -#endif /* EAP_SERVER_TNC */ - - eap_peap_state(data, PHASE2_METHOD); - next_type = sm->user->methods[0].method; - sm->user_eap_method_index = 1; - wpa_printf(MSG_DEBUG, "EAP-PEAP: try EAP type %d", next_type); - break; - case PHASE2_METHOD: - eap_peap_req_success(sm, data); - next_type = EAP_TYPE_NONE; - break; - case FAILURE: - break; - default: - wpa_printf(MSG_DEBUG, "EAP-PEAP: %s - unexpected state %d", - __func__, data->state); - break; - } - - eap_peap_phase2_init(sm, data, next_type); -} - - -static void eap_peap_process_phase2(struct eap_sm *sm, - struct eap_peap_data *data, - const struct wpabuf *respData, - struct wpabuf *in_buf) -{ - struct wpabuf *in_decrypted; - const struct eap_hdr *hdr; - size_t len; - - wpa_printf(MSG_DEBUG, "EAP-PEAP: received %lu bytes encrypted data for" - " Phase 2", (unsigned long) wpabuf_len(in_buf)); - - if (data->pending_phase2_resp) { - wpa_printf(MSG_DEBUG, "EAP-PEAP: Pending Phase 2 response - " - "skip decryption and use old data"); - eap_peap_process_phase2_response(sm, data, - data->pending_phase2_resp); - wpabuf_free(data->pending_phase2_resp); - data->pending_phase2_resp = NULL; - return; - } - - in_decrypted = tls_connection_decrypt(sm->ssl_ctx, data->ssl.conn, - in_buf); - if (in_decrypted == NULL) { - wpa_printf(MSG_INFO, "EAP-PEAP: Failed to decrypt Phase 2 " - "data"); - eap_peap_state(data, FAILURE); - return; - } - - wpa_hexdump_buf_key(MSG_DEBUG, "EAP-PEAP: Decrypted Phase 2 EAP", - in_decrypted); - - hdr = wpabuf_head(in_decrypted); - - if (data->peap_version == 0 && data->state != PHASE2_TLV) { - const struct eap_hdr *resp; - struct eap_hdr *nhdr; - struct wpabuf *nbuf = - wpabuf_alloc(sizeof(struct eap_hdr) + - wpabuf_len(in_decrypted)); - if (nbuf == NULL) { - wpabuf_free(in_decrypted); - return; - } - - resp = wpabuf_head(respData); - nhdr = wpabuf_put(nbuf, sizeof(*nhdr)); - nhdr->code = resp->code; - nhdr->identifier = resp->identifier; - nhdr->length = host_to_be16(sizeof(struct eap_hdr) + - wpabuf_len(in_decrypted)); - wpabuf_put_buf(nbuf, in_decrypted); - wpabuf_free(in_decrypted); - - in_decrypted = nbuf; - } else if (data->peap_version >= 2) { - struct eap_tlv_hdr *tlv; - struct wpabuf *nmsg; - - if (wpabuf_len(in_decrypted) < sizeof(*tlv) + sizeof(*hdr)) { - wpa_printf(MSG_INFO, "EAP-PEAPv2: Too short Phase 2 " - "EAP TLV"); - wpabuf_free(in_decrypted); - return; - } - tlv = wpabuf_mhead(in_decrypted); - if ((be_to_host16(tlv->tlv_type) & EAP_TLV_TYPE_MASK) != - EAP_TLV_EAP_PAYLOAD_TLV) { - wpa_printf(MSG_INFO, "EAP-PEAPv2: Not an EAP TLV"); - wpabuf_free(in_decrypted); - return; - } - if (sizeof(*tlv) + be_to_host16(tlv->length) > - wpabuf_len(in_decrypted)) { - wpa_printf(MSG_INFO, "EAP-PEAPv2: Invalid EAP TLV " - "length"); - wpabuf_free(in_decrypted); - return; - } - hdr = (struct eap_hdr *) (tlv + 1); - if (be_to_host16(hdr->length) > be_to_host16(tlv->length)) { - wpa_printf(MSG_INFO, "EAP-PEAPv2: No room for full " - "EAP packet in EAP TLV"); - wpabuf_free(in_decrypted); - return; - } - - nmsg = wpabuf_alloc(be_to_host16(hdr->length)); - if (nmsg == NULL) { - wpabuf_free(in_decrypted); - return; - } - - wpabuf_put_data(nmsg, hdr, be_to_host16(hdr->length)); - wpabuf_free(in_decrypted); - in_decrypted = nmsg; - } - - hdr = wpabuf_head(in_decrypted); - if (wpabuf_len(in_decrypted) < (int) sizeof(*hdr)) { - wpa_printf(MSG_INFO, "EAP-PEAP: Too short Phase 2 " - "EAP frame (len=%lu)", - (unsigned long) wpabuf_len(in_decrypted)); - wpabuf_free(in_decrypted); - eap_peap_req_failure(sm, data); - return; - } - len = be_to_host16(hdr->length); - if (len > wpabuf_len(in_decrypted)) { - wpa_printf(MSG_INFO, "EAP-PEAP: Length mismatch in " - "Phase 2 EAP frame (len=%lu hdr->length=%lu)", - (unsigned long) wpabuf_len(in_decrypted), - (unsigned long) len); - wpabuf_free(in_decrypted); - eap_peap_req_failure(sm, data); - return; - } - wpa_printf(MSG_DEBUG, "EAP-PEAP: received Phase 2: code=%d " - "identifier=%d length=%lu", hdr->code, hdr->identifier, - (unsigned long) len); - switch (hdr->code) { - case EAP_CODE_RESPONSE: - eap_peap_process_phase2_response(sm, data, in_decrypted); - break; - case EAP_CODE_SUCCESS: - wpa_printf(MSG_DEBUG, "EAP-PEAP: Phase 2 Success"); - if (data->state == SUCCESS_REQ) { - eap_peap_state(data, SUCCESS); - } - break; - case EAP_CODE_FAILURE: - wpa_printf(MSG_DEBUG, "EAP-PEAP: Phase 2 Failure"); - eap_peap_state(data, FAILURE); - break; - default: - wpa_printf(MSG_INFO, "EAP-PEAP: Unexpected code=%d in " - "Phase 2 EAP header", hdr->code); - break; - } - - wpabuf_free(in_decrypted); -} - - -static int eap_peapv2_start_phase2(struct eap_sm *sm, - struct eap_peap_data *data) -{ - struct wpabuf *buf, *buf2; - - wpa_printf(MSG_DEBUG, "EAP-PEAPv2: Phase1 done, include first Phase2 " - "payload in the same message"); - eap_peap_state(data, PHASE1_ID2); - if (eap_peap_phase2_init(sm, data, EAP_TYPE_IDENTITY)) - return -1; - - /* TODO: which Id to use here? */ - buf = data->phase2_method->buildReq(sm, data->phase2_priv, 6); - if (buf == NULL) - return -1; - - buf2 = eap_peapv2_tlv_eap_payload(buf); - if (buf2 == NULL) - return -1; - - wpa_hexdump_buf(MSG_DEBUG, "EAP-PEAPv2: Identity Request", buf2); - - buf = tls_connection_encrypt(sm->ssl_ctx, data->ssl.conn, - buf2); - wpabuf_free(buf2); - - if (buf == NULL) { - wpa_printf(MSG_INFO, "EAP-PEAPv2: Failed to encrypt Phase 2 " - "data"); - return -1; - } - - wpa_hexdump_buf(MSG_DEBUG, "EAP-PEAPv2: Encrypted Identity Request", - buf); - - /* Append TLS data into the pending buffer after the Server Finished */ - if (wpabuf_resize(&data->ssl.tls_out, wpabuf_len(buf)) < 0) { - wpabuf_free(buf); - return -1; - } - wpabuf_put_buf(data->ssl.tls_out, buf); - wpabuf_free(buf); - - return 0; -} - - -static int eap_peap_process_version(struct eap_sm *sm, void *priv, - int peer_version) -{ - struct eap_peap_data *data = priv; - - data->recv_version = peer_version; - if (data->force_version >= 0 && peer_version != data->force_version) { - wpa_printf(MSG_INFO, "EAP-PEAP: peer did not select the forced" - " version (forced=%d peer=%d) - reject", - data->force_version, peer_version); - return -1; - } - if (peer_version < data->peap_version) { - wpa_printf(MSG_DEBUG, "EAP-PEAP: peer ver=%d, own ver=%d; " - "use version %d", - peer_version, data->peap_version, peer_version); - data->peap_version = peer_version; - } - - return 0; -} - - -static void eap_peap_process_msg(struct eap_sm *sm, void *priv, - const struct wpabuf *respData) -{ - struct eap_peap_data *data = priv; - - switch (data->state) { - case PHASE1: - if (eap_server_tls_phase1(sm, &data->ssl) < 0) { - eap_peap_state(data, FAILURE); - break; - } - - if (data->peap_version >= 2 && - tls_connection_established(sm->ssl_ctx, data->ssl.conn)) { - if (eap_peapv2_start_phase2(sm, data)) { - eap_peap_state(data, FAILURE); - break; - } - } - break; - case PHASE2_START: - eap_peap_state(data, PHASE2_ID); - eap_peap_phase2_init(sm, data, EAP_TYPE_IDENTITY); - break; - case PHASE1_ID2: - case PHASE2_ID: - case PHASE2_METHOD: - case PHASE2_SOH: - case PHASE2_TLV: - eap_peap_process_phase2(sm, data, respData, data->ssl.tls_in); - break; - case SUCCESS_REQ: - eap_peap_state(data, SUCCESS); - break; - case FAILURE_REQ: - eap_peap_state(data, FAILURE); - break; - default: - wpa_printf(MSG_DEBUG, "EAP-PEAP: Unexpected state %d in %s", - data->state, __func__); - break; - } -} - - -static void eap_peap_process(struct eap_sm *sm, void *priv, - struct wpabuf *respData) -{ - struct eap_peap_data *data = priv; - if (eap_server_tls_process(sm, &data->ssl, respData, data, - EAP_TYPE_PEAP, eap_peap_process_version, - eap_peap_process_msg) < 0) - eap_peap_state(data, FAILURE); -} - - -static Boolean eap_peap_isDone(struct eap_sm *sm, void *priv) -{ - struct eap_peap_data *data = priv; - return data->state == SUCCESS || data->state == FAILURE; -} - - -static u8 * eap_peap_getKey(struct eap_sm *sm, void *priv, size_t *len) -{ - struct eap_peap_data *data = priv; - u8 *eapKeyData; - - if (data->state != SUCCESS) - return NULL; - - if (data->crypto_binding_used) { - u8 csk[128]; - /* - * Note: It looks like Microsoft implementation requires null - * termination for this label while the one used for deriving - * IPMK|CMK did not use null termination. - */ - peap_prfplus(data->peap_version, data->ipmk, 40, - "Session Key Generating Function", - (u8 *) "\00", 1, csk, sizeof(csk)); - wpa_hexdump_key(MSG_DEBUG, "EAP-PEAP: CSK", csk, sizeof(csk)); - eapKeyData = os_malloc(EAP_TLS_KEY_LEN); - if (eapKeyData) { - os_memcpy(eapKeyData, csk, EAP_TLS_KEY_LEN); - *len = EAP_TLS_KEY_LEN; - wpa_hexdump(MSG_DEBUG, "EAP-PEAP: Derived key", - eapKeyData, EAP_TLS_KEY_LEN); - } else { - wpa_printf(MSG_DEBUG, "EAP-PEAP: Failed to derive " - "key"); - } - - return eapKeyData; - } - - /* TODO: PEAPv1 - different label in some cases */ - eapKeyData = eap_server_tls_derive_key(sm, &data->ssl, - "client EAP encryption", - EAP_TLS_KEY_LEN); - if (eapKeyData) { - *len = EAP_TLS_KEY_LEN; - wpa_hexdump(MSG_DEBUG, "EAP-PEAP: Derived key", - eapKeyData, EAP_TLS_KEY_LEN); - } else { - wpa_printf(MSG_DEBUG, "EAP-PEAP: Failed to derive key"); - } - - return eapKeyData; -} - - -static Boolean eap_peap_isSuccess(struct eap_sm *sm, void *priv) -{ - struct eap_peap_data *data = priv; - return data->state == SUCCESS; -} - - -int eap_server_peap_register(void) -{ - struct eap_method *eap; - int ret; - - eap = eap_server_method_alloc(EAP_SERVER_METHOD_INTERFACE_VERSION, - EAP_VENDOR_IETF, EAP_TYPE_PEAP, "PEAP"); - if (eap == NULL) - return -1; - - eap->init = eap_peap_init; - eap->reset = eap_peap_reset; - eap->buildReq = eap_peap_buildReq; - eap->check = eap_peap_check; - eap->process = eap_peap_process; - eap->isDone = eap_peap_isDone; - eap->getKey = eap_peap_getKey; - eap->isSuccess = eap_peap_isSuccess; - - ret = eap_server_method_register(eap); - if (ret) - eap_server_method_free(eap); - return ret; -} diff --git a/hostapd-0.8/src/eap_server/eap_server_psk.c b/hostapd-0.8/src/eap_server/eap_server_psk.c deleted file mode 100644 index efc7a82..0000000 --- a/hostapd-0.8/src/eap_server/eap_server_psk.c +++ /dev/null @@ -1,518 +0,0 @@ -/* - * hostapd / EAP-PSK (RFC 4764) server - * Copyright (c) 2005-2007, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - * - * Note: EAP-PSK is an EAP authentication method and as such, completely - * different from WPA-PSK. This file is not needed for WPA-PSK functionality. - */ - -#include "includes.h" - -#include "common.h" -#include "crypto/aes_wrap.h" -#include "crypto/random.h" -#include "eap_common/eap_psk_common.h" -#include "eap_server/eap_i.h" - - -struct eap_psk_data { - enum { PSK_1, PSK_3, SUCCESS, FAILURE } state; - u8 rand_s[EAP_PSK_RAND_LEN]; - u8 rand_p[EAP_PSK_RAND_LEN]; - u8 *id_p, *id_s; - size_t id_p_len, id_s_len; - u8 ak[EAP_PSK_AK_LEN], kdk[EAP_PSK_KDK_LEN], tek[EAP_PSK_TEK_LEN]; - u8 msk[EAP_MSK_LEN]; - u8 emsk[EAP_EMSK_LEN]; -}; - - -static void * eap_psk_init(struct eap_sm *sm) -{ - struct eap_psk_data *data; - - data = os_zalloc(sizeof(*data)); - if (data == NULL) - return NULL; - data->state = PSK_1; - data->id_s = (u8 *) "hostapd"; - data->id_s_len = 7; - - return data; -} - - -static void eap_psk_reset(struct eap_sm *sm, void *priv) -{ - struct eap_psk_data *data = priv; - os_free(data->id_p); - os_free(data); -} - - -static struct wpabuf * eap_psk_build_1(struct eap_sm *sm, - struct eap_psk_data *data, u8 id) -{ - struct wpabuf *req; - struct eap_psk_hdr_1 *psk; - - wpa_printf(MSG_DEBUG, "EAP-PSK: PSK-1 (sending)"); - - if (random_get_bytes(data->rand_s, EAP_PSK_RAND_LEN)) { - wpa_printf(MSG_ERROR, "EAP-PSK: Failed to get random data"); - data->state = FAILURE; - return NULL; - } - wpa_hexdump(MSG_MSGDUMP, "EAP-PSK: RAND_S (server rand)", - data->rand_s, EAP_PSK_RAND_LEN); - - req = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_PSK, - sizeof(*psk) + data->id_s_len, - EAP_CODE_REQUEST, id); - if (req == NULL) { - wpa_printf(MSG_ERROR, "EAP-PSK: Failed to allocate memory " - "request"); - data->state = FAILURE; - return NULL; - } - - psk = wpabuf_put(req, sizeof(*psk)); - psk->flags = EAP_PSK_FLAGS_SET_T(0); /* T=0 */ - os_memcpy(psk->rand_s, data->rand_s, EAP_PSK_RAND_LEN); - wpabuf_put_data(req, data->id_s, data->id_s_len); - - return req; -} - - -static struct wpabuf * eap_psk_build_3(struct eap_sm *sm, - struct eap_psk_data *data, u8 id) -{ - struct wpabuf *req; - struct eap_psk_hdr_3 *psk; - u8 *buf, *pchannel, nonce[16]; - size_t buflen; - - wpa_printf(MSG_DEBUG, "EAP-PSK: PSK-3 (sending)"); - - req = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_PSK, - sizeof(*psk) + 4 + 16 + 1, EAP_CODE_REQUEST, id); - if (req == NULL) { - wpa_printf(MSG_ERROR, "EAP-PSK: Failed to allocate memory " - "request"); - data->state = FAILURE; - return NULL; - } - - psk = wpabuf_put(req, sizeof(*psk)); - psk->flags = EAP_PSK_FLAGS_SET_T(2); /* T=2 */ - os_memcpy(psk->rand_s, data->rand_s, EAP_PSK_RAND_LEN); - - /* MAC_S = OMAC1-AES-128(AK, ID_S||RAND_P) */ - buflen = data->id_s_len + EAP_PSK_RAND_LEN; - buf = os_malloc(buflen); - if (buf == NULL) - goto fail; - - os_memcpy(buf, data->id_s, data->id_s_len); - os_memcpy(buf + data->id_s_len, data->rand_p, EAP_PSK_RAND_LEN); - if (omac1_aes_128(data->ak, buf, buflen, psk->mac_s)) - goto fail; - os_free(buf); - - if (eap_psk_derive_keys(data->kdk, data->rand_p, data->tek, data->msk, - data->emsk)) - goto fail; - wpa_hexdump_key(MSG_DEBUG, "EAP-PSK: TEK", data->tek, EAP_PSK_TEK_LEN); - wpa_hexdump_key(MSG_DEBUG, "EAP-PSK: MSK", data->msk, EAP_MSK_LEN); - wpa_hexdump_key(MSG_DEBUG, "EAP-PSK: EMSK", data->emsk, EAP_EMSK_LEN); - - os_memset(nonce, 0, sizeof(nonce)); - pchannel = wpabuf_put(req, 4 + 16 + 1); - os_memcpy(pchannel, nonce + 12, 4); - os_memset(pchannel + 4, 0, 16); /* Tag */ - pchannel[4 + 16] = EAP_PSK_R_FLAG_DONE_SUCCESS << 6; - wpa_hexdump(MSG_DEBUG, "EAP-PSK: PCHANNEL (plaintext)", - pchannel, 4 + 16 + 1); - if (aes_128_eax_encrypt(data->tek, nonce, sizeof(nonce), - wpabuf_head(req), 22, - pchannel + 4 + 16, 1, pchannel + 4)) - goto fail; - wpa_hexdump(MSG_DEBUG, "EAP-PSK: PCHANNEL (encrypted)", - pchannel, 4 + 16 + 1); - - return req; - -fail: - wpabuf_free(req); - data->state = FAILURE; - return NULL; -} - - -static struct wpabuf * eap_psk_buildReq(struct eap_sm *sm, void *priv, u8 id) -{ - struct eap_psk_data *data = priv; - - switch (data->state) { - case PSK_1: - return eap_psk_build_1(sm, data, id); - case PSK_3: - return eap_psk_build_3(sm, data, id); - default: - wpa_printf(MSG_DEBUG, "EAP-PSK: Unknown state %d in buildReq", - data->state); - break; - } - return NULL; -} - - -static Boolean eap_psk_check(struct eap_sm *sm, void *priv, - struct wpabuf *respData) -{ - struct eap_psk_data *data = priv; - size_t len; - u8 t; - const u8 *pos; - - pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_PSK, respData, &len); - if (pos == NULL || len < 1) { - wpa_printf(MSG_INFO, "EAP-PSK: Invalid frame"); - return TRUE; - } - t = EAP_PSK_FLAGS_GET_T(*pos); - - wpa_printf(MSG_DEBUG, "EAP-PSK: received frame: T=%d", t); - - if (data->state == PSK_1 && t != 1) { - wpa_printf(MSG_DEBUG, "EAP-PSK: Expected PSK-2 - " - "ignore T=%d", t); - return TRUE; - } - - if (data->state == PSK_3 && t != 3) { - wpa_printf(MSG_DEBUG, "EAP-PSK: Expected PSK-4 - " - "ignore T=%d", t); - return TRUE; - } - - if ((t == 1 && len < sizeof(struct eap_psk_hdr_2)) || - (t == 3 && len < sizeof(struct eap_psk_hdr_4))) { - wpa_printf(MSG_DEBUG, "EAP-PSK: Too short frame"); - return TRUE; - } - - return FALSE; -} - - -static void eap_psk_process_2(struct eap_sm *sm, - struct eap_psk_data *data, - struct wpabuf *respData) -{ - const struct eap_psk_hdr_2 *resp; - u8 *pos, mac[EAP_PSK_MAC_LEN], *buf; - size_t left, buflen; - int i; - const u8 *cpos; - - if (data->state != PSK_1) - return; - - wpa_printf(MSG_DEBUG, "EAP-PSK: Received PSK-2"); - - cpos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_PSK, respData, - &left); - if (cpos == NULL || left < sizeof(*resp)) { - wpa_printf(MSG_INFO, "EAP-PSK: Invalid frame"); - return; - } - resp = (const struct eap_psk_hdr_2 *) cpos; - cpos = (const u8 *) (resp + 1); - left -= sizeof(*resp); - - os_free(data->id_p); - data->id_p = os_malloc(left); - if (data->id_p == NULL) { - wpa_printf(MSG_INFO, "EAP-PSK: Failed to allocate memory for " - "ID_P"); - return; - } - os_memcpy(data->id_p, cpos, left); - data->id_p_len = left; - wpa_hexdump_ascii(MSG_MSGDUMP, "EAP-PSK: ID_P", - data->id_p, data->id_p_len); - - if (eap_user_get(sm, data->id_p, data->id_p_len, 0) < 0) { - wpa_hexdump_ascii(MSG_DEBUG, "EAP-PSK: unknown ID_P", - data->id_p, data->id_p_len); - data->state = FAILURE; - return; - } - - for (i = 0; - i < EAP_MAX_METHODS && - (sm->user->methods[i].vendor != EAP_VENDOR_IETF || - sm->user->methods[i].method != EAP_TYPE_NONE); - i++) { - if (sm->user->methods[i].vendor == EAP_VENDOR_IETF && - sm->user->methods[i].method == EAP_TYPE_PSK) - break; - } - - if (i >= EAP_MAX_METHODS || - sm->user->methods[i].vendor != EAP_VENDOR_IETF || - sm->user->methods[i].method != EAP_TYPE_PSK) { - wpa_hexdump_ascii(MSG_DEBUG, - "EAP-PSK: EAP-PSK not enabled for ID_P", - data->id_p, data->id_p_len); - data->state = FAILURE; - return; - } - - if (sm->user->password == NULL || - sm->user->password_len != EAP_PSK_PSK_LEN) { - wpa_hexdump_ascii(MSG_DEBUG, "EAP-PSK: invalid password in " - "user database for ID_P", - data->id_p, data->id_p_len); - data->state = FAILURE; - return; - } - if (eap_psk_key_setup(sm->user->password, data->ak, data->kdk)) { - data->state = FAILURE; - return; - } - wpa_hexdump_key(MSG_DEBUG, "EAP-PSK: AK", data->ak, EAP_PSK_AK_LEN); - wpa_hexdump_key(MSG_DEBUG, "EAP-PSK: KDK", data->kdk, EAP_PSK_KDK_LEN); - - wpa_hexdump(MSG_MSGDUMP, "EAP-PSK: RAND_P (client rand)", - resp->rand_p, EAP_PSK_RAND_LEN); - os_memcpy(data->rand_p, resp->rand_p, EAP_PSK_RAND_LEN); - - /* MAC_P = OMAC1-AES-128(AK, ID_P||ID_S||RAND_S||RAND_P) */ - buflen = data->id_p_len + data->id_s_len + 2 * EAP_PSK_RAND_LEN; - buf = os_malloc(buflen); - if (buf == NULL) { - data->state = FAILURE; - return; - } - os_memcpy(buf, data->id_p, data->id_p_len); - pos = buf + data->id_p_len; - os_memcpy(pos, data->id_s, data->id_s_len); - pos += data->id_s_len; - os_memcpy(pos, data->rand_s, EAP_PSK_RAND_LEN); - pos += EAP_PSK_RAND_LEN; - os_memcpy(pos, data->rand_p, EAP_PSK_RAND_LEN); - if (omac1_aes_128(data->ak, buf, buflen, mac)) { - os_free(buf); - data->state = FAILURE; - return; - } - os_free(buf); - wpa_hexdump(MSG_DEBUG, "EAP-PSK: MAC_P", resp->mac_p, EAP_PSK_MAC_LEN); - if (os_memcmp(mac, resp->mac_p, EAP_PSK_MAC_LEN) != 0) { - wpa_printf(MSG_INFO, "EAP-PSK: Invalid MAC_P"); - wpa_hexdump(MSG_MSGDUMP, "EAP-PSK: Expected MAC_P", - mac, EAP_PSK_MAC_LEN); - data->state = FAILURE; - return; - } - - data->state = PSK_3; -} - - -static void eap_psk_process_4(struct eap_sm *sm, - struct eap_psk_data *data, - struct wpabuf *respData) -{ - const struct eap_psk_hdr_4 *resp; - u8 *decrypted, nonce[16]; - size_t left; - const u8 *pos, *tag; - - if (data->state != PSK_3) - return; - - wpa_printf(MSG_DEBUG, "EAP-PSK: Received PSK-4"); - - pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_PSK, respData, &left); - if (pos == NULL || left < sizeof(*resp)) { - wpa_printf(MSG_INFO, "EAP-PSK: Invalid frame"); - return; - } - resp = (const struct eap_psk_hdr_4 *) pos; - pos = (const u8 *) (resp + 1); - left -= sizeof(*resp); - - wpa_hexdump(MSG_MSGDUMP, "EAP-PSK: Encrypted PCHANNEL", pos, left); - - if (left < 4 + 16 + 1) { - wpa_printf(MSG_INFO, "EAP-PSK: Too short PCHANNEL data in " - "PSK-4 (len=%lu, expected 21)", - (unsigned long) left); - return; - } - - if (pos[0] == 0 && pos[1] == 0 && pos[2] == 0 && pos[3] == 0) { - wpa_printf(MSG_DEBUG, "EAP-PSK: Nonce did not increase"); - return; - } - - os_memset(nonce, 0, 12); - os_memcpy(nonce + 12, pos, 4); - pos += 4; - left -= 4; - tag = pos; - pos += 16; - left -= 16; - - decrypted = os_malloc(left); - if (decrypted == NULL) - return; - os_memcpy(decrypted, pos, left); - - if (aes_128_eax_decrypt(data->tek, nonce, sizeof(nonce), - wpabuf_head(respData), 22, decrypted, left, - tag)) { - wpa_printf(MSG_WARNING, "EAP-PSK: PCHANNEL decryption failed"); - os_free(decrypted); - data->state = FAILURE; - return; - } - wpa_hexdump(MSG_DEBUG, "EAP-PSK: Decrypted PCHANNEL message", - decrypted, left); - - /* Verify R flag */ - switch (decrypted[0] >> 6) { - case EAP_PSK_R_FLAG_CONT: - wpa_printf(MSG_DEBUG, "EAP-PSK: R flag - CONT - unsupported"); - data->state = FAILURE; - break; - case EAP_PSK_R_FLAG_DONE_SUCCESS: - wpa_printf(MSG_DEBUG, "EAP-PSK: R flag - DONE_SUCCESS"); - data->state = SUCCESS; - break; - case EAP_PSK_R_FLAG_DONE_FAILURE: - wpa_printf(MSG_DEBUG, "EAP-PSK: R flag - DONE_FAILURE"); - data->state = FAILURE; - break; - } - os_free(decrypted); -} - - -static void eap_psk_process(struct eap_sm *sm, void *priv, - struct wpabuf *respData) -{ - struct eap_psk_data *data = priv; - const u8 *pos; - size_t len; - - if (sm->user == NULL || sm->user->password == NULL) { - wpa_printf(MSG_INFO, "EAP-PSK: Plaintext password not " - "configured"); - data->state = FAILURE; - return; - } - - pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_PSK, respData, &len); - if (pos == NULL || len < 1) - return; - - switch (EAP_PSK_FLAGS_GET_T(*pos)) { - case 1: - eap_psk_process_2(sm, data, respData); - break; - case 3: - eap_psk_process_4(sm, data, respData); - break; - } -} - - -static Boolean eap_psk_isDone(struct eap_sm *sm, void *priv) -{ - struct eap_psk_data *data = priv; - return data->state == SUCCESS || data->state == FAILURE; -} - - -static u8 * eap_psk_getKey(struct eap_sm *sm, void *priv, size_t *len) -{ - struct eap_psk_data *data = priv; - u8 *key; - - if (data->state != SUCCESS) - return NULL; - - key = os_malloc(EAP_MSK_LEN); - if (key == NULL) - return NULL; - os_memcpy(key, data->msk, EAP_MSK_LEN); - *len = EAP_MSK_LEN; - - return key; -} - - -static u8 * eap_psk_get_emsk(struct eap_sm *sm, void *priv, size_t *len) -{ - struct eap_psk_data *data = priv; - u8 *key; - - if (data->state != SUCCESS) - return NULL; - - key = os_malloc(EAP_EMSK_LEN); - if (key == NULL) - return NULL; - os_memcpy(key, data->emsk, EAP_EMSK_LEN); - *len = EAP_EMSK_LEN; - - return key; -} - - -static Boolean eap_psk_isSuccess(struct eap_sm *sm, void *priv) -{ - struct eap_psk_data *data = priv; - return data->state == SUCCESS; -} - - -int eap_server_psk_register(void) -{ - struct eap_method *eap; - int ret; - - eap = eap_server_method_alloc(EAP_SERVER_METHOD_INTERFACE_VERSION, - EAP_VENDOR_IETF, EAP_TYPE_PSK, "PSK"); - if (eap == NULL) - return -1; - - eap->init = eap_psk_init; - eap->reset = eap_psk_reset; - eap->buildReq = eap_psk_buildReq; - eap->check = eap_psk_check; - eap->process = eap_psk_process; - eap->isDone = eap_psk_isDone; - eap->getKey = eap_psk_getKey; - eap->isSuccess = eap_psk_isSuccess; - eap->get_emsk = eap_psk_get_emsk; - - ret = eap_server_method_register(eap); - if (ret) - eap_server_method_free(eap); - return ret; -} diff --git a/hostapd-0.8/src/eap_server/eap_server_pwd.c b/hostapd-0.8/src/eap_server/eap_server_pwd.c deleted file mode 100644 index dd2557a..0000000 --- a/hostapd-0.8/src/eap_server/eap_server_pwd.c +++ /dev/null @@ -1,844 +0,0 @@ -/* - * hostapd / EAP-pwd (RFC 5931) server - * Copyright (c) 2010, Dan Harkins - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the BSD license. - * - * Alternatively, this software may be distributed under the terms of the - * GNU General Public License version 2 as published by the Free Software - * Foundation. - * - * See README and COPYING for more details. - */ - -#include "includes.h" - -#include "common.h" -#include "eap_server/eap_i.h" -#include "eap_common/eap_pwd_common.h" - - -struct eap_pwd_data { - enum { - PWD_ID_Req, PWD_Commit_Req, PWD_Confirm_Req, SUCCESS, FAILURE - } state; - u8 *id_peer; - size_t id_peer_len; - u8 *id_server; - size_t id_server_len; - u8 *password; - size_t password_len; - u32 token; - u16 group_num; - EAP_PWD_group *grp; - - BIGNUM *k; - BIGNUM *private_value; - BIGNUM *peer_scalar; - BIGNUM *my_scalar; - EC_POINT *my_element; - EC_POINT *peer_element; - - u8 my_confirm[SHA256_DIGEST_LENGTH]; - - u8 msk[EAP_MSK_LEN]; - u8 emsk[EAP_EMSK_LEN]; - - BN_CTX *bnctx; -}; - - -static const char * eap_pwd_state_txt(int state) -{ - switch (state) { - case PWD_ID_Req: - return "PWD-ID-Req"; - case PWD_Commit_Req: - return "PWD-Commit-Req"; - case PWD_Confirm_Req: - return "PWD-Confirm-Req"; - case SUCCESS: - return "SUCCESS"; - case FAILURE: - return "FAILURE"; - default: - return "PWD-Unk"; - } -} - - -static void eap_pwd_state(struct eap_pwd_data *data, int state) -{ - wpa_printf(MSG_DEBUG, "EAP-pwd: %s -> %s", - eap_pwd_state_txt(data->state), eap_pwd_state_txt(state)); - data->state = state; -} - - -static void * eap_pwd_init(struct eap_sm *sm) -{ - struct eap_pwd_data *data; - - if (sm->user == NULL || sm->user->password == NULL || - sm->user->password_len == 0) { - wpa_printf(MSG_INFO, "EAP-PWD (server): Password is not " - "configured"); - return NULL; - } - - data = os_zalloc(sizeof(*data)); - if (data == NULL) - return NULL; - - data->group_num = sm->pwd_group; - wpa_printf(MSG_DEBUG, "EAP-pwd: Selected group number %d", - data->group_num); - data->state = PWD_ID_Req; - - data->id_server = (u8 *) os_strdup("server"); - if (data->id_server) - data->id_server_len = os_strlen((char *) data->id_server); - - data->password = os_malloc(sm->user->password_len); - if (data->password == NULL) { - wpa_printf(MSG_INFO, "EAP-PWD: Memory allocation password " - "fail"); - os_free(data->id_server); - os_free(data); - return NULL; - } - data->password_len = sm->user->password_len; - os_memcpy(data->password, sm->user->password, data->password_len); - - data->bnctx = BN_CTX_new(); - if (data->bnctx == NULL) { - wpa_printf(MSG_INFO, "EAP-PWD: bn context allocation fail"); - os_free(data->password); - os_free(data->id_server); - os_free(data); - return NULL; - } - - return data; -} - - -static void eap_pwd_reset(struct eap_sm *sm, void *priv) -{ - struct eap_pwd_data *data = priv; - - BN_free(data->private_value); - BN_free(data->peer_scalar); - BN_free(data->my_scalar); - BN_free(data->k); - BN_CTX_free(data->bnctx); - EC_POINT_free(data->my_element); - EC_POINT_free(data->peer_element); - os_free(data->id_peer); - os_free(data->id_server); - os_free(data->password); - if (data->grp) { - EC_GROUP_free(data->grp->group); - EC_POINT_free(data->grp->pwe); - BN_free(data->grp->order); - BN_free(data->grp->prime); - os_free(data->grp); - } - os_free(data); -} - - -static struct wpabuf * -eap_pwd_build_id_req(struct eap_sm *sm, struct eap_pwd_data *data, u8 id) -{ - struct wpabuf *req; - - wpa_printf(MSG_DEBUG, "EAP-pwd: ID/Request"); - req = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_PWD, - sizeof(struct eap_pwd_hdr) + - sizeof(struct eap_pwd_id) + data->id_server_len, - EAP_CODE_REQUEST, id); - if (req == NULL) { - eap_pwd_state(data, FAILURE); - return NULL; - } - - /* an lfsr is good enough to generate unpredictable tokens */ - data->token = os_random(); - wpabuf_put_u8(req, EAP_PWD_OPCODE_ID_EXCH); - wpabuf_put_be16(req, data->group_num); - wpabuf_put_u8(req, EAP_PWD_DEFAULT_RAND_FUNC); - wpabuf_put_u8(req, EAP_PWD_DEFAULT_PRF); - wpabuf_put_data(req, &data->token, sizeof(data->token)); - wpabuf_put_u8(req, EAP_PWD_PREP_NONE); - wpabuf_put_data(req, data->id_server, data->id_server_len); - - return req; -} - - -static struct wpabuf * -eap_pwd_build_commit_req(struct eap_sm *sm, struct eap_pwd_data *data, u8 id) -{ - struct wpabuf *req = NULL; - BIGNUM *mask = NULL, *x = NULL, *y = NULL; - u8 *scalar = NULL, *element = NULL; - u16 offset; - - wpa_printf(MSG_DEBUG, "EAP-pwd: Commit/Request"); - - if (((data->private_value = BN_new()) == NULL) || - ((data->my_element = EC_POINT_new(data->grp->group)) == NULL) || - ((data->my_scalar = BN_new()) == NULL) || - ((mask = BN_new()) == NULL)) { - wpa_printf(MSG_INFO, "EAP-PWD (server): scalar allocation " - "fail"); - goto fin; - } - - BN_rand_range(data->private_value, data->grp->order); - BN_rand_range(mask, data->grp->order); - BN_add(data->my_scalar, data->private_value, mask); - BN_mod(data->my_scalar, data->my_scalar, data->grp->order, - data->bnctx); - - if (!EC_POINT_mul(data->grp->group, data->my_element, NULL, - data->grp->pwe, mask, data->bnctx)) { - wpa_printf(MSG_INFO, "EAP-PWD (server): element allocation " - "fail"); - eap_pwd_state(data, FAILURE); - goto fin; - } - - if (!EC_POINT_invert(data->grp->group, data->my_element, data->bnctx)) - { - wpa_printf(MSG_INFO, "EAP-PWD (server): element inversion " - "fail"); - goto fin; - } - BN_free(mask); - - if (((x = BN_new()) == NULL) || - ((y = BN_new()) == NULL)) { - wpa_printf(MSG_INFO, "EAP-PWD (server): point allocation " - "fail"); - goto fin; - } - if (!EC_POINT_get_affine_coordinates_GFp(data->grp->group, - data->my_element, x, y, - data->bnctx)) { - wpa_printf(MSG_INFO, "EAP-PWD (server): point assignment " - "fail"); - goto fin; - } - - if (((scalar = os_malloc(BN_num_bytes(data->grp->order))) == NULL) || - ((element = os_malloc(BN_num_bytes(data->grp->prime) * 2)) == - NULL)) { - wpa_printf(MSG_INFO, "EAP-PWD (server): data allocation fail"); - goto fin; - } - - /* - * bignums occupy as little memory as possible so one that is - * sufficiently smaller than the prime or order might need pre-pending - * with zeros. - */ - os_memset(scalar, 0, BN_num_bytes(data->grp->order)); - os_memset(element, 0, BN_num_bytes(data->grp->prime) * 2); - offset = BN_num_bytes(data->grp->order) - - BN_num_bytes(data->my_scalar); - BN_bn2bin(data->my_scalar, scalar + offset); - - offset = BN_num_bytes(data->grp->prime) - BN_num_bytes(x); - BN_bn2bin(x, element + offset); - offset = BN_num_bytes(data->grp->prime) - BN_num_bytes(y); - BN_bn2bin(y, element + BN_num_bytes(data->grp->prime) + offset); - - req = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_PWD, - sizeof(struct eap_pwd_hdr) + - (2 * BN_num_bytes(data->grp->prime)) + - BN_num_bytes(data->grp->order), - EAP_CODE_REQUEST, id); - if (req == NULL) - goto fin; - wpabuf_put_u8(req, EAP_PWD_OPCODE_COMMIT_EXCH); - - /* We send the element as (x,y) followed by the scalar */ - wpabuf_put_data(req, element, (2 * BN_num_bytes(data->grp->prime))); - wpabuf_put_data(req, scalar, BN_num_bytes(data->grp->order)); - -fin: - os_free(scalar); - os_free(element); - BN_free(x); - BN_free(y); - if (req == NULL) - eap_pwd_state(data, FAILURE); - - return req; -} - - -static struct wpabuf * -eap_pwd_build_confirm_req(struct eap_sm *sm, struct eap_pwd_data *data, u8 id) -{ - struct wpabuf *req = NULL; - BIGNUM *x = NULL, *y = NULL; - HMAC_CTX ctx; - u8 conf[SHA256_DIGEST_LENGTH], *cruft = NULL, *ptr; - u16 grp; - - wpa_printf(MSG_DEBUG, "EAP-pwd: Confirm/Request"); - - /* Each component of the cruft will be at most as big as the prime */ - if (((cruft = os_malloc(BN_num_bytes(data->grp->prime))) == NULL) || - ((x = BN_new()) == NULL) || ((y = BN_new()) == NULL)) { - wpa_printf(MSG_INFO, "EAP-PWD (server): debug allocation " - "fail"); - goto fin; - } - - /* - * commit is H(k | server_element | server_scalar | peer_element | - * peer_scalar | ciphersuite) - */ - H_Init(&ctx); - - /* - * Zero the memory each time because this is mod prime math and some - * value may start with a few zeros and the previous one did not. - * - * First is k - */ - os_memset(cruft, 0, BN_num_bytes(data->grp->prime)); - BN_bn2bin(data->k, cruft); - H_Update(&ctx, cruft, BN_num_bytes(data->grp->prime)); - - /* server element: x, y */ - if (!EC_POINT_get_affine_coordinates_GFp(data->grp->group, - data->my_element, x, y, - data->bnctx)) { - wpa_printf(MSG_INFO, "EAP-PWD (server): confirm point " - "assignment fail"); - goto fin; - } - - os_memset(cruft, 0, BN_num_bytes(data->grp->prime)); - BN_bn2bin(x, cruft); - H_Update(&ctx, cruft, BN_num_bytes(data->grp->prime)); - os_memset(cruft, 0, BN_num_bytes(data->grp->prime)); - BN_bn2bin(y, cruft); - H_Update(&ctx, cruft, BN_num_bytes(data->grp->prime)); - - /* server scalar */ - os_memset(cruft, 0, BN_num_bytes(data->grp->prime)); - BN_bn2bin(data->my_scalar, cruft); - H_Update(&ctx, cruft, BN_num_bytes(data->grp->order)); - - /* peer element: x, y */ - if (!EC_POINT_get_affine_coordinates_GFp(data->grp->group, - data->peer_element, x, y, - data->bnctx)) { - wpa_printf(MSG_INFO, "EAP-PWD (server): confirm point " - "assignment fail"); - goto fin; - } - - os_memset(cruft, 0, BN_num_bytes(data->grp->prime)); - BN_bn2bin(x, cruft); - H_Update(&ctx, cruft, BN_num_bytes(data->grp->prime)); - os_memset(cruft, 0, BN_num_bytes(data->grp->prime)); - BN_bn2bin(y, cruft); - H_Update(&ctx, cruft, BN_num_bytes(data->grp->prime)); - - /* peer scalar */ - os_memset(cruft, 0, BN_num_bytes(data->grp->prime)); - BN_bn2bin(data->peer_scalar, cruft); - H_Update(&ctx, cruft, BN_num_bytes(data->grp->order)); - - /* ciphersuite */ - grp = htons(data->group_num); - os_memset(cruft, 0, BN_num_bytes(data->grp->prime)); - ptr = cruft; - os_memcpy(ptr, &grp, sizeof(u16)); - ptr += sizeof(u16); - *ptr = EAP_PWD_DEFAULT_RAND_FUNC; - ptr += sizeof(u8); - *ptr = EAP_PWD_DEFAULT_PRF; - ptr += sizeof(u8); - H_Update(&ctx, cruft, ptr-cruft); - - /* all done with the random function */ - H_Final(&ctx, conf); - os_memcpy(data->my_confirm, conf, SHA256_DIGEST_LENGTH); - - req = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_PWD, - sizeof(struct eap_pwd_hdr) + SHA256_DIGEST_LENGTH, - EAP_CODE_REQUEST, id); - if (req == NULL) - goto fin; - - wpabuf_put_u8(req, EAP_PWD_OPCODE_CONFIRM_EXCH); - wpabuf_put_data(req, conf, SHA256_DIGEST_LENGTH); - -fin: - os_free(cruft); - BN_free(x); - BN_free(y); - if (req == NULL) - eap_pwd_state(data, FAILURE); - - return req; -} - - -static struct wpabuf * -eap_pwd_build_req(struct eap_sm *sm, void *priv, u8 id) -{ - struct eap_pwd_data *data = priv; - - switch (data->state) { - case PWD_ID_Req: - return eap_pwd_build_id_req(sm, data, id); - case PWD_Commit_Req: - return eap_pwd_build_commit_req(sm, data, id); - case PWD_Confirm_Req: - return eap_pwd_build_confirm_req(sm, data, id); - default: - wpa_printf(MSG_INFO, "EAP-pwd: Unknown state %d in build_req", - data->state); - break; - } - - return NULL; -} - - -static Boolean eap_pwd_check(struct eap_sm *sm, void *priv, - struct wpabuf *respData) -{ - struct eap_pwd_data *data = priv; - const u8 *pos; - size_t len; - - pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_PWD, respData, &len); - if (pos == NULL || len < 1) { - wpa_printf(MSG_INFO, "EAP-pwd: Invalid frame"); - return TRUE; - } - - wpa_printf(MSG_DEBUG, "EAP-pwd: Received frame: opcode=%d", *pos); - - if (data->state == PWD_ID_Req && *pos == EAP_PWD_OPCODE_ID_EXCH) - return FALSE; - - if (data->state == PWD_Commit_Req && - *pos == EAP_PWD_OPCODE_COMMIT_EXCH) - return FALSE; - - if (data->state == PWD_Confirm_Req && - *pos == EAP_PWD_OPCODE_CONFIRM_EXCH) - return FALSE; - - wpa_printf(MSG_INFO, "EAP-pwd: Unexpected opcode=%d in state=%d", - *pos, data->state); - - return TRUE; -} - - -static void eap_pwd_process_id_resp(struct eap_sm *sm, - struct eap_pwd_data *data, - const u8 *payload, size_t payload_len) -{ - struct eap_pwd_id *id; - - if (payload_len < sizeof(struct eap_pwd_id)) { - wpa_printf(MSG_INFO, "EAP-pwd: Invalid ID response"); - return; - } - - id = (struct eap_pwd_id *) payload; - if ((data->group_num != be_to_host16(id->group_num)) || - (id->random_function != EAP_PWD_DEFAULT_RAND_FUNC) || - (os_memcmp(id->token, (u8 *)&data->token, sizeof(data->token))) || - (id->prf != EAP_PWD_DEFAULT_PRF)) { - wpa_printf(MSG_INFO, "EAP-pwd: peer changed parameters"); - eap_pwd_state(data, FAILURE); - return; - } - data->id_peer = os_malloc(payload_len - sizeof(struct eap_pwd_id)); - if (data->id_peer == NULL) { - wpa_printf(MSG_INFO, "EAP-PWD: memory allocation id fail"); - return; - } - data->id_peer_len = payload_len - sizeof(struct eap_pwd_id); - os_memcpy(data->id_peer, id->identity, data->id_peer_len); - wpa_hexdump_ascii(MSG_DEBUG, "EAP-PWD (server): peer sent id of", - data->id_peer, data->id_peer_len); - - if ((data->grp = os_malloc(sizeof(EAP_PWD_group))) == NULL) { - wpa_printf(MSG_INFO, "EAP-PWD: failed to allocate memory for " - "group"); - return; - } - if (compute_password_element(data->grp, data->group_num, - data->password, data->password_len, - data->id_server, data->id_server_len, - data->id_peer, data->id_peer_len, - (u8 *) &data->token)) { - wpa_printf(MSG_INFO, "EAP-PWD (server): unable to compute " - "PWE"); - return; - } - wpa_printf(MSG_DEBUG, "EAP-PWD (server): computed %d bit PWE...", - BN_num_bits(data->grp->prime)); - - eap_pwd_state(data, PWD_Commit_Req); -} - - -static void -eap_pwd_process_commit_resp(struct eap_sm *sm, struct eap_pwd_data *data, - const u8 *payload, size_t payload_len) -{ - u8 *ptr; - BIGNUM *x = NULL, *y = NULL, *cofactor = NULL; - EC_POINT *K = NULL, *point = NULL; - int res = 0; - - wpa_printf(MSG_DEBUG, "EAP-pwd: Received commit response"); - - if (((data->peer_scalar = BN_new()) == NULL) || - ((data->k = BN_new()) == NULL) || - ((cofactor = BN_new()) == NULL) || - ((x = BN_new()) == NULL) || - ((y = BN_new()) == NULL) || - ((point = EC_POINT_new(data->grp->group)) == NULL) || - ((K = EC_POINT_new(data->grp->group)) == NULL) || - ((data->peer_element = EC_POINT_new(data->grp->group)) == NULL)) { - wpa_printf(MSG_INFO, "EAP-PWD (server): peer data allocation " - "fail"); - goto fin; - } - - if (!EC_GROUP_get_cofactor(data->grp->group, cofactor, NULL)) { - wpa_printf(MSG_INFO, "EAP-PWD (server): unable to get " - "cofactor for curve"); - goto fin; - } - - /* element, x then y, followed by scalar */ - ptr = (u8 *) payload; - BN_bin2bn(ptr, BN_num_bytes(data->grp->prime), x); - ptr += BN_num_bytes(data->grp->prime); - BN_bin2bn(ptr, BN_num_bytes(data->grp->prime), y); - ptr += BN_num_bytes(data->grp->prime); - BN_bin2bn(ptr, BN_num_bytes(data->grp->order), data->peer_scalar); - if (!EC_POINT_set_affine_coordinates_GFp(data->grp->group, - data->peer_element, x, y, - data->bnctx)) { - wpa_printf(MSG_INFO, "EAP-PWD (server): setting peer element " - "fail"); - goto fin; - } - - /* check to ensure peer's element is not in a small sub-group */ - if (BN_cmp(cofactor, BN_value_one())) { - if (!EC_POINT_mul(data->grp->group, point, NULL, - data->peer_element, cofactor, NULL)) { - wpa_printf(MSG_INFO, "EAP-PWD (server): cannot " - "multiply peer element by order"); - goto fin; - } - if (EC_POINT_is_at_infinity(data->grp->group, point)) { - wpa_printf(MSG_INFO, "EAP-PWD (server): peer element " - "is at infinity!\n"); - goto fin; - } - } - - /* compute the shared key, k */ - if ((!EC_POINT_mul(data->grp->group, K, NULL, data->grp->pwe, - data->peer_scalar, data->bnctx)) || - (!EC_POINT_add(data->grp->group, K, K, data->peer_element, - data->bnctx)) || - (!EC_POINT_mul(data->grp->group, K, NULL, K, data->private_value, - data->bnctx))) { - wpa_printf(MSG_INFO, "EAP-PWD (server): computing shared key " - "fail"); - goto fin; - } - - /* ensure that the shared key isn't in a small sub-group */ - if (BN_cmp(cofactor, BN_value_one())) { - if (!EC_POINT_mul(data->grp->group, K, NULL, K, cofactor, - NULL)) { - wpa_printf(MSG_INFO, "EAP-PWD (server): cannot " - "multiply shared key point by order!\n"); - goto fin; - } - } - - /* - * This check is strictly speaking just for the case above where - * co-factor > 1 but it was suggested that even though this is probably - * never going to happen it is a simple and safe check "just to be - * sure" so let's be safe. - */ - if (EC_POINT_is_at_infinity(data->grp->group, K)) { - wpa_printf(MSG_INFO, "EAP-PWD (server): shared key point is " - "at infinity"); - goto fin; - } - if (!EC_POINT_get_affine_coordinates_GFp(data->grp->group, K, data->k, - NULL, data->bnctx)) { - wpa_printf(MSG_INFO, "EAP-PWD (server): unable to extract " - "shared secret from secret point"); - goto fin; - } - res = 1; - -fin: - EC_POINT_free(K); - EC_POINT_free(point); - BN_free(cofactor); - BN_free(x); - BN_free(y); - - if (res) - eap_pwd_state(data, PWD_Confirm_Req); - else - eap_pwd_state(data, FAILURE); -} - - -static void -eap_pwd_process_confirm_resp(struct eap_sm *sm, struct eap_pwd_data *data, - const u8 *payload, size_t payload_len) -{ - BIGNUM *x = NULL, *y = NULL; - HMAC_CTX ctx; - u32 cs; - u16 grp; - u8 conf[SHA256_DIGEST_LENGTH], *cruft = NULL, *ptr; - - /* build up the ciphersuite: group | random_function | prf */ - grp = htons(data->group_num); - ptr = (u8 *) &cs; - os_memcpy(ptr, &grp, sizeof(u16)); - ptr += sizeof(u16); - *ptr = EAP_PWD_DEFAULT_RAND_FUNC; - ptr += sizeof(u8); - *ptr = EAP_PWD_DEFAULT_PRF; - - /* each component of the cruft will be at most as big as the prime */ - if (((cruft = os_malloc(BN_num_bytes(data->grp->prime))) == NULL) || - ((x = BN_new()) == NULL) || ((y = BN_new()) == NULL)) { - wpa_printf(MSG_INFO, "EAP-PWD (peer): allocation fail"); - goto fin; - } - - /* - * commit is H(k | peer_element | peer_scalar | server_element | - * server_scalar | ciphersuite) - */ - H_Init(&ctx); - - /* k */ - os_memset(cruft, 0, BN_num_bytes(data->grp->prime)); - BN_bn2bin(data->k, cruft); - H_Update(&ctx, cruft, BN_num_bytes(data->grp->prime)); - - /* peer element: x, y */ - if (!EC_POINT_get_affine_coordinates_GFp(data->grp->group, - data->peer_element, x, y, - data->bnctx)) { - wpa_printf(MSG_INFO, "EAP-PWD (server): confirm point " - "assignment fail"); - goto fin; - } - os_memset(cruft, 0, BN_num_bytes(data->grp->prime)); - BN_bn2bin(x, cruft); - H_Update(&ctx, cruft, BN_num_bytes(data->grp->prime)); - os_memset(cruft, 0, BN_num_bytes(data->grp->prime)); - BN_bn2bin(y, cruft); - H_Update(&ctx, cruft, BN_num_bytes(data->grp->prime)); - - /* peer scalar */ - os_memset(cruft, 0, BN_num_bytes(data->grp->prime)); - BN_bn2bin(data->peer_scalar, cruft); - H_Update(&ctx, cruft, BN_num_bytes(data->grp->order)); - - /* server element: x, y */ - if (!EC_POINT_get_affine_coordinates_GFp(data->grp->group, - data->my_element, x, y, - data->bnctx)) { - wpa_printf(MSG_INFO, "EAP-PWD (server): confirm point " - "assignment fail"); - goto fin; - } - - os_memset(cruft, 0, BN_num_bytes(data->grp->prime)); - BN_bn2bin(x, cruft); - H_Update(&ctx, cruft, BN_num_bytes(data->grp->prime)); - os_memset(cruft, 0, BN_num_bytes(data->grp->prime)); - BN_bn2bin(y, cruft); - H_Update(&ctx, cruft, BN_num_bytes(data->grp->prime)); - - /* server scalar */ - os_memset(cruft, 0, BN_num_bytes(data->grp->prime)); - BN_bn2bin(data->my_scalar, cruft); - H_Update(&ctx, cruft, BN_num_bytes(data->grp->order)); - - /* ciphersuite */ - os_memset(cruft, 0, BN_num_bytes(data->grp->prime)); - H_Update(&ctx, (u8 *)&cs, sizeof(u32)); - - /* all done */ - H_Final(&ctx, conf); - - ptr = (u8 *) payload; - if (os_memcmp(conf, ptr, SHA256_DIGEST_LENGTH)) { - wpa_printf(MSG_INFO, "EAP-PWD (server): confirm did not " - "verify"); - goto fin; - } - - wpa_printf(MSG_DEBUG, "EAP-pwd (server): confirm verified"); - if (compute_keys(data->grp, data->bnctx, data->k, - data->peer_scalar, data->my_scalar, conf, - data->my_confirm, &cs, data->msk, data->emsk) < 0) - eap_pwd_state(data, FAILURE); - else - eap_pwd_state(data, SUCCESS); - -fin: - os_free(cruft); - BN_free(x); - BN_free(y); -} - - -static void eap_pwd_process(struct eap_sm *sm, void *priv, - struct wpabuf *respData) -{ - struct eap_pwd_data *data = priv; - const u8 *pos; - size_t len; - u8 exch; - - pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_PWD, respData, &len); - if ((pos == NULL) || (len < 1)) { - wpa_printf(MSG_INFO, "Bad EAP header! pos %s and len = %d", - (pos == NULL) ? "is NULL" : "is not NULL", - (int) len); - return; - } - - exch = *pos & 0x3f; - switch (exch) { - case EAP_PWD_OPCODE_ID_EXCH: - eap_pwd_process_id_resp(sm, data, pos + 1, len - 1); - break; - case EAP_PWD_OPCODE_COMMIT_EXCH: - eap_pwd_process_commit_resp(sm, data, pos + 1, len - 1); - break; - case EAP_PWD_OPCODE_CONFIRM_EXCH: - eap_pwd_process_confirm_resp(sm, data, pos + 1, len - 1); - break; - } -} - - -static u8 * eap_pwd_getkey(struct eap_sm *sm, void *priv, size_t *len) -{ - struct eap_pwd_data *data = priv; - u8 *key; - - if (data->state != SUCCESS) - return NULL; - - key = os_malloc(EAP_MSK_LEN); - if (key == NULL) - return NULL; - - os_memcpy(key, data->msk, EAP_MSK_LEN); - *len = EAP_MSK_LEN; - - return key; -} - - -static u8 * eap_pwd_get_emsk(struct eap_sm *sm, void *priv, size_t *len) -{ - struct eap_pwd_data *data = priv; - u8 *key; - - if (data->state != SUCCESS) - return NULL; - - key = os_malloc(EAP_EMSK_LEN); - if (key == NULL) - return NULL; - - os_memcpy(key, data->emsk, EAP_EMSK_LEN); - *len = EAP_EMSK_LEN; - - return key; -} - - -static Boolean eap_pwd_is_success(struct eap_sm *sm, void *priv) -{ - struct eap_pwd_data *data = priv; - return data->state == SUCCESS; -} - - -static Boolean eap_pwd_is_done(struct eap_sm *sm, void *priv) -{ - struct eap_pwd_data *data = priv; - return (data->state == SUCCESS) || (data->state == FAILURE); -} - - -int eap_server_pwd_register(void) -{ - struct eap_method *eap; - int ret; - struct timeval tp; - struct timezone tz; - u32 sr; - - EVP_add_digest(EVP_sha256()); - - sr = 0xdeaddada; - (void) gettimeofday(&tp, &tz); - sr ^= (tp.tv_sec ^ tp.tv_usec); - srandom(sr); - - eap = eap_server_method_alloc(EAP_SERVER_METHOD_INTERFACE_VERSION, - EAP_VENDOR_IETF, EAP_TYPE_PWD, - "PWD"); - if (eap == NULL) - return -1; - - eap->init = eap_pwd_init; - eap->reset = eap_pwd_reset; - eap->buildReq = eap_pwd_build_req; - eap->check = eap_pwd_check; - eap->process = eap_pwd_process; - eap->isDone = eap_pwd_is_done; - eap->getKey = eap_pwd_getkey; - eap->get_emsk = eap_pwd_get_emsk; - eap->isSuccess = eap_pwd_is_success; - - ret = eap_server_method_register(eap); - if (ret) - eap_server_method_free(eap); - return ret; -} - diff --git a/hostapd-0.8/src/eap_server/eap_server_sake.c b/hostapd-0.8/src/eap_server/eap_server_sake.c deleted file mode 100644 index a9b515f..0000000 --- a/hostapd-0.8/src/eap_server/eap_server_sake.c +++ /dev/null @@ -1,543 +0,0 @@ -/* - * hostapd / EAP-SAKE (RFC 4763) server - * Copyright (c) 2006-2007, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#include "includes.h" - -#include "common.h" -#include "crypto/random.h" -#include "eap_server/eap_i.h" -#include "eap_common/eap_sake_common.h" - - -struct eap_sake_data { - enum { IDENTITY, CHALLENGE, CONFIRM, SUCCESS, FAILURE } state; - u8 rand_s[EAP_SAKE_RAND_LEN]; - u8 rand_p[EAP_SAKE_RAND_LEN]; - struct { - u8 auth[EAP_SAKE_TEK_AUTH_LEN]; - u8 cipher[EAP_SAKE_TEK_CIPHER_LEN]; - } tek; - u8 msk[EAP_MSK_LEN]; - u8 emsk[EAP_EMSK_LEN]; - u8 session_id; - u8 *peerid; - size_t peerid_len; - u8 *serverid; - size_t serverid_len; -}; - - -static const char * eap_sake_state_txt(int state) -{ - switch (state) { - case IDENTITY: - return "IDENTITY"; - case CHALLENGE: - return "CHALLENGE"; - case CONFIRM: - return "CONFIRM"; - case SUCCESS: - return "SUCCESS"; - case FAILURE: - return "FAILURE"; - default: - return "?"; - } -} - - -static void eap_sake_state(struct eap_sake_data *data, int state) -{ - wpa_printf(MSG_DEBUG, "EAP-SAKE: %s -> %s", - eap_sake_state_txt(data->state), - eap_sake_state_txt(state)); - data->state = state; -} - - -static void * eap_sake_init(struct eap_sm *sm) -{ - struct eap_sake_data *data; - - data = os_zalloc(sizeof(*data)); - if (data == NULL) - return NULL; - data->state = CHALLENGE; - - if (os_get_random(&data->session_id, 1)) { - wpa_printf(MSG_ERROR, "EAP-SAKE: Failed to get random data"); - os_free(data); - return NULL; - } - wpa_printf(MSG_DEBUG, "EAP-SAKE: Initialized Session ID %d", - data->session_id); - - /* TODO: add support for configuring SERVERID */ - data->serverid = (u8 *) os_strdup("hostapd"); - if (data->serverid) - data->serverid_len = os_strlen((char *) data->serverid); - - return data; -} - - -static void eap_sake_reset(struct eap_sm *sm, void *priv) -{ - struct eap_sake_data *data = priv; - os_free(data->serverid); - os_free(data->peerid); - os_free(data); -} - - -static struct wpabuf * eap_sake_build_msg(struct eap_sake_data *data, - u8 id, size_t length, u8 subtype) -{ - struct eap_sake_hdr *sake; - struct wpabuf *msg; - size_t plen; - - plen = sizeof(struct eap_sake_hdr) + length; - - msg = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_SAKE, plen, - EAP_CODE_REQUEST, id); - if (msg == NULL) { - wpa_printf(MSG_ERROR, "EAP-SAKE: Failed to allocate memory " - "request"); - return NULL; - } - - sake = wpabuf_put(msg, sizeof(*sake)); - sake->version = EAP_SAKE_VERSION; - sake->session_id = data->session_id; - sake->subtype = subtype; - - return msg; -} - - -static struct wpabuf * eap_sake_build_identity(struct eap_sm *sm, - struct eap_sake_data *data, - u8 id) -{ - struct wpabuf *msg; - size_t plen; - - wpa_printf(MSG_DEBUG, "EAP-SAKE: Request/Identity"); - - plen = 4; - if (data->serverid) - plen += 2 + data->serverid_len; - msg = eap_sake_build_msg(data, id, plen, EAP_SAKE_SUBTYPE_IDENTITY); - if (msg == NULL) { - data->state = FAILURE; - return NULL; - } - - wpa_printf(MSG_DEBUG, "EAP-SAKE: * AT_PERM_ID_REQ"); - eap_sake_add_attr(msg, EAP_SAKE_AT_PERM_ID_REQ, NULL, 2); - - if (data->serverid) { - wpa_printf(MSG_DEBUG, "EAP-SAKE: * AT_SERVERID"); - eap_sake_add_attr(msg, EAP_SAKE_AT_SERVERID, - data->serverid, data->serverid_len); - } - - return msg; -} - - -static struct wpabuf * eap_sake_build_challenge(struct eap_sm *sm, - struct eap_sake_data *data, - u8 id) -{ - struct wpabuf *msg; - size_t plen; - - wpa_printf(MSG_DEBUG, "EAP-SAKE: Request/Challenge"); - - if (random_get_bytes(data->rand_s, EAP_SAKE_RAND_LEN)) { - wpa_printf(MSG_ERROR, "EAP-SAKE: Failed to get random data"); - data->state = FAILURE; - return NULL; - } - wpa_hexdump(MSG_MSGDUMP, "EAP-SAKE: RAND_S (server rand)", - data->rand_s, EAP_SAKE_RAND_LEN); - - plen = 2 + EAP_SAKE_RAND_LEN; - if (data->serverid) - plen += 2 + data->serverid_len; - msg = eap_sake_build_msg(data, id, plen, EAP_SAKE_SUBTYPE_CHALLENGE); - if (msg == NULL) { - data->state = FAILURE; - return NULL; - } - - wpa_printf(MSG_DEBUG, "EAP-SAKE: * AT_RAND_S"); - eap_sake_add_attr(msg, EAP_SAKE_AT_RAND_S, - data->rand_s, EAP_SAKE_RAND_LEN); - - if (data->serverid) { - wpa_printf(MSG_DEBUG, "EAP-SAKE: * AT_SERVERID"); - eap_sake_add_attr(msg, EAP_SAKE_AT_SERVERID, - data->serverid, data->serverid_len); - } - - return msg; -} - - -static struct wpabuf * eap_sake_build_confirm(struct eap_sm *sm, - struct eap_sake_data *data, - u8 id) -{ - struct wpabuf *msg; - u8 *mic; - - wpa_printf(MSG_DEBUG, "EAP-SAKE: Request/Confirm"); - - msg = eap_sake_build_msg(data, id, 2 + EAP_SAKE_MIC_LEN, - EAP_SAKE_SUBTYPE_CONFIRM); - if (msg == NULL) { - data->state = FAILURE; - return NULL; - } - - wpa_printf(MSG_DEBUG, "EAP-SAKE: * AT_MIC_S"); - wpabuf_put_u8(msg, EAP_SAKE_AT_MIC_S); - wpabuf_put_u8(msg, 2 + EAP_SAKE_MIC_LEN); - mic = wpabuf_put(msg, EAP_SAKE_MIC_LEN); - if (eap_sake_compute_mic(data->tek.auth, data->rand_s, data->rand_p, - data->serverid, data->serverid_len, - data->peerid, data->peerid_len, 0, - wpabuf_head(msg), wpabuf_len(msg), mic, mic)) - { - wpa_printf(MSG_INFO, "EAP-SAKE: Failed to compute MIC"); - data->state = FAILURE; - os_free(msg); - return NULL; - } - - return msg; -} - - -static struct wpabuf * eap_sake_buildReq(struct eap_sm *sm, void *priv, u8 id) -{ - struct eap_sake_data *data = priv; - - switch (data->state) { - case IDENTITY: - return eap_sake_build_identity(sm, data, id); - case CHALLENGE: - return eap_sake_build_challenge(sm, data, id); - case CONFIRM: - return eap_sake_build_confirm(sm, data, id); - default: - wpa_printf(MSG_DEBUG, "EAP-SAKE: Unknown state %d in buildReq", - data->state); - break; - } - return NULL; -} - - -static Boolean eap_sake_check(struct eap_sm *sm, void *priv, - struct wpabuf *respData) -{ - struct eap_sake_data *data = priv; - struct eap_sake_hdr *resp; - size_t len; - u8 version, session_id, subtype; - const u8 *pos; - - pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_SAKE, respData, &len); - if (pos == NULL || len < sizeof(struct eap_sake_hdr)) { - wpa_printf(MSG_INFO, "EAP-SAKE: Invalid frame"); - return TRUE; - } - - resp = (struct eap_sake_hdr *) pos; - version = resp->version; - session_id = resp->session_id; - subtype = resp->subtype; - - if (version != EAP_SAKE_VERSION) { - wpa_printf(MSG_INFO, "EAP-SAKE: Unknown version %d", version); - return TRUE; - } - - if (session_id != data->session_id) { - wpa_printf(MSG_INFO, "EAP-SAKE: Session ID mismatch (%d,%d)", - session_id, data->session_id); - return TRUE; - } - - wpa_printf(MSG_DEBUG, "EAP-SAKE: Received frame: subtype=%d", subtype); - - if (data->state == IDENTITY && subtype == EAP_SAKE_SUBTYPE_IDENTITY) - return FALSE; - - if (data->state == CHALLENGE && subtype == EAP_SAKE_SUBTYPE_CHALLENGE) - return FALSE; - - if (data->state == CONFIRM && subtype == EAP_SAKE_SUBTYPE_CONFIRM) - return FALSE; - - if (subtype == EAP_SAKE_SUBTYPE_AUTH_REJECT) - return FALSE; - - wpa_printf(MSG_INFO, "EAP-SAKE: Unexpected subtype=%d in state=%d", - subtype, data->state); - - return TRUE; -} - - -static void eap_sake_process_identity(struct eap_sm *sm, - struct eap_sake_data *data, - const struct wpabuf *respData, - const u8 *payload, size_t payloadlen) -{ - if (data->state != IDENTITY) - return; - - wpa_printf(MSG_DEBUG, "EAP-SAKE: Received Response/Identity"); - /* TODO: update identity and select new user data */ - eap_sake_state(data, CHALLENGE); -} - - -static void eap_sake_process_challenge(struct eap_sm *sm, - struct eap_sake_data *data, - const struct wpabuf *respData, - const u8 *payload, size_t payloadlen) -{ - struct eap_sake_parse_attr attr; - u8 mic_p[EAP_SAKE_MIC_LEN]; - - if (data->state != CHALLENGE) - return; - - wpa_printf(MSG_DEBUG, "EAP-SAKE: Received Response/Challenge"); - - if (eap_sake_parse_attributes(payload, payloadlen, &attr)) - return; - - if (!attr.rand_p || !attr.mic_p) { - wpa_printf(MSG_INFO, "EAP-SAKE: Response/Challenge did not " - "include AT_RAND_P or AT_MIC_P"); - return; - } - - os_memcpy(data->rand_p, attr.rand_p, EAP_SAKE_RAND_LEN); - - os_free(data->peerid); - data->peerid = NULL; - data->peerid_len = 0; - if (attr.peerid) { - data->peerid = os_malloc(attr.peerid_len); - if (data->peerid == NULL) - return; - os_memcpy(data->peerid, attr.peerid, attr.peerid_len); - data->peerid_len = attr.peerid_len; - } - - if (sm->user == NULL || sm->user->password == NULL || - sm->user->password_len != 2 * EAP_SAKE_ROOT_SECRET_LEN) { - wpa_printf(MSG_INFO, "EAP-SAKE: Plaintext password with " - "%d-byte key not configured", - 2 * EAP_SAKE_ROOT_SECRET_LEN); - data->state = FAILURE; - return; - } - eap_sake_derive_keys(sm->user->password, - sm->user->password + EAP_SAKE_ROOT_SECRET_LEN, - data->rand_s, data->rand_p, - (u8 *) &data->tek, data->msk, data->emsk); - - eap_sake_compute_mic(data->tek.auth, data->rand_s, data->rand_p, - data->serverid, data->serverid_len, - data->peerid, data->peerid_len, 1, - wpabuf_head(respData), wpabuf_len(respData), - attr.mic_p, mic_p); - if (os_memcmp(attr.mic_p, mic_p, EAP_SAKE_MIC_LEN) != 0) { - wpa_printf(MSG_INFO, "EAP-SAKE: Incorrect AT_MIC_P"); - eap_sake_state(data, FAILURE); - return; - } - - eap_sake_state(data, CONFIRM); -} - - -static void eap_sake_process_confirm(struct eap_sm *sm, - struct eap_sake_data *data, - const struct wpabuf *respData, - const u8 *payload, size_t payloadlen) -{ - struct eap_sake_parse_attr attr; - u8 mic_p[EAP_SAKE_MIC_LEN]; - - if (data->state != CONFIRM) - return; - - wpa_printf(MSG_DEBUG, "EAP-SAKE: Received Response/Confirm"); - - if (eap_sake_parse_attributes(payload, payloadlen, &attr)) - return; - - if (!attr.mic_p) { - wpa_printf(MSG_INFO, "EAP-SAKE: Response/Confirm did not " - "include AT_MIC_P"); - return; - } - - eap_sake_compute_mic(data->tek.auth, data->rand_s, data->rand_p, - data->serverid, data->serverid_len, - data->peerid, data->peerid_len, 1, - wpabuf_head(respData), wpabuf_len(respData), - attr.mic_p, mic_p); - if (os_memcmp(attr.mic_p, mic_p, EAP_SAKE_MIC_LEN) != 0) { - wpa_printf(MSG_INFO, "EAP-SAKE: Incorrect AT_MIC_P"); - eap_sake_state(data, FAILURE); - } else - eap_sake_state(data, SUCCESS); -} - - -static void eap_sake_process_auth_reject(struct eap_sm *sm, - struct eap_sake_data *data, - const struct wpabuf *respData, - const u8 *payload, size_t payloadlen) -{ - wpa_printf(MSG_DEBUG, "EAP-SAKE: Received Response/Auth-Reject"); - eap_sake_state(data, FAILURE); -} - - -static void eap_sake_process(struct eap_sm *sm, void *priv, - struct wpabuf *respData) -{ - struct eap_sake_data *data = priv; - struct eap_sake_hdr *resp; - u8 subtype; - size_t len; - const u8 *pos, *end; - - pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_SAKE, respData, &len); - if (pos == NULL || len < sizeof(struct eap_sake_hdr)) - return; - - resp = (struct eap_sake_hdr *) pos; - end = pos + len; - subtype = resp->subtype; - pos = (u8 *) (resp + 1); - - wpa_hexdump(MSG_DEBUG, "EAP-SAKE: Received attributes", - pos, end - pos); - - switch (subtype) { - case EAP_SAKE_SUBTYPE_IDENTITY: - eap_sake_process_identity(sm, data, respData, pos, end - pos); - break; - case EAP_SAKE_SUBTYPE_CHALLENGE: - eap_sake_process_challenge(sm, data, respData, pos, end - pos); - break; - case EAP_SAKE_SUBTYPE_CONFIRM: - eap_sake_process_confirm(sm, data, respData, pos, end - pos); - break; - case EAP_SAKE_SUBTYPE_AUTH_REJECT: - eap_sake_process_auth_reject(sm, data, respData, pos, - end - pos); - break; - } -} - - -static Boolean eap_sake_isDone(struct eap_sm *sm, void *priv) -{ - struct eap_sake_data *data = priv; - return data->state == SUCCESS || data->state == FAILURE; -} - - -static u8 * eap_sake_getKey(struct eap_sm *sm, void *priv, size_t *len) -{ - struct eap_sake_data *data = priv; - u8 *key; - - if (data->state != SUCCESS) - return NULL; - - key = os_malloc(EAP_MSK_LEN); - if (key == NULL) - return NULL; - os_memcpy(key, data->msk, EAP_MSK_LEN); - *len = EAP_MSK_LEN; - - return key; -} - - -static u8 * eap_sake_get_emsk(struct eap_sm *sm, void *priv, size_t *len) -{ - struct eap_sake_data *data = priv; - u8 *key; - - if (data->state != SUCCESS) - return NULL; - - key = os_malloc(EAP_EMSK_LEN); - if (key == NULL) - return NULL; - os_memcpy(key, data->emsk, EAP_EMSK_LEN); - *len = EAP_EMSK_LEN; - - return key; -} - - -static Boolean eap_sake_isSuccess(struct eap_sm *sm, void *priv) -{ - struct eap_sake_data *data = priv; - return data->state == SUCCESS; -} - - -int eap_server_sake_register(void) -{ - struct eap_method *eap; - int ret; - - eap = eap_server_method_alloc(EAP_SERVER_METHOD_INTERFACE_VERSION, - EAP_VENDOR_IETF, EAP_TYPE_SAKE, "SAKE"); - if (eap == NULL) - return -1; - - eap->init = eap_sake_init; - eap->reset = eap_sake_reset; - eap->buildReq = eap_sake_buildReq; - eap->check = eap_sake_check; - eap->process = eap_sake_process; - eap->isDone = eap_sake_isDone; - eap->getKey = eap_sake_getKey; - eap->isSuccess = eap_sake_isSuccess; - eap->get_emsk = eap_sake_get_emsk; - - ret = eap_server_method_register(eap); - if (ret) - eap_server_method_free(eap); - return ret; -} diff --git a/hostapd-0.8/src/eap_server/eap_server_sim.c b/hostapd-0.8/src/eap_server/eap_server_sim.c deleted file mode 100644 index 29df2ff..0000000 --- a/hostapd-0.8/src/eap_server/eap_server_sim.c +++ /dev/null @@ -1,798 +0,0 @@ -/* - * hostapd / EAP-SIM (RFC 4186) - * Copyright (c) 2005-2008, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#include "includes.h" - -#include "common.h" -#include "crypto/random.h" -#include "eap_server/eap_i.h" -#include "eap_common/eap_sim_common.h" -#include "eap_server/eap_sim_db.h" - - -struct eap_sim_data { - u8 mk[EAP_SIM_MK_LEN]; - u8 nonce_mt[EAP_SIM_NONCE_MT_LEN]; - u8 nonce_s[EAP_SIM_NONCE_S_LEN]; - u8 k_aut[EAP_SIM_K_AUT_LEN]; - u8 k_encr[EAP_SIM_K_ENCR_LEN]; - u8 msk[EAP_SIM_KEYING_DATA_LEN]; - u8 emsk[EAP_EMSK_LEN]; - u8 kc[EAP_SIM_MAX_CHAL][EAP_SIM_KC_LEN]; - u8 sres[EAP_SIM_MAX_CHAL][EAP_SIM_SRES_LEN]; - u8 rand[EAP_SIM_MAX_CHAL][GSM_RAND_LEN]; - int num_chal; - enum { - START, CHALLENGE, REAUTH, NOTIFICATION, SUCCESS, FAILURE - } state; - char *next_pseudonym; - char *next_reauth_id; - u16 counter; - struct eap_sim_reauth *reauth; - u16 notification; - int use_result_ind; -}; - - -static const char * eap_sim_state_txt(int state) -{ - switch (state) { - case START: - return "START"; - case CHALLENGE: - return "CHALLENGE"; - case REAUTH: - return "REAUTH"; - case SUCCESS: - return "SUCCESS"; - case FAILURE: - return "FAILURE"; - case NOTIFICATION: - return "NOTIFICATION"; - default: - return "Unknown?!"; - } -} - - -static void eap_sim_state(struct eap_sim_data *data, int state) -{ - wpa_printf(MSG_DEBUG, "EAP-SIM: %s -> %s", - eap_sim_state_txt(data->state), - eap_sim_state_txt(state)); - data->state = state; -} - - -static void * eap_sim_init(struct eap_sm *sm) -{ - struct eap_sim_data *data; - - if (sm->eap_sim_db_priv == NULL) { - wpa_printf(MSG_WARNING, "EAP-SIM: eap_sim_db not configured"); - return NULL; - } - - data = os_zalloc(sizeof(*data)); - if (data == NULL) - return NULL; - data->state = START; - - return data; -} - - -static void eap_sim_reset(struct eap_sm *sm, void *priv) -{ - struct eap_sim_data *data = priv; - os_free(data->next_pseudonym); - os_free(data->next_reauth_id); - os_free(data); -} - - -static struct wpabuf * eap_sim_build_start(struct eap_sm *sm, - struct eap_sim_data *data, u8 id) -{ - struct eap_sim_msg *msg; - u8 ver[2]; - - wpa_printf(MSG_DEBUG, "EAP-SIM: Generating Start"); - msg = eap_sim_msg_init(EAP_CODE_REQUEST, id, EAP_TYPE_SIM, - EAP_SIM_SUBTYPE_START); - if (eap_sim_db_identity_known(sm->eap_sim_db_priv, sm->identity, - sm->identity_len)) { - wpa_printf(MSG_DEBUG, " AT_PERMANENT_ID_REQ"); - eap_sim_msg_add(msg, EAP_SIM_AT_PERMANENT_ID_REQ, 0, NULL, 0); - } else { - /* - * RFC 4186, Chap. 4.2.4 recommends that identity from EAP is - * ignored and the SIM/Start is used to request the identity. - */ - wpa_printf(MSG_DEBUG, " AT_ANY_ID_REQ"); - eap_sim_msg_add(msg, EAP_SIM_AT_ANY_ID_REQ, 0, NULL, 0); - } - wpa_printf(MSG_DEBUG, " AT_VERSION_LIST"); - ver[0] = 0; - ver[1] = EAP_SIM_VERSION; - eap_sim_msg_add(msg, EAP_SIM_AT_VERSION_LIST, sizeof(ver), - ver, sizeof(ver)); - return eap_sim_msg_finish(msg, NULL, NULL, 0); -} - - -static int eap_sim_build_encr(struct eap_sm *sm, struct eap_sim_data *data, - struct eap_sim_msg *msg, u16 counter, - const u8 *nonce_s) -{ - os_free(data->next_pseudonym); - data->next_pseudonym = - eap_sim_db_get_next_pseudonym(sm->eap_sim_db_priv, 0); - os_free(data->next_reauth_id); - if (data->counter <= EAP_SIM_MAX_FAST_REAUTHS) { - data->next_reauth_id = - eap_sim_db_get_next_reauth_id(sm->eap_sim_db_priv, 0); - } else { - wpa_printf(MSG_DEBUG, "EAP-SIM: Max fast re-authentication " - "count exceeded - force full authentication"); - data->next_reauth_id = NULL; - } - - if (data->next_pseudonym == NULL && data->next_reauth_id == NULL && - counter == 0 && nonce_s == NULL) - return 0; - - wpa_printf(MSG_DEBUG, " AT_IV"); - wpa_printf(MSG_DEBUG, " AT_ENCR_DATA"); - eap_sim_msg_add_encr_start(msg, EAP_SIM_AT_IV, EAP_SIM_AT_ENCR_DATA); - - if (counter > 0) { - wpa_printf(MSG_DEBUG, " *AT_COUNTER (%u)", counter); - eap_sim_msg_add(msg, EAP_SIM_AT_COUNTER, counter, NULL, 0); - } - - if (nonce_s) { - wpa_printf(MSG_DEBUG, " *AT_NONCE_S"); - eap_sim_msg_add(msg, EAP_SIM_AT_NONCE_S, 0, nonce_s, - EAP_SIM_NONCE_S_LEN); - } - - if (data->next_pseudonym) { - wpa_printf(MSG_DEBUG, " *AT_NEXT_PSEUDONYM (%s)", - data->next_pseudonym); - eap_sim_msg_add(msg, EAP_SIM_AT_NEXT_PSEUDONYM, - os_strlen(data->next_pseudonym), - (u8 *) data->next_pseudonym, - os_strlen(data->next_pseudonym)); - } - - if (data->next_reauth_id) { - wpa_printf(MSG_DEBUG, " *AT_NEXT_REAUTH_ID (%s)", - data->next_reauth_id); - eap_sim_msg_add(msg, EAP_SIM_AT_NEXT_REAUTH_ID, - os_strlen(data->next_reauth_id), - (u8 *) data->next_reauth_id, - os_strlen(data->next_reauth_id)); - } - - if (eap_sim_msg_add_encr_end(msg, data->k_encr, EAP_SIM_AT_PADDING)) { - wpa_printf(MSG_WARNING, "EAP-SIM: Failed to encrypt " - "AT_ENCR_DATA"); - return -1; - } - - return 0; -} - - -static struct wpabuf * eap_sim_build_challenge(struct eap_sm *sm, - struct eap_sim_data *data, - u8 id) -{ - struct eap_sim_msg *msg; - - wpa_printf(MSG_DEBUG, "EAP-SIM: Generating Challenge"); - msg = eap_sim_msg_init(EAP_CODE_REQUEST, id, EAP_TYPE_SIM, - EAP_SIM_SUBTYPE_CHALLENGE); - wpa_printf(MSG_DEBUG, " AT_RAND"); - eap_sim_msg_add(msg, EAP_SIM_AT_RAND, 0, (u8 *) data->rand, - data->num_chal * GSM_RAND_LEN); - - if (eap_sim_build_encr(sm, data, msg, 0, NULL)) { - eap_sim_msg_free(msg); - return NULL; - } - - if (sm->eap_sim_aka_result_ind) { - wpa_printf(MSG_DEBUG, " AT_RESULT_IND"); - eap_sim_msg_add(msg, EAP_SIM_AT_RESULT_IND, 0, NULL, 0); - } - - wpa_printf(MSG_DEBUG, " AT_MAC"); - eap_sim_msg_add_mac(msg, EAP_SIM_AT_MAC); - return eap_sim_msg_finish(msg, data->k_aut, data->nonce_mt, - EAP_SIM_NONCE_MT_LEN); -} - - -static struct wpabuf * eap_sim_build_reauth(struct eap_sm *sm, - struct eap_sim_data *data, u8 id) -{ - struct eap_sim_msg *msg; - - wpa_printf(MSG_DEBUG, "EAP-SIM: Generating Re-authentication"); - - if (random_get_bytes(data->nonce_s, EAP_SIM_NONCE_S_LEN)) - return NULL; - wpa_hexdump_key(MSG_MSGDUMP, "EAP-SIM: NONCE_S", - data->nonce_s, EAP_SIM_NONCE_S_LEN); - - eap_sim_derive_keys(data->mk, data->k_encr, data->k_aut, data->msk, - data->emsk); - eap_sim_derive_keys_reauth(data->counter, sm->identity, - sm->identity_len, data->nonce_s, data->mk, - data->msk, data->emsk); - - msg = eap_sim_msg_init(EAP_CODE_REQUEST, id, EAP_TYPE_SIM, - EAP_SIM_SUBTYPE_REAUTHENTICATION); - - if (eap_sim_build_encr(sm, data, msg, data->counter, data->nonce_s)) { - eap_sim_msg_free(msg); - return NULL; - } - - if (sm->eap_sim_aka_result_ind) { - wpa_printf(MSG_DEBUG, " AT_RESULT_IND"); - eap_sim_msg_add(msg, EAP_SIM_AT_RESULT_IND, 0, NULL, 0); - } - - wpa_printf(MSG_DEBUG, " AT_MAC"); - eap_sim_msg_add_mac(msg, EAP_SIM_AT_MAC); - return eap_sim_msg_finish(msg, data->k_aut, NULL, 0); -} - - -static struct wpabuf * eap_sim_build_notification(struct eap_sm *sm, - struct eap_sim_data *data, - u8 id) -{ - struct eap_sim_msg *msg; - - wpa_printf(MSG_DEBUG, "EAP-SIM: Generating Notification"); - msg = eap_sim_msg_init(EAP_CODE_REQUEST, id, EAP_TYPE_SIM, - EAP_SIM_SUBTYPE_NOTIFICATION); - wpa_printf(MSG_DEBUG, " AT_NOTIFICATION (%d)", data->notification); - eap_sim_msg_add(msg, EAP_SIM_AT_NOTIFICATION, data->notification, - NULL, 0); - if (data->use_result_ind) { - if (data->reauth) { - wpa_printf(MSG_DEBUG, " AT_IV"); - wpa_printf(MSG_DEBUG, " AT_ENCR_DATA"); - eap_sim_msg_add_encr_start(msg, EAP_SIM_AT_IV, - EAP_SIM_AT_ENCR_DATA); - wpa_printf(MSG_DEBUG, " *AT_COUNTER (%u)", - data->counter); - eap_sim_msg_add(msg, EAP_SIM_AT_COUNTER, data->counter, - NULL, 0); - - if (eap_sim_msg_add_encr_end(msg, data->k_encr, - EAP_SIM_AT_PADDING)) { - wpa_printf(MSG_WARNING, "EAP-SIM: Failed to " - "encrypt AT_ENCR_DATA"); - eap_sim_msg_free(msg); - return NULL; - } - } - - wpa_printf(MSG_DEBUG, " AT_MAC"); - eap_sim_msg_add_mac(msg, EAP_SIM_AT_MAC); - } - return eap_sim_msg_finish(msg, data->k_aut, NULL, 0); -} - - -static struct wpabuf * eap_sim_buildReq(struct eap_sm *sm, void *priv, u8 id) -{ - struct eap_sim_data *data = priv; - - switch (data->state) { - case START: - return eap_sim_build_start(sm, data, id); - case CHALLENGE: - return eap_sim_build_challenge(sm, data, id); - case REAUTH: - return eap_sim_build_reauth(sm, data, id); - case NOTIFICATION: - return eap_sim_build_notification(sm, data, id); - default: - wpa_printf(MSG_DEBUG, "EAP-SIM: Unknown state %d in " - "buildReq", data->state); - break; - } - return NULL; -} - - -static Boolean eap_sim_check(struct eap_sm *sm, void *priv, - struct wpabuf *respData) -{ - struct eap_sim_data *data = priv; - const u8 *pos; - size_t len; - u8 subtype; - - pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_SIM, respData, &len); - if (pos == NULL || len < 3) { - wpa_printf(MSG_INFO, "EAP-SIM: Invalid frame"); - return TRUE; - } - subtype = *pos; - - if (subtype == EAP_SIM_SUBTYPE_CLIENT_ERROR) - return FALSE; - - switch (data->state) { - case START: - if (subtype != EAP_SIM_SUBTYPE_START) { - wpa_printf(MSG_INFO, "EAP-SIM: Unexpected response " - "subtype %d", subtype); - return TRUE; - } - break; - case CHALLENGE: - if (subtype != EAP_SIM_SUBTYPE_CHALLENGE) { - wpa_printf(MSG_INFO, "EAP-SIM: Unexpected response " - "subtype %d", subtype); - return TRUE; - } - break; - case REAUTH: - if (subtype != EAP_SIM_SUBTYPE_REAUTHENTICATION) { - wpa_printf(MSG_INFO, "EAP-SIM: Unexpected response " - "subtype %d", subtype); - return TRUE; - } - break; - case NOTIFICATION: - if (subtype != EAP_SIM_SUBTYPE_NOTIFICATION) { - wpa_printf(MSG_INFO, "EAP-SIM: Unexpected response " - "subtype %d", subtype); - return TRUE; - } - break; - default: - wpa_printf(MSG_INFO, "EAP-SIM: Unexpected state (%d) for " - "processing a response", data->state); - return TRUE; - } - - return FALSE; -} - - -static int eap_sim_supported_ver(struct eap_sim_data *data, int version) -{ - return version == EAP_SIM_VERSION; -} - - -static void eap_sim_process_start(struct eap_sm *sm, - struct eap_sim_data *data, - struct wpabuf *respData, - struct eap_sim_attrs *attr) -{ - const u8 *identity; - size_t identity_len; - u8 ver_list[2]; - - wpa_printf(MSG_DEBUG, "EAP-SIM: Receive start response"); - - if (attr->identity) { - os_free(sm->identity); - sm->identity = os_malloc(attr->identity_len); - if (sm->identity) { - os_memcpy(sm->identity, attr->identity, - attr->identity_len); - sm->identity_len = attr->identity_len; - } - } - - identity = NULL; - identity_len = 0; - - if (sm->identity && sm->identity_len > 0 && - sm->identity[0] == EAP_SIM_PERMANENT_PREFIX) { - identity = sm->identity; - identity_len = sm->identity_len; - } else { - identity = eap_sim_db_get_permanent(sm->eap_sim_db_priv, - sm->identity, - sm->identity_len, - &identity_len); - if (identity == NULL) { - data->reauth = eap_sim_db_get_reauth_entry( - sm->eap_sim_db_priv, sm->identity, - sm->identity_len); - if (data->reauth) { - wpa_printf(MSG_DEBUG, "EAP-SIM: Using fast " - "re-authentication"); - identity = data->reauth->identity; - identity_len = data->reauth->identity_len; - data->counter = data->reauth->counter; - os_memcpy(data->mk, data->reauth->mk, - EAP_SIM_MK_LEN); - } - } - } - - if (identity == NULL) { - wpa_printf(MSG_DEBUG, "EAP-SIM: Could not get proper permanent" - " user name"); - eap_sim_state(data, FAILURE); - return; - } - - wpa_hexdump_ascii(MSG_DEBUG, "EAP-SIM: Identity", - identity, identity_len); - - if (data->reauth) { - eap_sim_state(data, REAUTH); - return; - } - - if (attr->nonce_mt == NULL || attr->selected_version < 0) { - wpa_printf(MSG_DEBUG, "EAP-SIM: Start/Response missing " - "required attributes"); - eap_sim_state(data, FAILURE); - return; - } - - if (!eap_sim_supported_ver(data, attr->selected_version)) { - wpa_printf(MSG_DEBUG, "EAP-SIM: Peer selected unsupported " - "version %d", attr->selected_version); - eap_sim_state(data, FAILURE); - return; - } - - data->counter = 0; /* reset re-auth counter since this is full auth */ - data->reauth = NULL; - - data->num_chal = eap_sim_db_get_gsm_triplets( - sm->eap_sim_db_priv, identity, identity_len, - EAP_SIM_MAX_CHAL, - (u8 *) data->rand, (u8 *) data->kc, (u8 *) data->sres, sm); - if (data->num_chal == EAP_SIM_DB_PENDING) { - wpa_printf(MSG_DEBUG, "EAP-SIM: GSM authentication triplets " - "not yet available - pending request"); - sm->method_pending = METHOD_PENDING_WAIT; - return; - } - if (data->num_chal < 2) { - wpa_printf(MSG_INFO, "EAP-SIM: Failed to get GSM " - "authentication triplets for the peer"); - eap_sim_state(data, FAILURE); - return; - } - - identity_len = sm->identity_len; - while (identity_len > 0 && sm->identity[identity_len - 1] == '\0') { - wpa_printf(MSG_DEBUG, "EAP-SIM: Workaround - drop last null " - "character from identity"); - identity_len--; - } - wpa_hexdump_ascii(MSG_DEBUG, "EAP-SIM: Identity for MK derivation", - sm->identity, identity_len); - - os_memcpy(data->nonce_mt, attr->nonce_mt, EAP_SIM_NONCE_MT_LEN); - WPA_PUT_BE16(ver_list, EAP_SIM_VERSION); - eap_sim_derive_mk(sm->identity, identity_len, attr->nonce_mt, - attr->selected_version, ver_list, sizeof(ver_list), - data->num_chal, (const u8 *) data->kc, data->mk); - eap_sim_derive_keys(data->mk, data->k_encr, data->k_aut, data->msk, - data->emsk); - - eap_sim_state(data, CHALLENGE); -} - - -static void eap_sim_process_challenge(struct eap_sm *sm, - struct eap_sim_data *data, - struct wpabuf *respData, - struct eap_sim_attrs *attr) -{ - const u8 *identity; - size_t identity_len; - - if (attr->mac == NULL || - eap_sim_verify_mac(data->k_aut, respData, attr->mac, - (u8 *) data->sres, - data->num_chal * EAP_SIM_SRES_LEN)) { - wpa_printf(MSG_WARNING, "EAP-SIM: Challenge message " - "did not include valid AT_MAC"); - eap_sim_state(data, FAILURE); - return; - } - - wpa_printf(MSG_DEBUG, "EAP-SIM: Challenge response includes the " - "correct AT_MAC"); - if (sm->eap_sim_aka_result_ind && attr->result_ind) { - data->use_result_ind = 1; - data->notification = EAP_SIM_SUCCESS; - eap_sim_state(data, NOTIFICATION); - } else - eap_sim_state(data, SUCCESS); - - identity = eap_sim_db_get_permanent(sm->eap_sim_db_priv, sm->identity, - sm->identity_len, &identity_len); - if (identity == NULL) { - identity = sm->identity; - identity_len = sm->identity_len; - } - - if (data->next_pseudonym) { - eap_sim_db_add_pseudonym(sm->eap_sim_db_priv, identity, - identity_len, - data->next_pseudonym); - data->next_pseudonym = NULL; - } - if (data->next_reauth_id) { - eap_sim_db_add_reauth(sm->eap_sim_db_priv, identity, - identity_len, - data->next_reauth_id, data->counter + 1, - data->mk); - data->next_reauth_id = NULL; - } -} - - -static void eap_sim_process_reauth(struct eap_sm *sm, - struct eap_sim_data *data, - struct wpabuf *respData, - struct eap_sim_attrs *attr) -{ - struct eap_sim_attrs eattr; - u8 *decrypted = NULL; - const u8 *identity, *id2; - size_t identity_len, id2_len; - - if (attr->mac == NULL || - eap_sim_verify_mac(data->k_aut, respData, attr->mac, data->nonce_s, - EAP_SIM_NONCE_S_LEN)) { - wpa_printf(MSG_WARNING, "EAP-SIM: Re-authentication message " - "did not include valid AT_MAC"); - goto fail; - } - - if (attr->encr_data == NULL || attr->iv == NULL) { - wpa_printf(MSG_WARNING, "EAP-SIM: Reauthentication " - "message did not include encrypted data"); - goto fail; - } - - decrypted = eap_sim_parse_encr(data->k_encr, attr->encr_data, - attr->encr_data_len, attr->iv, &eattr, - 0); - if (decrypted == NULL) { - wpa_printf(MSG_WARNING, "EAP-SIM: Failed to parse encrypted " - "data from reauthentication message"); - goto fail; - } - - if (eattr.counter != data->counter) { - wpa_printf(MSG_WARNING, "EAP-SIM: Re-authentication message " - "used incorrect counter %u, expected %u", - eattr.counter, data->counter); - goto fail; - } - os_free(decrypted); - decrypted = NULL; - - wpa_printf(MSG_DEBUG, "EAP-SIM: Re-authentication response includes " - "the correct AT_MAC"); - if (sm->eap_sim_aka_result_ind && attr->result_ind) { - data->use_result_ind = 1; - data->notification = EAP_SIM_SUCCESS; - eap_sim_state(data, NOTIFICATION); - } else - eap_sim_state(data, SUCCESS); - - if (data->reauth) { - identity = data->reauth->identity; - identity_len = data->reauth->identity_len; - } else { - identity = sm->identity; - identity_len = sm->identity_len; - } - - id2 = eap_sim_db_get_permanent(sm->eap_sim_db_priv, identity, - identity_len, &id2_len); - if (id2) { - identity = id2; - identity_len = id2_len; - } - - if (data->next_pseudonym) { - eap_sim_db_add_pseudonym(sm->eap_sim_db_priv, identity, - identity_len, data->next_pseudonym); - data->next_pseudonym = NULL; - } - if (data->next_reauth_id) { - eap_sim_db_add_reauth(sm->eap_sim_db_priv, identity, - identity_len, data->next_reauth_id, - data->counter + 1, data->mk); - data->next_reauth_id = NULL; - } else { - eap_sim_db_remove_reauth(sm->eap_sim_db_priv, data->reauth); - data->reauth = NULL; - } - - return; - -fail: - eap_sim_state(data, FAILURE); - eap_sim_db_remove_reauth(sm->eap_sim_db_priv, data->reauth); - data->reauth = NULL; - os_free(decrypted); -} - - -static void eap_sim_process_client_error(struct eap_sm *sm, - struct eap_sim_data *data, - struct wpabuf *respData, - struct eap_sim_attrs *attr) -{ - wpa_printf(MSG_DEBUG, "EAP-SIM: Client reported error %d", - attr->client_error_code); - if (data->notification == EAP_SIM_SUCCESS && data->use_result_ind) - eap_sim_state(data, SUCCESS); - else - eap_sim_state(data, FAILURE); -} - - -static void eap_sim_process_notification(struct eap_sm *sm, - struct eap_sim_data *data, - struct wpabuf *respData, - struct eap_sim_attrs *attr) -{ - wpa_printf(MSG_DEBUG, "EAP-SIM: Client replied to notification"); - if (data->notification == EAP_SIM_SUCCESS && data->use_result_ind) - eap_sim_state(data, SUCCESS); - else - eap_sim_state(data, FAILURE); -} - - -static void eap_sim_process(struct eap_sm *sm, void *priv, - struct wpabuf *respData) -{ - struct eap_sim_data *data = priv; - const u8 *pos, *end; - u8 subtype; - size_t len; - struct eap_sim_attrs attr; - - pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_SIM, respData, &len); - if (pos == NULL || len < 3) - return; - - end = pos + len; - subtype = *pos; - pos += 3; - - if (eap_sim_parse_attr(pos, end, &attr, 0, 0)) { - wpa_printf(MSG_DEBUG, "EAP-SIM: Failed to parse attributes"); - eap_sim_state(data, FAILURE); - return; - } - - if (subtype == EAP_SIM_SUBTYPE_CLIENT_ERROR) { - eap_sim_process_client_error(sm, data, respData, &attr); - return; - } - - switch (data->state) { - case START: - eap_sim_process_start(sm, data, respData, &attr); - break; - case CHALLENGE: - eap_sim_process_challenge(sm, data, respData, &attr); - break; - case REAUTH: - eap_sim_process_reauth(sm, data, respData, &attr); - break; - case NOTIFICATION: - eap_sim_process_notification(sm, data, respData, &attr); - break; - default: - wpa_printf(MSG_DEBUG, "EAP-SIM: Unknown state %d in " - "process", data->state); - break; - } -} - - -static Boolean eap_sim_isDone(struct eap_sm *sm, void *priv) -{ - struct eap_sim_data *data = priv; - return data->state == SUCCESS || data->state == FAILURE; -} - - -static u8 * eap_sim_getKey(struct eap_sm *sm, void *priv, size_t *len) -{ - struct eap_sim_data *data = priv; - u8 *key; - - if (data->state != SUCCESS) - return NULL; - - key = os_malloc(EAP_SIM_KEYING_DATA_LEN); - if (key == NULL) - return NULL; - os_memcpy(key, data->msk, EAP_SIM_KEYING_DATA_LEN); - *len = EAP_SIM_KEYING_DATA_LEN; - return key; -} - - -static u8 * eap_sim_get_emsk(struct eap_sm *sm, void *priv, size_t *len) -{ - struct eap_sim_data *data = priv; - u8 *key; - - if (data->state != SUCCESS) - return NULL; - - key = os_malloc(EAP_EMSK_LEN); - if (key == NULL) - return NULL; - os_memcpy(key, data->emsk, EAP_EMSK_LEN); - *len = EAP_EMSK_LEN; - return key; -} - - -static Boolean eap_sim_isSuccess(struct eap_sm *sm, void *priv) -{ - struct eap_sim_data *data = priv; - return data->state == SUCCESS; -} - - -int eap_server_sim_register(void) -{ - struct eap_method *eap; - int ret; - - eap = eap_server_method_alloc(EAP_SERVER_METHOD_INTERFACE_VERSION, - EAP_VENDOR_IETF, EAP_TYPE_SIM, "SIM"); - if (eap == NULL) - return -1; - - eap->init = eap_sim_init; - eap->reset = eap_sim_reset; - eap->buildReq = eap_sim_buildReq; - eap->check = eap_sim_check; - eap->process = eap_sim_process; - eap->isDone = eap_sim_isDone; - eap->getKey = eap_sim_getKey; - eap->isSuccess = eap_sim_isSuccess; - eap->get_emsk = eap_sim_get_emsk; - - ret = eap_server_method_register(eap); - if (ret) - eap_server_method_free(eap); - return ret; -} diff --git a/hostapd-0.8/src/eap_server/eap_server_tls.c b/hostapd-0.8/src/eap_server/eap_server_tls.c deleted file mode 100644 index c98fa18..0000000 --- a/hostapd-0.8/src/eap_server/eap_server_tls.c +++ /dev/null @@ -1,286 +0,0 @@ -/* - * hostapd / EAP-TLS (RFC 2716) - * Copyright (c) 2004-2008, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#include "includes.h" - -#include "common.h" -#include "eap_i.h" -#include "eap_tls_common.h" -#include "crypto/tls.h" - - -static void eap_tls_reset(struct eap_sm *sm, void *priv); - - -struct eap_tls_data { - struct eap_ssl_data ssl; - enum { START, CONTINUE, SUCCESS, FAILURE } state; - int established; -}; - - -static const char * eap_tls_state_txt(int state) -{ - switch (state) { - case START: - return "START"; - case CONTINUE: - return "CONTINUE"; - case SUCCESS: - return "SUCCESS"; - case FAILURE: - return "FAILURE"; - default: - return "Unknown?!"; - } -} - - -static void eap_tls_state(struct eap_tls_data *data, int state) -{ - wpa_printf(MSG_DEBUG, "EAP-TLS: %s -> %s", - eap_tls_state_txt(data->state), - eap_tls_state_txt(state)); - data->state = state; -} - - -static void * eap_tls_init(struct eap_sm *sm) -{ - struct eap_tls_data *data; - - data = os_zalloc(sizeof(*data)); - if (data == NULL) - return NULL; - data->state = START; - - if (eap_server_tls_ssl_init(sm, &data->ssl, 1)) { - wpa_printf(MSG_INFO, "EAP-TLS: Failed to initialize SSL."); - eap_tls_reset(sm, data); - return NULL; - } - - return data; -} - - -static void eap_tls_reset(struct eap_sm *sm, void *priv) -{ - struct eap_tls_data *data = priv; - if (data == NULL) - return; - eap_server_tls_ssl_deinit(sm, &data->ssl); - os_free(data); -} - - -static struct wpabuf * eap_tls_build_start(struct eap_sm *sm, - struct eap_tls_data *data, u8 id) -{ - struct wpabuf *req; - - req = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_TLS, 1, EAP_CODE_REQUEST, - id); - if (req == NULL) { - wpa_printf(MSG_ERROR, "EAP-TLS: Failed to allocate memory for " - "request"); - eap_tls_state(data, FAILURE); - return NULL; - } - - wpabuf_put_u8(req, EAP_TLS_FLAGS_START); - - eap_tls_state(data, CONTINUE); - - return req; -} - - -static struct wpabuf * eap_tls_buildReq(struct eap_sm *sm, void *priv, u8 id) -{ - struct eap_tls_data *data = priv; - struct wpabuf *res; - - if (data->ssl.state == FRAG_ACK) { - return eap_server_tls_build_ack(id, EAP_TYPE_TLS, 0); - } - - if (data->ssl.state == WAIT_FRAG_ACK) { - res = eap_server_tls_build_msg(&data->ssl, EAP_TYPE_TLS, 0, - id); - goto check_established; - } - - switch (data->state) { - case START: - return eap_tls_build_start(sm, data, id); - case CONTINUE: - if (tls_connection_established(sm->ssl_ctx, data->ssl.conn)) - data->established = 1; - break; - default: - wpa_printf(MSG_DEBUG, "EAP-TLS: %s - unexpected state %d", - __func__, data->state); - return NULL; - } - - res = eap_server_tls_build_msg(&data->ssl, EAP_TYPE_TLS, 0, id); - -check_established: - if (data->established && data->ssl.state != WAIT_FRAG_ACK) { - /* TLS handshake has been completed and there are no more - * fragments waiting to be sent out. */ - wpa_printf(MSG_DEBUG, "EAP-TLS: Done"); - eap_tls_state(data, SUCCESS); - } - - return res; -} - - -static Boolean eap_tls_check(struct eap_sm *sm, void *priv, - struct wpabuf *respData) -{ - const u8 *pos; - size_t len; - - pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_TLS, respData, &len); - if (pos == NULL || len < 1) { - wpa_printf(MSG_INFO, "EAP-TLS: Invalid frame"); - return TRUE; - } - - return FALSE; -} - - -static void eap_tls_process_msg(struct eap_sm *sm, void *priv, - const struct wpabuf *respData) -{ - struct eap_tls_data *data = priv; - if (data->state == SUCCESS && wpabuf_len(data->ssl.tls_in) == 0) { - wpa_printf(MSG_DEBUG, "EAP-TLS: Client acknowledged final TLS " - "handshake message"); - return; - } - if (eap_server_tls_phase1(sm, &data->ssl) < 0) - eap_tls_state(data, FAILURE); -} - - -static void eap_tls_process(struct eap_sm *sm, void *priv, - struct wpabuf *respData) -{ - struct eap_tls_data *data = priv; - if (eap_server_tls_process(sm, &data->ssl, respData, data, - EAP_TYPE_TLS, NULL, eap_tls_process_msg) < - 0) - eap_tls_state(data, FAILURE); -} - - -static Boolean eap_tls_isDone(struct eap_sm *sm, void *priv) -{ - struct eap_tls_data *data = priv; - return data->state == SUCCESS || data->state == FAILURE; -} - - -static u8 * eap_tls_getKey(struct eap_sm *sm, void *priv, size_t *len) -{ - struct eap_tls_data *data = priv; - u8 *eapKeyData; - - if (data->state != SUCCESS) - return NULL; - - eapKeyData = eap_server_tls_derive_key(sm, &data->ssl, - "client EAP encryption", - EAP_TLS_KEY_LEN); - if (eapKeyData) { - *len = EAP_TLS_KEY_LEN; - wpa_hexdump(MSG_DEBUG, "EAP-TLS: Derived key", - eapKeyData, EAP_TLS_KEY_LEN); - } else { - wpa_printf(MSG_DEBUG, "EAP-TLS: Failed to derive key"); - } - - return eapKeyData; -} - - -static u8 * eap_tls_get_emsk(struct eap_sm *sm, void *priv, size_t *len) -{ - struct eap_tls_data *data = priv; - u8 *eapKeyData, *emsk; - - if (data->state != SUCCESS) - return NULL; - - eapKeyData = eap_server_tls_derive_key(sm, &data->ssl, - "client EAP encryption", - EAP_TLS_KEY_LEN + EAP_EMSK_LEN); - if (eapKeyData) { - emsk = os_malloc(EAP_EMSK_LEN); - if (emsk) - os_memcpy(emsk, eapKeyData + EAP_TLS_KEY_LEN, - EAP_EMSK_LEN); - os_free(eapKeyData); - } else - emsk = NULL; - - if (emsk) { - *len = EAP_EMSK_LEN; - wpa_hexdump(MSG_DEBUG, "EAP-TLS: Derived EMSK", - emsk, EAP_EMSK_LEN); - } else { - wpa_printf(MSG_DEBUG, "EAP-TLS: Failed to derive EMSK"); - } - - return emsk; -} - - -static Boolean eap_tls_isSuccess(struct eap_sm *sm, void *priv) -{ - struct eap_tls_data *data = priv; - return data->state == SUCCESS; -} - - -int eap_server_tls_register(void) -{ - struct eap_method *eap; - int ret; - - eap = eap_server_method_alloc(EAP_SERVER_METHOD_INTERFACE_VERSION, - EAP_VENDOR_IETF, EAP_TYPE_TLS, "TLS"); - if (eap == NULL) - return -1; - - eap->init = eap_tls_init; - eap->reset = eap_tls_reset; - eap->buildReq = eap_tls_buildReq; - eap->check = eap_tls_check; - eap->process = eap_tls_process; - eap->isDone = eap_tls_isDone; - eap->getKey = eap_tls_getKey; - eap->isSuccess = eap_tls_isSuccess; - eap->get_emsk = eap_tls_get_emsk; - - ret = eap_server_method_register(eap); - if (ret) - eap_server_method_free(eap); - return ret; -} diff --git a/hostapd-0.8/src/eap_server/eap_server_tls_common.c b/hostapd-0.8/src/eap_server/eap_server_tls_common.c deleted file mode 100644 index e149ee3..0000000 --- a/hostapd-0.8/src/eap_server/eap_server_tls_common.c +++ /dev/null @@ -1,400 +0,0 @@ -/* - * EAP-TLS/PEAP/TTLS/FAST server common functions - * Copyright (c) 2004-2009, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#include "includes.h" - -#include "common.h" -#include "crypto/sha1.h" -#include "crypto/tls.h" -#include "eap_i.h" -#include "eap_tls_common.h" - - -static void eap_server_tls_free_in_buf(struct eap_ssl_data *data); - - -int eap_server_tls_ssl_init(struct eap_sm *sm, struct eap_ssl_data *data, - int verify_peer) -{ - data->eap = sm; - data->phase2 = sm->init_phase2; - - data->conn = tls_connection_init(sm->ssl_ctx); - if (data->conn == NULL) { - wpa_printf(MSG_INFO, "SSL: Failed to initialize new TLS " - "connection"); - return -1; - } - - if (tls_connection_set_verify(sm->ssl_ctx, data->conn, verify_peer)) { - wpa_printf(MSG_INFO, "SSL: Failed to configure verification " - "of TLS peer certificate"); - tls_connection_deinit(sm->ssl_ctx, data->conn); - data->conn = NULL; - return -1; - } - - data->tls_out_limit = sm->fragment_size > 0 ? sm->fragment_size : 1398; - if (data->phase2) { - /* Limit the fragment size in the inner TLS authentication - * since the outer authentication with EAP-PEAP does not yet - * support fragmentation */ - if (data->tls_out_limit > 100) - data->tls_out_limit -= 100; - } - return 0; -} - - -void eap_server_tls_ssl_deinit(struct eap_sm *sm, struct eap_ssl_data *data) -{ - tls_connection_deinit(sm->ssl_ctx, data->conn); - eap_server_tls_free_in_buf(data); - wpabuf_free(data->tls_out); - data->tls_out = NULL; -} - - -u8 * eap_server_tls_derive_key(struct eap_sm *sm, struct eap_ssl_data *data, - char *label, size_t len) -{ - struct tls_keys keys; - u8 *rnd = NULL, *out; - - out = os_malloc(len); - if (out == NULL) - return NULL; - - if (tls_connection_prf(sm->ssl_ctx, data->conn, label, 0, out, len) == - 0) - return out; - - if (tls_connection_get_keys(sm->ssl_ctx, data->conn, &keys)) - goto fail; - - if (keys.client_random == NULL || keys.server_random == NULL || - keys.master_key == NULL) - goto fail; - - rnd = os_malloc(keys.client_random_len + keys.server_random_len); - if (rnd == NULL) - goto fail; - os_memcpy(rnd, keys.client_random, keys.client_random_len); - os_memcpy(rnd + keys.client_random_len, keys.server_random, - keys.server_random_len); - - if (tls_prf(keys.master_key, keys.master_key_len, - label, rnd, keys.client_random_len + - keys.server_random_len, out, len)) - goto fail; - - os_free(rnd); - return out; - -fail: - os_free(out); - os_free(rnd); - return NULL; -} - - -struct wpabuf * eap_server_tls_build_msg(struct eap_ssl_data *data, - int eap_type, int version, u8 id) -{ - struct wpabuf *req; - u8 flags; - size_t send_len, plen; - - wpa_printf(MSG_DEBUG, "SSL: Generating Request"); - if (data->tls_out == NULL) { - wpa_printf(MSG_ERROR, "SSL: tls_out NULL in %s", __func__); - return NULL; - } - - flags = version; - send_len = wpabuf_len(data->tls_out) - data->tls_out_pos; - if (1 + send_len > data->tls_out_limit) { - send_len = data->tls_out_limit - 1; - flags |= EAP_TLS_FLAGS_MORE_FRAGMENTS; - if (data->tls_out_pos == 0) { - flags |= EAP_TLS_FLAGS_LENGTH_INCLUDED; - send_len -= 4; - } - } - - plen = 1 + send_len; - if (flags & EAP_TLS_FLAGS_LENGTH_INCLUDED) - plen += 4; - - req = eap_msg_alloc(EAP_VENDOR_IETF, eap_type, plen, - EAP_CODE_REQUEST, id); - if (req == NULL) - return NULL; - - wpabuf_put_u8(req, flags); /* Flags */ - if (flags & EAP_TLS_FLAGS_LENGTH_INCLUDED) - wpabuf_put_be32(req, wpabuf_len(data->tls_out)); - - wpabuf_put_data(req, wpabuf_head_u8(data->tls_out) + data->tls_out_pos, - send_len); - data->tls_out_pos += send_len; - - if (data->tls_out_pos == wpabuf_len(data->tls_out)) { - wpa_printf(MSG_DEBUG, "SSL: Sending out %lu bytes " - "(message sent completely)", - (unsigned long) send_len); - wpabuf_free(data->tls_out); - data->tls_out = NULL; - data->tls_out_pos = 0; - data->state = MSG; - } else { - wpa_printf(MSG_DEBUG, "SSL: Sending out %lu bytes " - "(%lu more to send)", (unsigned long) send_len, - (unsigned long) wpabuf_len(data->tls_out) - - data->tls_out_pos); - data->state = WAIT_FRAG_ACK; - } - - return req; -} - - -struct wpabuf * eap_server_tls_build_ack(u8 id, int eap_type, int version) -{ - struct wpabuf *req; - - req = eap_msg_alloc(EAP_VENDOR_IETF, eap_type, 1, EAP_CODE_REQUEST, - id); - if (req == NULL) - return NULL; - wpa_printf(MSG_DEBUG, "SSL: Building ACK"); - wpabuf_put_u8(req, version); /* Flags */ - return req; -} - - -static int eap_server_tls_process_cont(struct eap_ssl_data *data, - const u8 *buf, size_t len) -{ - /* Process continuation of a pending message */ - if (len > wpabuf_tailroom(data->tls_in)) { - wpa_printf(MSG_DEBUG, "SSL: Fragment overflow"); - return -1; - } - - wpabuf_put_data(data->tls_in, buf, len); - wpa_printf(MSG_DEBUG, "SSL: Received %lu bytes, waiting for %lu " - "bytes more", (unsigned long) len, - (unsigned long) wpabuf_tailroom(data->tls_in)); - - return 0; -} - - -static int eap_server_tls_process_fragment(struct eap_ssl_data *data, - u8 flags, u32 message_length, - const u8 *buf, size_t len) -{ - /* Process a fragment that is not the last one of the message */ - if (data->tls_in == NULL && !(flags & EAP_TLS_FLAGS_LENGTH_INCLUDED)) { - wpa_printf(MSG_DEBUG, "SSL: No Message Length field in a " - "fragmented packet"); - return -1; - } - - if (data->tls_in == NULL) { - /* First fragment of the message */ - - /* Limit length to avoid rogue peers from causing large - * memory allocations. */ - if (message_length > 65536) { - wpa_printf(MSG_INFO, "SSL: Too long TLS fragment (size" - " over 64 kB)"); - return -1; - } - - data->tls_in = wpabuf_alloc(message_length); - if (data->tls_in == NULL) { - wpa_printf(MSG_DEBUG, "SSL: No memory for message"); - return -1; - } - wpabuf_put_data(data->tls_in, buf, len); - wpa_printf(MSG_DEBUG, "SSL: Received %lu bytes in first " - "fragment, waiting for %lu bytes more", - (unsigned long) len, - (unsigned long) wpabuf_tailroom(data->tls_in)); - } - - return 0; -} - - -int eap_server_tls_phase1(struct eap_sm *sm, struct eap_ssl_data *data) -{ - if (data->tls_out) { - /* This should not happen.. */ - wpa_printf(MSG_INFO, "SSL: pending tls_out data when " - "processing new message"); - wpabuf_free(data->tls_out); - WPA_ASSERT(data->tls_out == NULL); - } - - data->tls_out = tls_connection_server_handshake(sm->ssl_ctx, - data->conn, - data->tls_in, NULL); - if (data->tls_out == NULL) { - wpa_printf(MSG_INFO, "SSL: TLS processing failed"); - return -1; - } - if (tls_connection_get_failed(sm->ssl_ctx, data->conn)) { - /* TLS processing has failed - return error */ - wpa_printf(MSG_DEBUG, "SSL: Failed - tls_out available to " - "report error"); - return -1; - } - - return 0; -} - - -static int eap_server_tls_reassemble(struct eap_ssl_data *data, u8 flags, - const u8 **pos, size_t *left) -{ - unsigned int tls_msg_len = 0; - const u8 *end = *pos + *left; - - if (flags & EAP_TLS_FLAGS_LENGTH_INCLUDED) { - if (*left < 4) { - wpa_printf(MSG_INFO, "SSL: Short frame with TLS " - "length"); - return -1; - } - tls_msg_len = WPA_GET_BE32(*pos); - wpa_printf(MSG_DEBUG, "SSL: TLS Message Length: %d", - tls_msg_len); - *pos += 4; - *left -= 4; - } - - wpa_printf(MSG_DEBUG, "SSL: Received packet: Flags 0x%x " - "Message Length %u", flags, tls_msg_len); - - if (data->state == WAIT_FRAG_ACK) { - if (*left != 0) { - wpa_printf(MSG_DEBUG, "SSL: Unexpected payload in " - "WAIT_FRAG_ACK state"); - return -1; - } - wpa_printf(MSG_DEBUG, "SSL: Fragment acknowledged"); - return 1; - } - - if (data->tls_in && - eap_server_tls_process_cont(data, *pos, end - *pos) < 0) - return -1; - - if (flags & EAP_TLS_FLAGS_MORE_FRAGMENTS) { - if (eap_server_tls_process_fragment(data, flags, tls_msg_len, - *pos, end - *pos) < 0) - return -1; - - data->state = FRAG_ACK; - return 1; - } - - if (data->state == FRAG_ACK) { - wpa_printf(MSG_DEBUG, "SSL: All fragments received"); - data->state = MSG; - } - - if (data->tls_in == NULL) { - /* Wrap unfragmented messages as wpabuf without extra copy */ - wpabuf_set(&data->tmpbuf, *pos, end - *pos); - data->tls_in = &data->tmpbuf; - } - - return 0; -} - - -static void eap_server_tls_free_in_buf(struct eap_ssl_data *data) -{ - if (data->tls_in != &data->tmpbuf) - wpabuf_free(data->tls_in); - data->tls_in = NULL; -} - - -struct wpabuf * eap_server_tls_encrypt(struct eap_sm *sm, - struct eap_ssl_data *data, - const struct wpabuf *plain) -{ - struct wpabuf *buf; - - buf = tls_connection_encrypt(sm->ssl_ctx, data->conn, - plain); - if (buf == NULL) { - wpa_printf(MSG_INFO, "SSL: Failed to encrypt Phase 2 data"); - return NULL; - } - - return buf; -} - - -int eap_server_tls_process(struct eap_sm *sm, struct eap_ssl_data *data, - struct wpabuf *respData, void *priv, int eap_type, - int (*proc_version)(struct eap_sm *sm, void *priv, - int peer_version), - void (*proc_msg)(struct eap_sm *sm, void *priv, - const struct wpabuf *respData)) -{ - const u8 *pos; - u8 flags; - size_t left; - int ret, res = 0; - - pos = eap_hdr_validate(EAP_VENDOR_IETF, eap_type, respData, &left); - if (pos == NULL || left < 1) - return 0; /* Should not happen - frame already validated */ - flags = *pos++; - left--; - wpa_printf(MSG_DEBUG, "SSL: Received packet(len=%lu) - Flags 0x%02x", - (unsigned long) wpabuf_len(respData), flags); - - if (proc_version && - proc_version(sm, priv, flags & EAP_TLS_VERSION_MASK) < 0) - return -1; - - ret = eap_server_tls_reassemble(data, flags, &pos, &left); - if (ret < 0) { - res = -1; - goto done; - } else if (ret == 1) - return 0; - - if (proc_msg) - proc_msg(sm, priv, respData); - - if (tls_connection_get_write_alerts(sm->ssl_ctx, data->conn) > 1) { - wpa_printf(MSG_INFO, "SSL: Locally detected fatal error in " - "TLS processing"); - res = -1; - } - -done: - eap_server_tls_free_in_buf(data); - - return res; -} diff --git a/hostapd-0.8/src/eap_server/eap_server_tnc.c b/hostapd-0.8/src/eap_server/eap_server_tnc.c deleted file mode 100644 index a2d6f17..0000000 --- a/hostapd-0.8/src/eap_server/eap_server_tnc.c +++ /dev/null @@ -1,582 +0,0 @@ -/* - * EAP server method: EAP-TNC (Trusted Network Connect) - * Copyright (c) 2007-2010, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#include "includes.h" - -#include "common.h" -#include "base64.h" -#include "eap_i.h" -#include "tncs.h" - - -struct eap_tnc_data { - enum eap_tnc_state { - START, CONTINUE, RECOMMENDATION, FRAG_ACK, WAIT_FRAG_ACK, DONE, - FAIL - } state; - enum { ALLOW, ISOLATE, NO_ACCESS, NO_RECOMMENDATION } recommendation; - struct tncs_data *tncs; - struct wpabuf *in_buf; - struct wpabuf *out_buf; - size_t out_used; - size_t fragment_size; - unsigned int was_done:1; - unsigned int was_fail:1; -}; - - -/* EAP-TNC Flags */ -#define EAP_TNC_FLAGS_LENGTH_INCLUDED 0x80 -#define EAP_TNC_FLAGS_MORE_FRAGMENTS 0x40 -#define EAP_TNC_FLAGS_START 0x20 -#define EAP_TNC_VERSION_MASK 0x07 - -#define EAP_TNC_VERSION 1 - - -static const char * eap_tnc_state_txt(enum eap_tnc_state state) -{ - switch (state) { - case START: - return "START"; - case CONTINUE: - return "CONTINUE"; - case RECOMMENDATION: - return "RECOMMENDATION"; - case FRAG_ACK: - return "FRAG_ACK"; - case WAIT_FRAG_ACK: - return "WAIT_FRAG_ACK"; - case DONE: - return "DONE"; - case FAIL: - return "FAIL"; - } - return "??"; -} - - -static void eap_tnc_set_state(struct eap_tnc_data *data, - enum eap_tnc_state new_state) -{ - wpa_printf(MSG_DEBUG, "EAP-TNC: %s -> %s", - eap_tnc_state_txt(data->state), - eap_tnc_state_txt(new_state)); - data->state = new_state; -} - - -static void * eap_tnc_init(struct eap_sm *sm) -{ - struct eap_tnc_data *data; - - data = os_zalloc(sizeof(*data)); - if (data == NULL) - return NULL; - eap_tnc_set_state(data, START); - data->tncs = tncs_init(); - if (data->tncs == NULL) { - os_free(data); - return NULL; - } - - data->fragment_size = sm->fragment_size > 100 ? - sm->fragment_size - 98 : 1300; - - return data; -} - - -static void eap_tnc_reset(struct eap_sm *sm, void *priv) -{ - struct eap_tnc_data *data = priv; - wpabuf_free(data->in_buf); - wpabuf_free(data->out_buf); - tncs_deinit(data->tncs); - os_free(data); -} - - -static struct wpabuf * eap_tnc_build_start(struct eap_sm *sm, - struct eap_tnc_data *data, u8 id) -{ - struct wpabuf *req; - - req = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_TNC, 1, EAP_CODE_REQUEST, - id); - if (req == NULL) { - wpa_printf(MSG_ERROR, "EAP-TNC: Failed to allocate memory for " - "request"); - eap_tnc_set_state(data, FAIL); - return NULL; - } - - wpabuf_put_u8(req, EAP_TNC_FLAGS_START | EAP_TNC_VERSION); - - eap_tnc_set_state(data, CONTINUE); - - return req; -} - - -static struct wpabuf * eap_tnc_build(struct eap_sm *sm, - struct eap_tnc_data *data) -{ - struct wpabuf *req; - u8 *rpos, *rpos1; - size_t rlen; - char *start_buf, *end_buf; - size_t start_len, end_len; - size_t imv_len; - - imv_len = tncs_total_send_len(data->tncs); - - start_buf = tncs_if_tnccs_start(data->tncs); - if (start_buf == NULL) - return NULL; - start_len = os_strlen(start_buf); - end_buf = tncs_if_tnccs_end(); - if (end_buf == NULL) { - os_free(start_buf); - return NULL; - } - end_len = os_strlen(end_buf); - - rlen = start_len + imv_len + end_len; - req = wpabuf_alloc(rlen); - if (req == NULL) { - os_free(start_buf); - os_free(end_buf); - return NULL; - } - - wpabuf_put_data(req, start_buf, start_len); - os_free(start_buf); - - rpos1 = wpabuf_put(req, 0); - rpos = tncs_copy_send_buf(data->tncs, rpos1); - wpabuf_put(req, rpos - rpos1); - - wpabuf_put_data(req, end_buf, end_len); - os_free(end_buf); - - wpa_hexdump_ascii(MSG_MSGDUMP, "EAP-TNC: Request", - wpabuf_head(req), wpabuf_len(req)); - - return req; -} - - -static struct wpabuf * eap_tnc_build_recommendation(struct eap_sm *sm, - struct eap_tnc_data *data) -{ - switch (data->recommendation) { - case ALLOW: - eap_tnc_set_state(data, DONE); - break; - case ISOLATE: - eap_tnc_set_state(data, FAIL); - /* TODO: support assignment to a different VLAN */ - break; - case NO_ACCESS: - eap_tnc_set_state(data, FAIL); - break; - case NO_RECOMMENDATION: - eap_tnc_set_state(data, DONE); - break; - default: - wpa_printf(MSG_DEBUG, "EAP-TNC: Unknown recommendation"); - return NULL; - } - - return eap_tnc_build(sm, data); -} - - -static struct wpabuf * eap_tnc_build_frag_ack(u8 id, u8 code) -{ - struct wpabuf *msg; - - msg = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_TNC, 1, code, id); - if (msg == NULL) { - wpa_printf(MSG_ERROR, "EAP-TNC: Failed to allocate memory " - "for fragment ack"); - return NULL; - } - wpabuf_put_u8(msg, EAP_TNC_VERSION); /* Flags */ - - wpa_printf(MSG_DEBUG, "EAP-TNC: Send fragment ack"); - - return msg; -} - - -static struct wpabuf * eap_tnc_build_msg(struct eap_tnc_data *data, u8 id) -{ - struct wpabuf *req; - u8 flags; - size_t send_len, plen; - - wpa_printf(MSG_DEBUG, "EAP-TNC: Generating Request"); - - flags = EAP_TNC_VERSION; - send_len = wpabuf_len(data->out_buf) - data->out_used; - if (1 + send_len > data->fragment_size) { - send_len = data->fragment_size - 1; - flags |= EAP_TNC_FLAGS_MORE_FRAGMENTS; - if (data->out_used == 0) { - flags |= EAP_TNC_FLAGS_LENGTH_INCLUDED; - send_len -= 4; - } - } - - plen = 1 + send_len; - if (flags & EAP_TNC_FLAGS_LENGTH_INCLUDED) - plen += 4; - req = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_TNC, plen, - EAP_CODE_REQUEST, id); - if (req == NULL) - return NULL; - - wpabuf_put_u8(req, flags); /* Flags */ - if (flags & EAP_TNC_FLAGS_LENGTH_INCLUDED) - wpabuf_put_be32(req, wpabuf_len(data->out_buf)); - - wpabuf_put_data(req, wpabuf_head_u8(data->out_buf) + data->out_used, - send_len); - data->out_used += send_len; - - if (data->out_used == wpabuf_len(data->out_buf)) { - wpa_printf(MSG_DEBUG, "EAP-TNC: Sending out %lu bytes " - "(message sent completely)", - (unsigned long) send_len); - wpabuf_free(data->out_buf); - data->out_buf = NULL; - data->out_used = 0; - if (data->was_fail) - eap_tnc_set_state(data, FAIL); - else if (data->was_done) - eap_tnc_set_state(data, DONE); - } else { - wpa_printf(MSG_DEBUG, "EAP-TNC: Sending out %lu bytes " - "(%lu more to send)", (unsigned long) send_len, - (unsigned long) wpabuf_len(data->out_buf) - - data->out_used); - if (data->state == FAIL) - data->was_fail = 1; - else if (data->state == DONE) - data->was_done = 1; - eap_tnc_set_state(data, WAIT_FRAG_ACK); - } - - return req; -} - - -static struct wpabuf * eap_tnc_buildReq(struct eap_sm *sm, void *priv, u8 id) -{ - struct eap_tnc_data *data = priv; - - switch (data->state) { - case START: - tncs_init_connection(data->tncs); - return eap_tnc_build_start(sm, data, id); - case CONTINUE: - if (data->out_buf == NULL) { - data->out_buf = eap_tnc_build(sm, data); - if (data->out_buf == NULL) { - wpa_printf(MSG_DEBUG, "EAP-TNC: Failed to " - "generate message"); - return NULL; - } - data->out_used = 0; - } - return eap_tnc_build_msg(data, id); - case RECOMMENDATION: - if (data->out_buf == NULL) { - data->out_buf = eap_tnc_build_recommendation(sm, data); - if (data->out_buf == NULL) { - wpa_printf(MSG_DEBUG, "EAP-TNC: Failed to " - "generate recommendation message"); - return NULL; - } - data->out_used = 0; - } - return eap_tnc_build_msg(data, id); - case WAIT_FRAG_ACK: - return eap_tnc_build_msg(data, id); - case FRAG_ACK: - return eap_tnc_build_frag_ack(id, EAP_CODE_REQUEST); - case DONE: - case FAIL: - return NULL; - } - - return NULL; -} - - -static Boolean eap_tnc_check(struct eap_sm *sm, void *priv, - struct wpabuf *respData) -{ - struct eap_tnc_data *data = priv; - const u8 *pos; - size_t len; - - pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_TNC, respData, - &len); - if (pos == NULL) { - wpa_printf(MSG_INFO, "EAP-TNC: Invalid frame"); - return TRUE; - } - - if (len == 0 && data->state != WAIT_FRAG_ACK) { - wpa_printf(MSG_INFO, "EAP-TNC: Invalid frame (empty)"); - return TRUE; - } - - if (len == 0) - return FALSE; /* Fragment ACK does not include flags */ - - if ((*pos & EAP_TNC_VERSION_MASK) != EAP_TNC_VERSION) { - wpa_printf(MSG_DEBUG, "EAP-TNC: Unsupported version %d", - *pos & EAP_TNC_VERSION_MASK); - return TRUE; - } - - if (*pos & EAP_TNC_FLAGS_START) { - wpa_printf(MSG_DEBUG, "EAP-TNC: Peer used Start flag"); - return TRUE; - } - - return FALSE; -} - - -static void tncs_process(struct eap_tnc_data *data, struct wpabuf *inbuf) -{ - enum tncs_process_res res; - - res = tncs_process_if_tnccs(data->tncs, wpabuf_head(inbuf), - wpabuf_len(inbuf)); - switch (res) { - case TNCCS_RECOMMENDATION_ALLOW: - wpa_printf(MSG_DEBUG, "EAP-TNC: TNCS allowed access"); - eap_tnc_set_state(data, RECOMMENDATION); - data->recommendation = ALLOW; - break; - case TNCCS_RECOMMENDATION_NO_RECOMMENDATION: - wpa_printf(MSG_DEBUG, "EAP-TNC: TNCS has no recommendation"); - eap_tnc_set_state(data, RECOMMENDATION); - data->recommendation = NO_RECOMMENDATION; - break; - case TNCCS_RECOMMENDATION_ISOLATE: - wpa_printf(MSG_DEBUG, "EAP-TNC: TNCS requested isolation"); - eap_tnc_set_state(data, RECOMMENDATION); - data->recommendation = ISOLATE; - break; - case TNCCS_RECOMMENDATION_NO_ACCESS: - wpa_printf(MSG_DEBUG, "EAP-TNC: TNCS rejected access"); - eap_tnc_set_state(data, RECOMMENDATION); - data->recommendation = NO_ACCESS; - break; - case TNCCS_PROCESS_ERROR: - wpa_printf(MSG_DEBUG, "EAP-TNC: TNCS processing error"); - eap_tnc_set_state(data, FAIL); - break; - default: - break; - } -} - - -static int eap_tnc_process_cont(struct eap_tnc_data *data, - const u8 *buf, size_t len) -{ - /* Process continuation of a pending message */ - if (len > wpabuf_tailroom(data->in_buf)) { - wpa_printf(MSG_DEBUG, "EAP-TNC: Fragment overflow"); - eap_tnc_set_state(data, FAIL); - return -1; - } - - wpabuf_put_data(data->in_buf, buf, len); - wpa_printf(MSG_DEBUG, "EAP-TNC: Received %lu bytes, waiting for %lu " - "bytes more", (unsigned long) len, - (unsigned long) wpabuf_tailroom(data->in_buf)); - - return 0; -} - - -static int eap_tnc_process_fragment(struct eap_tnc_data *data, - u8 flags, u32 message_length, - const u8 *buf, size_t len) -{ - /* Process a fragment that is not the last one of the message */ - if (data->in_buf == NULL && !(flags & EAP_TNC_FLAGS_LENGTH_INCLUDED)) { - wpa_printf(MSG_DEBUG, "EAP-TNC: No Message Length field in a " - "fragmented packet"); - return -1; - } - - if (data->in_buf == NULL) { - /* First fragment of the message */ - data->in_buf = wpabuf_alloc(message_length); - if (data->in_buf == NULL) { - wpa_printf(MSG_DEBUG, "EAP-TNC: No memory for " - "message"); - return -1; - } - wpabuf_put_data(data->in_buf, buf, len); - wpa_printf(MSG_DEBUG, "EAP-TNC: Received %lu bytes in first " - "fragment, waiting for %lu bytes more", - (unsigned long) len, - (unsigned long) wpabuf_tailroom(data->in_buf)); - } - - return 0; -} - - -static void eap_tnc_process(struct eap_sm *sm, void *priv, - struct wpabuf *respData) -{ - struct eap_tnc_data *data = priv; - const u8 *pos, *end; - size_t len; - u8 flags; - u32 message_length = 0; - struct wpabuf tmpbuf; - - pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_TNC, respData, &len); - if (pos == NULL) - return; /* Should not happen; message already verified */ - - end = pos + len; - - if (len == 1 && (data->state == DONE || data->state == FAIL)) { - wpa_printf(MSG_DEBUG, "EAP-TNC: Peer acknowledged the last " - "message"); - return; - } - - if (len == 0) { - /* fragment ack */ - flags = 0; - } else - flags = *pos++; - - if (flags & EAP_TNC_FLAGS_LENGTH_INCLUDED) { - if (end - pos < 4) { - wpa_printf(MSG_DEBUG, "EAP-TNC: Message underflow"); - eap_tnc_set_state(data, FAIL); - return; - } - message_length = WPA_GET_BE32(pos); - pos += 4; - - if (message_length < (u32) (end - pos)) { - wpa_printf(MSG_DEBUG, "EAP-TNC: Invalid Message " - "Length (%d; %ld remaining in this msg)", - message_length, (long) (end - pos)); - eap_tnc_set_state(data, FAIL); - return; - } - } - wpa_printf(MSG_DEBUG, "EAP-TNC: Received packet: Flags 0x%x " - "Message Length %u", flags, message_length); - - if (data->state == WAIT_FRAG_ACK) { - if (len > 1) { - wpa_printf(MSG_DEBUG, "EAP-TNC: Unexpected payload " - "in WAIT_FRAG_ACK state"); - eap_tnc_set_state(data, FAIL); - return; - } - wpa_printf(MSG_DEBUG, "EAP-TNC: Fragment acknowledged"); - eap_tnc_set_state(data, CONTINUE); - return; - } - - if (data->in_buf && eap_tnc_process_cont(data, pos, end - pos) < 0) { - eap_tnc_set_state(data, FAIL); - return; - } - - if (flags & EAP_TNC_FLAGS_MORE_FRAGMENTS) { - if (eap_tnc_process_fragment(data, flags, message_length, - pos, end - pos) < 0) - eap_tnc_set_state(data, FAIL); - else - eap_tnc_set_state(data, FRAG_ACK); - return; - } else if (data->state == FRAG_ACK) { - wpa_printf(MSG_DEBUG, "EAP-TNC: All fragments received"); - eap_tnc_set_state(data, CONTINUE); - } - - if (data->in_buf == NULL) { - /* Wrap unfragmented messages as wpabuf without extra copy */ - wpabuf_set(&tmpbuf, pos, end - pos); - data->in_buf = &tmpbuf; - } - - wpa_hexdump_ascii(MSG_MSGDUMP, "EAP-TNC: Received payload", - wpabuf_head(data->in_buf), wpabuf_len(data->in_buf)); - tncs_process(data, data->in_buf); - - if (data->in_buf != &tmpbuf) - wpabuf_free(data->in_buf); - data->in_buf = NULL; -} - - -static Boolean eap_tnc_isDone(struct eap_sm *sm, void *priv) -{ - struct eap_tnc_data *data = priv; - return data->state == DONE || data->state == FAIL; -} - - -static Boolean eap_tnc_isSuccess(struct eap_sm *sm, void *priv) -{ - struct eap_tnc_data *data = priv; - return data->state == DONE; -} - - -int eap_server_tnc_register(void) -{ - struct eap_method *eap; - int ret; - - eap = eap_server_method_alloc(EAP_SERVER_METHOD_INTERFACE_VERSION, - EAP_VENDOR_IETF, EAP_TYPE_TNC, "TNC"); - if (eap == NULL) - return -1; - - eap->init = eap_tnc_init; - eap->reset = eap_tnc_reset; - eap->buildReq = eap_tnc_buildReq; - eap->check = eap_tnc_check; - eap->process = eap_tnc_process; - eap->isDone = eap_tnc_isDone; - eap->isSuccess = eap_tnc_isSuccess; - - ret = eap_server_method_register(eap); - if (ret) - eap_server_method_free(eap); - return ret; -} diff --git a/hostapd-0.8/src/eap_server/eap_server_ttls.c b/hostapd-0.8/src/eap_server/eap_server_ttls.c deleted file mode 100644 index 702c50c..0000000 --- a/hostapd-0.8/src/eap_server/eap_server_ttls.c +++ /dev/null @@ -1,1430 +0,0 @@ -/* - * hostapd / EAP-TTLS (RFC 5281) - * Copyright (c) 2004-2008, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#include "includes.h" - -#include "common.h" -#include "crypto/ms_funcs.h" -#include "crypto/sha1.h" -#include "crypto/tls.h" -#include "eap_server/eap_i.h" -#include "eap_server/eap_tls_common.h" -#include "eap_common/chap.h" -#include "eap_common/eap_ttls.h" - - -/* Maximum supported TTLS version - * 0 = RFC 5281 - * 1 = draft-funk-eap-ttls-v1-00.txt - */ -#ifndef EAP_TTLS_VERSION -#define EAP_TTLS_VERSION 0 /* TTLSv1 implementation is not yet complete */ -#endif /* EAP_TTLS_VERSION */ - - -#define MSCHAPV2_KEY_LEN 16 - - -static void eap_ttls_reset(struct eap_sm *sm, void *priv); - - -struct eap_ttls_data { - struct eap_ssl_data ssl; - enum { - START, PHASE1, PHASE2_START, PHASE2_METHOD, - PHASE2_MSCHAPV2_RESP, PHASE_FINISHED, SUCCESS, FAILURE - } state; - - int ttls_version; - int force_version; - const struct eap_method *phase2_method; - void *phase2_priv; - int mschapv2_resp_ok; - u8 mschapv2_auth_response[20]; - u8 mschapv2_ident; - int tls_ia_configured; - struct wpabuf *pending_phase2_eap_resp; - int tnc_started; -}; - - -static const char * eap_ttls_state_txt(int state) -{ - switch (state) { - case START: - return "START"; - case PHASE1: - return "PHASE1"; - case PHASE2_START: - return "PHASE2_START"; - case PHASE2_METHOD: - return "PHASE2_METHOD"; - case PHASE2_MSCHAPV2_RESP: - return "PHASE2_MSCHAPV2_RESP"; - case PHASE_FINISHED: - return "PHASE_FINISHED"; - case SUCCESS: - return "SUCCESS"; - case FAILURE: - return "FAILURE"; - default: - return "Unknown?!"; - } -} - - -static void eap_ttls_state(struct eap_ttls_data *data, int state) -{ - wpa_printf(MSG_DEBUG, "EAP-TTLS: %s -> %s", - eap_ttls_state_txt(data->state), - eap_ttls_state_txt(state)); - data->state = state; -} - - -static u8 * eap_ttls_avp_hdr(u8 *avphdr, u32 avp_code, u32 vendor_id, - int mandatory, size_t len) -{ - struct ttls_avp_vendor *avp; - u8 flags; - size_t hdrlen; - - avp = (struct ttls_avp_vendor *) avphdr; - flags = mandatory ? AVP_FLAGS_MANDATORY : 0; - if (vendor_id) { - flags |= AVP_FLAGS_VENDOR; - hdrlen = sizeof(*avp); - avp->vendor_id = host_to_be32(vendor_id); - } else { - hdrlen = sizeof(struct ttls_avp); - } - - avp->avp_code = host_to_be32(avp_code); - avp->avp_length = host_to_be32((flags << 24) | (hdrlen + len)); - - return avphdr + hdrlen; -} - - -static struct wpabuf * eap_ttls_avp_encapsulate(struct wpabuf *resp, - u32 avp_code, int mandatory) -{ - struct wpabuf *avp; - u8 *pos; - - avp = wpabuf_alloc(sizeof(struct ttls_avp) + wpabuf_len(resp) + 4); - if (avp == NULL) { - wpabuf_free(resp); - return NULL; - } - - pos = eap_ttls_avp_hdr(wpabuf_mhead(avp), avp_code, 0, mandatory, - wpabuf_len(resp)); - os_memcpy(pos, wpabuf_head(resp), wpabuf_len(resp)); - pos += wpabuf_len(resp); - AVP_PAD((const u8 *) wpabuf_head(avp), pos); - wpabuf_free(resp); - wpabuf_put(avp, pos - (u8 *) wpabuf_head(avp)); - return avp; -} - - -struct eap_ttls_avp { - /* Note: eap is allocated memory; caller is responsible for freeing - * it. All the other pointers are pointing to the packet data, i.e., - * they must not be freed separately. */ - u8 *eap; - size_t eap_len; - u8 *user_name; - size_t user_name_len; - u8 *user_password; - size_t user_password_len; - u8 *chap_challenge; - size_t chap_challenge_len; - u8 *chap_password; - size_t chap_password_len; - u8 *mschap_challenge; - size_t mschap_challenge_len; - u8 *mschap_response; - size_t mschap_response_len; - u8 *mschap2_response; - size_t mschap2_response_len; -}; - - -static int eap_ttls_avp_parse(struct wpabuf *buf, struct eap_ttls_avp *parse) -{ - struct ttls_avp *avp; - u8 *pos; - int left; - - pos = wpabuf_mhead(buf); - left = wpabuf_len(buf); - os_memset(parse, 0, sizeof(*parse)); - - while (left > 0) { - u32 avp_code, avp_length, vendor_id = 0; - u8 avp_flags, *dpos; - size_t pad, dlen; - avp = (struct ttls_avp *) pos; - avp_code = be_to_host32(avp->avp_code); - avp_length = be_to_host32(avp->avp_length); - avp_flags = (avp_length >> 24) & 0xff; - avp_length &= 0xffffff; - wpa_printf(MSG_DEBUG, "EAP-TTLS: AVP: code=%d flags=0x%02x " - "length=%d", (int) avp_code, avp_flags, - (int) avp_length); - if ((int) avp_length > left) { - wpa_printf(MSG_WARNING, "EAP-TTLS: AVP overflow " - "(len=%d, left=%d) - dropped", - (int) avp_length, left); - goto fail; - } - if (avp_length < sizeof(*avp)) { - wpa_printf(MSG_WARNING, "EAP-TTLS: Invalid AVP length " - "%d", avp_length); - goto fail; - } - dpos = (u8 *) (avp + 1); - dlen = avp_length - sizeof(*avp); - if (avp_flags & AVP_FLAGS_VENDOR) { - if (dlen < 4) { - wpa_printf(MSG_WARNING, "EAP-TTLS: vendor AVP " - "underflow"); - goto fail; - } - vendor_id = be_to_host32(* (be32 *) dpos); - wpa_printf(MSG_DEBUG, "EAP-TTLS: AVP vendor_id %d", - (int) vendor_id); - dpos += 4; - dlen -= 4; - } - - wpa_hexdump(MSG_DEBUG, "EAP-TTLS: AVP data", dpos, dlen); - - if (vendor_id == 0 && avp_code == RADIUS_ATTR_EAP_MESSAGE) { - wpa_printf(MSG_DEBUG, "EAP-TTLS: AVP - EAP Message"); - if (parse->eap == NULL) { - parse->eap = os_malloc(dlen); - if (parse->eap == NULL) { - wpa_printf(MSG_WARNING, "EAP-TTLS: " - "failed to allocate memory " - "for Phase 2 EAP data"); - goto fail; - } - os_memcpy(parse->eap, dpos, dlen); - parse->eap_len = dlen; - } else { - u8 *neweap = os_realloc(parse->eap, - parse->eap_len + dlen); - if (neweap == NULL) { - wpa_printf(MSG_WARNING, "EAP-TTLS: " - "failed to allocate memory " - "for Phase 2 EAP data"); - goto fail; - } - os_memcpy(neweap + parse->eap_len, dpos, dlen); - parse->eap = neweap; - parse->eap_len += dlen; - } - } else if (vendor_id == 0 && - avp_code == RADIUS_ATTR_USER_NAME) { - wpa_hexdump_ascii(MSG_DEBUG, "EAP-TTLS: User-Name", - dpos, dlen); - parse->user_name = dpos; - parse->user_name_len = dlen; - } else if (vendor_id == 0 && - avp_code == RADIUS_ATTR_USER_PASSWORD) { - u8 *password = dpos; - size_t password_len = dlen; - while (password_len > 0 && - password[password_len - 1] == '\0') { - password_len--; - } - wpa_hexdump_ascii_key(MSG_DEBUG, "EAP-TTLS: " - "User-Password (PAP)", - password, password_len); - parse->user_password = password; - parse->user_password_len = password_len; - } else if (vendor_id == 0 && - avp_code == RADIUS_ATTR_CHAP_CHALLENGE) { - wpa_hexdump(MSG_DEBUG, - "EAP-TTLS: CHAP-Challenge (CHAP)", - dpos, dlen); - parse->chap_challenge = dpos; - parse->chap_challenge_len = dlen; - } else if (vendor_id == 0 && - avp_code == RADIUS_ATTR_CHAP_PASSWORD) { - wpa_hexdump(MSG_DEBUG, - "EAP-TTLS: CHAP-Password (CHAP)", - dpos, dlen); - parse->chap_password = dpos; - parse->chap_password_len = dlen; - } else if (vendor_id == RADIUS_VENDOR_ID_MICROSOFT && - avp_code == RADIUS_ATTR_MS_CHAP_CHALLENGE) { - wpa_hexdump(MSG_DEBUG, - "EAP-TTLS: MS-CHAP-Challenge", - dpos, dlen); - parse->mschap_challenge = dpos; - parse->mschap_challenge_len = dlen; - } else if (vendor_id == RADIUS_VENDOR_ID_MICROSOFT && - avp_code == RADIUS_ATTR_MS_CHAP_RESPONSE) { - wpa_hexdump(MSG_DEBUG, - "EAP-TTLS: MS-CHAP-Response (MSCHAP)", - dpos, dlen); - parse->mschap_response = dpos; - parse->mschap_response_len = dlen; - } else if (vendor_id == RADIUS_VENDOR_ID_MICROSOFT && - avp_code == RADIUS_ATTR_MS_CHAP2_RESPONSE) { - wpa_hexdump(MSG_DEBUG, - "EAP-TTLS: MS-CHAP2-Response (MSCHAPV2)", - dpos, dlen); - parse->mschap2_response = dpos; - parse->mschap2_response_len = dlen; - } else if (avp_flags & AVP_FLAGS_MANDATORY) { - wpa_printf(MSG_WARNING, "EAP-TTLS: Unsupported " - "mandatory AVP code %d vendor_id %d - " - "dropped", (int) avp_code, (int) vendor_id); - goto fail; - } else { - wpa_printf(MSG_DEBUG, "EAP-TTLS: Ignoring unsupported " - "AVP code %d vendor_id %d", - (int) avp_code, (int) vendor_id); - } - - pad = (4 - (avp_length & 3)) & 3; - pos += avp_length + pad; - left -= avp_length + pad; - } - - return 0; - -fail: - os_free(parse->eap); - parse->eap = NULL; - return -1; -} - - -static u8 * eap_ttls_implicit_challenge(struct eap_sm *sm, - struct eap_ttls_data *data, size_t len) -{ - struct tls_keys keys; - u8 *challenge, *rnd; - - if (data->ttls_version == 0) { - return eap_server_tls_derive_key(sm, &data->ssl, - "ttls challenge", len); - } - - os_memset(&keys, 0, sizeof(keys)); - if (tls_connection_get_keys(sm->ssl_ctx, data->ssl.conn, &keys) || - keys.client_random == NULL || keys.server_random == NULL || - keys.inner_secret == NULL) { - wpa_printf(MSG_INFO, "EAP-TTLS: Could not get inner secret, " - "client random, or server random to derive " - "implicit challenge"); - return NULL; - } - - rnd = os_malloc(keys.client_random_len + keys.server_random_len); - challenge = os_malloc(len); - if (rnd == NULL || challenge == NULL) { - wpa_printf(MSG_INFO, "EAP-TTLS: No memory for implicit " - "challenge derivation"); - os_free(rnd); - os_free(challenge); - return NULL; - } - os_memcpy(rnd, keys.server_random, keys.server_random_len); - os_memcpy(rnd + keys.server_random_len, keys.client_random, - keys.client_random_len); - - if (tls_prf(keys.inner_secret, keys.inner_secret_len, - "inner application challenge", rnd, - keys.client_random_len + keys.server_random_len, - challenge, len)) { - wpa_printf(MSG_DEBUG, "EAP-TTLS: Failed to derive implicit " - "challenge"); - os_free(rnd); - os_free(challenge); - return NULL; - } - - os_free(rnd); - - wpa_hexdump_key(MSG_DEBUG, "EAP-TTLS: Derived implicit challenge", - challenge, len); - - return challenge; -} - - -static void * eap_ttls_init(struct eap_sm *sm) -{ - struct eap_ttls_data *data; - - data = os_zalloc(sizeof(*data)); - if (data == NULL) - return NULL; - data->ttls_version = EAP_TTLS_VERSION; - data->force_version = -1; - if (sm->user && sm->user->force_version >= 0) { - data->force_version = sm->user->force_version; - wpa_printf(MSG_DEBUG, "EAP-TTLS: forcing version %d", - data->force_version); - data->ttls_version = data->force_version; - } - data->state = START; - - if (!(tls_capabilities(sm->ssl_ctx) & TLS_CAPABILITY_IA) && - data->ttls_version > 0) { - if (data->force_version > 0) { - wpa_printf(MSG_INFO, "EAP-TTLS: Forced TTLSv%d and " - "TLS library does not support TLS/IA.", - data->force_version); - eap_ttls_reset(sm, data); - return NULL; - } - data->ttls_version = 0; - } - - if (eap_server_tls_ssl_init(sm, &data->ssl, 0)) { - wpa_printf(MSG_INFO, "EAP-TTLS: Failed to initialize SSL."); - eap_ttls_reset(sm, data); - return NULL; - } - - return data; -} - - -static void eap_ttls_reset(struct eap_sm *sm, void *priv) -{ - struct eap_ttls_data *data = priv; - if (data == NULL) - return; - if (data->phase2_priv && data->phase2_method) - data->phase2_method->reset(sm, data->phase2_priv); - eap_server_tls_ssl_deinit(sm, &data->ssl); - wpabuf_free(data->pending_phase2_eap_resp); - os_free(data); -} - - -static struct wpabuf * eap_ttls_build_start(struct eap_sm *sm, - struct eap_ttls_data *data, u8 id) -{ - struct wpabuf *req; - - req = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_TTLS, 1, - EAP_CODE_REQUEST, id); - if (req == NULL) { - wpa_printf(MSG_ERROR, "EAP-TTLS: Failed to allocate memory for" - " request"); - eap_ttls_state(data, FAILURE); - return NULL; - } - - wpabuf_put_u8(req, EAP_TLS_FLAGS_START | data->ttls_version); - - eap_ttls_state(data, PHASE1); - - return req; -} - - -static struct wpabuf * eap_ttls_build_phase2_eap_req( - struct eap_sm *sm, struct eap_ttls_data *data, u8 id) -{ - struct wpabuf *buf, *encr_req; - - - buf = data->phase2_method->buildReq(sm, data->phase2_priv, id); - if (buf == NULL) - return NULL; - - wpa_hexdump_buf_key(MSG_DEBUG, - "EAP-TTLS/EAP: Encapsulate Phase 2 data", buf); - - buf = eap_ttls_avp_encapsulate(buf, RADIUS_ATTR_EAP_MESSAGE, 1); - if (buf == NULL) { - wpa_printf(MSG_DEBUG, "EAP-TTLS/EAP: Failed to encapsulate " - "packet"); - return NULL; - } - - wpa_hexdump_buf_key(MSG_DEBUG, "EAP-TTLS/EAP: Encrypt encapsulated " - "Phase 2 data", buf); - - encr_req = eap_server_tls_encrypt(sm, &data->ssl, buf); - wpabuf_free(buf); - - return encr_req; -} - - -static struct wpabuf * eap_ttls_build_phase2_mschapv2( - struct eap_sm *sm, struct eap_ttls_data *data) -{ - struct wpabuf *encr_req, msgbuf; - u8 *req, *pos, *end; - int ret; - - pos = req = os_malloc(100); - if (req == NULL) - return NULL; - end = req + 100; - - if (data->mschapv2_resp_ok) { - pos = eap_ttls_avp_hdr(pos, RADIUS_ATTR_MS_CHAP2_SUCCESS, - RADIUS_VENDOR_ID_MICROSOFT, 1, 43); - *pos++ = data->mschapv2_ident; - ret = os_snprintf((char *) pos, end - pos, "S="); - if (ret >= 0 && ret < end - pos) - pos += ret; - pos += wpa_snprintf_hex_uppercase( - (char *) pos, end - pos, data->mschapv2_auth_response, - sizeof(data->mschapv2_auth_response)); - } else { - pos = eap_ttls_avp_hdr(pos, RADIUS_ATTR_MS_CHAP_ERROR, - RADIUS_VENDOR_ID_MICROSOFT, 1, 6); - os_memcpy(pos, "Failed", 6); - pos += 6; - AVP_PAD(req, pos); - } - - wpabuf_set(&msgbuf, req, pos - req); - wpa_hexdump_buf_key(MSG_DEBUG, "EAP-TTLS/MSCHAPV2: Encrypting Phase 2 " - "data", &msgbuf); - - encr_req = eap_server_tls_encrypt(sm, &data->ssl, &msgbuf); - os_free(req); - - return encr_req; -} - - -static struct wpabuf * eap_ttls_build_phase_finished( - struct eap_sm *sm, struct eap_ttls_data *data, int final) -{ - return tls_connection_ia_send_phase_finished(sm->ssl_ctx, - data->ssl.conn, final); -} - - -static struct wpabuf * eap_ttls_buildReq(struct eap_sm *sm, void *priv, u8 id) -{ - struct eap_ttls_data *data = priv; - - if (data->ssl.state == FRAG_ACK) { - return eap_server_tls_build_ack(id, EAP_TYPE_TTLS, - data->ttls_version); - } - - if (data->ssl.state == WAIT_FRAG_ACK) { - return eap_server_tls_build_msg(&data->ssl, EAP_TYPE_TTLS, - data->ttls_version, id); - } - - switch (data->state) { - case START: - return eap_ttls_build_start(sm, data, id); - case PHASE1: - if (tls_connection_established(sm->ssl_ctx, data->ssl.conn)) { - wpa_printf(MSG_DEBUG, "EAP-TTLS: Phase1 done, " - "starting Phase2"); - eap_ttls_state(data, PHASE2_START); - } - break; - case PHASE2_METHOD: - wpabuf_free(data->ssl.tls_out); - data->ssl.tls_out_pos = 0; - data->ssl.tls_out = eap_ttls_build_phase2_eap_req(sm, data, - id); - break; - case PHASE2_MSCHAPV2_RESP: - wpabuf_free(data->ssl.tls_out); - data->ssl.tls_out_pos = 0; - data->ssl.tls_out = eap_ttls_build_phase2_mschapv2(sm, data); - break; - case PHASE_FINISHED: - wpabuf_free(data->ssl.tls_out); - data->ssl.tls_out_pos = 0; - data->ssl.tls_out = eap_ttls_build_phase_finished(sm, data, 1); - break; - default: - wpa_printf(MSG_DEBUG, "EAP-TTLS: %s - unexpected state %d", - __func__, data->state); - return NULL; - } - - return eap_server_tls_build_msg(&data->ssl, EAP_TYPE_TTLS, - data->ttls_version, id); -} - - -static Boolean eap_ttls_check(struct eap_sm *sm, void *priv, - struct wpabuf *respData) -{ - const u8 *pos; - size_t len; - - pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_TTLS, respData, &len); - if (pos == NULL || len < 1) { - wpa_printf(MSG_INFO, "EAP-TTLS: Invalid frame"); - return TRUE; - } - - return FALSE; -} - - -static int eap_ttls_ia_permute_inner_secret(struct eap_sm *sm, - struct eap_ttls_data *data, - const u8 *key, size_t key_len) -{ - u8 *buf; - size_t buf_len; - int ret; - - if (key) { - buf_len = 2 + key_len; - buf = os_malloc(buf_len); - if (buf == NULL) - return -1; - WPA_PUT_BE16(buf, key_len); - os_memcpy(buf + 2, key, key_len); - } else { - buf = NULL; - buf_len = 0; - } - - wpa_hexdump_key(MSG_DEBUG, "EAP-TTLS: Session keys for TLS/IA inner " - "secret permutation", buf, buf_len); - ret = tls_connection_ia_permute_inner_secret(sm->ssl_ctx, - data->ssl.conn, - buf, buf_len); - os_free(buf); - - return ret; -} - - -static void eap_ttls_process_phase2_pap(struct eap_sm *sm, - struct eap_ttls_data *data, - const u8 *user_password, - size_t user_password_len) -{ - if (!sm->user || !sm->user->password || sm->user->password_hash || - !(sm->user->ttls_auth & EAP_TTLS_AUTH_PAP)) { - wpa_printf(MSG_DEBUG, "EAP-TTLS/PAP: No plaintext user " - "password configured"); - eap_ttls_state(data, FAILURE); - return; - } - - if (sm->user->password_len != user_password_len || - os_memcmp(sm->user->password, user_password, user_password_len) != - 0) { - wpa_printf(MSG_DEBUG, "EAP-TTLS/PAP: Invalid user password"); - eap_ttls_state(data, FAILURE); - return; - } - - wpa_printf(MSG_DEBUG, "EAP-TTLS/PAP: Correct user password"); - eap_ttls_state(data, data->ttls_version > 0 ? PHASE_FINISHED : - SUCCESS); -} - - -static void eap_ttls_process_phase2_chap(struct eap_sm *sm, - struct eap_ttls_data *data, - const u8 *challenge, - size_t challenge_len, - const u8 *password, - size_t password_len) -{ - u8 *chal, hash[CHAP_MD5_LEN]; - - if (challenge == NULL || password == NULL || - challenge_len != EAP_TTLS_CHAP_CHALLENGE_LEN || - password_len != 1 + EAP_TTLS_CHAP_PASSWORD_LEN) { - wpa_printf(MSG_DEBUG, "EAP-TTLS/CHAP: Invalid CHAP attributes " - "(challenge len %lu password len %lu)", - (unsigned long) challenge_len, - (unsigned long) password_len); - eap_ttls_state(data, FAILURE); - return; - } - - if (!sm->user || !sm->user->password || sm->user->password_hash || - !(sm->user->ttls_auth & EAP_TTLS_AUTH_CHAP)) { - wpa_printf(MSG_DEBUG, "EAP-TTLS/CHAP: No plaintext user " - "password configured"); - eap_ttls_state(data, FAILURE); - return; - } - - chal = eap_ttls_implicit_challenge(sm, data, - EAP_TTLS_CHAP_CHALLENGE_LEN + 1); - if (chal == NULL) { - wpa_printf(MSG_DEBUG, "EAP-TTLS/CHAP: Failed to generate " - "challenge from TLS data"); - eap_ttls_state(data, FAILURE); - return; - } - - if (os_memcmp(challenge, chal, EAP_TTLS_CHAP_CHALLENGE_LEN) != 0 || - password[0] != chal[EAP_TTLS_CHAP_CHALLENGE_LEN]) { - wpa_printf(MSG_DEBUG, "EAP-TTLS/CHAP: Challenge mismatch"); - os_free(chal); - eap_ttls_state(data, FAILURE); - return; - } - os_free(chal); - - /* MD5(Ident + Password + Challenge) */ - chap_md5(password[0], sm->user->password, sm->user->password_len, - challenge, challenge_len, hash); - - if (os_memcmp(hash, password + 1, EAP_TTLS_CHAP_PASSWORD_LEN) == 0) { - wpa_printf(MSG_DEBUG, "EAP-TTLS/CHAP: Correct user password"); - eap_ttls_state(data, data->ttls_version > 0 ? PHASE_FINISHED : - SUCCESS); - } else { - wpa_printf(MSG_DEBUG, "EAP-TTLS/CHAP: Invalid user password"); - eap_ttls_state(data, FAILURE); - } -} - - -static void eap_ttls_process_phase2_mschap(struct eap_sm *sm, - struct eap_ttls_data *data, - u8 *challenge, size_t challenge_len, - u8 *response, size_t response_len) -{ - u8 *chal, nt_response[24]; - - if (challenge == NULL || response == NULL || - challenge_len != EAP_TTLS_MSCHAP_CHALLENGE_LEN || - response_len != EAP_TTLS_MSCHAP_RESPONSE_LEN) { - wpa_printf(MSG_DEBUG, "EAP-TTLS/MSCHAP: Invalid MS-CHAP " - "attributes (challenge len %lu response len %lu)", - (unsigned long) challenge_len, - (unsigned long) response_len); - eap_ttls_state(data, FAILURE); - return; - } - - if (!sm->user || !sm->user->password || - !(sm->user->ttls_auth & EAP_TTLS_AUTH_MSCHAP)) { - wpa_printf(MSG_DEBUG, "EAP-TTLS/MSCHAP: No user password " - "configured"); - eap_ttls_state(data, FAILURE); - return; - } - - chal = eap_ttls_implicit_challenge(sm, data, - EAP_TTLS_MSCHAP_CHALLENGE_LEN + 1); - if (chal == NULL) { - wpa_printf(MSG_DEBUG, "EAP-TTLS/MSCHAP: Failed to generate " - "challenge from TLS data"); - eap_ttls_state(data, FAILURE); - return; - } - - if (os_memcmp(challenge, chal, EAP_TTLS_MSCHAP_CHALLENGE_LEN) != 0 || - response[0] != chal[EAP_TTLS_MSCHAP_CHALLENGE_LEN]) { - wpa_printf(MSG_DEBUG, "EAP-TTLS/MSCHAP: Challenge mismatch"); - os_free(chal); - eap_ttls_state(data, FAILURE); - return; - } - os_free(chal); - - if (sm->user->password_hash) - challenge_response(challenge, sm->user->password, nt_response); - else - nt_challenge_response(challenge, sm->user->password, - sm->user->password_len, nt_response); - - if (os_memcmp(nt_response, response + 2 + 24, 24) == 0) { - wpa_printf(MSG_DEBUG, "EAP-TTLS/MSCHAP: Correct response"); - eap_ttls_state(data, data->ttls_version > 0 ? PHASE_FINISHED : - SUCCESS); - } else { - wpa_printf(MSG_DEBUG, "EAP-TTLS/MSCHAP: Invalid NT-Response"); - wpa_hexdump(MSG_MSGDUMP, "EAP-TTLS/MSCHAP: Received", - response + 2 + 24, 24); - wpa_hexdump(MSG_MSGDUMP, "EAP-TTLS/MSCHAP: Expected", - nt_response, 24); - eap_ttls_state(data, FAILURE); - } -} - - -static void eap_ttls_process_phase2_mschapv2(struct eap_sm *sm, - struct eap_ttls_data *data, - u8 *challenge, - size_t challenge_len, - u8 *response, size_t response_len) -{ - u8 *chal, *username, nt_response[24], *rx_resp, *peer_challenge, - *auth_challenge; - size_t username_len, i; - - if (challenge == NULL || response == NULL || - challenge_len != EAP_TTLS_MSCHAPV2_CHALLENGE_LEN || - response_len != EAP_TTLS_MSCHAPV2_RESPONSE_LEN) { - wpa_printf(MSG_DEBUG, "EAP-TTLS/MSCHAPV2: Invalid MS-CHAP2 " - "attributes (challenge len %lu response len %lu)", - (unsigned long) challenge_len, - (unsigned long) response_len); - eap_ttls_state(data, FAILURE); - return; - } - - if (!sm->user || !sm->user->password || - !(sm->user->ttls_auth & EAP_TTLS_AUTH_MSCHAPV2)) { - wpa_printf(MSG_DEBUG, "EAP-TTLS/MSCHAPV2: No user password " - "configured"); - eap_ttls_state(data, FAILURE); - return; - } - - /* MSCHAPv2 does not include optional domain name in the - * challenge-response calculation, so remove domain prefix - * (if present). */ - username = sm->identity; - username_len = sm->identity_len; - for (i = 0; i < username_len; i++) { - if (username[i] == '\\') { - username_len -= i + 1; - username += i + 1; - break; - } - } - - chal = eap_ttls_implicit_challenge( - sm, data, EAP_TTLS_MSCHAPV2_CHALLENGE_LEN + 1); - if (chal == NULL) { - wpa_printf(MSG_DEBUG, "EAP-TTLS/MSCHAPV2: Failed to generate " - "challenge from TLS data"); - eap_ttls_state(data, FAILURE); - return; - } - - if (os_memcmp(challenge, chal, EAP_TTLS_MSCHAPV2_CHALLENGE_LEN) != 0 || - response[0] != chal[EAP_TTLS_MSCHAPV2_CHALLENGE_LEN]) { - wpa_printf(MSG_DEBUG, "EAP-TTLS/MSCHAPV2: Challenge mismatch"); - os_free(chal); - eap_ttls_state(data, FAILURE); - return; - } - os_free(chal); - - auth_challenge = challenge; - peer_challenge = response + 2; - - wpa_hexdump_ascii(MSG_MSGDUMP, "EAP-TTLS/MSCHAPV2: User", - username, username_len); - wpa_hexdump(MSG_MSGDUMP, "EAP-TTLS/MSCHAPV2: auth_challenge", - auth_challenge, EAP_TTLS_MSCHAPV2_CHALLENGE_LEN); - wpa_hexdump(MSG_MSGDUMP, "EAP-TTLS/MSCHAPV2: peer_challenge", - peer_challenge, EAP_TTLS_MSCHAPV2_CHALLENGE_LEN); - - if (sm->user->password_hash) { - generate_nt_response_pwhash(auth_challenge, peer_challenge, - username, username_len, - sm->user->password, - nt_response); - } else { - generate_nt_response(auth_challenge, peer_challenge, - username, username_len, - sm->user->password, - sm->user->password_len, - nt_response); - } - - rx_resp = response + 2 + EAP_TTLS_MSCHAPV2_CHALLENGE_LEN + 8; - if (os_memcmp(nt_response, rx_resp, 24) == 0) { - wpa_printf(MSG_DEBUG, "EAP-TTLS/MSCHAPV2: Correct " - "NT-Response"); - data->mschapv2_resp_ok = 1; - if (data->ttls_version > 0) { - const u8 *pw_hash; - u8 pw_hash_buf[16], pw_hash_hash[16], master_key[16]; - u8 session_key[2 * MSCHAPV2_KEY_LEN]; - - if (sm->user->password_hash) - pw_hash = sm->user->password; - else { - nt_password_hash(sm->user->password, - sm->user->password_len, - pw_hash_buf); - pw_hash = pw_hash_buf; - } - hash_nt_password_hash(pw_hash, pw_hash_hash); - get_master_key(pw_hash_hash, nt_response, master_key); - get_asymetric_start_key(master_key, session_key, - MSCHAPV2_KEY_LEN, 0, 0); - get_asymetric_start_key(master_key, - session_key + MSCHAPV2_KEY_LEN, - MSCHAPV2_KEY_LEN, 1, 0); - eap_ttls_ia_permute_inner_secret(sm, data, - session_key, - sizeof(session_key)); - } - - if (sm->user->password_hash) { - generate_authenticator_response_pwhash( - sm->user->password, - peer_challenge, auth_challenge, - username, username_len, nt_response, - data->mschapv2_auth_response); - } else { - generate_authenticator_response( - sm->user->password, sm->user->password_len, - peer_challenge, auth_challenge, - username, username_len, nt_response, - data->mschapv2_auth_response); - } - } else { - wpa_printf(MSG_DEBUG, "EAP-TTLS/MSCHAPV2: Invalid " - "NT-Response"); - wpa_hexdump(MSG_MSGDUMP, "EAP-TTLS/MSCHAPV2: Received", - rx_resp, 24); - wpa_hexdump(MSG_MSGDUMP, "EAP-TTLS/MSCHAPV2: Expected", - nt_response, 24); - data->mschapv2_resp_ok = 0; - } - eap_ttls_state(data, PHASE2_MSCHAPV2_RESP); - data->mschapv2_ident = response[0]; -} - - -static int eap_ttls_phase2_eap_init(struct eap_sm *sm, - struct eap_ttls_data *data, - EapType eap_type) -{ - if (data->phase2_priv && data->phase2_method) { - data->phase2_method->reset(sm, data->phase2_priv); - data->phase2_method = NULL; - data->phase2_priv = NULL; - } - data->phase2_method = eap_server_get_eap_method(EAP_VENDOR_IETF, - eap_type); - if (!data->phase2_method) - return -1; - - sm->init_phase2 = 1; - data->phase2_priv = data->phase2_method->init(sm); - sm->init_phase2 = 0; - return data->phase2_priv == NULL ? -1 : 0; -} - - -static void eap_ttls_process_phase2_eap_response(struct eap_sm *sm, - struct eap_ttls_data *data, - u8 *in_data, size_t in_len) -{ - u8 next_type = EAP_TYPE_NONE; - struct eap_hdr *hdr; - u8 *pos; - size_t left; - struct wpabuf buf; - const struct eap_method *m = data->phase2_method; - void *priv = data->phase2_priv; - - if (priv == NULL) { - wpa_printf(MSG_DEBUG, "EAP-TTLS/EAP: %s - Phase2 not " - "initialized?!", __func__); - return; - } - - hdr = (struct eap_hdr *) in_data; - pos = (u8 *) (hdr + 1); - - if (in_len > sizeof(*hdr) && *pos == EAP_TYPE_NAK) { - left = in_len - sizeof(*hdr); - wpa_hexdump(MSG_DEBUG, "EAP-TTLS/EAP: Phase2 type Nak'ed; " - "allowed types", pos + 1, left - 1); - eap_sm_process_nak(sm, pos + 1, left - 1); - if (sm->user && sm->user_eap_method_index < EAP_MAX_METHODS && - sm->user->methods[sm->user_eap_method_index].method != - EAP_TYPE_NONE) { - next_type = sm->user->methods[ - sm->user_eap_method_index++].method; - wpa_printf(MSG_DEBUG, "EAP-TTLS: try EAP type %d", - next_type); - if (eap_ttls_phase2_eap_init(sm, data, next_type)) { - wpa_printf(MSG_DEBUG, "EAP-TTLS: Failed to " - "initialize EAP type %d", - next_type); - eap_ttls_state(data, FAILURE); - return; - } - } else { - eap_ttls_state(data, FAILURE); - } - return; - } - - wpabuf_set(&buf, in_data, in_len); - - if (m->check(sm, priv, &buf)) { - wpa_printf(MSG_DEBUG, "EAP-TTLS/EAP: Phase2 check() asked to " - "ignore the packet"); - return; - } - - m->process(sm, priv, &buf); - - if (sm->method_pending == METHOD_PENDING_WAIT) { - wpa_printf(MSG_DEBUG, "EAP-TTLS/EAP: Phase2 method is in " - "pending wait state - save decrypted response"); - wpabuf_free(data->pending_phase2_eap_resp); - data->pending_phase2_eap_resp = wpabuf_dup(&buf); - } - - if (!m->isDone(sm, priv)) - return; - - if (!m->isSuccess(sm, priv)) { - wpa_printf(MSG_DEBUG, "EAP-TTLS/EAP: Phase2 method failed"); - eap_ttls_state(data, FAILURE); - return; - } - - switch (data->state) { - case PHASE2_START: - if (eap_user_get(sm, sm->identity, sm->identity_len, 1) != 0) { - wpa_hexdump_ascii(MSG_DEBUG, "EAP_TTLS: Phase2 " - "Identity not found in the user " - "database", - sm->identity, sm->identity_len); - eap_ttls_state(data, FAILURE); - break; - } - - eap_ttls_state(data, PHASE2_METHOD); - next_type = sm->user->methods[0].method; - sm->user_eap_method_index = 1; - wpa_printf(MSG_DEBUG, "EAP-TTLS: try EAP type %d", next_type); - if (eap_ttls_phase2_eap_init(sm, data, next_type)) { - wpa_printf(MSG_DEBUG, "EAP-TTLS: Failed to initialize " - "EAP type %d", next_type); - eap_ttls_state(data, FAILURE); - } - break; - case PHASE2_METHOD: - if (data->ttls_version > 0) { - if (m->getKey) { - u8 *key; - size_t key_len; - key = m->getKey(sm, priv, &key_len); - eap_ttls_ia_permute_inner_secret(sm, data, - key, key_len); - } - eap_ttls_state(data, PHASE_FINISHED); - } else - eap_ttls_state(data, SUCCESS); - break; - case FAILURE: - break; - default: - wpa_printf(MSG_DEBUG, "EAP-TTLS: %s - unexpected state %d", - __func__, data->state); - break; - } -} - - -static void eap_ttls_process_phase2_eap(struct eap_sm *sm, - struct eap_ttls_data *data, - const u8 *eap, size_t eap_len) -{ - struct eap_hdr *hdr; - size_t len; - - if (data->state == PHASE2_START) { - wpa_printf(MSG_DEBUG, "EAP-TTLS/EAP: initializing Phase 2"); - if (eap_ttls_phase2_eap_init(sm, data, EAP_TYPE_IDENTITY) < 0) - { - wpa_printf(MSG_DEBUG, "EAP-TTLS/EAP: failed to " - "initialize EAP-Identity"); - return; - } - } - - if (eap_len < sizeof(*hdr)) { - wpa_printf(MSG_DEBUG, "EAP-TTLS/EAP: too short Phase 2 EAP " - "packet (len=%lu)", (unsigned long) eap_len); - return; - } - - hdr = (struct eap_hdr *) eap; - len = be_to_host16(hdr->length); - wpa_printf(MSG_DEBUG, "EAP-TTLS/EAP: received Phase 2 EAP: code=%d " - "identifier=%d length=%lu", hdr->code, hdr->identifier, - (unsigned long) len); - if (len > eap_len) { - wpa_printf(MSG_INFO, "EAP-TTLS/EAP: Length mismatch in Phase 2" - " EAP frame (hdr len=%lu, data len in AVP=%lu)", - (unsigned long) len, (unsigned long) eap_len); - return; - } - - switch (hdr->code) { - case EAP_CODE_RESPONSE: - eap_ttls_process_phase2_eap_response(sm, data, (u8 *) hdr, - len); - break; - default: - wpa_printf(MSG_INFO, "EAP-TTLS/EAP: Unexpected code=%d in " - "Phase 2 EAP header", hdr->code); - break; - } -} - - -static void eap_ttls_process_phase2(struct eap_sm *sm, - struct eap_ttls_data *data, - struct wpabuf *in_buf) -{ - struct wpabuf *in_decrypted; - struct eap_ttls_avp parse; - - wpa_printf(MSG_DEBUG, "EAP-TTLS: received %lu bytes encrypted data for" - " Phase 2", (unsigned long) wpabuf_len(in_buf)); - - if (data->pending_phase2_eap_resp) { - wpa_printf(MSG_DEBUG, "EAP-TTLS: Pending Phase 2 EAP response " - "- skip decryption and use old data"); - eap_ttls_process_phase2_eap( - sm, data, wpabuf_head(data->pending_phase2_eap_resp), - wpabuf_len(data->pending_phase2_eap_resp)); - wpabuf_free(data->pending_phase2_eap_resp); - data->pending_phase2_eap_resp = NULL; - return; - } - - in_decrypted = tls_connection_decrypt(sm->ssl_ctx, data->ssl.conn, - in_buf); - if (in_decrypted == NULL) { - wpa_printf(MSG_INFO, "EAP-TTLS: Failed to decrypt Phase 2 " - "data"); - eap_ttls_state(data, FAILURE); - return; - } - - if (data->state == PHASE_FINISHED) { - if (wpabuf_len(in_decrypted) == 0 && - tls_connection_ia_final_phase_finished(sm->ssl_ctx, - data->ssl.conn)) { - wpa_printf(MSG_DEBUG, "EAP-TTLS: FinalPhaseFinished " - "received"); - eap_ttls_state(data, SUCCESS); - } else { - wpa_printf(MSG_INFO, "EAP-TTLS: Did not receive valid " - "FinalPhaseFinished"); - eap_ttls_state(data, FAILURE); - } - - wpabuf_free(in_decrypted); - return; - } - - wpa_hexdump_buf_key(MSG_DEBUG, "EAP-TTLS: Decrypted Phase 2 EAP", - in_decrypted); - - if (eap_ttls_avp_parse(in_decrypted, &parse) < 0) { - wpa_printf(MSG_DEBUG, "EAP-TTLS: Failed to parse AVPs"); - wpabuf_free(in_decrypted); - eap_ttls_state(data, FAILURE); - return; - } - - if (parse.user_name) { - os_free(sm->identity); - sm->identity = os_malloc(parse.user_name_len); - if (sm->identity) { - os_memcpy(sm->identity, parse.user_name, - parse.user_name_len); - sm->identity_len = parse.user_name_len; - } - if (eap_user_get(sm, parse.user_name, parse.user_name_len, 1) - != 0) { - wpa_printf(MSG_DEBUG, "EAP-TTLS: Phase2 Identity not " - "found in the user database"); - eap_ttls_state(data, FAILURE); - goto done; - } - } - -#ifdef EAP_SERVER_TNC - if (data->tnc_started && parse.eap == NULL) { - wpa_printf(MSG_DEBUG, "EAP-TTLS: TNC started but no EAP " - "response from peer"); - eap_ttls_state(data, FAILURE); - goto done; - } -#endif /* EAP_SERVER_TNC */ - - if (parse.eap) { - eap_ttls_process_phase2_eap(sm, data, parse.eap, - parse.eap_len); - } else if (parse.user_password) { - eap_ttls_process_phase2_pap(sm, data, parse.user_password, - parse.user_password_len); - } else if (parse.chap_password) { - eap_ttls_process_phase2_chap(sm, data, - parse.chap_challenge, - parse.chap_challenge_len, - parse.chap_password, - parse.chap_password_len); - } else if (parse.mschap_response) { - eap_ttls_process_phase2_mschap(sm, data, - parse.mschap_challenge, - parse.mschap_challenge_len, - parse.mschap_response, - parse.mschap_response_len); - } else if (parse.mschap2_response) { - eap_ttls_process_phase2_mschapv2(sm, data, - parse.mschap_challenge, - parse.mschap_challenge_len, - parse.mschap2_response, - parse.mschap2_response_len); - } - -done: - wpabuf_free(in_decrypted); - os_free(parse.eap); -} - - -static void eap_ttls_start_tnc(struct eap_sm *sm, struct eap_ttls_data *data) -{ -#ifdef EAP_SERVER_TNC - if (!sm->tnc || data->state != SUCCESS || data->tnc_started) - return; - - wpa_printf(MSG_DEBUG, "EAP-TTLS: Initialize TNC"); - if (eap_ttls_phase2_eap_init(sm, data, EAP_TYPE_TNC)) { - wpa_printf(MSG_DEBUG, "EAP-TTLS: Failed to initialize TNC"); - eap_ttls_state(data, FAILURE); - return; - } - - data->tnc_started = 1; - eap_ttls_state(data, PHASE2_METHOD); -#endif /* EAP_SERVER_TNC */ -} - - -static int eap_ttls_process_version(struct eap_sm *sm, void *priv, - int peer_version) -{ - struct eap_ttls_data *data = priv; - if (peer_version < data->ttls_version) { - wpa_printf(MSG_DEBUG, "EAP-TTLS: peer ver=%d, own ver=%d; " - "use version %d", - peer_version, data->ttls_version, peer_version); - data->ttls_version = peer_version; - } - - if (data->ttls_version > 0 && !data->tls_ia_configured) { - if (tls_connection_set_ia(sm->ssl_ctx, data->ssl.conn, 1)) { - wpa_printf(MSG_INFO, "EAP-TTLS: Failed to enable " - "TLS/IA"); - return -1; - } - data->tls_ia_configured = 1; - } - - return 0; -} - - -static void eap_ttls_process_msg(struct eap_sm *sm, void *priv, - const struct wpabuf *respData) -{ - struct eap_ttls_data *data = priv; - - switch (data->state) { - case PHASE1: - if (eap_server_tls_phase1(sm, &data->ssl) < 0) - eap_ttls_state(data, FAILURE); - break; - case PHASE2_START: - case PHASE2_METHOD: - case PHASE_FINISHED: - eap_ttls_process_phase2(sm, data, data->ssl.tls_in); - eap_ttls_start_tnc(sm, data); - break; - case PHASE2_MSCHAPV2_RESP: - if (data->mschapv2_resp_ok && wpabuf_len(data->ssl.tls_in) == - 0) { - wpa_printf(MSG_DEBUG, "EAP-TTLS/MSCHAPV2: Peer " - "acknowledged response"); - eap_ttls_state(data, data->ttls_version > 0 ? - PHASE_FINISHED : SUCCESS); - } else if (!data->mschapv2_resp_ok) { - wpa_printf(MSG_DEBUG, "EAP-TTLS/MSCHAPV2: Peer " - "acknowledged error"); - eap_ttls_state(data, FAILURE); - } else { - wpa_printf(MSG_DEBUG, "EAP-TTLS/MSCHAPV2: Unexpected " - "frame from peer (payload len %lu, " - "expected empty frame)", - (unsigned long) - wpabuf_len(data->ssl.tls_in)); - eap_ttls_state(data, FAILURE); - } - eap_ttls_start_tnc(sm, data); - break; - default: - wpa_printf(MSG_DEBUG, "EAP-TTLS: Unexpected state %d in %s", - data->state, __func__); - break; - } -} - - -static void eap_ttls_process(struct eap_sm *sm, void *priv, - struct wpabuf *respData) -{ - struct eap_ttls_data *data = priv; - if (eap_server_tls_process(sm, &data->ssl, respData, data, - EAP_TYPE_TTLS, eap_ttls_process_version, - eap_ttls_process_msg) < 0) - eap_ttls_state(data, FAILURE); -} - - -static Boolean eap_ttls_isDone(struct eap_sm *sm, void *priv) -{ - struct eap_ttls_data *data = priv; - return data->state == SUCCESS || data->state == FAILURE; -} - - -static u8 * eap_ttls_v1_derive_key(struct eap_sm *sm, - struct eap_ttls_data *data) -{ - struct tls_keys keys; - u8 *rnd, *key; - - os_memset(&keys, 0, sizeof(keys)); - if (tls_connection_get_keys(sm->ssl_ctx, data->ssl.conn, &keys) || - keys.client_random == NULL || keys.server_random == NULL || - keys.inner_secret == NULL) { - wpa_printf(MSG_INFO, "EAP-TTLS: Could not get inner secret, " - "client random, or server random to derive keying " - "material"); - return NULL; - } - - rnd = os_malloc(keys.client_random_len + keys.server_random_len); - key = os_malloc(EAP_TLS_KEY_LEN); - if (rnd == NULL || key == NULL) { - wpa_printf(MSG_INFO, "EAP-TTLS: No memory for key derivation"); - os_free(rnd); - os_free(key); - return NULL; - } - os_memcpy(rnd, keys.client_random, keys.client_random_len); - os_memcpy(rnd + keys.client_random_len, keys.server_random, - keys.server_random_len); - - if (tls_prf(keys.inner_secret, keys.inner_secret_len, - "ttls v1 keying material", rnd, keys.client_random_len + - keys.server_random_len, key, EAP_TLS_KEY_LEN)) { - wpa_printf(MSG_DEBUG, "EAP-TTLS: Failed to derive key"); - os_free(rnd); - os_free(key); - return NULL; - } - - wpa_hexdump(MSG_DEBUG, "EAP-TTLS: client/server random", - rnd, keys.client_random_len + keys.server_random_len); - wpa_hexdump_key(MSG_DEBUG, "EAP-TTLS: TLS/IA inner secret", - keys.inner_secret, keys.inner_secret_len); - - os_free(rnd); - - return key; -} - - -static u8 * eap_ttls_getKey(struct eap_sm *sm, void *priv, size_t *len) -{ - struct eap_ttls_data *data = priv; - u8 *eapKeyData; - - if (data->state != SUCCESS) - return NULL; - - if (data->ttls_version == 0) { - eapKeyData = eap_server_tls_derive_key(sm, &data->ssl, - "ttls keying material", - EAP_TLS_KEY_LEN); - } else { - eapKeyData = eap_ttls_v1_derive_key(sm, data); - } - - if (eapKeyData) { - *len = EAP_TLS_KEY_LEN; - wpa_hexdump_key(MSG_DEBUG, "EAP-TTLS: Derived key", - eapKeyData, EAP_TLS_KEY_LEN); - } else { - wpa_printf(MSG_DEBUG, "EAP-TTLS: Failed to derive key"); - } - - return eapKeyData; -} - - -static Boolean eap_ttls_isSuccess(struct eap_sm *sm, void *priv) -{ - struct eap_ttls_data *data = priv; - return data->state == SUCCESS; -} - - -int eap_server_ttls_register(void) -{ - struct eap_method *eap; - int ret; - - eap = eap_server_method_alloc(EAP_SERVER_METHOD_INTERFACE_VERSION, - EAP_VENDOR_IETF, EAP_TYPE_TTLS, "TTLS"); - if (eap == NULL) - return -1; - - eap->init = eap_ttls_init; - eap->reset = eap_ttls_reset; - eap->buildReq = eap_ttls_buildReq; - eap->check = eap_ttls_check; - eap->process = eap_ttls_process; - eap->isDone = eap_ttls_isDone; - eap->getKey = eap_ttls_getKey; - eap->isSuccess = eap_ttls_isSuccess; - - ret = eap_server_method_register(eap); - if (ret) - eap_server_method_free(eap); - return ret; -} diff --git a/hostapd-0.8/src/eap_server/eap_server_vendor_test.c b/hostapd-0.8/src/eap_server/eap_server_vendor_test.c deleted file mode 100644 index 0dd0aca..0000000 --- a/hostapd-0.8/src/eap_server/eap_server_vendor_test.c +++ /dev/null @@ -1,198 +0,0 @@ -/* - * hostapd / Test method for vendor specific (expanded) EAP type - * Copyright (c) 2005-2007, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#include "includes.h" - -#include "common.h" -#include "eap_i.h" - - -#define EAP_VENDOR_ID 0xfffefd -#define EAP_VENDOR_TYPE 0xfcfbfaf9 - - -struct eap_vendor_test_data { - enum { INIT, CONFIRM, SUCCESS, FAILURE } state; -}; - - -static const char * eap_vendor_test_state_txt(int state) -{ - switch (state) { - case INIT: - return "INIT"; - case CONFIRM: - return "CONFIRM"; - case SUCCESS: - return "SUCCESS"; - case FAILURE: - return "FAILURE"; - default: - return "?"; - } -} - - -static void eap_vendor_test_state(struct eap_vendor_test_data *data, - int state) -{ - wpa_printf(MSG_DEBUG, "EAP-VENDOR-TEST: %s -> %s", - eap_vendor_test_state_txt(data->state), - eap_vendor_test_state_txt(state)); - data->state = state; -} - - -static void * eap_vendor_test_init(struct eap_sm *sm) -{ - struct eap_vendor_test_data *data; - - data = os_zalloc(sizeof(*data)); - if (data == NULL) - return NULL; - data->state = INIT; - - return data; -} - - -static void eap_vendor_test_reset(struct eap_sm *sm, void *priv) -{ - struct eap_vendor_test_data *data = priv; - os_free(data); -} - - -static struct wpabuf * eap_vendor_test_buildReq(struct eap_sm *sm, void *priv, - u8 id) -{ - struct eap_vendor_test_data *data = priv; - struct wpabuf *req; - - req = eap_msg_alloc(EAP_VENDOR_ID, EAP_VENDOR_TYPE, 1, - EAP_CODE_REQUEST, id); - if (req == NULL) { - wpa_printf(MSG_ERROR, "EAP-VENDOR-TEST: Failed to allocate " - "memory for request"); - return NULL; - } - - wpabuf_put_u8(req, data->state == INIT ? 1 : 3); - - return req; -} - - -static Boolean eap_vendor_test_check(struct eap_sm *sm, void *priv, - struct wpabuf *respData) -{ - const u8 *pos; - size_t len; - - pos = eap_hdr_validate(EAP_VENDOR_ID, EAP_VENDOR_TYPE, respData, &len); - if (pos == NULL || len < 1) { - wpa_printf(MSG_INFO, "EAP-VENDOR-TEST: Invalid frame"); - return TRUE; - } - - return FALSE; -} - - -static void eap_vendor_test_process(struct eap_sm *sm, void *priv, - struct wpabuf *respData) -{ - struct eap_vendor_test_data *data = priv; - const u8 *pos; - size_t len; - - pos = eap_hdr_validate(EAP_VENDOR_ID, EAP_VENDOR_TYPE, respData, &len); - if (pos == NULL || len < 1) - return; - - if (data->state == INIT) { - if (*pos == 2) - eap_vendor_test_state(data, CONFIRM); - else - eap_vendor_test_state(data, FAILURE); - } else if (data->state == CONFIRM) { - if (*pos == 4) - eap_vendor_test_state(data, SUCCESS); - else - eap_vendor_test_state(data, FAILURE); - } else - eap_vendor_test_state(data, FAILURE); -} - - -static Boolean eap_vendor_test_isDone(struct eap_sm *sm, void *priv) -{ - struct eap_vendor_test_data *data = priv; - return data->state == SUCCESS; -} - - -static u8 * eap_vendor_test_getKey(struct eap_sm *sm, void *priv, size_t *len) -{ - struct eap_vendor_test_data *data = priv; - u8 *key; - const int key_len = 64; - - if (data->state != SUCCESS) - return NULL; - - key = os_malloc(key_len); - if (key == NULL) - return NULL; - - os_memset(key, 0x11, key_len / 2); - os_memset(key + key_len / 2, 0x22, key_len / 2); - *len = key_len; - - return key; -} - - -static Boolean eap_vendor_test_isSuccess(struct eap_sm *sm, void *priv) -{ - struct eap_vendor_test_data *data = priv; - return data->state == SUCCESS; -} - - -int eap_server_vendor_test_register(void) -{ - struct eap_method *eap; - int ret; - - eap = eap_server_method_alloc(EAP_SERVER_METHOD_INTERFACE_VERSION, - EAP_VENDOR_ID, EAP_VENDOR_TYPE, - "VENDOR-TEST"); - if (eap == NULL) - return -1; - - eap->init = eap_vendor_test_init; - eap->reset = eap_vendor_test_reset; - eap->buildReq = eap_vendor_test_buildReq; - eap->check = eap_vendor_test_check; - eap->process = eap_vendor_test_process; - eap->isDone = eap_vendor_test_isDone; - eap->getKey = eap_vendor_test_getKey; - eap->isSuccess = eap_vendor_test_isSuccess; - - ret = eap_server_method_register(eap); - if (ret) - eap_server_method_free(eap); - return ret; -} diff --git a/hostapd-0.8/src/eap_server/eap_server_wsc.c b/hostapd-0.8/src/eap_server/eap_server_wsc.c deleted file mode 100644 index e944a4d..0000000 --- a/hostapd-0.8/src/eap_server/eap_server_wsc.c +++ /dev/null @@ -1,517 +0,0 @@ -/* - * EAP-WSC server for Wi-Fi Protected Setup - * Copyright (c) 2007-2008, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#include "includes.h" - -#include "common.h" -#include "eloop.h" -#include "eap_i.h" -#include "eap_common/eap_wsc_common.h" -#include "p2p/p2p.h" -#include "wps/wps.h" - - -struct eap_wsc_data { - enum { START, MESG, FRAG_ACK, WAIT_FRAG_ACK, DONE, FAIL } state; - int registrar; - struct wpabuf *in_buf; - struct wpabuf *out_buf; - enum wsc_op_code in_op_code, out_op_code; - size_t out_used; - size_t fragment_size; - struct wps_data *wps; - int ext_reg_timeout; -}; - - -#ifndef CONFIG_NO_STDOUT_DEBUG -static const char * eap_wsc_state_txt(int state) -{ - switch (state) { - case START: - return "START"; - case MESG: - return "MESG"; - case FRAG_ACK: - return "FRAG_ACK"; - case WAIT_FRAG_ACK: - return "WAIT_FRAG_ACK"; - case DONE: - return "DONE"; - case FAIL: - return "FAIL"; - default: - return "?"; - } -} -#endif /* CONFIG_NO_STDOUT_DEBUG */ - - -static void eap_wsc_state(struct eap_wsc_data *data, int state) -{ - wpa_printf(MSG_DEBUG, "EAP-WSC: %s -> %s", - eap_wsc_state_txt(data->state), - eap_wsc_state_txt(state)); - data->state = state; -} - - -static void eap_wsc_ext_reg_timeout(void *eloop_ctx, void *timeout_ctx) -{ - struct eap_sm *sm = eloop_ctx; - struct eap_wsc_data *data = timeout_ctx; - - if (sm->method_pending != METHOD_PENDING_WAIT) - return; - - wpa_printf(MSG_DEBUG, "EAP-WSC: Timeout while waiting for an External " - "Registrar"); - data->ext_reg_timeout = 1; - eap_sm_pending_cb(sm); -} - - -static void * eap_wsc_init(struct eap_sm *sm) -{ - struct eap_wsc_data *data; - int registrar; - struct wps_config cfg; - - if (sm->identity && sm->identity_len == WSC_ID_REGISTRAR_LEN && - os_memcmp(sm->identity, WSC_ID_REGISTRAR, WSC_ID_REGISTRAR_LEN) == - 0) - registrar = 0; /* Supplicant is Registrar */ - else if (sm->identity && sm->identity_len == WSC_ID_ENROLLEE_LEN && - os_memcmp(sm->identity, WSC_ID_ENROLLEE, WSC_ID_ENROLLEE_LEN) - == 0) - registrar = 1; /* Supplicant is Enrollee */ - else { - wpa_hexdump_ascii(MSG_INFO, "EAP-WSC: Unexpected identity", - sm->identity, sm->identity_len); - return NULL; - } - - data = os_zalloc(sizeof(*data)); - if (data == NULL) - return NULL; - data->state = registrar ? START : MESG; - data->registrar = registrar; - - os_memset(&cfg, 0, sizeof(cfg)); - cfg.wps = sm->wps; - cfg.registrar = registrar; - if (registrar) { - if (sm->wps == NULL || sm->wps->registrar == NULL) { - wpa_printf(MSG_INFO, "EAP-WSC: WPS Registrar not " - "initialized"); - os_free(data); - return NULL; - } - } else { - if (sm->user == NULL || sm->user->password == NULL) { - /* - * In theory, this should not really be needed, but - * Windows 7 uses Registrar mode to probe AP's WPS - * capabilities before trying to use Enrollee and fails - * if the AP does not allow that probing to happen.. - */ - wpa_printf(MSG_DEBUG, "EAP-WSC: No AP PIN (password) " - "configured for Enrollee functionality - " - "allow for probing capabilities (M1)"); - } else { - cfg.pin = sm->user->password; - cfg.pin_len = sm->user->password_len; - } - } - cfg.assoc_wps_ie = sm->assoc_wps_ie; - cfg.peer_addr = sm->peer_addr; -#ifdef CONFIG_P2P - if (sm->assoc_p2p_ie) { - wpa_printf(MSG_DEBUG, "EAP-WSC: Prefer PSK format for P2P " - "client"); - cfg.use_psk_key = 1; - cfg.p2p_dev_addr = p2p_get_go_dev_addr(sm->assoc_p2p_ie); - } -#endif /* CONFIG_P2P */ - data->wps = wps_init(&cfg); - if (data->wps == NULL) { - os_free(data); - return NULL; - } - data->fragment_size = sm->fragment_size > 0 ? sm->fragment_size : - WSC_FRAGMENT_SIZE; - - return data; -} - - -static void eap_wsc_reset(struct eap_sm *sm, void *priv) -{ - struct eap_wsc_data *data = priv; - eloop_cancel_timeout(eap_wsc_ext_reg_timeout, sm, data); - wpabuf_free(data->in_buf); - wpabuf_free(data->out_buf); - wps_deinit(data->wps); - os_free(data); -} - - -static struct wpabuf * eap_wsc_build_start(struct eap_sm *sm, - struct eap_wsc_data *data, u8 id) -{ - struct wpabuf *req; - - req = eap_msg_alloc(EAP_VENDOR_WFA, EAP_VENDOR_TYPE_WSC, 2, - EAP_CODE_REQUEST, id); - if (req == NULL) { - wpa_printf(MSG_ERROR, "EAP-WSC: Failed to allocate memory for " - "request"); - return NULL; - } - - wpa_printf(MSG_DEBUG, "EAP-WSC: Send WSC/Start"); - wpabuf_put_u8(req, WSC_Start); /* Op-Code */ - wpabuf_put_u8(req, 0); /* Flags */ - - return req; -} - - -static struct wpabuf * eap_wsc_build_msg(struct eap_wsc_data *data, u8 id) -{ - struct wpabuf *req; - u8 flags; - size_t send_len, plen; - - flags = 0; - send_len = wpabuf_len(data->out_buf) - data->out_used; - if (2 + send_len > data->fragment_size) { - send_len = data->fragment_size - 2; - flags |= WSC_FLAGS_MF; - if (data->out_used == 0) { - flags |= WSC_FLAGS_LF; - send_len -= 2; - } - } - plen = 2 + send_len; - if (flags & WSC_FLAGS_LF) - plen += 2; - req = eap_msg_alloc(EAP_VENDOR_WFA, EAP_VENDOR_TYPE_WSC, plen, - EAP_CODE_REQUEST, id); - if (req == NULL) { - wpa_printf(MSG_ERROR, "EAP-WSC: Failed to allocate memory for " - "request"); - return NULL; - } - - wpabuf_put_u8(req, data->out_op_code); /* Op-Code */ - wpabuf_put_u8(req, flags); /* Flags */ - if (flags & WSC_FLAGS_LF) - wpabuf_put_be16(req, wpabuf_len(data->out_buf)); - - wpabuf_put_data(req, wpabuf_head_u8(data->out_buf) + data->out_used, - send_len); - data->out_used += send_len; - - if (data->out_used == wpabuf_len(data->out_buf)) { - wpa_printf(MSG_DEBUG, "EAP-WSC: Sending out %lu bytes " - "(message sent completely)", - (unsigned long) send_len); - wpabuf_free(data->out_buf); - data->out_buf = NULL; - data->out_used = 0; - eap_wsc_state(data, MESG); - } else { - wpa_printf(MSG_DEBUG, "EAP-WSC: Sending out %lu bytes " - "(%lu more to send)", (unsigned long) send_len, - (unsigned long) wpabuf_len(data->out_buf) - - data->out_used); - eap_wsc_state(data, WAIT_FRAG_ACK); - } - - return req; -} - - -static struct wpabuf * eap_wsc_buildReq(struct eap_sm *sm, void *priv, u8 id) -{ - struct eap_wsc_data *data = priv; - - switch (data->state) { - case START: - return eap_wsc_build_start(sm, data, id); - case MESG: - if (data->out_buf == NULL) { - data->out_buf = wps_get_msg(data->wps, - &data->out_op_code); - if (data->out_buf == NULL) { - wpa_printf(MSG_DEBUG, "EAP-WSC: Failed to " - "receive message from WPS"); - return NULL; - } - data->out_used = 0; - } - /* pass through */ - case WAIT_FRAG_ACK: - return eap_wsc_build_msg(data, id); - case FRAG_ACK: - return eap_wsc_build_frag_ack(id, EAP_CODE_REQUEST); - default: - wpa_printf(MSG_DEBUG, "EAP-WSC: Unexpected state %d in " - "buildReq", data->state); - return NULL; - } -} - - -static Boolean eap_wsc_check(struct eap_sm *sm, void *priv, - struct wpabuf *respData) -{ - const u8 *pos; - size_t len; - - pos = eap_hdr_validate(EAP_VENDOR_WFA, EAP_VENDOR_TYPE_WSC, - respData, &len); - if (pos == NULL || len < 2) { - wpa_printf(MSG_INFO, "EAP-WSC: Invalid frame"); - return TRUE; - } - - return FALSE; -} - - -static int eap_wsc_process_cont(struct eap_wsc_data *data, - const u8 *buf, size_t len, u8 op_code) -{ - /* Process continuation of a pending message */ - if (op_code != data->in_op_code) { - wpa_printf(MSG_DEBUG, "EAP-WSC: Unexpected Op-Code %d in " - "fragment (expected %d)", - op_code, data->in_op_code); - eap_wsc_state(data, FAIL); - return -1; - } - - if (len > wpabuf_tailroom(data->in_buf)) { - wpa_printf(MSG_DEBUG, "EAP-WSC: Fragment overflow"); - eap_wsc_state(data, FAIL); - return -1; - } - - wpabuf_put_data(data->in_buf, buf, len); - wpa_printf(MSG_DEBUG, "EAP-WSC: Received %lu bytes, waiting for %lu " - "bytes more", (unsigned long) len, - (unsigned long) wpabuf_tailroom(data->in_buf)); - - return 0; -} - - -static int eap_wsc_process_fragment(struct eap_wsc_data *data, - u8 flags, u8 op_code, u16 message_length, - const u8 *buf, size_t len) -{ - /* Process a fragment that is not the last one of the message */ - if (data->in_buf == NULL && !(flags & WSC_FLAGS_LF)) { - wpa_printf(MSG_DEBUG, "EAP-WSC: No Message Length " - "field in a fragmented packet"); - return -1; - } - - if (data->in_buf == NULL) { - /* First fragment of the message */ - data->in_buf = wpabuf_alloc(message_length); - if (data->in_buf == NULL) { - wpa_printf(MSG_DEBUG, "EAP-WSC: No memory for " - "message"); - return -1; - } - data->in_op_code = op_code; - wpabuf_put_data(data->in_buf, buf, len); - wpa_printf(MSG_DEBUG, "EAP-WSC: Received %lu bytes in " - "first fragment, waiting for %lu bytes more", - (unsigned long) len, - (unsigned long) wpabuf_tailroom(data->in_buf)); - } - - return 0; -} - - -static void eap_wsc_process(struct eap_sm *sm, void *priv, - struct wpabuf *respData) -{ - struct eap_wsc_data *data = priv; - const u8 *start, *pos, *end; - size_t len; - u8 op_code, flags; - u16 message_length = 0; - enum wps_process_res res; - struct wpabuf tmpbuf; - - eloop_cancel_timeout(eap_wsc_ext_reg_timeout, sm, data); - if (data->ext_reg_timeout) { - eap_wsc_state(data, FAIL); - return; - } - - pos = eap_hdr_validate(EAP_VENDOR_WFA, EAP_VENDOR_TYPE_WSC, - respData, &len); - if (pos == NULL || len < 2) - return; /* Should not happen; message already verified */ - - start = pos; - end = start + len; - - op_code = *pos++; - flags = *pos++; - if (flags & WSC_FLAGS_LF) { - if (end - pos < 2) { - wpa_printf(MSG_DEBUG, "EAP-WSC: Message underflow"); - return; - } - message_length = WPA_GET_BE16(pos); - pos += 2; - - if (message_length < end - pos) { - wpa_printf(MSG_DEBUG, "EAP-WSC: Invalid Message " - "Length"); - return; - } - } - - wpa_printf(MSG_DEBUG, "EAP-WSC: Received packet: Op-Code %d " - "Flags 0x%x Message Length %d", - op_code, flags, message_length); - - if (data->state == WAIT_FRAG_ACK) { - if (op_code != WSC_FRAG_ACK) { - wpa_printf(MSG_DEBUG, "EAP-WSC: Unexpected Op-Code %d " - "in WAIT_FRAG_ACK state", op_code); - eap_wsc_state(data, FAIL); - return; - } - wpa_printf(MSG_DEBUG, "EAP-WSC: Fragment acknowledged"); - eap_wsc_state(data, MESG); - return; - } - - if (op_code != WSC_ACK && op_code != WSC_NACK && op_code != WSC_MSG && - op_code != WSC_Done) { - wpa_printf(MSG_DEBUG, "EAP-WSC: Unexpected Op-Code %d", - op_code); - eap_wsc_state(data, FAIL); - return; - } - - if (data->in_buf && - eap_wsc_process_cont(data, pos, end - pos, op_code) < 0) { - eap_wsc_state(data, FAIL); - return; - } - - if (flags & WSC_FLAGS_MF) { - if (eap_wsc_process_fragment(data, flags, op_code, - message_length, pos, end - pos) < - 0) - eap_wsc_state(data, FAIL); - else - eap_wsc_state(data, FRAG_ACK); - return; - } - - if (data->in_buf == NULL) { - /* Wrap unfragmented messages as wpabuf without extra copy */ - wpabuf_set(&tmpbuf, pos, end - pos); - data->in_buf = &tmpbuf; - } - - res = wps_process_msg(data->wps, op_code, data->in_buf); - switch (res) { - case WPS_DONE: - wpa_printf(MSG_DEBUG, "EAP-WSC: WPS processing completed " - "successfully - report EAP failure"); - eap_wsc_state(data, FAIL); - break; - case WPS_CONTINUE: - eap_wsc_state(data, MESG); - break; - case WPS_FAILURE: - wpa_printf(MSG_DEBUG, "EAP-WSC: WPS processing failed"); - eap_wsc_state(data, FAIL); - break; - case WPS_PENDING: - eap_wsc_state(data, MESG); - sm->method_pending = METHOD_PENDING_WAIT; - eloop_cancel_timeout(eap_wsc_ext_reg_timeout, sm, data); - eloop_register_timeout(5, 0, eap_wsc_ext_reg_timeout, - sm, data); - break; - } - - if (data->in_buf != &tmpbuf) - wpabuf_free(data->in_buf); - data->in_buf = NULL; -} - - -static Boolean eap_wsc_isDone(struct eap_sm *sm, void *priv) -{ - struct eap_wsc_data *data = priv; - return data->state == FAIL; -} - - -static Boolean eap_wsc_isSuccess(struct eap_sm *sm, void *priv) -{ - /* EAP-WSC will always result in EAP-Failure */ - return FALSE; -} - - -static int eap_wsc_getTimeout(struct eap_sm *sm, void *priv) -{ - /* Recommended retransmit times: retransmit timeout 5 seconds, - * per-message timeout 15 seconds, i.e., 3 tries. */ - sm->MaxRetrans = 2; /* total 3 attempts */ - return 5; -} - - -int eap_server_wsc_register(void) -{ - struct eap_method *eap; - int ret; - - eap = eap_server_method_alloc(EAP_SERVER_METHOD_INTERFACE_VERSION, - EAP_VENDOR_WFA, EAP_VENDOR_TYPE_WSC, - "WSC"); - if (eap == NULL) - return -1; - - eap->init = eap_wsc_init; - eap->reset = eap_wsc_reset; - eap->buildReq = eap_wsc_buildReq; - eap->check = eap_wsc_check; - eap->process = eap_wsc_process; - eap->isDone = eap_wsc_isDone; - eap->isSuccess = eap_wsc_isSuccess; - eap->getTimeout = eap_wsc_getTimeout; - - ret = eap_server_method_register(eap); - if (ret) - eap_server_method_free(eap); - return ret; -} diff --git a/hostapd-0.8/src/eap_server/eap_sim_db.c b/hostapd-0.8/src/eap_server/eap_sim_db.c deleted file mode 100644 index 248b216..0000000 --- a/hostapd-0.8/src/eap_server/eap_sim_db.c +++ /dev/null @@ -1,1338 +0,0 @@ -/* - * hostapd / EAP-SIM database/authenticator gateway - * Copyright (c) 2005-2007, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - * - * This is an example implementation of the EAP-SIM/AKA database/authentication - * gateway interface that is using an external program as an SS7 gateway to - * GSM/UMTS authentication center (HLR/AuC). hlr_auc_gw is an example - * implementation of such a gateway program. This eap_sim_db.c takes care of - * EAP-SIM/AKA pseudonyms and re-auth identities. It can be used with different - * gateway implementations for HLR/AuC access. Alternatively, it can also be - * completely replaced if the in-memory database of pseudonyms/re-auth - * identities is not suitable for some cases. - */ - -#include "includes.h" -#include - -#include "common.h" -#include "crypto/random.h" -#include "eap_common/eap_sim_common.h" -#include "eap_server/eap_sim_db.h" -#include "eloop.h" - -struct eap_sim_pseudonym { - struct eap_sim_pseudonym *next; - u8 *identity; - size_t identity_len; - char *pseudonym; -}; - -struct eap_sim_db_pending { - struct eap_sim_db_pending *next; - u8 imsi[20]; - size_t imsi_len; - enum { PENDING, SUCCESS, FAILURE } state; - void *cb_session_ctx; - struct os_time timestamp; - int aka; - union { - struct { - u8 kc[EAP_SIM_MAX_CHAL][EAP_SIM_KC_LEN]; - u8 sres[EAP_SIM_MAX_CHAL][EAP_SIM_SRES_LEN]; - u8 rand[EAP_SIM_MAX_CHAL][GSM_RAND_LEN]; - int num_chal; - } sim; - struct { - u8 rand[EAP_AKA_RAND_LEN]; - u8 autn[EAP_AKA_AUTN_LEN]; - u8 ik[EAP_AKA_IK_LEN]; - u8 ck[EAP_AKA_CK_LEN]; - u8 res[EAP_AKA_RES_MAX_LEN]; - size_t res_len; - } aka; - } u; -}; - -struct eap_sim_db_data { - int sock; - char *fname; - char *local_sock; - void (*get_complete_cb)(void *ctx, void *session_ctx); - void *ctx; - struct eap_sim_pseudonym *pseudonyms; - struct eap_sim_reauth *reauths; - struct eap_sim_db_pending *pending; -}; - - -static struct eap_sim_db_pending * -eap_sim_db_get_pending(struct eap_sim_db_data *data, const u8 *imsi, - size_t imsi_len, int aka) -{ - struct eap_sim_db_pending *entry, *prev = NULL; - - entry = data->pending; - while (entry) { - if (entry->aka == aka && entry->imsi_len == imsi_len && - os_memcmp(entry->imsi, imsi, imsi_len) == 0) { - if (prev) - prev->next = entry->next; - else - data->pending = entry->next; - break; - } - prev = entry; - entry = entry->next; - } - return entry; -} - - -static void eap_sim_db_add_pending(struct eap_sim_db_data *data, - struct eap_sim_db_pending *entry) -{ - entry->next = data->pending; - data->pending = entry; -} - - -static void eap_sim_db_sim_resp_auth(struct eap_sim_db_data *data, - const char *imsi, char *buf) -{ - char *start, *end, *pos; - struct eap_sim_db_pending *entry; - int num_chal; - - /* - * SIM-RESP-AUTH Kc(i):SRES(i):RAND(i) ... - * SIM-RESP-AUTH FAILURE - * (IMSI = ASCII string, Kc/SRES/RAND = hex string) - */ - - entry = eap_sim_db_get_pending(data, (u8 *) imsi, os_strlen(imsi), 0); - if (entry == NULL) { - wpa_printf(MSG_DEBUG, "EAP-SIM DB: No pending entry for the " - "received message found"); - return; - } - - start = buf; - if (os_strncmp(start, "FAILURE", 7) == 0) { - wpa_printf(MSG_DEBUG, "EAP-SIM DB: External server reported " - "failure"); - entry->state = FAILURE; - eap_sim_db_add_pending(data, entry); - data->get_complete_cb(data->ctx, entry->cb_session_ctx); - return; - } - - num_chal = 0; - while (num_chal < EAP_SIM_MAX_CHAL) { - end = os_strchr(start, ' '); - if (end) - *end = '\0'; - - pos = os_strchr(start, ':'); - if (pos == NULL) - goto parse_fail; - *pos = '\0'; - if (hexstr2bin(start, entry->u.sim.kc[num_chal], - EAP_SIM_KC_LEN)) - goto parse_fail; - - start = pos + 1; - pos = os_strchr(start, ':'); - if (pos == NULL) - goto parse_fail; - *pos = '\0'; - if (hexstr2bin(start, entry->u.sim.sres[num_chal], - EAP_SIM_SRES_LEN)) - goto parse_fail; - - start = pos + 1; - if (hexstr2bin(start, entry->u.sim.rand[num_chal], - GSM_RAND_LEN)) - goto parse_fail; - - num_chal++; - if (end == NULL) - break; - else - start = end + 1; - } - entry->u.sim.num_chal = num_chal; - - entry->state = SUCCESS; - wpa_printf(MSG_DEBUG, "EAP-SIM DB: Authentication data parsed " - "successfully - callback"); - eap_sim_db_add_pending(data, entry); - data->get_complete_cb(data->ctx, entry->cb_session_ctx); - return; - -parse_fail: - wpa_printf(MSG_DEBUG, "EAP-SIM DB: Failed to parse response string"); - os_free(entry); -} - - -static void eap_sim_db_aka_resp_auth(struct eap_sim_db_data *data, - const char *imsi, char *buf) -{ - char *start, *end; - struct eap_sim_db_pending *entry; - - /* - * AKA-RESP-AUTH - * AKA-RESP-AUTH FAILURE - * (IMSI = ASCII string, RAND/AUTN/IK/CK/RES = hex string) - */ - - entry = eap_sim_db_get_pending(data, (u8 *) imsi, os_strlen(imsi), 1); - if (entry == NULL) { - wpa_printf(MSG_DEBUG, "EAP-SIM DB: No pending entry for the " - "received message found"); - return; - } - - start = buf; - if (os_strncmp(start, "FAILURE", 7) == 0) { - wpa_printf(MSG_DEBUG, "EAP-SIM DB: External server reported " - "failure"); - entry->state = FAILURE; - eap_sim_db_add_pending(data, entry); - data->get_complete_cb(data->ctx, entry->cb_session_ctx); - return; - } - - end = os_strchr(start, ' '); - if (end == NULL) - goto parse_fail; - *end = '\0'; - if (hexstr2bin(start, entry->u.aka.rand, EAP_AKA_RAND_LEN)) - goto parse_fail; - - start = end + 1; - end = os_strchr(start, ' '); - if (end == NULL) - goto parse_fail; - *end = '\0'; - if (hexstr2bin(start, entry->u.aka.autn, EAP_AKA_AUTN_LEN)) - goto parse_fail; - - start = end + 1; - end = os_strchr(start, ' '); - if (end == NULL) - goto parse_fail; - *end = '\0'; - if (hexstr2bin(start, entry->u.aka.ik, EAP_AKA_IK_LEN)) - goto parse_fail; - - start = end + 1; - end = os_strchr(start, ' '); - if (end == NULL) - goto parse_fail; - *end = '\0'; - if (hexstr2bin(start, entry->u.aka.ck, EAP_AKA_CK_LEN)) - goto parse_fail; - - start = end + 1; - end = os_strchr(start, ' '); - if (end) - *end = '\0'; - else { - end = start; - while (*end) - end++; - } - entry->u.aka.res_len = (end - start) / 2; - if (entry->u.aka.res_len > EAP_AKA_RES_MAX_LEN) { - wpa_printf(MSG_DEBUG, "EAP-SIM DB: Too long RES"); - entry->u.aka.res_len = 0; - goto parse_fail; - } - if (hexstr2bin(start, entry->u.aka.res, entry->u.aka.res_len)) - goto parse_fail; - - entry->state = SUCCESS; - wpa_printf(MSG_DEBUG, "EAP-SIM DB: Authentication data parsed " - "successfully - callback"); - eap_sim_db_add_pending(data, entry); - data->get_complete_cb(data->ctx, entry->cb_session_ctx); - return; - -parse_fail: - wpa_printf(MSG_DEBUG, "EAP-SIM DB: Failed to parse response string"); - os_free(entry); -} - - -static void eap_sim_db_receive(int sock, void *eloop_ctx, void *sock_ctx) -{ - struct eap_sim_db_data *data = eloop_ctx; - char buf[1000], *pos, *cmd, *imsi; - int res; - - res = recv(sock, buf, sizeof(buf), 0); - if (res < 0) - return; - wpa_hexdump_ascii_key(MSG_MSGDUMP, "EAP-SIM DB: Received from an " - "external source", (u8 *) buf, res); - if (res == 0) - return; - if (res >= (int) sizeof(buf)) - res = sizeof(buf) - 1; - buf[res] = '\0'; - - if (data->get_complete_cb == NULL) { - wpa_printf(MSG_DEBUG, "EAP-SIM DB: No get_complete_cb " - "registered"); - return; - } - - /* ... */ - - cmd = buf; - pos = os_strchr(cmd, ' '); - if (pos == NULL) - goto parse_fail; - *pos = '\0'; - imsi = pos + 1; - pos = os_strchr(imsi, ' '); - if (pos == NULL) - goto parse_fail; - *pos = '\0'; - wpa_printf(MSG_DEBUG, "EAP-SIM DB: External response=%s for IMSI %s", - cmd, imsi); - - if (os_strcmp(cmd, "SIM-RESP-AUTH") == 0) - eap_sim_db_sim_resp_auth(data, imsi, pos + 1); - else if (os_strcmp(cmd, "AKA-RESP-AUTH") == 0) - eap_sim_db_aka_resp_auth(data, imsi, pos + 1); - else - wpa_printf(MSG_INFO, "EAP-SIM DB: Unknown external response " - "'%s'", cmd); - return; - -parse_fail: - wpa_printf(MSG_DEBUG, "EAP-SIM DB: Failed to parse response string"); -} - - -static int eap_sim_db_open_socket(struct eap_sim_db_data *data) -{ - struct sockaddr_un addr; - static int counter = 0; - - if (os_strncmp(data->fname, "unix:", 5) != 0) - return -1; - - data->sock = socket(PF_UNIX, SOCK_DGRAM, 0); - if (data->sock < 0) { - perror("socket(eap_sim_db)"); - return -1; - } - - os_memset(&addr, 0, sizeof(addr)); - addr.sun_family = AF_UNIX; - os_snprintf(addr.sun_path, sizeof(addr.sun_path), - "/tmp/eap_sim_db_%d-%d", getpid(), counter++); - data->local_sock = os_strdup(addr.sun_path); - if (bind(data->sock, (struct sockaddr *) &addr, sizeof(addr)) < 0) { - perror("bind(eap_sim_db)"); - close(data->sock); - data->sock = -1; - return -1; - } - - os_memset(&addr, 0, sizeof(addr)); - addr.sun_family = AF_UNIX; - os_strlcpy(addr.sun_path, data->fname + 5, sizeof(addr.sun_path)); - if (connect(data->sock, (struct sockaddr *) &addr, sizeof(addr)) < 0) { - perror("connect(eap_sim_db)"); - wpa_hexdump_ascii(MSG_INFO, "HLR/AuC GW socket", - (u8 *) addr.sun_path, - os_strlen(addr.sun_path)); - close(data->sock); - data->sock = -1; - return -1; - } - - eloop_register_read_sock(data->sock, eap_sim_db_receive, data, NULL); - - return 0; -} - - -static void eap_sim_db_close_socket(struct eap_sim_db_data *data) -{ - if (data->sock >= 0) { - eloop_unregister_read_sock(data->sock); - close(data->sock); - data->sock = -1; - } - if (data->local_sock) { - unlink(data->local_sock); - os_free(data->local_sock); - data->local_sock = NULL; - } -} - - -/** - * eap_sim_db_init - Initialize EAP-SIM DB / authentication gateway interface - * @config: Configuration data (e.g., file name) - * @get_complete_cb: Callback function for reporting availability of triplets - * @ctx: Context pointer for get_complete_cb - * Returns: Pointer to a private data structure or %NULL on failure - */ -void * eap_sim_db_init(const char *config, - void (*get_complete_cb)(void *ctx, void *session_ctx), - void *ctx) -{ - struct eap_sim_db_data *data; - - data = os_zalloc(sizeof(*data)); - if (data == NULL) - return NULL; - - data->sock = -1; - data->get_complete_cb = get_complete_cb; - data->ctx = ctx; - data->fname = os_strdup(config); - if (data->fname == NULL) - goto fail; - - if (os_strncmp(data->fname, "unix:", 5) == 0) { - if (eap_sim_db_open_socket(data)) - goto fail; - } - - return data; - -fail: - eap_sim_db_close_socket(data); - os_free(data->fname); - os_free(data); - return NULL; -} - - -static void eap_sim_db_free_pseudonym(struct eap_sim_pseudonym *p) -{ - os_free(p->identity); - os_free(p->pseudonym); - os_free(p); -} - - -static void eap_sim_db_free_reauth(struct eap_sim_reauth *r) -{ - os_free(r->identity); - os_free(r->reauth_id); - os_free(r); -} - - -/** - * eap_sim_db_deinit - Deinitialize EAP-SIM DB/authentication gw interface - * @priv: Private data pointer from eap_sim_db_init() - */ -void eap_sim_db_deinit(void *priv) -{ - struct eap_sim_db_data *data = priv; - struct eap_sim_pseudonym *p, *prev; - struct eap_sim_reauth *r, *prevr; - struct eap_sim_db_pending *pending, *prev_pending; - - eap_sim_db_close_socket(data); - os_free(data->fname); - - p = data->pseudonyms; - while (p) { - prev = p; - p = p->next; - eap_sim_db_free_pseudonym(prev); - } - - r = data->reauths; - while (r) { - prevr = r; - r = r->next; - eap_sim_db_free_reauth(prevr); - } - - pending = data->pending; - while (pending) { - prev_pending = pending; - pending = pending->next; - os_free(prev_pending); - } - - os_free(data); -} - - -static int eap_sim_db_send(struct eap_sim_db_data *data, const char *msg, - size_t len) -{ - int _errno = 0; - - if (send(data->sock, msg, len, 0) < 0) { - _errno = errno; - perror("send[EAP-SIM DB UNIX]"); - } - - if (_errno == ENOTCONN || _errno == EDESTADDRREQ || _errno == EINVAL || - _errno == ECONNREFUSED) { - /* Try to reconnect */ - eap_sim_db_close_socket(data); - if (eap_sim_db_open_socket(data) < 0) - return -1; - wpa_printf(MSG_DEBUG, "EAP-SIM DB: Reconnected to the " - "external server"); - if (send(data->sock, msg, len, 0) < 0) { - perror("send[EAP-SIM DB UNIX]"); - return -1; - } - } - - return 0; -} - - -static void eap_sim_db_expire_pending(struct eap_sim_db_data *data) -{ - /* TODO: add limit for maximum length for pending list; remove latest - * (i.e., last) entry from the list if the limit is reached; could also - * use timeout to expire pending entries */ -} - - -/** - * eap_sim_db_get_gsm_triplets - Get GSM triplets - * @priv: Private data pointer from eap_sim_db_init() - * @identity: User name identity - * @identity_len: Length of identity in bytes - * @max_chal: Maximum number of triplets - * @_rand: Buffer for RAND values - * @kc: Buffer for Kc values - * @sres: Buffer for SRES values - * @cb_session_ctx: Session callback context for get_complete_cb() - * Returns: Number of triplets received (has to be less than or equal to - * max_chal), -1 (EAP_SIM_DB_FAILURE) on error (e.g., user not found), or - * -2 (EAP_SIM_DB_PENDING) if results are not yet available. In this case, the - * callback function registered with eap_sim_db_init() will be called once the - * results become available. - * - * In most cases, the user name is '1' | IMSI, i.e., 1 followed by the IMSI in - * ASCII format. - * - * When using an external server for GSM triplets, this function can always - * start a request and return EAP_SIM_DB_PENDING immediately if authentication - * triplets are not available. Once the triplets are received, callback - * function registered with eap_sim_db_init() is called to notify EAP state - * machine to reprocess the message. This eap_sim_db_get_gsm_triplets() - * function will then be called again and the newly received triplets will then - * be given to the caller. - */ -int eap_sim_db_get_gsm_triplets(void *priv, const u8 *identity, - size_t identity_len, int max_chal, - u8 *_rand, u8 *kc, u8 *sres, - void *cb_session_ctx) -{ - struct eap_sim_db_data *data = priv; - struct eap_sim_db_pending *entry; - int len, ret; - size_t i; - char msg[40]; - - if (identity_len < 2 || identity[0] != EAP_SIM_PERMANENT_PREFIX) { - wpa_hexdump_ascii(MSG_DEBUG, "EAP-SIM DB: unexpected identity", - identity, identity_len); - return EAP_SIM_DB_FAILURE; - } - identity++; - identity_len--; - for (i = 0; i < identity_len; i++) { - if (identity[i] == '@') { - identity_len = i; - break; - } - } - if (identity_len + 1 > sizeof(entry->imsi)) { - wpa_hexdump_ascii(MSG_DEBUG, "EAP-SIM DB: unexpected identity", - identity, identity_len); - return EAP_SIM_DB_FAILURE; - } - wpa_hexdump_ascii(MSG_DEBUG, "EAP-SIM DB: Get GSM triplets for IMSI", - identity, identity_len); - - entry = eap_sim_db_get_pending(data, identity, identity_len, 0); - if (entry) { - int num_chal; - if (entry->state == FAILURE) { - wpa_printf(MSG_DEBUG, "EAP-SIM DB: Pending entry -> " - "failure"); - os_free(entry); - return EAP_SIM_DB_FAILURE; - } - - if (entry->state == PENDING) { - wpa_printf(MSG_DEBUG, "EAP-SIM DB: Pending entry -> " - "still pending"); - eap_sim_db_add_pending(data, entry); - return EAP_SIM_DB_PENDING; - } - - wpa_printf(MSG_DEBUG, "EAP-SIM DB: Pending entry -> " - "%d challenges", entry->u.sim.num_chal); - num_chal = entry->u.sim.num_chal; - if (num_chal > max_chal) - num_chal = max_chal; - os_memcpy(_rand, entry->u.sim.rand, num_chal * GSM_RAND_LEN); - os_memcpy(sres, entry->u.sim.sres, - num_chal * EAP_SIM_SRES_LEN); - os_memcpy(kc, entry->u.sim.kc, num_chal * EAP_SIM_KC_LEN); - os_free(entry); - return num_chal; - } - - if (data->sock < 0) { - if (eap_sim_db_open_socket(data) < 0) - return EAP_SIM_DB_FAILURE; - } - - len = os_snprintf(msg, sizeof(msg), "SIM-REQ-AUTH "); - if (len < 0 || len + identity_len >= sizeof(msg)) - return EAP_SIM_DB_FAILURE; - os_memcpy(msg + len, identity, identity_len); - len += identity_len; - ret = os_snprintf(msg + len, sizeof(msg) - len, " %d", max_chal); - if (ret < 0 || (size_t) ret >= sizeof(msg) - len) - return EAP_SIM_DB_FAILURE; - len += ret; - - wpa_hexdump(MSG_DEBUG, "EAP-SIM DB: requesting SIM authentication " - "data for IMSI", identity, identity_len); - if (eap_sim_db_send(data, msg, len) < 0) - return EAP_SIM_DB_FAILURE; - - entry = os_zalloc(sizeof(*entry)); - if (entry == NULL) - return EAP_SIM_DB_FAILURE; - - os_get_time(&entry->timestamp); - os_memcpy(entry->imsi, identity, identity_len); - entry->imsi_len = identity_len; - entry->cb_session_ctx = cb_session_ctx; - entry->state = PENDING; - eap_sim_db_add_pending(data, entry); - eap_sim_db_expire_pending(data); - - return EAP_SIM_DB_PENDING; -} - - -static struct eap_sim_pseudonym * -eap_sim_db_get_pseudonym(struct eap_sim_db_data *data, const u8 *identity, - size_t identity_len) -{ - char *pseudonym; - size_t len; - struct eap_sim_pseudonym *p; - - if (identity_len == 0 || - (identity[0] != EAP_SIM_PSEUDONYM_PREFIX && - identity[0] != EAP_AKA_PSEUDONYM_PREFIX)) - return NULL; - - /* Remove possible realm from identity */ - len = 0; - while (len < identity_len) { - if (identity[len] == '@') - break; - len++; - } - - pseudonym = os_malloc(len + 1); - if (pseudonym == NULL) - return NULL; - os_memcpy(pseudonym, identity, len); - pseudonym[len] = '\0'; - - p = data->pseudonyms; - while (p) { - if (os_strcmp(p->pseudonym, pseudonym) == 0) - break; - p = p->next; - } - - os_free(pseudonym); - - return p; -} - - -static struct eap_sim_pseudonym * -eap_sim_db_get_pseudonym_id(struct eap_sim_db_data *data, const u8 *identity, - size_t identity_len) -{ - struct eap_sim_pseudonym *p; - - if (identity_len == 0 || - (identity[0] != EAP_SIM_PERMANENT_PREFIX && - identity[0] != EAP_AKA_PERMANENT_PREFIX)) - return NULL; - - p = data->pseudonyms; - while (p) { - if (identity_len == p->identity_len && - os_memcmp(p->identity, identity, identity_len) == 0) - break; - p = p->next; - } - - return p; -} - - -static struct eap_sim_reauth * -eap_sim_db_get_reauth(struct eap_sim_db_data *data, const u8 *identity, - size_t identity_len) -{ - char *reauth_id; - size_t len; - struct eap_sim_reauth *r; - - if (identity_len == 0 || - (identity[0] != EAP_SIM_REAUTH_ID_PREFIX && - identity[0] != EAP_AKA_REAUTH_ID_PREFIX)) - return NULL; - - /* Remove possible realm from identity */ - len = 0; - while (len < identity_len) { - if (identity[len] == '@') - break; - len++; - } - - reauth_id = os_malloc(len + 1); - if (reauth_id == NULL) - return NULL; - os_memcpy(reauth_id, identity, len); - reauth_id[len] = '\0'; - - r = data->reauths; - while (r) { - if (os_strcmp(r->reauth_id, reauth_id) == 0) - break; - r = r->next; - } - - os_free(reauth_id); - - return r; -} - - -static struct eap_sim_reauth * -eap_sim_db_get_reauth_id(struct eap_sim_db_data *data, const u8 *identity, - size_t identity_len) -{ - struct eap_sim_pseudonym *p; - struct eap_sim_reauth *r; - - if (identity_len == 0) - return NULL; - - p = eap_sim_db_get_pseudonym(data, identity, identity_len); - if (p == NULL) - p = eap_sim_db_get_pseudonym_id(data, identity, identity_len); - if (p) { - identity = p->identity; - identity_len = p->identity_len; - } - - r = data->reauths; - while (r) { - if (identity_len == r->identity_len && - os_memcmp(r->identity, identity, identity_len) == 0) - break; - r = r->next; - } - - return r; -} - - -/** - * eap_sim_db_identity_known - Verify whether the given identity is known - * @priv: Private data pointer from eap_sim_db_init() - * @identity: User name identity - * @identity_len: Length of identity in bytes - * Returns: 0 if the user is found or -1 on failure - * - * In most cases, the user name is ['0','1'] | IMSI, i.e., 1 followed by the - * IMSI in ASCII format, ['2','3'] | pseudonym, or ['4','5'] | reauth_id. - */ -int eap_sim_db_identity_known(void *priv, const u8 *identity, - size_t identity_len) -{ - struct eap_sim_db_data *data = priv; - - if (identity == NULL || identity_len < 2) - return -1; - - if (identity[0] == EAP_SIM_PSEUDONYM_PREFIX || - identity[0] == EAP_AKA_PSEUDONYM_PREFIX) { - struct eap_sim_pseudonym *p = - eap_sim_db_get_pseudonym(data, identity, identity_len); - return p ? 0 : -1; - } - - if (identity[0] == EAP_SIM_REAUTH_ID_PREFIX || - identity[0] == EAP_AKA_REAUTH_ID_PREFIX) { - struct eap_sim_reauth *r = - eap_sim_db_get_reauth(data, identity, identity_len); - return r ? 0 : -1; - } - - if (identity[0] != EAP_SIM_PERMANENT_PREFIX && - identity[0] != EAP_AKA_PERMANENT_PREFIX) { - /* Unknown identity prefix */ - return -1; - } - - /* TODO: Should consider asking HLR/AuC gateway whether this permanent - * identity is known. If it is, EAP-SIM/AKA can skip identity request. - * In case of EAP-AKA, this would reduce number of needed round-trips. - * Ideally, this would be done with one wait, i.e., just request - * authentication data and store it for the next use. This would then - * need to use similar pending-request functionality as the normal - * request for authentication data at later phase. - */ - return -1; -} - - -static char * eap_sim_db_get_next(struct eap_sim_db_data *data, char prefix) -{ - char *id, *pos, *end; - u8 buf[10]; - - if (random_get_bytes(buf, sizeof(buf))) - return NULL; - id = os_malloc(sizeof(buf) * 2 + 2); - if (id == NULL) - return NULL; - - pos = id; - end = id + sizeof(buf) * 2 + 2; - *pos++ = prefix; - pos += wpa_snprintf_hex(pos, end - pos, buf, sizeof(buf)); - - return id; -} - - -/** - * eap_sim_db_get_next_pseudonym - EAP-SIM DB: Get next pseudonym - * @priv: Private data pointer from eap_sim_db_init() - * @aka: Using EAP-AKA instead of EAP-SIM - * Returns: Next pseudonym (allocated string) or %NULL on failure - * - * This function is used to generate a pseudonym for EAP-SIM. The returned - * pseudonym is not added to database at this point; it will need to be added - * with eap_sim_db_add_pseudonym() once the authentication has been completed - * successfully. Caller is responsible for freeing the returned buffer. - */ -char * eap_sim_db_get_next_pseudonym(void *priv, int aka) -{ - struct eap_sim_db_data *data = priv; - return eap_sim_db_get_next(data, aka ? EAP_AKA_PSEUDONYM_PREFIX : - EAP_SIM_PSEUDONYM_PREFIX); -} - - -/** - * eap_sim_db_get_next_reauth_id - EAP-SIM DB: Get next reauth_id - * @priv: Private data pointer from eap_sim_db_init() - * @aka: Using EAP-AKA instead of EAP-SIM - * Returns: Next reauth_id (allocated string) or %NULL on failure - * - * This function is used to generate a fast re-authentication identity for - * EAP-SIM. The returned reauth_id is not added to database at this point; it - * will need to be added with eap_sim_db_add_reauth() once the authentication - * has been completed successfully. Caller is responsible for freeing the - * returned buffer. - */ -char * eap_sim_db_get_next_reauth_id(void *priv, int aka) -{ - struct eap_sim_db_data *data = priv; - return eap_sim_db_get_next(data, aka ? EAP_AKA_REAUTH_ID_PREFIX : - EAP_SIM_REAUTH_ID_PREFIX); -} - - -/** - * eap_sim_db_add_pseudonym - EAP-SIM DB: Add new pseudonym - * @priv: Private data pointer from eap_sim_db_init() - * @identity: Identity of the user (may be permanent identity or pseudonym) - * @identity_len: Length of identity - * @pseudonym: Pseudonym for this user. This needs to be an allocated buffer, - * e.g., return value from eap_sim_db_get_next_pseudonym(). Caller must not - * free it. - * Returns: 0 on success, -1 on failure - * - * This function adds a new pseudonym for EAP-SIM user. EAP-SIM DB is - * responsible of freeing pseudonym buffer once it is not needed anymore. - */ -int eap_sim_db_add_pseudonym(void *priv, const u8 *identity, - size_t identity_len, char *pseudonym) -{ - struct eap_sim_db_data *data = priv; - struct eap_sim_pseudonym *p; - wpa_hexdump_ascii(MSG_DEBUG, "EAP-SIM DB: Add pseudonym for identity", - identity, identity_len); - wpa_printf(MSG_DEBUG, "EAP-SIM DB: Pseudonym: %s", pseudonym); - - /* TODO: could store last two pseudonyms */ - p = eap_sim_db_get_pseudonym(data, identity, identity_len); - if (p == NULL) - p = eap_sim_db_get_pseudonym_id(data, identity, identity_len); - - if (p) { - wpa_printf(MSG_DEBUG, "EAP-SIM DB: Replacing previous " - "pseudonym: %s", p->pseudonym); - os_free(p->pseudonym); - p->pseudonym = pseudonym; - return 0; - } - - p = os_zalloc(sizeof(*p)); - if (p == NULL) { - os_free(pseudonym); - return -1; - } - - p->next = data->pseudonyms; - p->identity = os_malloc(identity_len); - if (p->identity == NULL) { - os_free(p); - os_free(pseudonym); - return -1; - } - os_memcpy(p->identity, identity, identity_len); - p->identity_len = identity_len; - p->pseudonym = pseudonym; - data->pseudonyms = p; - - wpa_printf(MSG_DEBUG, "EAP-SIM DB: Added new pseudonym entry"); - return 0; -} - - -static struct eap_sim_reauth * -eap_sim_db_add_reauth_data(struct eap_sim_db_data *data, const u8 *identity, - size_t identity_len, char *reauth_id, u16 counter) -{ - struct eap_sim_reauth *r; - - wpa_hexdump_ascii(MSG_DEBUG, "EAP-SIM DB: Add reauth_id for identity", - identity, identity_len); - wpa_printf(MSG_DEBUG, "EAP-SIM DB: reauth_id: %s", reauth_id); - - r = eap_sim_db_get_reauth(data, identity, identity_len); - if (r == NULL) - r = eap_sim_db_get_reauth_id(data, identity, identity_len); - - if (r) { - wpa_printf(MSG_DEBUG, "EAP-SIM DB: Replacing previous " - "reauth_id: %s", r->reauth_id); - os_free(r->reauth_id); - r->reauth_id = reauth_id; - } else { - r = os_zalloc(sizeof(*r)); - if (r == NULL) { - os_free(reauth_id); - return NULL; - } - - r->next = data->reauths; - r->identity = os_malloc(identity_len); - if (r->identity == NULL) { - os_free(r); - os_free(reauth_id); - return NULL; - } - os_memcpy(r->identity, identity, identity_len); - r->identity_len = identity_len; - r->reauth_id = reauth_id; - data->reauths = r; - wpa_printf(MSG_DEBUG, "EAP-SIM DB: Added new reauth entry"); - } - - r->counter = counter; - - return r; -} - - -/** - * eap_sim_db_add_reauth - EAP-SIM DB: Add new re-authentication entry - * @priv: Private data pointer from eap_sim_db_init() - * @identity: Identity of the user (may be permanent identity or pseudonym) - * @identity_len: Length of identity - * @reauth_id: reauth_id for this user. This needs to be an allocated buffer, - * e.g., return value from eap_sim_db_get_next_reauth_id(). Caller must not - * free it. - * @counter: AT_COUNTER value for fast re-authentication - * @mk: 16-byte MK from the previous full authentication or %NULL - * Returns: 0 on success, -1 on failure - * - * This function adds a new re-authentication entry for an EAP-SIM user. - * EAP-SIM DB is responsible of freeing reauth_id buffer once it is not needed - * anymore. - */ -int eap_sim_db_add_reauth(void *priv, const u8 *identity, - size_t identity_len, char *reauth_id, u16 counter, - const u8 *mk) -{ - struct eap_sim_db_data *data = priv; - struct eap_sim_reauth *r; - - r = eap_sim_db_add_reauth_data(data, identity, identity_len, reauth_id, - counter); - if (r == NULL) - return -1; - - os_memcpy(r->mk, mk, EAP_SIM_MK_LEN); - r->aka_prime = 0; - - return 0; -} - - -#ifdef EAP_SERVER_AKA_PRIME -/** - * eap_sim_db_add_reauth_prime - EAP-AKA' DB: Add new re-authentication entry - * @priv: Private data pointer from eap_sim_db_init() - * @identity: Identity of the user (may be permanent identity or pseudonym) - * @identity_len: Length of identity - * @reauth_id: reauth_id for this user. This needs to be an allocated buffer, - * e.g., return value from eap_sim_db_get_next_reauth_id(). Caller must not - * free it. - * @counter: AT_COUNTER value for fast re-authentication - * @k_encr: K_encr from the previous full authentication - * @k_aut: K_aut from the previous full authentication - * @k_re: 32-byte K_re from the previous full authentication - * Returns: 0 on success, -1 on failure - * - * This function adds a new re-authentication entry for an EAP-AKA' user. - * EAP-SIM DB is responsible of freeing reauth_id buffer once it is not needed - * anymore. - */ -int eap_sim_db_add_reauth_prime(void *priv, const u8 *identity, - size_t identity_len, char *reauth_id, - u16 counter, const u8 *k_encr, const u8 *k_aut, - const u8 *k_re) -{ - struct eap_sim_db_data *data = priv; - struct eap_sim_reauth *r; - - r = eap_sim_db_add_reauth_data(data, identity, identity_len, reauth_id, - counter); - if (r == NULL) - return -1; - - r->aka_prime = 1; - os_memcpy(r->k_encr, k_encr, EAP_SIM_K_ENCR_LEN); - os_memcpy(r->k_aut, k_aut, EAP_AKA_PRIME_K_AUT_LEN); - os_memcpy(r->k_re, k_re, EAP_AKA_PRIME_K_RE_LEN); - - return 0; -} -#endif /* EAP_SERVER_AKA_PRIME */ - - -/** - * eap_sim_db_get_permanent - EAP-SIM DB: Get permanent identity - * @priv: Private data pointer from eap_sim_db_init() - * @identity: Identity of the user (may be permanent identity or pseudonym) - * @identity_len: Length of identity - * @len: Buffer for length of the returned permanent identity - * Returns: Pointer to the permanent identity, or %NULL if not found - */ -const u8 * eap_sim_db_get_permanent(void *priv, const u8 *identity, - size_t identity_len, size_t *len) -{ - struct eap_sim_db_data *data = priv; - struct eap_sim_pseudonym *p; - - if (identity == NULL) - return NULL; - - p = eap_sim_db_get_pseudonym(data, identity, identity_len); - if (p == NULL) - p = eap_sim_db_get_pseudonym_id(data, identity, identity_len); - if (p == NULL) - return NULL; - - *len = p->identity_len; - return p->identity; -} - - -/** - * eap_sim_db_get_reauth_entry - EAP-SIM DB: Get re-authentication entry - * @priv: Private data pointer from eap_sim_db_init() - * @identity: Identity of the user (may be permanent identity, pseudonym, or - * reauth_id) - * @identity_len: Length of identity - * Returns: Pointer to the re-auth entry, or %NULL if not found - */ -struct eap_sim_reauth * -eap_sim_db_get_reauth_entry(void *priv, const u8 *identity, - size_t identity_len) -{ - struct eap_sim_db_data *data = priv; - struct eap_sim_reauth *r; - - if (identity == NULL) - return NULL; - r = eap_sim_db_get_reauth(data, identity, identity_len); - if (r == NULL) - r = eap_sim_db_get_reauth_id(data, identity, identity_len); - return r; -} - - -/** - * eap_sim_db_remove_reauth - EAP-SIM DB: Remove re-authentication entry - * @priv: Private data pointer from eap_sim_db_init() - * @reauth: Pointer to re-authentication entry from - * eap_sim_db_get_reauth_entry() - */ -void eap_sim_db_remove_reauth(void *priv, struct eap_sim_reauth *reauth) -{ - struct eap_sim_db_data *data = priv; - struct eap_sim_reauth *r, *prev = NULL; - r = data->reauths; - while (r) { - if (r == reauth) { - if (prev) - prev->next = r->next; - else - data->reauths = r->next; - eap_sim_db_free_reauth(r); - return; - } - prev = r; - r = r->next; - } -} - - -/** - * eap_sim_db_get_aka_auth - Get AKA authentication values - * @priv: Private data pointer from eap_sim_db_init() - * @identity: User name identity - * @identity_len: Length of identity in bytes - * @_rand: Buffer for RAND value - * @autn: Buffer for AUTN value - * @ik: Buffer for IK value - * @ck: Buffer for CK value - * @res: Buffer for RES value - * @res_len: Buffer for RES length - * @cb_session_ctx: Session callback context for get_complete_cb() - * Returns: 0 on success, -1 (EAP_SIM_DB_FAILURE) on error (e.g., user not - * found), or -2 (EAP_SIM_DB_PENDING) if results are not yet available. In this - * case, the callback function registered with eap_sim_db_init() will be - * called once the results become available. - * - * In most cases, the user name is '0' | IMSI, i.e., 0 followed by the IMSI in - * ASCII format. - * - * When using an external server for AKA authentication, this function can - * always start a request and return EAP_SIM_DB_PENDING immediately if - * authentication triplets are not available. Once the authentication data are - * received, callback function registered with eap_sim_db_init() is called to - * notify EAP state machine to reprocess the message. This - * eap_sim_db_get_aka_auth() function will then be called again and the newly - * received triplets will then be given to the caller. - */ -int eap_sim_db_get_aka_auth(void *priv, const u8 *identity, - size_t identity_len, u8 *_rand, u8 *autn, u8 *ik, - u8 *ck, u8 *res, size_t *res_len, - void *cb_session_ctx) -{ - struct eap_sim_db_data *data = priv; - struct eap_sim_db_pending *entry; - int len; - size_t i; - char msg[40]; - - if (identity_len < 2 || identity == NULL || - identity[0] != EAP_AKA_PERMANENT_PREFIX) { - wpa_hexdump_ascii(MSG_DEBUG, "EAP-SIM DB: unexpected identity", - identity, identity_len); - return EAP_SIM_DB_FAILURE; - } - identity++; - identity_len--; - for (i = 0; i < identity_len; i++) { - if (identity[i] == '@') { - identity_len = i; - break; - } - } - if (identity_len + 1 > sizeof(entry->imsi)) { - wpa_hexdump_ascii(MSG_DEBUG, "EAP-SIM DB: unexpected identity", - identity, identity_len); - return EAP_SIM_DB_FAILURE; - } - wpa_hexdump_ascii(MSG_DEBUG, "EAP-SIM DB: Get AKA auth for IMSI", - identity, identity_len); - - entry = eap_sim_db_get_pending(data, identity, identity_len, 1); - if (entry) { - if (entry->state == FAILURE) { - os_free(entry); - wpa_printf(MSG_DEBUG, "EAP-SIM DB: Failure"); - return EAP_SIM_DB_FAILURE; - } - - if (entry->state == PENDING) { - eap_sim_db_add_pending(data, entry); - wpa_printf(MSG_DEBUG, "EAP-SIM DB: Pending"); - return EAP_SIM_DB_PENDING; - } - - wpa_printf(MSG_DEBUG, "EAP-SIM DB: Returning successfully " - "received authentication data"); - os_memcpy(_rand, entry->u.aka.rand, EAP_AKA_RAND_LEN); - os_memcpy(autn, entry->u.aka.autn, EAP_AKA_AUTN_LEN); - os_memcpy(ik, entry->u.aka.ik, EAP_AKA_IK_LEN); - os_memcpy(ck, entry->u.aka.ck, EAP_AKA_CK_LEN); - os_memcpy(res, entry->u.aka.res, EAP_AKA_RES_MAX_LEN); - *res_len = entry->u.aka.res_len; - os_free(entry); - return 0; - } - - if (data->sock < 0) { - if (eap_sim_db_open_socket(data) < 0) - return EAP_SIM_DB_FAILURE; - } - - len = os_snprintf(msg, sizeof(msg), "AKA-REQ-AUTH "); - if (len < 0 || len + identity_len >= sizeof(msg)) - return EAP_SIM_DB_FAILURE; - os_memcpy(msg + len, identity, identity_len); - len += identity_len; - - wpa_hexdump(MSG_DEBUG, "EAP-SIM DB: requesting AKA authentication " - "data for IMSI", identity, identity_len); - if (eap_sim_db_send(data, msg, len) < 0) - return EAP_SIM_DB_FAILURE; - - entry = os_zalloc(sizeof(*entry)); - if (entry == NULL) - return EAP_SIM_DB_FAILURE; - - os_get_time(&entry->timestamp); - entry->aka = 1; - os_memcpy(entry->imsi, identity, identity_len); - entry->imsi_len = identity_len; - entry->cb_session_ctx = cb_session_ctx; - entry->state = PENDING; - eap_sim_db_add_pending(data, entry); - eap_sim_db_expire_pending(data); - - return EAP_SIM_DB_PENDING; -} - - -/** - * eap_sim_db_resynchronize - Resynchronize AKA AUTN - * @priv: Private data pointer from eap_sim_db_init() - * @identity: User name identity - * @identity_len: Length of identity in bytes - * @auts: AUTS value from the peer - * @_rand: RAND value used in the rejected message - * Returns: 0 on success, -1 on failure - * - * This function is called when the peer reports synchronization failure in the - * AUTN value by sending AUTS. The AUTS and RAND values should be sent to - * HLR/AuC to allow it to resynchronize with the peer. After this, - * eap_sim_db_get_aka_auth() will be called again to to fetch updated - * RAND/AUTN values for the next challenge. - */ -int eap_sim_db_resynchronize(void *priv, const u8 *identity, - size_t identity_len, const u8 *auts, - const u8 *_rand) -{ - struct eap_sim_db_data *data = priv; - size_t i; - - if (identity_len < 2 || identity == NULL || - identity[0] != EAP_AKA_PERMANENT_PREFIX) { - wpa_hexdump_ascii(MSG_DEBUG, "EAP-SIM DB: unexpected identity", - identity, identity_len); - return -1; - } - identity++; - identity_len--; - for (i = 0; i < identity_len; i++) { - if (identity[i] == '@') { - identity_len = i; - break; - } - } - if (identity_len > 20) { - wpa_hexdump_ascii(MSG_DEBUG, "EAP-SIM DB: unexpected identity", - identity, identity_len); - return -1; - } - - if (data->sock >= 0) { - char msg[100]; - int len, ret; - - len = os_snprintf(msg, sizeof(msg), "AKA-AUTS "); - if (len < 0 || len + identity_len >= sizeof(msg)) - return -1; - os_memcpy(msg + len, identity, identity_len); - len += identity_len; - - ret = os_snprintf(msg + len, sizeof(msg) - len, " "); - if (ret < 0 || (size_t) ret >= sizeof(msg) - len) - return -1; - len += ret; - len += wpa_snprintf_hex(msg + len, sizeof(msg) - len, - auts, EAP_AKA_AUTS_LEN); - ret = os_snprintf(msg + len, sizeof(msg) - len, " "); - if (ret < 0 || (size_t) ret >= sizeof(msg) - len) - return -1; - len += ret; - len += wpa_snprintf_hex(msg + len, sizeof(msg) - len, - _rand, EAP_AKA_RAND_LEN); - wpa_hexdump(MSG_DEBUG, "EAP-SIM DB: reporting AKA AUTS for " - "IMSI", identity, identity_len); - if (eap_sim_db_send(data, msg, len) < 0) - return -1; - } - - return 0; -} diff --git a/hostapd-0.8/src/eap_server/eap_sim_db.h b/hostapd-0.8/src/eap_server/eap_sim_db.h deleted file mode 100644 index ab89ae9..0000000 --- a/hostapd-0.8/src/eap_server/eap_sim_db.h +++ /dev/null @@ -1,91 +0,0 @@ -/* - * hostapd / EAP-SIM database/authenticator gateway - * Copyright (c) 2005-2007, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#ifndef EAP_SIM_DB_H -#define EAP_SIM_DB_H - -#include "eap_common/eap_sim_common.h" - -/* Identity prefixes */ -#define EAP_SIM_PERMANENT_PREFIX '1' -#define EAP_SIM_PSEUDONYM_PREFIX '3' -#define EAP_SIM_REAUTH_ID_PREFIX '5' -#define EAP_AKA_PERMANENT_PREFIX '0' -#define EAP_AKA_PSEUDONYM_PREFIX '2' -#define EAP_AKA_REAUTH_ID_PREFIX '4' - -void * eap_sim_db_init(const char *config, - void (*get_complete_cb)(void *ctx, void *session_ctx), - void *ctx); - -void eap_sim_db_deinit(void *priv); - -int eap_sim_db_get_gsm_triplets(void *priv, const u8 *identity, - size_t identity_len, int max_chal, - u8 *_rand, u8 *kc, u8 *sres, - void *cb_session_ctx); - -#define EAP_SIM_DB_FAILURE -1 -#define EAP_SIM_DB_PENDING -2 - -int eap_sim_db_identity_known(void *priv, const u8 *identity, - size_t identity_len); - -char * eap_sim_db_get_next_pseudonym(void *priv, int aka); - -char * eap_sim_db_get_next_reauth_id(void *priv, int aka); - -int eap_sim_db_add_pseudonym(void *priv, const u8 *identity, - size_t identity_len, char *pseudonym); - -int eap_sim_db_add_reauth(void *priv, const u8 *identity, - size_t identity_len, char *reauth_id, u16 counter, - const u8 *mk); -int eap_sim_db_add_reauth_prime(void *priv, const u8 *identity, - size_t identity_len, char *reauth_id, - u16 counter, const u8 *k_encr, const u8 *k_aut, - const u8 *k_re); - -const u8 * eap_sim_db_get_permanent(void *priv, const u8 *identity, - size_t identity_len, size_t *len); - -struct eap_sim_reauth { - struct eap_sim_reauth *next; - u8 *identity; - size_t identity_len; - char *reauth_id; - u16 counter; - int aka_prime; - u8 mk[EAP_SIM_MK_LEN]; - u8 k_encr[EAP_SIM_K_ENCR_LEN]; - u8 k_aut[EAP_AKA_PRIME_K_AUT_LEN]; - u8 k_re[EAP_AKA_PRIME_K_RE_LEN]; -}; - -struct eap_sim_reauth * -eap_sim_db_get_reauth_entry(void *priv, const u8 *identity, - size_t identity_len); - -void eap_sim_db_remove_reauth(void *priv, struct eap_sim_reauth *reauth); - -int eap_sim_db_get_aka_auth(void *priv, const u8 *identity, - size_t identity_len, u8 *_rand, u8 *autn, u8 *ik, - u8 *ck, u8 *res, size_t *res_len, - void *cb_session_ctx); - -int eap_sim_db_resynchronize(void *priv, const u8 *identity, - size_t identity_len, const u8 *auts, - const u8 *_rand); - -#endif /* EAP_SIM_DB_H */ diff --git a/hostapd-0.8/src/eap_server/eap_tls_common.h b/hostapd-0.8/src/eap_server/eap_tls_common.h deleted file mode 100644 index c34c401..0000000 --- a/hostapd-0.8/src/eap_server/eap_tls_common.h +++ /dev/null @@ -1,91 +0,0 @@ -/* - * EAP-TLS/PEAP/TTLS/FAST server common functions - * Copyright (c) 2004-2009, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#ifndef EAP_TLS_COMMON_H -#define EAP_TLS_COMMON_H - -/** - * struct eap_ssl_data - TLS data for EAP methods - */ -struct eap_ssl_data { - /** - * conn - TLS connection context data from tls_connection_init() - */ - struct tls_connection *conn; - - /** - * tls_out - TLS message to be sent out in fragments - */ - struct wpabuf *tls_out; - - /** - * tls_out_pos - The current position in the outgoing TLS message - */ - size_t tls_out_pos; - - /** - * tls_out_limit - Maximum fragment size for outgoing TLS messages - */ - size_t tls_out_limit; - - /** - * tls_in - Received TLS message buffer for re-assembly - */ - struct wpabuf *tls_in; - - /** - * phase2 - Whether this TLS connection is used in EAP phase 2 (tunnel) - */ - int phase2; - - /** - * eap - EAP state machine allocated with eap_server_sm_init() - */ - struct eap_sm *eap; - - enum { MSG, FRAG_ACK, WAIT_FRAG_ACK } state; - struct wpabuf tmpbuf; -}; - - -/* EAP TLS Flags */ -#define EAP_TLS_FLAGS_LENGTH_INCLUDED 0x80 -#define EAP_TLS_FLAGS_MORE_FRAGMENTS 0x40 -#define EAP_TLS_FLAGS_START 0x20 -#define EAP_TLS_VERSION_MASK 0x07 - - /* could be up to 128 bytes, but only the first 64 bytes are used */ -#define EAP_TLS_KEY_LEN 64 - - -int eap_server_tls_ssl_init(struct eap_sm *sm, struct eap_ssl_data *data, - int verify_peer); -void eap_server_tls_ssl_deinit(struct eap_sm *sm, struct eap_ssl_data *data); -u8 * eap_server_tls_derive_key(struct eap_sm *sm, struct eap_ssl_data *data, - char *label, size_t len); -struct wpabuf * eap_server_tls_build_msg(struct eap_ssl_data *data, - int eap_type, int version, u8 id); -struct wpabuf * eap_server_tls_build_ack(u8 id, int eap_type, int version); -int eap_server_tls_phase1(struct eap_sm *sm, struct eap_ssl_data *data); -struct wpabuf * eap_server_tls_encrypt(struct eap_sm *sm, - struct eap_ssl_data *data, - const struct wpabuf *plain); -int eap_server_tls_process(struct eap_sm *sm, struct eap_ssl_data *data, - struct wpabuf *respData, void *priv, int eap_type, - int (*proc_version)(struct eap_sm *sm, void *priv, - int peer_version), - void (*proc_msg)(struct eap_sm *sm, void *priv, - const struct wpabuf *respData)); - -#endif /* EAP_TLS_COMMON_H */ diff --git a/hostapd-0.8/src/eap_server/ikev2.c b/hostapd-0.8/src/eap_server/ikev2.c deleted file mode 100644 index 9624d53..0000000 --- a/hostapd-0.8/src/eap_server/ikev2.c +++ /dev/null @@ -1,1206 +0,0 @@ -/* - * IKEv2 initiator (RFC 4306) for EAP-IKEV2 - * Copyright (c) 2007, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#include "includes.h" - -#include "common.h" -#include "crypto/dh_groups.h" -#include "crypto/random.h" -#include "ikev2.h" - - -static int ikev2_process_idr(struct ikev2_initiator_data *data, - const u8 *idr, size_t idr_len); - - -void ikev2_initiator_deinit(struct ikev2_initiator_data *data) -{ - ikev2_free_keys(&data->keys); - wpabuf_free(data->r_dh_public); - wpabuf_free(data->i_dh_private); - os_free(data->IDi); - os_free(data->IDr); - os_free(data->shared_secret); - wpabuf_free(data->i_sign_msg); - wpabuf_free(data->r_sign_msg); - os_free(data->key_pad); -} - - -static int ikev2_derive_keys(struct ikev2_initiator_data *data) -{ - u8 *buf, *pos, *pad, skeyseed[IKEV2_MAX_HASH_LEN]; - size_t buf_len, pad_len; - struct wpabuf *shared; - const struct ikev2_integ_alg *integ; - const struct ikev2_prf_alg *prf; - const struct ikev2_encr_alg *encr; - int ret; - const u8 *addr[2]; - size_t len[2]; - - /* RFC 4306, Sect. 2.14 */ - - integ = ikev2_get_integ(data->proposal.integ); - prf = ikev2_get_prf(data->proposal.prf); - encr = ikev2_get_encr(data->proposal.encr); - if (integ == NULL || prf == NULL || encr == NULL) { - wpa_printf(MSG_INFO, "IKEV2: Unsupported proposal"); - return -1; - } - - shared = dh_derive_shared(data->r_dh_public, data->i_dh_private, - data->dh); - if (shared == NULL) - return -1; - - /* Construct Ni | Nr | SPIi | SPIr */ - - buf_len = data->i_nonce_len + data->r_nonce_len + 2 * IKEV2_SPI_LEN; - buf = os_malloc(buf_len); - if (buf == NULL) { - wpabuf_free(shared); - return -1; - } - - pos = buf; - os_memcpy(pos, data->i_nonce, data->i_nonce_len); - pos += data->i_nonce_len; - os_memcpy(pos, data->r_nonce, data->r_nonce_len); - pos += data->r_nonce_len; - os_memcpy(pos, data->i_spi, IKEV2_SPI_LEN); - pos += IKEV2_SPI_LEN; - os_memcpy(pos, data->r_spi, IKEV2_SPI_LEN); - - /* SKEYSEED = prf(Ni | Nr, g^ir) */ - - /* Use zero-padding per RFC 4306, Sect. 2.14 */ - pad_len = data->dh->prime_len - wpabuf_len(shared); - pad = os_zalloc(pad_len ? pad_len : 1); - if (pad == NULL) { - wpabuf_free(shared); - os_free(buf); - return -1; - } - addr[0] = pad; - len[0] = pad_len; - addr[1] = wpabuf_head(shared); - len[1] = wpabuf_len(shared); - if (ikev2_prf_hash(prf->id, buf, data->i_nonce_len + data->r_nonce_len, - 2, addr, len, skeyseed) < 0) { - wpabuf_free(shared); - os_free(buf); - os_free(pad); - return -1; - } - os_free(pad); - wpabuf_free(shared); - - /* DH parameters are not needed anymore, so free them */ - wpabuf_free(data->r_dh_public); - data->r_dh_public = NULL; - wpabuf_free(data->i_dh_private); - data->i_dh_private = NULL; - - wpa_hexdump_key(MSG_DEBUG, "IKEV2: SKEYSEED", - skeyseed, prf->hash_len); - - ret = ikev2_derive_sk_keys(prf, integ, encr, skeyseed, buf, buf_len, - &data->keys); - os_free(buf); - return ret; -} - - -static int ikev2_parse_transform(struct ikev2_initiator_data *data, - struct ikev2_proposal_data *prop, - const u8 *pos, const u8 *end) -{ - int transform_len; - const struct ikev2_transform *t; - u16 transform_id; - const u8 *tend; - - if (end - pos < (int) sizeof(*t)) { - wpa_printf(MSG_INFO, "IKEV2: Too short transform"); - return -1; - } - - t = (const struct ikev2_transform *) pos; - transform_len = WPA_GET_BE16(t->transform_length); - if (transform_len < (int) sizeof(*t) || pos + transform_len > end) { - wpa_printf(MSG_INFO, "IKEV2: Invalid transform length %d", - transform_len); - return -1; - } - tend = pos + transform_len; - - transform_id = WPA_GET_BE16(t->transform_id); - - wpa_printf(MSG_DEBUG, "IKEV2: Transform:"); - wpa_printf(MSG_DEBUG, "IKEV2: Type: %d Transform Length: %d " - "Transform Type: %d Transform ID: %d", - t->type, transform_len, t->transform_type, transform_id); - - if (t->type != 0 && t->type != 3) { - wpa_printf(MSG_INFO, "IKEV2: Unexpected Transform type"); - return -1; - } - - pos = (const u8 *) (t + 1); - if (pos < tend) { - wpa_hexdump(MSG_DEBUG, "IKEV2: Transform Attributes", - pos, tend - pos); - } - - switch (t->transform_type) { - case IKEV2_TRANSFORM_ENCR: - if (ikev2_get_encr(transform_id) && - transform_id == data->proposal.encr) { - if (transform_id == ENCR_AES_CBC) { - if (tend - pos != 4) { - wpa_printf(MSG_DEBUG, "IKEV2: No " - "Transform Attr for AES"); - break; - } - if (WPA_GET_BE16(pos) != 0x800e) { - wpa_printf(MSG_DEBUG, "IKEV2: Not a " - "Key Size attribute for " - "AES"); - break; - } - if (WPA_GET_BE16(pos + 2) != 128) { - wpa_printf(MSG_DEBUG, "IKEV2: " - "Unsupported AES key size " - "%d bits", - WPA_GET_BE16(pos + 2)); - break; - } - } - prop->encr = transform_id; - } - break; - case IKEV2_TRANSFORM_PRF: - if (ikev2_get_prf(transform_id) && - transform_id == data->proposal.prf) - prop->prf = transform_id; - break; - case IKEV2_TRANSFORM_INTEG: - if (ikev2_get_integ(transform_id) && - transform_id == data->proposal.integ) - prop->integ = transform_id; - break; - case IKEV2_TRANSFORM_DH: - if (dh_groups_get(transform_id) && - transform_id == data->proposal.dh) - prop->dh = transform_id; - break; - } - - return transform_len; -} - - -static int ikev2_parse_proposal(struct ikev2_initiator_data *data, - struct ikev2_proposal_data *prop, - const u8 *pos, const u8 *end) -{ - const u8 *pend, *ppos; - int proposal_len, i; - const struct ikev2_proposal *p; - - if (end - pos < (int) sizeof(*p)) { - wpa_printf(MSG_INFO, "IKEV2: Too short proposal"); - return -1; - } - - p = (const struct ikev2_proposal *) pos; - proposal_len = WPA_GET_BE16(p->proposal_length); - if (proposal_len < (int) sizeof(*p) || pos + proposal_len > end) { - wpa_printf(MSG_INFO, "IKEV2: Invalid proposal length %d", - proposal_len); - return -1; - } - wpa_printf(MSG_DEBUG, "IKEV2: SAi1 Proposal # %d", - p->proposal_num); - wpa_printf(MSG_DEBUG, "IKEV2: Type: %d Proposal Length: %d " - " Protocol ID: %d", - p->type, proposal_len, p->protocol_id); - wpa_printf(MSG_DEBUG, "IKEV2: SPI Size: %d Transforms: %d", - p->spi_size, p->num_transforms); - - if (p->type != 0 && p->type != 2) { - wpa_printf(MSG_INFO, "IKEV2: Unexpected Proposal type"); - return -1; - } - - if (p->protocol_id != IKEV2_PROTOCOL_IKE) { - wpa_printf(MSG_DEBUG, "IKEV2: Unexpected Protocol ID " - "(only IKE allowed for EAP-IKEv2)"); - return -1; - } - - if (p->proposal_num != prop->proposal_num) { - if (p->proposal_num == prop->proposal_num + 1) - prop->proposal_num = p->proposal_num; - else { - wpa_printf(MSG_INFO, "IKEV2: Unexpected Proposal #"); - return -1; - } - } - - ppos = (const u8 *) (p + 1); - pend = pos + proposal_len; - if (ppos + p->spi_size > pend) { - wpa_printf(MSG_INFO, "IKEV2: Not enough room for SPI " - "in proposal"); - return -1; - } - if (p->spi_size) { - wpa_hexdump(MSG_DEBUG, "IKEV2: SPI", - ppos, p->spi_size); - ppos += p->spi_size; - } - - /* - * For initial IKE_SA negotiation, SPI Size MUST be zero; for - * subsequent negotiations, it must be 8 for IKE. We only support - * initial case for now. - */ - if (p->spi_size != 0) { - wpa_printf(MSG_INFO, "IKEV2: Unexpected SPI Size"); - return -1; - } - - if (p->num_transforms == 0) { - wpa_printf(MSG_INFO, "IKEV2: At least one transform required"); - return -1; - } - - for (i = 0; i < (int) p->num_transforms; i++) { - int tlen = ikev2_parse_transform(data, prop, ppos, pend); - if (tlen < 0) - return -1; - ppos += tlen; - } - - if (ppos != pend) { - wpa_printf(MSG_INFO, "IKEV2: Unexpected data after " - "transforms"); - return -1; - } - - return proposal_len; -} - - -static int ikev2_process_sar1(struct ikev2_initiator_data *data, - const u8 *sar1, size_t sar1_len) -{ - struct ikev2_proposal_data prop; - const u8 *pos, *end; - int found = 0; - - /* Security Association Payloads: */ - - if (sar1 == NULL) { - wpa_printf(MSG_INFO, "IKEV2: SAr1 not received"); - return -1; - } - - os_memset(&prop, 0, sizeof(prop)); - prop.proposal_num = 1; - - pos = sar1; - end = sar1 + sar1_len; - - while (pos < end) { - int plen; - - prop.integ = -1; - prop.prf = -1; - prop.encr = -1; - prop.dh = -1; - plen = ikev2_parse_proposal(data, &prop, pos, end); - if (plen < 0) - return -1; - - if (!found && prop.integ != -1 && prop.prf != -1 && - prop.encr != -1 && prop.dh != -1) { - found = 1; - } - - pos += plen; - - /* Only one proposal expected in SAr */ - break; - } - - if (pos != end) { - wpa_printf(MSG_INFO, "IKEV2: Unexpected data after proposal"); - return -1; - } - - if (!found) { - wpa_printf(MSG_INFO, "IKEV2: No acceptable proposal found"); - return -1; - } - - wpa_printf(MSG_DEBUG, "IKEV2: Accepted proposal #%d: ENCR:%d PRF:%d " - "INTEG:%d D-H:%d", data->proposal.proposal_num, - data->proposal.encr, data->proposal.prf, - data->proposal.integ, data->proposal.dh); - - return 0; -} - - -static int ikev2_process_ker(struct ikev2_initiator_data *data, - const u8 *ker, size_t ker_len) -{ - u16 group; - - /* - * Key Exchange Payload: - * DH Group # (16 bits) - * RESERVED (16 bits) - * Key Exchange Data (Diffie-Hellman public value) - */ - - if (ker == NULL) { - wpa_printf(MSG_INFO, "IKEV2: KEr not received"); - return -1; - } - - if (ker_len < 4 + 96) { - wpa_printf(MSG_INFO, "IKEV2: Too show Key Exchange Payload"); - return -1; - } - - group = WPA_GET_BE16(ker); - wpa_printf(MSG_DEBUG, "IKEV2: KEr DH Group #%u", group); - - if (group != data->proposal.dh) { - wpa_printf(MSG_DEBUG, "IKEV2: KEr DH Group #%u does not match " - "with the selected proposal (%u)", - group, data->proposal.dh); - return -1; - } - - if (data->dh == NULL) { - wpa_printf(MSG_INFO, "IKEV2: Unsupported DH group"); - return -1; - } - - /* RFC 4306, Section 3.4: - * The length of DH public value MUST be equal to the lenght of the - * prime modulus. - */ - if (ker_len - 4 != data->dh->prime_len) { - wpa_printf(MSG_INFO, "IKEV2: Invalid DH public value length " - "%ld (expected %ld)", - (long) (ker_len - 4), (long) data->dh->prime_len); - return -1; - } - - wpabuf_free(data->r_dh_public); - data->r_dh_public = wpabuf_alloc_copy(ker + 4, ker_len - 4); - if (data->r_dh_public == NULL) - return -1; - - wpa_hexdump_buf(MSG_DEBUG, "IKEV2: KEr Diffie-Hellman Public Value", - data->r_dh_public); - - return 0; -} - - -static int ikev2_process_nr(struct ikev2_initiator_data *data, - const u8 *nr, size_t nr_len) -{ - if (nr == NULL) { - wpa_printf(MSG_INFO, "IKEV2: Nr not received"); - return -1; - } - - if (nr_len < IKEV2_NONCE_MIN_LEN || nr_len > IKEV2_NONCE_MAX_LEN) { - wpa_printf(MSG_INFO, "IKEV2: Invalid Nr length %ld", - (long) nr_len); - return -1; - } - - data->r_nonce_len = nr_len; - os_memcpy(data->r_nonce, nr, nr_len); - wpa_hexdump(MSG_MSGDUMP, "IKEV2: Nr", - data->r_nonce, data->r_nonce_len); - - return 0; -} - - -static int ikev2_process_sa_init_encr(struct ikev2_initiator_data *data, - const struct ikev2_hdr *hdr, - const u8 *encrypted, - size_t encrypted_len, u8 next_payload) -{ - u8 *decrypted; - size_t decrypted_len; - struct ikev2_payloads pl; - int ret = 0; - - decrypted = ikev2_decrypt_payload(data->proposal.encr, - data->proposal.integ, &data->keys, 0, - hdr, encrypted, encrypted_len, - &decrypted_len); - if (decrypted == NULL) - return -1; - - wpa_printf(MSG_DEBUG, "IKEV2: Processing decrypted payloads"); - - if (ikev2_parse_payloads(&pl, next_payload, decrypted, - decrypted + decrypted_len) < 0) { - wpa_printf(MSG_INFO, "IKEV2: Failed to parse decrypted " - "payloads"); - return -1; - } - - if (pl.idr) - ret = ikev2_process_idr(data, pl.idr, pl.idr_len); - - os_free(decrypted); - - return ret; -} - - -static int ikev2_process_sa_init(struct ikev2_initiator_data *data, - const struct ikev2_hdr *hdr, - struct ikev2_payloads *pl) -{ - if (ikev2_process_sar1(data, pl->sa, pl->sa_len) < 0 || - ikev2_process_ker(data, pl->ke, pl->ke_len) < 0 || - ikev2_process_nr(data, pl->nonce, pl->nonce_len) < 0) - return -1; - - os_memcpy(data->r_spi, hdr->r_spi, IKEV2_SPI_LEN); - - if (ikev2_derive_keys(data) < 0) - return -1; - - if (pl->encrypted) { - wpa_printf(MSG_DEBUG, "IKEV2: Encrypted payload in SA_INIT - " - "try to get IDr from it"); - if (ikev2_process_sa_init_encr(data, hdr, pl->encrypted, - pl->encrypted_len, - pl->encr_next_payload) < 0) { - wpa_printf(MSG_INFO, "IKEV2: Failed to process " - "encrypted payload"); - return -1; - } - } - - data->state = SA_AUTH; - - return 0; -} - - -static int ikev2_process_idr(struct ikev2_initiator_data *data, - const u8 *idr, size_t idr_len) -{ - u8 id_type; - - if (idr == NULL) { - wpa_printf(MSG_INFO, "IKEV2: No IDr received"); - return -1; - } - - if (idr_len < 4) { - wpa_printf(MSG_INFO, "IKEV2: Too short IDr payload"); - return -1; - } - - id_type = idr[0]; - idr += 4; - idr_len -= 4; - - wpa_printf(MSG_DEBUG, "IKEV2: IDr ID Type %d", id_type); - wpa_hexdump_ascii(MSG_DEBUG, "IKEV2: IDr", idr, idr_len); - if (data->IDr) { - if (id_type != data->IDr_type || idr_len != data->IDr_len || - os_memcmp(idr, data->IDr, idr_len) != 0) { - wpa_printf(MSG_INFO, "IKEV2: IDr differs from the one " - "received earlier"); - wpa_printf(MSG_DEBUG, "IKEV2: Previous IDr ID Type %d", - id_type); - wpa_hexdump_ascii(MSG_DEBUG, "Previous IKEV2: IDr", - data->IDr, data->IDr_len); - return -1; - } - os_free(data->IDr); - } - data->IDr = os_malloc(idr_len); - if (data->IDr == NULL) - return -1; - os_memcpy(data->IDr, idr, idr_len); - data->IDr_len = idr_len; - data->IDr_type = id_type; - - return 0; -} - - -static int ikev2_process_cert(struct ikev2_initiator_data *data, - const u8 *cert, size_t cert_len) -{ - u8 cert_encoding; - - if (cert == NULL) { - if (data->peer_auth == PEER_AUTH_CERT) { - wpa_printf(MSG_INFO, "IKEV2: No Certificate received"); - return -1; - } - return 0; - } - - if (cert_len < 1) { - wpa_printf(MSG_INFO, "IKEV2: No Cert Encoding field"); - return -1; - } - - cert_encoding = cert[0]; - cert++; - cert_len--; - - wpa_printf(MSG_DEBUG, "IKEV2: Cert Encoding %d", cert_encoding); - wpa_hexdump(MSG_MSGDUMP, "IKEV2: Certificate Data", cert, cert_len); - - /* TODO: validate certificate */ - - return 0; -} - - -static int ikev2_process_auth_cert(struct ikev2_initiator_data *data, - u8 method, const u8 *auth, size_t auth_len) -{ - if (method != AUTH_RSA_SIGN) { - wpa_printf(MSG_INFO, "IKEV2: Unsupported authentication " - "method %d", method); - return -1; - } - - /* TODO: validate AUTH */ - return 0; -} - - -static int ikev2_process_auth_secret(struct ikev2_initiator_data *data, - u8 method, const u8 *auth, - size_t auth_len) -{ - u8 auth_data[IKEV2_MAX_HASH_LEN]; - const struct ikev2_prf_alg *prf; - - if (method != AUTH_SHARED_KEY_MIC) { - wpa_printf(MSG_INFO, "IKEV2: Unsupported authentication " - "method %d", method); - return -1; - } - - /* msg | Ni | prf(SK_pr,IDr') */ - if (ikev2_derive_auth_data(data->proposal.prf, data->r_sign_msg, - data->IDr, data->IDr_len, data->IDr_type, - &data->keys, 0, data->shared_secret, - data->shared_secret_len, - data->i_nonce, data->i_nonce_len, - data->key_pad, data->key_pad_len, - auth_data) < 0) { - wpa_printf(MSG_INFO, "IKEV2: Could not derive AUTH data"); - return -1; - } - - wpabuf_free(data->r_sign_msg); - data->r_sign_msg = NULL; - - prf = ikev2_get_prf(data->proposal.prf); - if (prf == NULL) - return -1; - - if (auth_len != prf->hash_len || - os_memcmp(auth, auth_data, auth_len) != 0) { - wpa_printf(MSG_INFO, "IKEV2: Invalid Authentication Data"); - wpa_hexdump(MSG_DEBUG, "IKEV2: Received Authentication Data", - auth, auth_len); - wpa_hexdump(MSG_DEBUG, "IKEV2: Expected Authentication Data", - auth_data, prf->hash_len); - return -1; - } - - wpa_printf(MSG_DEBUG, "IKEV2: Peer authenticated successfully " - "using shared keys"); - - return 0; -} - - -static int ikev2_process_auth(struct ikev2_initiator_data *data, - const u8 *auth, size_t auth_len) -{ - u8 auth_method; - - if (auth == NULL) { - wpa_printf(MSG_INFO, "IKEV2: No Authentication Payload"); - return -1; - } - - if (auth_len < 4) { - wpa_printf(MSG_INFO, "IKEV2: Too short Authentication " - "Payload"); - return -1; - } - - auth_method = auth[0]; - auth += 4; - auth_len -= 4; - - wpa_printf(MSG_DEBUG, "IKEV2: Auth Method %d", auth_method); - wpa_hexdump(MSG_MSGDUMP, "IKEV2: Authentication Data", auth, auth_len); - - switch (data->peer_auth) { - case PEER_AUTH_CERT: - return ikev2_process_auth_cert(data, auth_method, auth, - auth_len); - case PEER_AUTH_SECRET: - return ikev2_process_auth_secret(data, auth_method, auth, - auth_len); - } - - return -1; -} - - -static int ikev2_process_sa_auth_decrypted(struct ikev2_initiator_data *data, - u8 next_payload, - u8 *payload, size_t payload_len) -{ - struct ikev2_payloads pl; - - wpa_printf(MSG_DEBUG, "IKEV2: Processing decrypted payloads"); - - if (ikev2_parse_payloads(&pl, next_payload, payload, payload + - payload_len) < 0) { - wpa_printf(MSG_INFO, "IKEV2: Failed to parse decrypted " - "payloads"); - return -1; - } - - if (ikev2_process_idr(data, pl.idr, pl.idr_len) < 0 || - ikev2_process_cert(data, pl.cert, pl.cert_len) < 0 || - ikev2_process_auth(data, pl.auth, pl.auth_len) < 0) - return -1; - - return 0; -} - - -static int ikev2_process_sa_auth(struct ikev2_initiator_data *data, - const struct ikev2_hdr *hdr, - struct ikev2_payloads *pl) -{ - u8 *decrypted; - size_t decrypted_len; - int ret; - - decrypted = ikev2_decrypt_payload(data->proposal.encr, - data->proposal.integ, - &data->keys, 0, hdr, pl->encrypted, - pl->encrypted_len, &decrypted_len); - if (decrypted == NULL) - return -1; - - ret = ikev2_process_sa_auth_decrypted(data, pl->encr_next_payload, - decrypted, decrypted_len); - os_free(decrypted); - - if (ret == 0 && !data->unknown_user) { - wpa_printf(MSG_DEBUG, "IKEV2: Authentication completed"); - data->state = IKEV2_DONE; - } - - return ret; -} - - -static int ikev2_validate_rx_state(struct ikev2_initiator_data *data, - u8 exchange_type, u32 message_id) -{ - switch (data->state) { - case SA_INIT: - /* Expect to receive IKE_SA_INIT: HDR, SAr, KEr, Nr, [CERTREQ], - * [SK{IDr}] */ - if (exchange_type != IKE_SA_INIT) { - wpa_printf(MSG_INFO, "IKEV2: Unexpected Exchange Type " - "%u in SA_INIT state", exchange_type); - return -1; - } - if (message_id != 0) { - wpa_printf(MSG_INFO, "IKEV2: Unexpected Message ID %u " - "in SA_INIT state", message_id); - return -1; - } - break; - case SA_AUTH: - /* Expect to receive IKE_SA_AUTH: - * HDR, SK {IDr, [CERT,] [CERTREQ,] [NFID,] AUTH} - */ - if (exchange_type != IKE_SA_AUTH) { - wpa_printf(MSG_INFO, "IKEV2: Unexpected Exchange Type " - "%u in SA_AUTH state", exchange_type); - return -1; - } - if (message_id != 1) { - wpa_printf(MSG_INFO, "IKEV2: Unexpected Message ID %u " - "in SA_AUTH state", message_id); - return -1; - } - break; - case CHILD_SA: - if (exchange_type != CREATE_CHILD_SA) { - wpa_printf(MSG_INFO, "IKEV2: Unexpected Exchange Type " - "%u in CHILD_SA state", exchange_type); - return -1; - } - if (message_id != 2) { - wpa_printf(MSG_INFO, "IKEV2: Unexpected Message ID %u " - "in CHILD_SA state", message_id); - return -1; - } - break; - case IKEV2_DONE: - return -1; - } - - return 0; -} - - -int ikev2_initiator_process(struct ikev2_initiator_data *data, - const struct wpabuf *buf) -{ - const struct ikev2_hdr *hdr; - u32 length, message_id; - const u8 *pos, *end; - struct ikev2_payloads pl; - - wpa_printf(MSG_MSGDUMP, "IKEV2: Received message (len %lu)", - (unsigned long) wpabuf_len(buf)); - - if (wpabuf_len(buf) < sizeof(*hdr)) { - wpa_printf(MSG_INFO, "IKEV2: Too short frame to include HDR"); - return -1; - } - - hdr = (const struct ikev2_hdr *) wpabuf_head(buf); - end = wpabuf_head_u8(buf) + wpabuf_len(buf); - message_id = WPA_GET_BE32(hdr->message_id); - length = WPA_GET_BE32(hdr->length); - - wpa_hexdump(MSG_DEBUG, "IKEV2: IKE_SA Initiator's SPI", - hdr->i_spi, IKEV2_SPI_LEN); - wpa_hexdump(MSG_DEBUG, "IKEV2: IKE_SA Initiator's SPI", - hdr->r_spi, IKEV2_SPI_LEN); - wpa_printf(MSG_DEBUG, "IKEV2: Next Payload: %u Version: 0x%x " - "Exchange Type: %u", - hdr->next_payload, hdr->version, hdr->exchange_type); - wpa_printf(MSG_DEBUG, "IKEV2: Message ID: %u Length: %u", - message_id, length); - - if (hdr->version != IKEV2_VERSION) { - wpa_printf(MSG_INFO, "IKEV2: Unsupported HDR version 0x%x " - "(expected 0x%x)", hdr->version, IKEV2_VERSION); - return -1; - } - - if (length != wpabuf_len(buf)) { - wpa_printf(MSG_INFO, "IKEV2: Invalid length (HDR: %lu != " - "RX: %lu)", (unsigned long) length, - (unsigned long) wpabuf_len(buf)); - return -1; - } - - if (ikev2_validate_rx_state(data, hdr->exchange_type, message_id) < 0) - return -1; - - if ((hdr->flags & (IKEV2_HDR_INITIATOR | IKEV2_HDR_RESPONSE)) != - IKEV2_HDR_RESPONSE) { - wpa_printf(MSG_INFO, "IKEV2: Unexpected Flags value 0x%x", - hdr->flags); - return -1; - } - - if (data->state != SA_INIT) { - if (os_memcmp(data->i_spi, hdr->i_spi, IKEV2_SPI_LEN) != 0) { - wpa_printf(MSG_INFO, "IKEV2: Unexpected IKE_SA " - "Initiator's SPI"); - return -1; - } - if (os_memcmp(data->r_spi, hdr->r_spi, IKEV2_SPI_LEN) != 0) { - wpa_printf(MSG_INFO, "IKEV2: Unexpected IKE_SA " - "Responder's SPI"); - return -1; - } - } - - pos = (const u8 *) (hdr + 1); - if (ikev2_parse_payloads(&pl, hdr->next_payload, pos, end) < 0) - return -1; - - switch (data->state) { - case SA_INIT: - if (ikev2_process_sa_init(data, hdr, &pl) < 0) - return -1; - wpabuf_free(data->r_sign_msg); - data->r_sign_msg = wpabuf_dup(buf); - break; - case SA_AUTH: - if (ikev2_process_sa_auth(data, hdr, &pl) < 0) - return -1; - break; - case CHILD_SA: - case IKEV2_DONE: - break; - } - - return 0; -} - - -static void ikev2_build_hdr(struct ikev2_initiator_data *data, - struct wpabuf *msg, u8 exchange_type, - u8 next_payload, u32 message_id) -{ - struct ikev2_hdr *hdr; - - wpa_printf(MSG_DEBUG, "IKEV2: Adding HDR"); - - /* HDR - RFC 4306, Sect. 3.1 */ - hdr = wpabuf_put(msg, sizeof(*hdr)); - os_memcpy(hdr->i_spi, data->i_spi, IKEV2_SPI_LEN); - os_memcpy(hdr->r_spi, data->r_spi, IKEV2_SPI_LEN); - hdr->next_payload = next_payload; - hdr->version = IKEV2_VERSION; - hdr->exchange_type = exchange_type; - hdr->flags = IKEV2_HDR_INITIATOR; - WPA_PUT_BE32(hdr->message_id, message_id); -} - - -static int ikev2_build_sai(struct ikev2_initiator_data *data, - struct wpabuf *msg, u8 next_payload) -{ - struct ikev2_payload_hdr *phdr; - size_t plen; - struct ikev2_proposal *p; - struct ikev2_transform *t; - - wpa_printf(MSG_DEBUG, "IKEV2: Adding SAi payload"); - - /* SAi1 - RFC 4306, Sect. 2.7 and 3.3 */ - phdr = wpabuf_put(msg, sizeof(*phdr)); - phdr->next_payload = next_payload; - phdr->flags = 0; - - /* TODO: support for multiple proposals */ - p = wpabuf_put(msg, sizeof(*p)); - p->proposal_num = data->proposal.proposal_num; - p->protocol_id = IKEV2_PROTOCOL_IKE; - p->num_transforms = 4; - - t = wpabuf_put(msg, sizeof(*t)); - t->type = 3; - t->transform_type = IKEV2_TRANSFORM_ENCR; - WPA_PUT_BE16(t->transform_id, data->proposal.encr); - if (data->proposal.encr == ENCR_AES_CBC) { - /* Transform Attribute: Key Len = 128 bits */ - wpabuf_put_be16(msg, 0x800e); /* AF=1, AttrType=14 */ - wpabuf_put_be16(msg, 128); /* 128-bit key */ - } - plen = (u8 *) wpabuf_put(msg, 0) - (u8 *) t; - WPA_PUT_BE16(t->transform_length, plen); - - t = wpabuf_put(msg, sizeof(*t)); - t->type = 3; - WPA_PUT_BE16(t->transform_length, sizeof(*t)); - t->transform_type = IKEV2_TRANSFORM_PRF; - WPA_PUT_BE16(t->transform_id, data->proposal.prf); - - t = wpabuf_put(msg, sizeof(*t)); - t->type = 3; - WPA_PUT_BE16(t->transform_length, sizeof(*t)); - t->transform_type = IKEV2_TRANSFORM_INTEG; - WPA_PUT_BE16(t->transform_id, data->proposal.integ); - - t = wpabuf_put(msg, sizeof(*t)); - WPA_PUT_BE16(t->transform_length, sizeof(*t)); - t->transform_type = IKEV2_TRANSFORM_DH; - WPA_PUT_BE16(t->transform_id, data->proposal.dh); - - plen = (u8 *) wpabuf_put(msg, 0) - (u8 *) p; - WPA_PUT_BE16(p->proposal_length, plen); - - plen = (u8 *) wpabuf_put(msg, 0) - (u8 *) phdr; - WPA_PUT_BE16(phdr->payload_length, plen); - - return 0; -} - - -static int ikev2_build_kei(struct ikev2_initiator_data *data, - struct wpabuf *msg, u8 next_payload) -{ - struct ikev2_payload_hdr *phdr; - size_t plen; - struct wpabuf *pv; - - wpa_printf(MSG_DEBUG, "IKEV2: Adding KEi payload"); - - data->dh = dh_groups_get(data->proposal.dh); - pv = dh_init(data->dh, &data->i_dh_private); - if (pv == NULL) { - wpa_printf(MSG_DEBUG, "IKEV2: Failed to initialize DH"); - return -1; - } - - /* KEi - RFC 4306, Sect. 3.4 */ - phdr = wpabuf_put(msg, sizeof(*phdr)); - phdr->next_payload = next_payload; - phdr->flags = 0; - - wpabuf_put_be16(msg, data->proposal.dh); /* DH Group # */ - wpabuf_put(msg, 2); /* RESERVED */ - /* - * RFC 4306, Sect. 3.4: possible zero padding for public value to - * match the length of the prime. - */ - wpabuf_put(msg, data->dh->prime_len - wpabuf_len(pv)); - wpabuf_put_buf(msg, pv); - os_free(pv); - - plen = (u8 *) wpabuf_put(msg, 0) - (u8 *) phdr; - WPA_PUT_BE16(phdr->payload_length, plen); - return 0; -} - - -static int ikev2_build_ni(struct ikev2_initiator_data *data, - struct wpabuf *msg, u8 next_payload) -{ - struct ikev2_payload_hdr *phdr; - size_t plen; - - wpa_printf(MSG_DEBUG, "IKEV2: Adding Ni payload"); - - /* Ni - RFC 4306, Sect. 3.9 */ - phdr = wpabuf_put(msg, sizeof(*phdr)); - phdr->next_payload = next_payload; - phdr->flags = 0; - wpabuf_put_data(msg, data->i_nonce, data->i_nonce_len); - plen = (u8 *) wpabuf_put(msg, 0) - (u8 *) phdr; - WPA_PUT_BE16(phdr->payload_length, plen); - return 0; -} - - -static int ikev2_build_idi(struct ikev2_initiator_data *data, - struct wpabuf *msg, u8 next_payload) -{ - struct ikev2_payload_hdr *phdr; - size_t plen; - - wpa_printf(MSG_DEBUG, "IKEV2: Adding IDi payload"); - - if (data->IDi == NULL) { - wpa_printf(MSG_INFO, "IKEV2: No IDi available"); - return -1; - } - - /* IDi - RFC 4306, Sect. 3.5 */ - phdr = wpabuf_put(msg, sizeof(*phdr)); - phdr->next_payload = next_payload; - phdr->flags = 0; - wpabuf_put_u8(msg, ID_KEY_ID); - wpabuf_put(msg, 3); /* RESERVED */ - wpabuf_put_data(msg, data->IDi, data->IDi_len); - plen = (u8 *) wpabuf_put(msg, 0) - (u8 *) phdr; - WPA_PUT_BE16(phdr->payload_length, plen); - return 0; -} - - -static int ikev2_build_auth(struct ikev2_initiator_data *data, - struct wpabuf *msg, u8 next_payload) -{ - struct ikev2_payload_hdr *phdr; - size_t plen; - const struct ikev2_prf_alg *prf; - - wpa_printf(MSG_DEBUG, "IKEV2: Adding AUTH payload"); - - prf = ikev2_get_prf(data->proposal.prf); - if (prf == NULL) - return -1; - - /* Authentication - RFC 4306, Sect. 3.8 */ - phdr = wpabuf_put(msg, sizeof(*phdr)); - phdr->next_payload = next_payload; - phdr->flags = 0; - wpabuf_put_u8(msg, AUTH_SHARED_KEY_MIC); - wpabuf_put(msg, 3); /* RESERVED */ - - /* msg | Nr | prf(SK_pi,IDi') */ - if (ikev2_derive_auth_data(data->proposal.prf, data->i_sign_msg, - data->IDi, data->IDi_len, ID_KEY_ID, - &data->keys, 1, data->shared_secret, - data->shared_secret_len, - data->r_nonce, data->r_nonce_len, - data->key_pad, data->key_pad_len, - wpabuf_put(msg, prf->hash_len)) < 0) { - wpa_printf(MSG_INFO, "IKEV2: Could not derive AUTH data"); - return -1; - } - wpabuf_free(data->i_sign_msg); - data->i_sign_msg = NULL; - - plen = (u8 *) wpabuf_put(msg, 0) - (u8 *) phdr; - WPA_PUT_BE16(phdr->payload_length, plen); - return 0; -} - - -static struct wpabuf * ikev2_build_sa_init(struct ikev2_initiator_data *data) -{ - struct wpabuf *msg; - - /* build IKE_SA_INIT: HDR, SAi, KEi, Ni */ - - if (os_get_random(data->i_spi, IKEV2_SPI_LEN)) - return NULL; - wpa_hexdump(MSG_DEBUG, "IKEV2: IKE_SA Initiator's SPI", - data->i_spi, IKEV2_SPI_LEN); - - data->i_nonce_len = IKEV2_NONCE_MIN_LEN; - if (random_get_bytes(data->i_nonce, data->i_nonce_len)) - return NULL; - wpa_hexdump(MSG_DEBUG, "IKEV2: Ni", data->i_nonce, data->i_nonce_len); - - msg = wpabuf_alloc(sizeof(struct ikev2_hdr) + 1000); - if (msg == NULL) - return NULL; - - ikev2_build_hdr(data, msg, IKE_SA_INIT, IKEV2_PAYLOAD_SA, 0); - if (ikev2_build_sai(data, msg, IKEV2_PAYLOAD_KEY_EXCHANGE) || - ikev2_build_kei(data, msg, IKEV2_PAYLOAD_NONCE) || - ikev2_build_ni(data, msg, IKEV2_PAYLOAD_NO_NEXT_PAYLOAD)) { - wpabuf_free(msg); - return NULL; - } - - ikev2_update_hdr(msg); - - wpa_hexdump_buf(MSG_MSGDUMP, "IKEV2: Sending message (SA_INIT)", msg); - - wpabuf_free(data->i_sign_msg); - data->i_sign_msg = wpabuf_dup(msg); - - return msg; -} - - -static struct wpabuf * ikev2_build_sa_auth(struct ikev2_initiator_data *data) -{ - struct wpabuf *msg, *plain; - const u8 *secret; - size_t secret_len; - - secret = data->get_shared_secret(data->cb_ctx, data->IDr, - data->IDr_len, &secret_len); - if (secret == NULL) { - wpa_printf(MSG_INFO, "IKEV2: Could not get shared secret - " - "use fake value"); - /* RFC 5106, Sect. 7: - * Use a random key to fake AUTH generation in order to prevent - * probing of user identities. - */ - data->unknown_user = 1; - os_free(data->shared_secret); - data->shared_secret = os_malloc(16); - if (data->shared_secret == NULL) - return NULL; - data->shared_secret_len = 16; - if (random_get_bytes(data->shared_secret, 16)) - return NULL; - } else { - os_free(data->shared_secret); - data->shared_secret = os_malloc(secret_len); - if (data->shared_secret == NULL) - return NULL; - os_memcpy(data->shared_secret, secret, secret_len); - data->shared_secret_len = secret_len; - } - - /* build IKE_SA_AUTH: HDR, SK {IDi, [CERT,] [CERTREQ,] AUTH} */ - - msg = wpabuf_alloc(sizeof(struct ikev2_hdr) + data->IDr_len + 1000); - if (msg == NULL) - return NULL; - ikev2_build_hdr(data, msg, IKE_SA_AUTH, IKEV2_PAYLOAD_ENCRYPTED, 1); - - plain = wpabuf_alloc(data->IDr_len + 1000); - if (plain == NULL) { - wpabuf_free(msg); - return NULL; - } - - if (ikev2_build_idi(data, plain, IKEV2_PAYLOAD_AUTHENTICATION) || - ikev2_build_auth(data, plain, IKEV2_PAYLOAD_NO_NEXT_PAYLOAD) || - ikev2_build_encrypted(data->proposal.encr, data->proposal.integ, - &data->keys, 1, msg, plain, - IKEV2_PAYLOAD_IDi)) { - wpabuf_free(plain); - wpabuf_free(msg); - return NULL; - } - wpabuf_free(plain); - - wpa_hexdump_buf(MSG_MSGDUMP, "IKEV2: Sending message (SA_AUTH)", msg); - - return msg; -} - - -struct wpabuf * ikev2_initiator_build(struct ikev2_initiator_data *data) -{ - switch (data->state) { - case SA_INIT: - return ikev2_build_sa_init(data); - case SA_AUTH: - return ikev2_build_sa_auth(data); - case CHILD_SA: - return NULL; - case IKEV2_DONE: - return NULL; - } - return NULL; -} diff --git a/hostapd-0.8/src/eap_server/ikev2.h b/hostapd-0.8/src/eap_server/ikev2.h deleted file mode 100644 index 8349fbe..0000000 --- a/hostapd-0.8/src/eap_server/ikev2.h +++ /dev/null @@ -1,67 +0,0 @@ -/* - * IKEv2 initiator (RFC 4306) for EAP-IKEV2 - * Copyright (c) 2007, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#ifndef IKEV2_H -#define IKEV2_H - -#include "eap_common/ikev2_common.h" - -struct ikev2_proposal_data { - u8 proposal_num; - int integ; - int prf; - int encr; - int dh; -}; - - -struct ikev2_initiator_data { - enum { SA_INIT, SA_AUTH, CHILD_SA, IKEV2_DONE } state; - u8 i_spi[IKEV2_SPI_LEN]; - u8 r_spi[IKEV2_SPI_LEN]; - u8 i_nonce[IKEV2_NONCE_MAX_LEN]; - size_t i_nonce_len; - u8 r_nonce[IKEV2_NONCE_MAX_LEN]; - size_t r_nonce_len; - struct wpabuf *r_dh_public; - struct wpabuf *i_dh_private; - struct ikev2_proposal_data proposal; - const struct dh_group *dh; - struct ikev2_keys keys; - u8 *IDi; - size_t IDi_len; - u8 *IDr; - size_t IDr_len; - u8 IDr_type; - struct wpabuf *r_sign_msg; - struct wpabuf *i_sign_msg; - u8 *shared_secret; - size_t shared_secret_len; - enum { PEER_AUTH_CERT, PEER_AUTH_SECRET } peer_auth; - u8 *key_pad; - size_t key_pad_len; - - const u8 * (*get_shared_secret)(void *ctx, const u8 *IDr, - size_t IDr_len, size_t *secret_len); - void *cb_ctx; - int unknown_user; -}; - - -void ikev2_initiator_deinit(struct ikev2_initiator_data *data); -int ikev2_initiator_process(struct ikev2_initiator_data *data, - const struct wpabuf *buf); -struct wpabuf * ikev2_initiator_build(struct ikev2_initiator_data *data); - -#endif /* IKEV2_H */ diff --git a/hostapd-0.8/src/eap_server/tncs.c b/hostapd-0.8/src/eap_server/tncs.c deleted file mode 100644 index 637b6f8..0000000 --- a/hostapd-0.8/src/eap_server/tncs.c +++ /dev/null @@ -1,1273 +0,0 @@ -/* - * EAP-TNC - TNCS (IF-IMV, IF-TNCCS, and IF-TNCCS-SOH) - * Copyright (c) 2007-2008, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#include "includes.h" -#include - -#include "common.h" -#include "base64.h" -#include "tncs.h" -#include "eap_common/eap_tlv_common.h" -#include "eap_common/eap_defs.h" - - -/* TODO: TNCS must be thread-safe; review the code and add locking etc. if - * needed.. */ - -#define TNC_CONFIG_FILE "/etc/tnc_config" -#define IF_TNCCS_START \ -"\n" \ -"\n" -#define IF_TNCCS_END "\n" - -/* TNC IF-IMV */ - -typedef unsigned long TNC_UInt32; -typedef unsigned char *TNC_BufferReference; - -typedef TNC_UInt32 TNC_IMVID; -typedef TNC_UInt32 TNC_ConnectionID; -typedef TNC_UInt32 TNC_ConnectionState; -typedef TNC_UInt32 TNC_RetryReason; -typedef TNC_UInt32 TNC_IMV_Action_Recommendation; -typedef TNC_UInt32 TNC_IMV_Evaluation_Result; -typedef TNC_UInt32 TNC_MessageType; -typedef TNC_MessageType *TNC_MessageTypeList; -typedef TNC_UInt32 TNC_VendorID; -typedef TNC_UInt32 TNC_Subtype; -typedef TNC_UInt32 TNC_Version; -typedef TNC_UInt32 TNC_Result; -typedef TNC_UInt32 TNC_AttributeID; - -typedef TNC_Result (*TNC_TNCS_BindFunctionPointer)( - TNC_IMVID imvID, - char *functionName, - void **pOutfunctionPointer); - -#define TNC_RESULT_SUCCESS 0 -#define TNC_RESULT_NOT_INITIALIZED 1 -#define TNC_RESULT_ALREADY_INITIALIZED 2 -#define TNC_RESULT_NO_COMMON_VERSION 3 -#define TNC_RESULT_CANT_RETRY 4 -#define TNC_RESULT_WONT_RETRY 5 -#define TNC_RESULT_INVALID_PARAMETER 6 -#define TNC_RESULT_CANT_RESPOND 7 -#define TNC_RESULT_ILLEGAL_OPERATION 8 -#define TNC_RESULT_OTHER 9 -#define TNC_RESULT_FATAL 10 - -#define TNC_CONNECTION_STATE_CREATE 0 -#define TNC_CONNECTION_STATE_HANDSHAKE 1 -#define TNC_CONNECTION_STATE_ACCESS_ALLOWED 2 -#define TNC_CONNECTION_STATE_ACCESS_ISOLATED 3 -#define TNC_CONNECTION_STATE_ACCESS_NONE 4 -#define TNC_CONNECTION_STATE_DELETE 5 - -#define TNC_IFIMV_VERSION_1 1 - -#define TNC_VENDORID_ANY ((TNC_VendorID) 0xffffff) -#define TNC_SUBTYPE_ANY ((TNC_Subtype) 0xff) - -/* TNCC-TNCS Message Types */ -#define TNC_TNCCS_RECOMMENDATION 0x00000001 -#define TNC_TNCCS_ERROR 0x00000002 -#define TNC_TNCCS_PREFERREDLANGUAGE 0x00000003 -#define TNC_TNCCS_REASONSTRINGS 0x00000004 - -/* Possible TNC_IMV_Action_Recommendation values: */ -enum IMV_Action_Recommendation { - TNC_IMV_ACTION_RECOMMENDATION_ALLOW, - TNC_IMV_ACTION_RECOMMENDATION_NO_ACCESS, - TNC_IMV_ACTION_RECOMMENDATION_ISOLATE, - TNC_IMV_ACTION_RECOMMENDATION_NO_RECOMMENDATION -}; - -/* Possible TNC_IMV_Evaluation_Result values: */ -enum IMV_Evaluation_Result { - TNC_IMV_EVALUATION_RESULT_COMPLIANT, - TNC_IMV_EVALUATION_RESULT_NONCOMPLIANT_MINOR, - TNC_IMV_EVALUATION_RESULT_NONCOMPLIANT_MAJOR, - TNC_IMV_EVALUATION_RESULT_ERROR, - TNC_IMV_EVALUATION_RESULT_DONT_KNOW -}; - -struct tnc_if_imv { - struct tnc_if_imv *next; - char *name; - char *path; - void *dlhandle; /* from dlopen() */ - TNC_IMVID imvID; - TNC_MessageTypeList supported_types; - size_t num_supported_types; - - /* Functions implemented by IMVs (with TNC_IMV_ prefix) */ - TNC_Result (*Initialize)( - TNC_IMVID imvID, - TNC_Version minVersion, - TNC_Version maxVersion, - TNC_Version *pOutActualVersion); - TNC_Result (*NotifyConnectionChange)( - TNC_IMVID imvID, - TNC_ConnectionID connectionID, - TNC_ConnectionState newState); - TNC_Result (*ReceiveMessage)( - TNC_IMVID imvID, - TNC_ConnectionID connectionID, - TNC_BufferReference message, - TNC_UInt32 messageLength, - TNC_MessageType messageType); - TNC_Result (*SolicitRecommendation)( - TNC_IMVID imvID, - TNC_ConnectionID connectionID); - TNC_Result (*BatchEnding)( - TNC_IMVID imvID, - TNC_ConnectionID connectionID); - TNC_Result (*Terminate)(TNC_IMVID imvID); - TNC_Result (*ProvideBindFunction)( - TNC_IMVID imvID, - TNC_TNCS_BindFunctionPointer bindFunction); -}; - - -#define TNC_MAX_IMV_ID 10 - -struct tncs_data { - struct tncs_data *next; - struct tnc_if_imv *imv; /* local copy of tncs_global_data->imv */ - TNC_ConnectionID connectionID; - unsigned int last_batchid; - enum IMV_Action_Recommendation recommendation; - int done; - - struct conn_imv { - u8 *imv_send; - size_t imv_send_len; - enum IMV_Action_Recommendation recommendation; - int recommendation_set; - } imv_data[TNC_MAX_IMV_ID]; - - char *tncs_message; -}; - - -struct tncs_global { - struct tnc_if_imv *imv; - TNC_ConnectionID next_conn_id; - struct tncs_data *connections; -}; - -static struct tncs_global *tncs_global_data = NULL; - - -static struct tnc_if_imv * tncs_get_imv(TNC_IMVID imvID) -{ - struct tnc_if_imv *imv; - - if (imvID >= TNC_MAX_IMV_ID || tncs_global_data == NULL) - return NULL; - imv = tncs_global_data->imv; - while (imv) { - if (imv->imvID == imvID) - return imv; - imv = imv->next; - } - return NULL; -} - - -static struct tncs_data * tncs_get_conn(TNC_ConnectionID connectionID) -{ - struct tncs_data *tncs; - - if (tncs_global_data == NULL) - return NULL; - - tncs = tncs_global_data->connections; - while (tncs) { - if (tncs->connectionID == connectionID) - return tncs; - tncs = tncs->next; - } - - wpa_printf(MSG_DEBUG, "TNC: Connection ID %lu not found", - (unsigned long) connectionID); - - return NULL; -} - - -/* TNCS functions that IMVs can call */ -TNC_Result TNC_TNCS_ReportMessageTypes( - TNC_IMVID imvID, - TNC_MessageTypeList supportedTypes, - TNC_UInt32 typeCount) -{ - TNC_UInt32 i; - struct tnc_if_imv *imv; - - wpa_printf(MSG_DEBUG, "TNC: TNC_TNCS_ReportMessageTypes(imvID=%lu " - "typeCount=%lu)", - (unsigned long) imvID, (unsigned long) typeCount); - - for (i = 0; i < typeCount; i++) { - wpa_printf(MSG_DEBUG, "TNC: supportedTypes[%lu] = %lu", - i, supportedTypes[i]); - } - - imv = tncs_get_imv(imvID); - if (imv == NULL) - return TNC_RESULT_INVALID_PARAMETER; - os_free(imv->supported_types); - imv->supported_types = - os_malloc(typeCount * sizeof(TNC_MessageType)); - if (imv->supported_types == NULL) - return TNC_RESULT_FATAL; - os_memcpy(imv->supported_types, supportedTypes, - typeCount * sizeof(TNC_MessageType)); - imv->num_supported_types = typeCount; - - return TNC_RESULT_SUCCESS; -} - - -TNC_Result TNC_TNCS_SendMessage( - TNC_IMVID imvID, - TNC_ConnectionID connectionID, - TNC_BufferReference message, - TNC_UInt32 messageLength, - TNC_MessageType messageType) -{ - struct tncs_data *tncs; - unsigned char *b64; - size_t b64len; - - wpa_printf(MSG_DEBUG, "TNC: TNC_TNCS_SendMessage(imvID=%lu " - "connectionID=%lu messageType=%lu)", - imvID, connectionID, messageType); - wpa_hexdump_ascii(MSG_DEBUG, "TNC: TNC_TNCS_SendMessage", - message, messageLength); - - if (tncs_get_imv(imvID) == NULL) - return TNC_RESULT_INVALID_PARAMETER; - - tncs = tncs_get_conn(connectionID); - if (tncs == NULL) - return TNC_RESULT_INVALID_PARAMETER; - - b64 = base64_encode(message, messageLength, &b64len); - if (b64 == NULL) - return TNC_RESULT_FATAL; - - os_free(tncs->imv_data[imvID].imv_send); - tncs->imv_data[imvID].imv_send_len = 0; - tncs->imv_data[imvID].imv_send = os_zalloc(b64len + 100); - if (tncs->imv_data[imvID].imv_send == NULL) { - os_free(b64); - return TNC_RESULT_OTHER; - } - - tncs->imv_data[imvID].imv_send_len = - os_snprintf((char *) tncs->imv_data[imvID].imv_send, - b64len + 100, - "%08X" - "%s", - (unsigned int) messageType, b64); - - os_free(b64); - - return TNC_RESULT_SUCCESS; -} - - -TNC_Result TNC_TNCS_RequestHandshakeRetry( - TNC_IMVID imvID, - TNC_ConnectionID connectionID, - TNC_RetryReason reason) -{ - wpa_printf(MSG_DEBUG, "TNC: TNC_TNCS_RequestHandshakeRetry"); - /* TODO */ - return TNC_RESULT_SUCCESS; -} - - -TNC_Result TNC_TNCS_ProvideRecommendation( - TNC_IMVID imvID, - TNC_ConnectionID connectionID, - TNC_IMV_Action_Recommendation recommendation, - TNC_IMV_Evaluation_Result evaluation) -{ - struct tncs_data *tncs; - - wpa_printf(MSG_DEBUG, "TNC: TNC_TNCS_ProvideRecommendation(imvID=%lu " - "connectionID=%lu recommendation=%lu evaluation=%lu)", - (unsigned long) imvID, (unsigned long) connectionID, - (unsigned long) recommendation, (unsigned long) evaluation); - - if (tncs_get_imv(imvID) == NULL) - return TNC_RESULT_INVALID_PARAMETER; - - tncs = tncs_get_conn(connectionID); - if (tncs == NULL) - return TNC_RESULT_INVALID_PARAMETER; - - tncs->imv_data[imvID].recommendation = recommendation; - tncs->imv_data[imvID].recommendation_set = 1; - - return TNC_RESULT_SUCCESS; -} - - -TNC_Result TNC_TNCS_GetAttribute( - TNC_IMVID imvID, - TNC_ConnectionID connectionID, - TNC_AttributeID attribureID, - TNC_UInt32 bufferLength, - TNC_BufferReference buffer, - TNC_UInt32 *pOutValueLength) -{ - wpa_printf(MSG_DEBUG, "TNC: TNC_TNCS_GetAttribute"); - /* TODO */ - return TNC_RESULT_SUCCESS; -} - - -TNC_Result TNC_TNCS_SetAttribute( - TNC_IMVID imvID, - TNC_ConnectionID connectionID, - TNC_AttributeID attribureID, - TNC_UInt32 bufferLength, - TNC_BufferReference buffer) -{ - wpa_printf(MSG_DEBUG, "TNC: TNC_TNCS_SetAttribute"); - /* TODO */ - return TNC_RESULT_SUCCESS; -} - - -TNC_Result TNC_TNCS_BindFunction( - TNC_IMVID imvID, - char *functionName, - void **pOutFunctionPointer) -{ - wpa_printf(MSG_DEBUG, "TNC: TNC_TNCS_BindFunction(imcID=%lu, " - "functionName='%s')", (unsigned long) imvID, functionName); - - if (tncs_get_imv(imvID) == NULL) - return TNC_RESULT_INVALID_PARAMETER; - - if (pOutFunctionPointer == NULL) - return TNC_RESULT_INVALID_PARAMETER; - - if (os_strcmp(functionName, "TNC_TNCS_ReportMessageTypes") == 0) - *pOutFunctionPointer = TNC_TNCS_ReportMessageTypes; - else if (os_strcmp(functionName, "TNC_TNCS_SendMessage") == 0) - *pOutFunctionPointer = TNC_TNCS_SendMessage; - else if (os_strcmp(functionName, "TNC_TNCS_RequestHandshakeRetry") == - 0) - *pOutFunctionPointer = TNC_TNCS_RequestHandshakeRetry; - else if (os_strcmp(functionName, "TNC_TNCS_ProvideRecommendation") == - 0) - *pOutFunctionPointer = TNC_TNCS_ProvideRecommendation; - else if (os_strcmp(functionName, "TNC_TNCS_GetAttribute") == 0) - *pOutFunctionPointer = TNC_TNCS_GetAttribute; - else if (os_strcmp(functionName, "TNC_TNCS_SetAttribute") == 0) - *pOutFunctionPointer = TNC_TNCS_SetAttribute; - else - *pOutFunctionPointer = NULL; - - return TNC_RESULT_SUCCESS; -} - - -static void * tncs_get_sym(void *handle, char *func) -{ - void *fptr; - - fptr = dlsym(handle, func); - - return fptr; -} - - -static int tncs_imv_resolve_funcs(struct tnc_if_imv *imv) -{ - void *handle = imv->dlhandle; - - /* Mandatory IMV functions */ - imv->Initialize = tncs_get_sym(handle, "TNC_IMV_Initialize"); - if (imv->Initialize == NULL) { - wpa_printf(MSG_ERROR, "TNC: IMV does not export " - "TNC_IMV_Initialize"); - return -1; - } - - imv->SolicitRecommendation = tncs_get_sym( - handle, "TNC_IMV_SolicitRecommendation"); - if (imv->SolicitRecommendation == NULL) { - wpa_printf(MSG_ERROR, "TNC: IMV does not export " - "TNC_IMV_SolicitRecommendation"); - return -1; - } - - imv->ProvideBindFunction = - tncs_get_sym(handle, "TNC_IMV_ProvideBindFunction"); - if (imv->ProvideBindFunction == NULL) { - wpa_printf(MSG_ERROR, "TNC: IMV does not export " - "TNC_IMV_ProvideBindFunction"); - return -1; - } - - /* Optional IMV functions */ - imv->NotifyConnectionChange = - tncs_get_sym(handle, "TNC_IMV_NotifyConnectionChange"); - imv->ReceiveMessage = tncs_get_sym(handle, "TNC_IMV_ReceiveMessage"); - imv->BatchEnding = tncs_get_sym(handle, "TNC_IMV_BatchEnding"); - imv->Terminate = tncs_get_sym(handle, "TNC_IMV_Terminate"); - - return 0; -} - - -static int tncs_imv_initialize(struct tnc_if_imv *imv) -{ - TNC_Result res; - TNC_Version imv_ver; - - wpa_printf(MSG_DEBUG, "TNC: Calling TNC_IMV_Initialize for IMV '%s'", - imv->name); - res = imv->Initialize(imv->imvID, TNC_IFIMV_VERSION_1, - TNC_IFIMV_VERSION_1, &imv_ver); - wpa_printf(MSG_DEBUG, "TNC: TNC_IMV_Initialize: res=%lu imv_ver=%lu", - (unsigned long) res, (unsigned long) imv_ver); - - return res == TNC_RESULT_SUCCESS ? 0 : -1; -} - - -static int tncs_imv_terminate(struct tnc_if_imv *imv) -{ - TNC_Result res; - - if (imv->Terminate == NULL) - return 0; - - wpa_printf(MSG_DEBUG, "TNC: Calling TNC_IMV_Terminate for IMV '%s'", - imv->name); - res = imv->Terminate(imv->imvID); - wpa_printf(MSG_DEBUG, "TNC: TNC_IMV_Terminate: %lu", - (unsigned long) res); - - return res == TNC_RESULT_SUCCESS ? 0 : -1; -} - - -static int tncs_imv_provide_bind_function(struct tnc_if_imv *imv) -{ - TNC_Result res; - - wpa_printf(MSG_DEBUG, "TNC: Calling TNC_IMV_ProvideBindFunction for " - "IMV '%s'", imv->name); - res = imv->ProvideBindFunction(imv->imvID, TNC_TNCS_BindFunction); - wpa_printf(MSG_DEBUG, "TNC: TNC_IMV_ProvideBindFunction: res=%lu", - (unsigned long) res); - - return res == TNC_RESULT_SUCCESS ? 0 : -1; -} - - -static int tncs_imv_notify_connection_change(struct tnc_if_imv *imv, - TNC_ConnectionID conn, - TNC_ConnectionState state) -{ - TNC_Result res; - - if (imv->NotifyConnectionChange == NULL) - return 0; - - wpa_printf(MSG_DEBUG, "TNC: Calling TNC_IMV_NotifyConnectionChange(%d)" - " for IMV '%s'", (int) state, imv->name); - res = imv->NotifyConnectionChange(imv->imvID, conn, state); - wpa_printf(MSG_DEBUG, "TNC: TNC_IMC_NotifyConnectionChange: %lu", - (unsigned long) res); - - return res == TNC_RESULT_SUCCESS ? 0 : -1; -} - - -static int tncs_load_imv(struct tnc_if_imv *imv) -{ - if (imv->path == NULL) { - wpa_printf(MSG_DEBUG, "TNC: No IMV configured"); - return -1; - } - - wpa_printf(MSG_DEBUG, "TNC: Opening IMV: %s (%s)", - imv->name, imv->path); - imv->dlhandle = dlopen(imv->path, RTLD_LAZY); - if (imv->dlhandle == NULL) { - wpa_printf(MSG_ERROR, "TNC: Failed to open IMV '%s' (%s): %s", - imv->name, imv->path, dlerror()); - return -1; - } - - if (tncs_imv_resolve_funcs(imv) < 0) { - wpa_printf(MSG_ERROR, "TNC: Failed to resolve IMV functions"); - return -1; - } - - if (tncs_imv_initialize(imv) < 0 || - tncs_imv_provide_bind_function(imv) < 0) { - wpa_printf(MSG_ERROR, "TNC: Failed to initialize IMV"); - return -1; - } - - return 0; -} - - -static void tncs_free_imv(struct tnc_if_imv *imv) -{ - os_free(imv->name); - os_free(imv->path); - os_free(imv->supported_types); -} - -static void tncs_unload_imv(struct tnc_if_imv *imv) -{ - tncs_imv_terminate(imv); - - if (imv->dlhandle) - dlclose(imv->dlhandle); - - tncs_free_imv(imv); -} - - -static int tncs_supported_type(struct tnc_if_imv *imv, unsigned int type) -{ - size_t i; - unsigned int vendor, subtype; - - if (imv == NULL || imv->supported_types == NULL) - return 0; - - vendor = type >> 8; - subtype = type & 0xff; - - for (i = 0; i < imv->num_supported_types; i++) { - unsigned int svendor, ssubtype; - svendor = imv->supported_types[i] >> 8; - ssubtype = imv->supported_types[i] & 0xff; - if ((vendor == svendor || svendor == TNC_VENDORID_ANY) && - (subtype == ssubtype || ssubtype == TNC_SUBTYPE_ANY)) - return 1; - } - - return 0; -} - - -static void tncs_send_to_imvs(struct tncs_data *tncs, unsigned int type, - const u8 *msg, size_t len) -{ - struct tnc_if_imv *imv; - TNC_Result res; - - wpa_hexdump_ascii(MSG_MSGDUMP, "TNC: Message to IMV(s)", msg, len); - - for (imv = tncs->imv; imv; imv = imv->next) { - if (imv->ReceiveMessage == NULL || - !tncs_supported_type(imv, type)) - continue; - - wpa_printf(MSG_DEBUG, "TNC: Call ReceiveMessage for IMV '%s'", - imv->name); - res = imv->ReceiveMessage(imv->imvID, tncs->connectionID, - (TNC_BufferReference) msg, len, - type); - wpa_printf(MSG_DEBUG, "TNC: ReceiveMessage: %lu", - (unsigned long) res); - } -} - - -static void tncs_batch_ending(struct tncs_data *tncs) -{ - struct tnc_if_imv *imv; - TNC_Result res; - - for (imv = tncs->imv; imv; imv = imv->next) { - if (imv->BatchEnding == NULL) - continue; - - wpa_printf(MSG_DEBUG, "TNC: Call BatchEnding for IMV '%s'", - imv->name); - res = imv->BatchEnding(imv->imvID, tncs->connectionID); - wpa_printf(MSG_DEBUG, "TNC: BatchEnding: %lu", - (unsigned long) res); - } -} - - -static void tncs_solicit_recommendation(struct tncs_data *tncs) -{ - struct tnc_if_imv *imv; - TNC_Result res; - - for (imv = tncs->imv; imv; imv = imv->next) { - if (tncs->imv_data[imv->imvID].recommendation_set) - continue; - - wpa_printf(MSG_DEBUG, "TNC: Call SolicitRecommendation for " - "IMV '%s'", imv->name); - res = imv->SolicitRecommendation(imv->imvID, - tncs->connectionID); - wpa_printf(MSG_DEBUG, "TNC: SolicitRecommendation: %lu", - (unsigned long) res); - } -} - - -void tncs_init_connection(struct tncs_data *tncs) -{ - struct tnc_if_imv *imv; - int i; - - for (imv = tncs->imv; imv; imv = imv->next) { - tncs_imv_notify_connection_change( - imv, tncs->connectionID, TNC_CONNECTION_STATE_CREATE); - tncs_imv_notify_connection_change( - imv, tncs->connectionID, - TNC_CONNECTION_STATE_HANDSHAKE); - } - - for (i = 0; i < TNC_MAX_IMV_ID; i++) { - os_free(tncs->imv_data[i].imv_send); - tncs->imv_data[i].imv_send = NULL; - tncs->imv_data[i].imv_send_len = 0; - } -} - - -size_t tncs_total_send_len(struct tncs_data *tncs) -{ - int i; - size_t len = 0; - - for (i = 0; i < TNC_MAX_IMV_ID; i++) - len += tncs->imv_data[i].imv_send_len; - if (tncs->tncs_message) - len += os_strlen(tncs->tncs_message); - return len; -} - - -u8 * tncs_copy_send_buf(struct tncs_data *tncs, u8 *pos) -{ - int i; - - for (i = 0; i < TNC_MAX_IMV_ID; i++) { - if (tncs->imv_data[i].imv_send == NULL) - continue; - - os_memcpy(pos, tncs->imv_data[i].imv_send, - tncs->imv_data[i].imv_send_len); - pos += tncs->imv_data[i].imv_send_len; - os_free(tncs->imv_data[i].imv_send); - tncs->imv_data[i].imv_send = NULL; - tncs->imv_data[i].imv_send_len = 0; - } - - if (tncs->tncs_message) { - size_t len = os_strlen(tncs->tncs_message); - os_memcpy(pos, tncs->tncs_message, len); - pos += len; - os_free(tncs->tncs_message); - tncs->tncs_message = NULL; - } - - return pos; -} - - -char * tncs_if_tnccs_start(struct tncs_data *tncs) -{ - char *buf = os_malloc(1000); - if (buf == NULL) - return NULL; - tncs->last_batchid++; - os_snprintf(buf, 1000, IF_TNCCS_START, tncs->last_batchid); - return buf; -} - - -char * tncs_if_tnccs_end(void) -{ - char *buf = os_malloc(100); - if (buf == NULL) - return NULL; - os_snprintf(buf, 100, IF_TNCCS_END); - return buf; -} - - -static int tncs_get_type(char *start, unsigned int *type) -{ - char *pos = os_strstr(start, ""); - if (pos == NULL) - return -1; - pos += 6; - *type = strtoul(pos, NULL, 16); - return 0; -} - - -static unsigned char * tncs_get_base64(char *start, size_t *decoded_len) -{ - char *pos, *pos2; - unsigned char *decoded; - - pos = os_strstr(start, ""); - if (pos == NULL) - return NULL; - - pos += 8; - pos2 = os_strstr(pos, ""); - if (pos2 == NULL) - return NULL; - *pos2 = '\0'; - - decoded = base64_decode((unsigned char *) pos, os_strlen(pos), - decoded_len); - *pos2 = '<'; - if (decoded == NULL) { - wpa_printf(MSG_DEBUG, "TNC: Failed to decode Base64 data"); - } - - return decoded; -} - - -static enum tncs_process_res tncs_derive_recommendation(struct tncs_data *tncs) -{ - enum IMV_Action_Recommendation rec; - struct tnc_if_imv *imv; - TNC_ConnectionState state; - char *txt; - - wpa_printf(MSG_DEBUG, "TNC: No more messages from IMVs"); - - if (tncs->done) - return TNCCS_PROCESS_OK_NO_RECOMMENDATION; - - tncs_solicit_recommendation(tncs); - - /* Select the most restrictive recommendation */ - rec = TNC_IMV_ACTION_RECOMMENDATION_NO_RECOMMENDATION; - for (imv = tncs->imv; imv; imv = imv->next) { - TNC_IMV_Action_Recommendation irec; - irec = tncs->imv_data[imv->imvID].recommendation; - if (irec == TNC_IMV_ACTION_RECOMMENDATION_NO_ACCESS) - rec = TNC_IMV_ACTION_RECOMMENDATION_NO_ACCESS; - if (irec == TNC_IMV_ACTION_RECOMMENDATION_ISOLATE && - rec != TNC_IMV_ACTION_RECOMMENDATION_NO_ACCESS) - rec = TNC_IMV_ACTION_RECOMMENDATION_ISOLATE; - if (irec == TNC_IMV_ACTION_RECOMMENDATION_ALLOW && - rec == TNC_IMV_ACTION_RECOMMENDATION_NO_RECOMMENDATION) - rec = TNC_IMV_ACTION_RECOMMENDATION_ALLOW; - } - - wpa_printf(MSG_DEBUG, "TNC: Recommendation: %d", rec); - tncs->recommendation = rec; - tncs->done = 1; - - txt = NULL; - switch (rec) { - case TNC_IMV_ACTION_RECOMMENDATION_ALLOW: - case TNC_IMV_ACTION_RECOMMENDATION_NO_RECOMMENDATION: - txt = "allow"; - state = TNC_CONNECTION_STATE_ACCESS_ALLOWED; - break; - case TNC_IMV_ACTION_RECOMMENDATION_ISOLATE: - txt = "isolate"; - state = TNC_CONNECTION_STATE_ACCESS_ISOLATED; - break; - case TNC_IMV_ACTION_RECOMMENDATION_NO_ACCESS: - txt = "none"; - state = TNC_CONNECTION_STATE_ACCESS_NONE; - break; - default: - state = TNC_CONNECTION_STATE_ACCESS_ALLOWED; - break; - } - - if (txt) { - os_free(tncs->tncs_message); - tncs->tncs_message = os_zalloc(200); - if (tncs->tncs_message) { - os_snprintf(tncs->tncs_message, 199, - "%08X" - "" - "" - "", - TNC_TNCCS_RECOMMENDATION, txt); - } - } - - for (imv = tncs->imv; imv; imv = imv->next) { - tncs_imv_notify_connection_change(imv, tncs->connectionID, - state); - } - - switch (rec) { - case TNC_IMV_ACTION_RECOMMENDATION_ALLOW: - return TNCCS_RECOMMENDATION_ALLOW; - case TNC_IMV_ACTION_RECOMMENDATION_NO_ACCESS: - return TNCCS_RECOMMENDATION_NO_ACCESS; - case TNC_IMV_ACTION_RECOMMENDATION_ISOLATE: - return TNCCS_RECOMMENDATION_ISOLATE; - case TNC_IMV_ACTION_RECOMMENDATION_NO_RECOMMENDATION: - return TNCCS_RECOMMENDATION_NO_RECOMMENDATION; - default: - return TNCCS_PROCESS_ERROR; - } -} - - -enum tncs_process_res tncs_process_if_tnccs(struct tncs_data *tncs, - const u8 *msg, size_t len) -{ - char *buf, *start, *end, *pos, *pos2, *payload; - unsigned int batch_id; - unsigned char *decoded; - size_t decoded_len; - - buf = os_malloc(len + 1); - if (buf == NULL) - return TNCCS_PROCESS_ERROR; - - os_memcpy(buf, msg, len); - buf[len] = '\0'; - start = os_strstr(buf, ""); - if (start == NULL || end == NULL || start > end) { - os_free(buf); - return TNCCS_PROCESS_ERROR; - } - - start += 13; - while (*start == ' ') - start++; - *end = '\0'; - - pos = os_strstr(start, "BatchId="); - if (pos == NULL) { - os_free(buf); - return TNCCS_PROCESS_ERROR; - } - - pos += 8; - if (*pos == '"') - pos++; - batch_id = atoi(pos); - wpa_printf(MSG_DEBUG, "TNC: Received IF-TNCCS BatchId=%u", - batch_id); - if (batch_id != tncs->last_batchid + 1) { - wpa_printf(MSG_DEBUG, "TNC: Unexpected IF-TNCCS BatchId " - "%u (expected %u)", - batch_id, tncs->last_batchid + 1); - os_free(buf); - return TNCCS_PROCESS_ERROR; - } - tncs->last_batchid = batch_id; - - while (*pos != '\0' && *pos != '>') - pos++; - if (*pos == '\0') { - os_free(buf); - return TNCCS_PROCESS_ERROR; - } - pos++; - payload = start; - - /* - * - * 01234567 - * foo== - * - */ - - while (*start) { - char *endpos; - unsigned int type; - - pos = os_strstr(start, ""); - if (pos == NULL) - break; - start = pos + 17; - end = os_strstr(start, ""); - if (end == NULL) - break; - *end = '\0'; - endpos = end; - end += 18; - - if (tncs_get_type(start, &type) < 0) { - *endpos = '<'; - start = end; - continue; - } - wpa_printf(MSG_DEBUG, "TNC: IMC-IMV-Message Type 0x%x", type); - - decoded = tncs_get_base64(start, &decoded_len); - if (decoded == NULL) { - *endpos = '<'; - start = end; - continue; - } - - tncs_send_to_imvs(tncs, type, decoded, decoded_len); - - os_free(decoded); - - start = end; - } - - /* - * - * 01234567 - * - * foo== - * - */ - - start = payload; - while (*start) { - unsigned int type; - char *xml, *xmlend, *endpos; - - pos = os_strstr(start, ""); - if (pos == NULL) - break; - start = pos + 19; - end = os_strstr(start, ""); - if (end == NULL) - break; - *end = '\0'; - endpos = end; - end += 20; - - if (tncs_get_type(start, &type) < 0) { - *endpos = '<'; - start = end; - continue; - } - wpa_printf(MSG_DEBUG, "TNC: TNCC-TNCS-Message Type 0x%x", - type); - - /* Base64 OR XML */ - decoded = NULL; - xml = NULL; - xmlend = NULL; - pos = os_strstr(start, ""); - if (pos) { - pos += 5; - pos2 = os_strstr(pos, ""); - if (pos2 == NULL) { - *endpos = '<'; - start = end; - continue; - } - xmlend = pos2; - xml = pos; - } else { - decoded = tncs_get_base64(start, &decoded_len); - if (decoded == NULL) { - *endpos = '<'; - start = end; - continue; - } - } - - if (decoded) { - wpa_hexdump_ascii(MSG_MSGDUMP, - "TNC: TNCC-TNCS-Message Base64", - decoded, decoded_len); - os_free(decoded); - } - - if (xml) { - wpa_hexdump_ascii(MSG_MSGDUMP, - "TNC: TNCC-TNCS-Message XML", - (unsigned char *) xml, - xmlend - xml); - } - - start = end; - } - - os_free(buf); - - tncs_batch_ending(tncs); - - if (tncs_total_send_len(tncs) == 0) - return tncs_derive_recommendation(tncs); - - return TNCCS_PROCESS_OK_NO_RECOMMENDATION; -} - - -static struct tnc_if_imv * tncs_parse_imv(int id, char *start, char *end, - int *error) -{ - struct tnc_if_imv *imv; - char *pos, *pos2; - - if (id >= TNC_MAX_IMV_ID) { - wpa_printf(MSG_DEBUG, "TNC: Too many IMVs"); - return NULL; - } - - imv = os_zalloc(sizeof(*imv)); - if (imv == NULL) { - *error = 1; - return NULL; - } - - imv->imvID = id; - - pos = start; - wpa_printf(MSG_DEBUG, "TNC: Configured IMV: %s", pos); - if (pos + 1 >= end || *pos != '"') { - wpa_printf(MSG_ERROR, "TNC: Ignoring invalid IMV line '%s' " - "(no starting quotation mark)", start); - os_free(imv); - return NULL; - } - - pos++; - pos2 = pos; - while (pos2 < end && *pos2 != '"') - pos2++; - if (pos2 >= end) { - wpa_printf(MSG_ERROR, "TNC: Ignoring invalid IMV line '%s' " - "(no ending quotation mark)", start); - os_free(imv); - return NULL; - } - *pos2 = '\0'; - wpa_printf(MSG_DEBUG, "TNC: Name: '%s'", pos); - imv->name = os_strdup(pos); - - pos = pos2 + 1; - if (pos >= end || *pos != ' ') { - wpa_printf(MSG_ERROR, "TNC: Ignoring invalid IMV line '%s' " - "(no space after name)", start); - os_free(imv); - return NULL; - } - - pos++; - wpa_printf(MSG_DEBUG, "TNC: IMV file: '%s'", pos); - imv->path = os_strdup(pos); - - return imv; -} - - -static int tncs_read_config(struct tncs_global *global) -{ - char *config, *end, *pos, *line_end; - size_t config_len; - struct tnc_if_imv *imv, *last; - int id = 0; - - last = NULL; - - config = os_readfile(TNC_CONFIG_FILE, &config_len); - if (config == NULL) { - wpa_printf(MSG_ERROR, "TNC: Could not open TNC configuration " - "file '%s'", TNC_CONFIG_FILE); - return -1; - } - - end = config + config_len; - for (pos = config; pos < end; pos = line_end + 1) { - line_end = pos; - while (*line_end != '\n' && *line_end != '\r' && - line_end < end) - line_end++; - *line_end = '\0'; - - if (os_strncmp(pos, "IMV ", 4) == 0) { - int error = 0; - - imv = tncs_parse_imv(id++, pos + 4, line_end, &error); - if (error) - return -1; - if (imv) { - if (last == NULL) - global->imv = imv; - else - last->next = imv; - last = imv; - } - } - } - - os_free(config); - - return 0; -} - - -struct tncs_data * tncs_init(void) -{ - struct tncs_data *tncs; - - if (tncs_global_data == NULL) - return NULL; - - tncs = os_zalloc(sizeof(*tncs)); - if (tncs == NULL) - return NULL; - tncs->imv = tncs_global_data->imv; - tncs->connectionID = tncs_global_data->next_conn_id++; - tncs->next = tncs_global_data->connections; - tncs_global_data->connections = tncs; - - return tncs; -} - - -void tncs_deinit(struct tncs_data *tncs) -{ - int i; - struct tncs_data *prev, *conn; - - if (tncs == NULL) - return; - - for (i = 0; i < TNC_MAX_IMV_ID; i++) - os_free(tncs->imv_data[i].imv_send); - - prev = NULL; - conn = tncs_global_data->connections; - while (conn) { - if (conn == tncs) { - if (prev) - prev->next = tncs->next; - else - tncs_global_data->connections = tncs->next; - break; - } - prev = conn; - conn = conn->next; - } - - os_free(tncs->tncs_message); - os_free(tncs); -} - - -int tncs_global_init(void) -{ - struct tnc_if_imv *imv; - - tncs_global_data = os_zalloc(sizeof(*tncs_global_data)); - if (tncs_global_data == NULL) - return -1; - - if (tncs_read_config(tncs_global_data) < 0) { - wpa_printf(MSG_ERROR, "TNC: Failed to read TNC configuration"); - goto failed; - } - - for (imv = tncs_global_data->imv; imv; imv = imv->next) { - if (tncs_load_imv(imv)) { - wpa_printf(MSG_ERROR, "TNC: Failed to load IMV '%s'", - imv->name); - goto failed; - } - } - - return 0; - -failed: - tncs_global_deinit(); - return -1; -} - - -void tncs_global_deinit(void) -{ - struct tnc_if_imv *imv, *prev; - - if (tncs_global_data == NULL) - return; - - imv = tncs_global_data->imv; - while (imv) { - tncs_unload_imv(imv); - - prev = imv; - imv = imv->next; - os_free(prev); - } - - os_free(tncs_global_data); - tncs_global_data = NULL; -} - - -struct wpabuf * tncs_build_soh_request(void) -{ - struct wpabuf *buf; - - /* - * Build a SoH Request TLV (to be used inside SoH EAP Extensions - * Method) - */ - - buf = wpabuf_alloc(8 + 4); - if (buf == NULL) - return NULL; - - /* Vendor-Specific TLV (Microsoft) - SoH Request */ - wpabuf_put_be16(buf, EAP_TLV_VENDOR_SPECIFIC_TLV); /* TLV Type */ - wpabuf_put_be16(buf, 8); /* Length */ - - wpabuf_put_be32(buf, EAP_VENDOR_MICROSOFT); /* Vendor_Id */ - - wpabuf_put_be16(buf, 0x02); /* TLV Type - SoH Request TLV */ - wpabuf_put_be16(buf, 0); /* Length */ - - return buf; -} - - -struct wpabuf * tncs_process_soh(const u8 *soh_tlv, size_t soh_tlv_len, - int *failure) -{ - wpa_hexdump(MSG_DEBUG, "TNC: SoH TLV", soh_tlv, soh_tlv_len); - *failure = 0; - - /* TODO: return MS-SoH Response TLV */ - - return NULL; -} diff --git a/hostapd-0.8/src/eap_server/tncs.h b/hostapd-0.8/src/eap_server/tncs.h deleted file mode 100644 index 18a3a1f..0000000 --- a/hostapd-0.8/src/eap_server/tncs.h +++ /dev/null @@ -1,49 +0,0 @@ -/* - * EAP-TNC - TNCS (IF-IMV, IF-TNCCS, and IF-TNCCS-SOH) - * Copyright (c) 2007-2008, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#ifndef TNCS_H -#define TNCS_H - -struct tncs_data; - -struct tncs_data * tncs_init(void); -void tncs_deinit(struct tncs_data *tncs); -void tncs_init_connection(struct tncs_data *tncs); -size_t tncs_total_send_len(struct tncs_data *tncs); -u8 * tncs_copy_send_buf(struct tncs_data *tncs, u8 *pos); -char * tncs_if_tnccs_start(struct tncs_data *tncs); -char * tncs_if_tnccs_end(void); - -enum tncs_process_res { - TNCCS_PROCESS_ERROR = -1, - TNCCS_PROCESS_OK_NO_RECOMMENDATION = 0, - TNCCS_RECOMMENDATION_ERROR, - TNCCS_RECOMMENDATION_ALLOW, - TNCCS_RECOMMENDATION_NONE, - TNCCS_RECOMMENDATION_ISOLATE, - TNCCS_RECOMMENDATION_NO_ACCESS, - TNCCS_RECOMMENDATION_NO_RECOMMENDATION -}; - -enum tncs_process_res tncs_process_if_tnccs(struct tncs_data *tncs, - const u8 *msg, size_t len); - -int tncs_global_init(void); -void tncs_global_deinit(void); - -struct wpabuf * tncs_build_soh_request(void); -struct wpabuf * tncs_process_soh(const u8 *soh_tlv, size_t soh_tlv_len, - int *failure); - -#endif /* TNCS_H */ diff --git a/hostapd-0.8/src/eapol_auth/Makefile b/hostapd-0.8/src/eapol_auth/Makefile deleted file mode 100644 index 9c41962..0000000 --- a/hostapd-0.8/src/eapol_auth/Makefile +++ /dev/null @@ -1,8 +0,0 @@ -all: - @echo Nothing to be made. - -clean: - rm -f *~ *.o *.d - -install: - @echo Nothing to be made. diff --git a/hostapd-0.8/src/eapol_auth/eapol_auth_dump.c b/hostapd-0.8/src/eapol_auth/eapol_auth_dump.c deleted file mode 100644 index a0f0e8d..0000000 --- a/hostapd-0.8/src/eapol_auth/eapol_auth_dump.c +++ /dev/null @@ -1,231 +0,0 @@ -/* - * IEEE 802.1X-2004 Authenticator - State dump - * Copyright (c) 2002-2009, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#include "includes.h" - -#include "common.h" -#include "eap_server/eap.h" -#include "eapol_auth_sm.h" -#include "eapol_auth_sm_i.h" - -static inline const char * port_type_txt(PortTypes pt) -{ - switch (pt) { - case ForceUnauthorized: return "ForceUnauthorized"; - case ForceAuthorized: return "ForceAuthorized"; - case Auto: return "Auto"; - default: return "Unknown"; - } -} - - -static inline const char * port_state_txt(PortState ps) -{ - switch (ps) { - case Unauthorized: return "Unauthorized"; - case Authorized: return "Authorized"; - default: return "Unknown"; - } -} - - -static inline const char * ctrl_dir_txt(ControlledDirection dir) -{ - switch (dir) { - case Both: return "Both"; - case In: return "In"; - default: return "Unknown"; - } -} - - -static inline const char * auth_pae_state_txt(int s) -{ - switch (s) { - case AUTH_PAE_INITIALIZE: return "INITIALIZE"; - case AUTH_PAE_DISCONNECTED: return "DISCONNECTED"; - case AUTH_PAE_CONNECTING: return "CONNECTING"; - case AUTH_PAE_AUTHENTICATING: return "AUTHENTICATING"; - case AUTH_PAE_AUTHENTICATED: return "AUTHENTICATED"; - case AUTH_PAE_ABORTING: return "ABORTING"; - case AUTH_PAE_HELD: return "HELD"; - case AUTH_PAE_FORCE_AUTH: return "FORCE_AUTH"; - case AUTH_PAE_FORCE_UNAUTH: return "FORCE_UNAUTH"; - case AUTH_PAE_RESTART: return "RESTART"; - default: return "Unknown"; - } -} - - -static inline const char * be_auth_state_txt(int s) -{ - switch (s) { - case BE_AUTH_REQUEST: return "REQUEST"; - case BE_AUTH_RESPONSE: return "RESPONSE"; - case BE_AUTH_SUCCESS: return "SUCCESS"; - case BE_AUTH_FAIL: return "FAIL"; - case BE_AUTH_TIMEOUT: return "TIMEOUT"; - case BE_AUTH_IDLE: return "IDLE"; - case BE_AUTH_INITIALIZE: return "INITIALIZE"; - case BE_AUTH_IGNORE: return "IGNORE"; - default: return "Unknown"; - } -} - - -static inline const char * reauth_timer_state_txt(int s) -{ - switch (s) { - case REAUTH_TIMER_INITIALIZE: return "INITIALIZE"; - case REAUTH_TIMER_REAUTHENTICATE: return "REAUTHENTICATE"; - default: return "Unknown"; - } -} - - -static inline const char * auth_key_tx_state_txt(int s) -{ - switch (s) { - case AUTH_KEY_TX_NO_KEY_TRANSMIT: return "NO_KEY_TRANSMIT"; - case AUTH_KEY_TX_KEY_TRANSMIT: return "KEY_TRANSMIT"; - default: return "Unknown"; - } -} - - -static inline const char * key_rx_state_txt(int s) -{ - switch (s) { - case KEY_RX_NO_KEY_RECEIVE: return "NO_KEY_RECEIVE"; - case KEY_RX_KEY_RECEIVE: return "KEY_RECEIVE"; - default: return "Unknown"; - } -} - - -static inline const char * ctrl_dir_state_txt(int s) -{ - switch (s) { - case CTRL_DIR_FORCE_BOTH: return "FORCE_BOTH"; - case CTRL_DIR_IN_OR_BOTH: return "IN_OR_BOTH"; - default: return "Unknown"; - } -} - - -void eapol_auth_dump_state(FILE *f, const char *prefix, - struct eapol_state_machine *sm) -{ - fprintf(f, "%sEAPOL state machine:\n", prefix); - fprintf(f, "%s aWhile=%d quietWhile=%d reAuthWhen=%d\n", prefix, - sm->aWhile, sm->quietWhile, sm->reAuthWhen); -#define _SB(b) ((b) ? "TRUE" : "FALSE") - fprintf(f, - "%s authAbort=%s authFail=%s authPortStatus=%s authStart=%s\n" - "%s authTimeout=%s authSuccess=%s eapFail=%s eapolEap=%s\n" - "%s eapSuccess=%s eapTimeout=%s initialize=%s " - "keyAvailable=%s\n" - "%s keyDone=%s keyRun=%s keyTxEnabled=%s portControl=%s\n" - "%s portEnabled=%s portValid=%s reAuthenticate=%s\n", - prefix, _SB(sm->authAbort), _SB(sm->authFail), - port_state_txt(sm->authPortStatus), _SB(sm->authStart), - prefix, _SB(sm->authTimeout), _SB(sm->authSuccess), - _SB(sm->eap_if->eapFail), _SB(sm->eapolEap), - prefix, _SB(sm->eap_if->eapSuccess), - _SB(sm->eap_if->eapTimeout), - _SB(sm->initialize), _SB(sm->eap_if->eapKeyAvailable), - prefix, _SB(sm->keyDone), _SB(sm->keyRun), - _SB(sm->keyTxEnabled), port_type_txt(sm->portControl), - prefix, _SB(sm->eap_if->portEnabled), _SB(sm->portValid), - _SB(sm->reAuthenticate)); - - fprintf(f, "%s Authenticator PAE:\n" - "%s state=%s\n" - "%s eapolLogoff=%s eapolStart=%s eapRestart=%s\n" - "%s portMode=%s reAuthCount=%d\n" - "%s quietPeriod=%d reAuthMax=%d\n" - "%s authEntersConnecting=%d\n" - "%s authEapLogoffsWhileConnecting=%d\n" - "%s authEntersAuthenticating=%d\n" - "%s authAuthSuccessesWhileAuthenticating=%d\n" - "%s authAuthTimeoutsWhileAuthenticating=%d\n" - "%s authAuthFailWhileAuthenticating=%d\n" - "%s authAuthEapStartsWhileAuthenticating=%d\n" - "%s authAuthEapLogoffWhileAuthenticating=%d\n" - "%s authAuthReauthsWhileAuthenticated=%d\n" - "%s authAuthEapStartsWhileAuthenticated=%d\n" - "%s authAuthEapLogoffWhileAuthenticated=%d\n", - prefix, prefix, auth_pae_state_txt(sm->auth_pae_state), prefix, - _SB(sm->eapolLogoff), _SB(sm->eapolStart), - _SB(sm->eap_if->eapRestart), - prefix, port_type_txt(sm->portMode), sm->reAuthCount, - prefix, sm->quietPeriod, sm->reAuthMax, - prefix, sm->authEntersConnecting, - prefix, sm->authEapLogoffsWhileConnecting, - prefix, sm->authEntersAuthenticating, - prefix, sm->authAuthSuccessesWhileAuthenticating, - prefix, sm->authAuthTimeoutsWhileAuthenticating, - prefix, sm->authAuthFailWhileAuthenticating, - prefix, sm->authAuthEapStartsWhileAuthenticating, - prefix, sm->authAuthEapLogoffWhileAuthenticating, - prefix, sm->authAuthReauthsWhileAuthenticated, - prefix, sm->authAuthEapStartsWhileAuthenticated, - prefix, sm->authAuthEapLogoffWhileAuthenticated); - - fprintf(f, "%s Backend Authentication:\n" - "%s state=%s\n" - "%s eapNoReq=%s eapReq=%s eapResp=%s\n" - "%s serverTimeout=%d\n" - "%s backendResponses=%d\n" - "%s backendAccessChallenges=%d\n" - "%s backendOtherRequestsToSupplicant=%d\n" - "%s backendAuthSuccesses=%d\n" - "%s backendAuthFails=%d\n", - prefix, prefix, - be_auth_state_txt(sm->be_auth_state), - prefix, _SB(sm->eap_if->eapNoReq), _SB(sm->eap_if->eapReq), - _SB(sm->eap_if->eapResp), - prefix, sm->serverTimeout, - prefix, sm->backendResponses, - prefix, sm->backendAccessChallenges, - prefix, sm->backendOtherRequestsToSupplicant, - prefix, sm->backendAuthSuccesses, - prefix, sm->backendAuthFails); - - fprintf(f, "%s Reauthentication Timer:\n" - "%s state=%s\n" - "%s reAuthPeriod=%d reAuthEnabled=%s\n", prefix, prefix, - reauth_timer_state_txt(sm->reauth_timer_state), prefix, - sm->reAuthPeriod, _SB(sm->reAuthEnabled)); - - fprintf(f, "%s Authenticator Key Transmit:\n" - "%s state=%s\n", prefix, prefix, - auth_key_tx_state_txt(sm->auth_key_tx_state)); - - fprintf(f, "%s Key Receive:\n" - "%s state=%s\n" - "%s rxKey=%s\n", prefix, prefix, - key_rx_state_txt(sm->key_rx_state), prefix, _SB(sm->rxKey)); - - fprintf(f, "%s Controlled Directions:\n" - "%s state=%s\n" - "%s adminControlledDirections=%s " - "operControlledDirections=%s\n" - "%s operEdge=%s\n", prefix, prefix, - ctrl_dir_state_txt(sm->ctrl_dir_state), - prefix, ctrl_dir_txt(sm->adminControlledDirections), - ctrl_dir_txt(sm->operControlledDirections), - prefix, _SB(sm->operEdge)); -#undef _SB -} diff --git a/hostapd-0.8/src/eapol_auth/eapol_auth_sm.c b/hostapd-0.8/src/eapol_auth/eapol_auth_sm.c deleted file mode 100644 index 841a1c5..0000000 --- a/hostapd-0.8/src/eapol_auth/eapol_auth_sm.c +++ /dev/null @@ -1,1145 +0,0 @@ -/* - * IEEE 802.1X-2004 Authenticator - EAPOL state machine - * Copyright (c) 2002-2009, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#include "includes.h" - -#include "common.h" -#include "eloop.h" -#include "state_machine.h" -#include "common/eapol_common.h" -#include "eap_common/eap_defs.h" -#include "eap_common/eap_common.h" -#include "eap_server/eap.h" -#include "eapol_auth_sm.h" -#include "eapol_auth_sm_i.h" - -#define STATE_MACHINE_DATA struct eapol_state_machine -#define STATE_MACHINE_DEBUG_PREFIX "IEEE 802.1X" -#define STATE_MACHINE_ADDR sm->addr - -static struct eapol_callbacks eapol_cb; - -/* EAPOL state machines are described in IEEE Std 802.1X-2004, Chap. 8.2 */ - -#define setPortAuthorized() \ -sm->eapol->cb.set_port_authorized(sm->eapol->conf.ctx, sm->sta, 1) -#define setPortUnauthorized() \ -sm->eapol->cb.set_port_authorized(sm->eapol->conf.ctx, sm->sta, 0) - -/* procedures */ -#define txCannedFail() eapol_auth_tx_canned_eap(sm, 0) -#define txCannedSuccess() eapol_auth_tx_canned_eap(sm, 1) -#define txReq() eapol_auth_tx_req(sm) -#define abortAuth() sm->eapol->cb.abort_auth(sm->eapol->conf.ctx, sm->sta) -#define txKey() sm->eapol->cb.tx_key(sm->eapol->conf.ctx, sm->sta) -#define processKey() do { } while (0) - - -static void eapol_sm_step_run(struct eapol_state_machine *sm); -static void eapol_sm_step_cb(void *eloop_ctx, void *timeout_ctx); -static void eapol_auth_initialize(struct eapol_state_machine *sm); - - -static void eapol_auth_logger(struct eapol_authenticator *eapol, - const u8 *addr, eapol_logger_level level, - const char *txt) -{ - if (eapol->cb.logger == NULL) - return; - eapol->cb.logger(eapol->conf.ctx, addr, level, txt); -} - - -static void eapol_auth_vlogger(struct eapol_authenticator *eapol, - const u8 *addr, eapol_logger_level level, - const char *fmt, ...) -{ - char *format; - int maxlen; - va_list ap; - - if (eapol->cb.logger == NULL) - return; - - maxlen = os_strlen(fmt) + 100; - format = os_malloc(maxlen); - if (!format) - return; - - va_start(ap, fmt); - vsnprintf(format, maxlen, fmt, ap); - va_end(ap); - - eapol_auth_logger(eapol, addr, level, format); - - os_free(format); -} - - -static void eapol_auth_tx_canned_eap(struct eapol_state_machine *sm, - int success) -{ - struct eap_hdr eap; - - os_memset(&eap, 0, sizeof(eap)); - - eap.code = success ? EAP_CODE_SUCCESS : EAP_CODE_FAILURE; - eap.identifier = ++sm->last_eap_id; - eap.length = host_to_be16(sizeof(eap)); - - eapol_auth_vlogger(sm->eapol, sm->addr, EAPOL_LOGGER_DEBUG, - "Sending canned EAP packet %s (identifier %d)", - success ? "SUCCESS" : "FAILURE", eap.identifier); - sm->eapol->cb.eapol_send(sm->eapol->conf.ctx, sm->sta, - IEEE802_1X_TYPE_EAP_PACKET, - (u8 *) &eap, sizeof(eap)); - sm->dot1xAuthEapolFramesTx++; -} - - -static void eapol_auth_tx_req(struct eapol_state_machine *sm) -{ - if (sm->eap_if->eapReqData == NULL || - wpabuf_len(sm->eap_if->eapReqData) < sizeof(struct eap_hdr)) { - eapol_auth_logger(sm->eapol, sm->addr, - EAPOL_LOGGER_DEBUG, - "TxReq called, but there is no EAP request " - "from authentication server"); - return; - } - - if (sm->flags & EAPOL_SM_WAIT_START) { - wpa_printf(MSG_DEBUG, "EAPOL: Drop EAPOL TX to " MACSTR - " while waiting for EAPOL-Start", - MAC2STR(sm->addr)); - return; - } - - sm->last_eap_id = eap_get_id(sm->eap_if->eapReqData); - eapol_auth_vlogger(sm->eapol, sm->addr, EAPOL_LOGGER_DEBUG, - "Sending EAP Packet (identifier %d)", - sm->last_eap_id); - sm->eapol->cb.eapol_send(sm->eapol->conf.ctx, sm->sta, - IEEE802_1X_TYPE_EAP_PACKET, - wpabuf_head(sm->eap_if->eapReqData), - wpabuf_len(sm->eap_if->eapReqData)); - sm->dot1xAuthEapolFramesTx++; - if (eap_get_type(sm->eap_if->eapReqData) == EAP_TYPE_IDENTITY) - sm->dot1xAuthEapolReqIdFramesTx++; - else - sm->dot1xAuthEapolReqFramesTx++; -} - - -/** - * eapol_port_timers_tick - Port Timers state machine - * @eloop_ctx: struct eapol_state_machine * - * @timeout_ctx: Not used - * - * This statemachine is implemented as a function that will be called - * once a second as a registered event loop timeout. - */ -static void eapol_port_timers_tick(void *eloop_ctx, void *timeout_ctx) -{ - struct eapol_state_machine *state = timeout_ctx; - - if (state->aWhile > 0) { - state->aWhile--; - if (state->aWhile == 0) { - wpa_printf(MSG_DEBUG, "IEEE 802.1X: " MACSTR - " - aWhile --> 0", - MAC2STR(state->addr)); - } - } - - if (state->quietWhile > 0) { - state->quietWhile--; - if (state->quietWhile == 0) { - wpa_printf(MSG_DEBUG, "IEEE 802.1X: " MACSTR - " - quietWhile --> 0", - MAC2STR(state->addr)); - } - } - - if (state->reAuthWhen > 0) { - state->reAuthWhen--; - if (state->reAuthWhen == 0) { - wpa_printf(MSG_DEBUG, "IEEE 802.1X: " MACSTR - " - reAuthWhen --> 0", - MAC2STR(state->addr)); - } - } - - if (state->eap_if->retransWhile > 0) { - state->eap_if->retransWhile--; - if (state->eap_if->retransWhile == 0) { - wpa_printf(MSG_DEBUG, "IEEE 802.1X: " MACSTR - " - (EAP) retransWhile --> 0", - MAC2STR(state->addr)); - } - } - - eapol_sm_step_run(state); - - eloop_register_timeout(1, 0, eapol_port_timers_tick, eloop_ctx, state); -} - - - -/* Authenticator PAE state machine */ - -SM_STATE(AUTH_PAE, INITIALIZE) -{ - SM_ENTRY_MA(AUTH_PAE, INITIALIZE, auth_pae); - sm->portMode = Auto; -} - - -SM_STATE(AUTH_PAE, DISCONNECTED) -{ - int from_initialize = sm->auth_pae_state == AUTH_PAE_INITIALIZE; - - if (sm->eapolLogoff) { - if (sm->auth_pae_state == AUTH_PAE_CONNECTING) - sm->authEapLogoffsWhileConnecting++; - else if (sm->auth_pae_state == AUTH_PAE_AUTHENTICATED) - sm->authAuthEapLogoffWhileAuthenticated++; - } - - SM_ENTRY_MA(AUTH_PAE, DISCONNECTED, auth_pae); - - sm->authPortStatus = Unauthorized; - setPortUnauthorized(); - sm->reAuthCount = 0; - sm->eapolLogoff = FALSE; - if (!from_initialize) { - sm->eapol->cb.finished(sm->eapol->conf.ctx, sm->sta, 0, - sm->flags & EAPOL_SM_PREAUTH); - } -} - - -SM_STATE(AUTH_PAE, RESTART) -{ - if (sm->auth_pae_state == AUTH_PAE_AUTHENTICATED) { - if (sm->reAuthenticate) - sm->authAuthReauthsWhileAuthenticated++; - if (sm->eapolStart) - sm->authAuthEapStartsWhileAuthenticated++; - if (sm->eapolLogoff) - sm->authAuthEapLogoffWhileAuthenticated++; - } - - SM_ENTRY_MA(AUTH_PAE, RESTART, auth_pae); - - sm->eap_if->eapRestart = TRUE; -} - - -SM_STATE(AUTH_PAE, CONNECTING) -{ - if (sm->auth_pae_state != AUTH_PAE_CONNECTING) - sm->authEntersConnecting++; - - SM_ENTRY_MA(AUTH_PAE, CONNECTING, auth_pae); - - sm->reAuthenticate = FALSE; - sm->reAuthCount++; -} - - -SM_STATE(AUTH_PAE, HELD) -{ - if (sm->auth_pae_state == AUTH_PAE_AUTHENTICATING && sm->authFail) - sm->authAuthFailWhileAuthenticating++; - - SM_ENTRY_MA(AUTH_PAE, HELD, auth_pae); - - sm->authPortStatus = Unauthorized; - setPortUnauthorized(); - sm->quietWhile = sm->quietPeriod; - sm->eapolLogoff = FALSE; - - eapol_auth_vlogger(sm->eapol, sm->addr, EAPOL_LOGGER_WARNING, - "authentication failed - EAP type: %d (%s)", - sm->eap_type_authsrv, - eap_server_get_name(0, sm->eap_type_authsrv)); - if (sm->eap_type_authsrv != sm->eap_type_supp) { - eapol_auth_vlogger(sm->eapol, sm->addr, EAPOL_LOGGER_INFO, - "Supplicant used different EAP type: " - "%d (%s)", sm->eap_type_supp, - eap_server_get_name(0, sm->eap_type_supp)); - } - sm->eapol->cb.finished(sm->eapol->conf.ctx, sm->sta, 0, - sm->flags & EAPOL_SM_PREAUTH); -} - - -SM_STATE(AUTH_PAE, AUTHENTICATED) -{ - char *extra = ""; - - if (sm->auth_pae_state == AUTH_PAE_AUTHENTICATING && sm->authSuccess) - sm->authAuthSuccessesWhileAuthenticating++; - - SM_ENTRY_MA(AUTH_PAE, AUTHENTICATED, auth_pae); - - sm->authPortStatus = Authorized; - setPortAuthorized(); - sm->reAuthCount = 0; - if (sm->flags & EAPOL_SM_PREAUTH) - extra = " (pre-authentication)"; - else if (sm->flags & EAPOL_SM_FROM_PMKSA_CACHE) - extra = " (PMKSA cache)"; - eapol_auth_vlogger(sm->eapol, sm->addr, EAPOL_LOGGER_INFO, - "authenticated - EAP type: %d (%s)%s", - sm->eap_type_authsrv, - eap_server_get_name(0, sm->eap_type_authsrv), - extra); - sm->eapol->cb.finished(sm->eapol->conf.ctx, sm->sta, 1, - sm->flags & EAPOL_SM_PREAUTH); -} - - -SM_STATE(AUTH_PAE, AUTHENTICATING) -{ - SM_ENTRY_MA(AUTH_PAE, AUTHENTICATING, auth_pae); - - sm->eapolStart = FALSE; - sm->authSuccess = FALSE; - sm->authFail = FALSE; - sm->authTimeout = FALSE; - sm->authStart = TRUE; - sm->keyRun = FALSE; - sm->keyDone = FALSE; -} - - -SM_STATE(AUTH_PAE, ABORTING) -{ - if (sm->auth_pae_state == AUTH_PAE_AUTHENTICATING) { - if (sm->authTimeout) - sm->authAuthTimeoutsWhileAuthenticating++; - if (sm->eapolStart) - sm->authAuthEapStartsWhileAuthenticating++; - if (sm->eapolLogoff) - sm->authAuthEapLogoffWhileAuthenticating++; - } - - SM_ENTRY_MA(AUTH_PAE, ABORTING, auth_pae); - - sm->authAbort = TRUE; - sm->keyRun = FALSE; - sm->keyDone = FALSE; -} - - -SM_STATE(AUTH_PAE, FORCE_AUTH) -{ - SM_ENTRY_MA(AUTH_PAE, FORCE_AUTH, auth_pae); - - sm->authPortStatus = Authorized; - setPortAuthorized(); - sm->portMode = ForceAuthorized; - sm->eapolStart = FALSE; - txCannedSuccess(); -} - - -SM_STATE(AUTH_PAE, FORCE_UNAUTH) -{ - SM_ENTRY_MA(AUTH_PAE, FORCE_UNAUTH, auth_pae); - - sm->authPortStatus = Unauthorized; - setPortUnauthorized(); - sm->portMode = ForceUnauthorized; - sm->eapolStart = FALSE; - txCannedFail(); -} - - -SM_STEP(AUTH_PAE) -{ - if ((sm->portControl == Auto && sm->portMode != sm->portControl) || - sm->initialize || !sm->eap_if->portEnabled) - SM_ENTER_GLOBAL(AUTH_PAE, INITIALIZE); - else if (sm->portControl == ForceAuthorized && - sm->portMode != sm->portControl && - !(sm->initialize || !sm->eap_if->portEnabled)) - SM_ENTER_GLOBAL(AUTH_PAE, FORCE_AUTH); - else if (sm->portControl == ForceUnauthorized && - sm->portMode != sm->portControl && - !(sm->initialize || !sm->eap_if->portEnabled)) - SM_ENTER_GLOBAL(AUTH_PAE, FORCE_UNAUTH); - else { - switch (sm->auth_pae_state) { - case AUTH_PAE_INITIALIZE: - SM_ENTER(AUTH_PAE, DISCONNECTED); - break; - case AUTH_PAE_DISCONNECTED: - SM_ENTER(AUTH_PAE, RESTART); - break; - case AUTH_PAE_RESTART: - if (!sm->eap_if->eapRestart) - SM_ENTER(AUTH_PAE, CONNECTING); - break; - case AUTH_PAE_HELD: - if (sm->quietWhile == 0) - SM_ENTER(AUTH_PAE, RESTART); - break; - case AUTH_PAE_CONNECTING: - if (sm->eapolLogoff || sm->reAuthCount > sm->reAuthMax) - SM_ENTER(AUTH_PAE, DISCONNECTED); - else if ((sm->eap_if->eapReq && - sm->reAuthCount <= sm->reAuthMax) || - sm->eap_if->eapSuccess || sm->eap_if->eapFail) - SM_ENTER(AUTH_PAE, AUTHENTICATING); - break; - case AUTH_PAE_AUTHENTICATED: - if (sm->eapolStart || sm->reAuthenticate) - SM_ENTER(AUTH_PAE, RESTART); - else if (sm->eapolLogoff || !sm->portValid) - SM_ENTER(AUTH_PAE, DISCONNECTED); - break; - case AUTH_PAE_AUTHENTICATING: - if (sm->authSuccess && sm->portValid) - SM_ENTER(AUTH_PAE, AUTHENTICATED); - else if (sm->authFail || - (sm->keyDone && !sm->portValid)) - SM_ENTER(AUTH_PAE, HELD); - else if (sm->eapolStart || sm->eapolLogoff || - sm->authTimeout) - SM_ENTER(AUTH_PAE, ABORTING); - break; - case AUTH_PAE_ABORTING: - if (sm->eapolLogoff && !sm->authAbort) - SM_ENTER(AUTH_PAE, DISCONNECTED); - else if (!sm->eapolLogoff && !sm->authAbort) - SM_ENTER(AUTH_PAE, RESTART); - break; - case AUTH_PAE_FORCE_AUTH: - if (sm->eapolStart) - SM_ENTER(AUTH_PAE, FORCE_AUTH); - break; - case AUTH_PAE_FORCE_UNAUTH: - if (sm->eapolStart) - SM_ENTER(AUTH_PAE, FORCE_UNAUTH); - break; - } - } -} - - - -/* Backend Authentication state machine */ - -SM_STATE(BE_AUTH, INITIALIZE) -{ - SM_ENTRY_MA(BE_AUTH, INITIALIZE, be_auth); - - abortAuth(); - sm->eap_if->eapNoReq = FALSE; - sm->authAbort = FALSE; -} - - -SM_STATE(BE_AUTH, REQUEST) -{ - SM_ENTRY_MA(BE_AUTH, REQUEST, be_auth); - - txReq(); - sm->eap_if->eapReq = FALSE; - sm->backendOtherRequestsToSupplicant++; - - /* - * Clearing eapolEap here is not specified in IEEE Std 802.1X-2004, but - * it looks like this would be logical thing to do there since the old - * EAP response would not be valid anymore after the new EAP request - * was sent out. - * - * A race condition has been reported, in which hostapd ended up - * sending out EAP-Response/Identity as a response to the first - * EAP-Request from the main EAP method. This can be avoided by - * clearing eapolEap here. - */ - sm->eapolEap = FALSE; -} - - -SM_STATE(BE_AUTH, RESPONSE) -{ - SM_ENTRY_MA(BE_AUTH, RESPONSE, be_auth); - - sm->authTimeout = FALSE; - sm->eapolEap = FALSE; - sm->eap_if->eapNoReq = FALSE; - sm->aWhile = sm->serverTimeout; - sm->eap_if->eapResp = TRUE; - /* sendRespToServer(); */ - sm->backendResponses++; -} - - -SM_STATE(BE_AUTH, SUCCESS) -{ - SM_ENTRY_MA(BE_AUTH, SUCCESS, be_auth); - - txReq(); - sm->authSuccess = TRUE; - sm->keyRun = TRUE; -} - - -SM_STATE(BE_AUTH, FAIL) -{ - SM_ENTRY_MA(BE_AUTH, FAIL, be_auth); - - txReq(); - sm->authFail = TRUE; -} - - -SM_STATE(BE_AUTH, TIMEOUT) -{ - SM_ENTRY_MA(BE_AUTH, TIMEOUT, be_auth); - - sm->authTimeout = TRUE; -} - - -SM_STATE(BE_AUTH, IDLE) -{ - SM_ENTRY_MA(BE_AUTH, IDLE, be_auth); - - sm->authStart = FALSE; -} - - -SM_STATE(BE_AUTH, IGNORE) -{ - SM_ENTRY_MA(BE_AUTH, IGNORE, be_auth); - - sm->eap_if->eapNoReq = FALSE; -} - - -SM_STEP(BE_AUTH) -{ - if (sm->portControl != Auto || sm->initialize || sm->authAbort) { - SM_ENTER_GLOBAL(BE_AUTH, INITIALIZE); - return; - } - - switch (sm->be_auth_state) { - case BE_AUTH_INITIALIZE: - SM_ENTER(BE_AUTH, IDLE); - break; - case BE_AUTH_REQUEST: - if (sm->eapolEap) - SM_ENTER(BE_AUTH, RESPONSE); - else if (sm->eap_if->eapReq) - SM_ENTER(BE_AUTH, REQUEST); - else if (sm->eap_if->eapTimeout) - SM_ENTER(BE_AUTH, TIMEOUT); - break; - case BE_AUTH_RESPONSE: - if (sm->eap_if->eapNoReq) - SM_ENTER(BE_AUTH, IGNORE); - if (sm->eap_if->eapReq) { - sm->backendAccessChallenges++; - SM_ENTER(BE_AUTH, REQUEST); - } else if (sm->aWhile == 0) - SM_ENTER(BE_AUTH, TIMEOUT); - else if (sm->eap_if->eapFail) { - sm->backendAuthFails++; - SM_ENTER(BE_AUTH, FAIL); - } else if (sm->eap_if->eapSuccess) { - sm->backendAuthSuccesses++; - SM_ENTER(BE_AUTH, SUCCESS); - } - break; - case BE_AUTH_SUCCESS: - SM_ENTER(BE_AUTH, IDLE); - break; - case BE_AUTH_FAIL: - SM_ENTER(BE_AUTH, IDLE); - break; - case BE_AUTH_TIMEOUT: - SM_ENTER(BE_AUTH, IDLE); - break; - case BE_AUTH_IDLE: - if (sm->eap_if->eapFail && sm->authStart) - SM_ENTER(BE_AUTH, FAIL); - else if (sm->eap_if->eapReq && sm->authStart) - SM_ENTER(BE_AUTH, REQUEST); - else if (sm->eap_if->eapSuccess && sm->authStart) - SM_ENTER(BE_AUTH, SUCCESS); - break; - case BE_AUTH_IGNORE: - if (sm->eapolEap) - SM_ENTER(BE_AUTH, RESPONSE); - else if (sm->eap_if->eapReq) - SM_ENTER(BE_AUTH, REQUEST); - else if (sm->eap_if->eapTimeout) - SM_ENTER(BE_AUTH, TIMEOUT); - break; - } -} - - - -/* Reauthentication Timer state machine */ - -SM_STATE(REAUTH_TIMER, INITIALIZE) -{ - SM_ENTRY_MA(REAUTH_TIMER, INITIALIZE, reauth_timer); - - sm->reAuthWhen = sm->reAuthPeriod; -} - - -SM_STATE(REAUTH_TIMER, REAUTHENTICATE) -{ - SM_ENTRY_MA(REAUTH_TIMER, REAUTHENTICATE, reauth_timer); - - sm->reAuthenticate = TRUE; - sm->eapol->cb.eapol_event(sm->eapol->conf.ctx, sm->sta, - EAPOL_AUTH_REAUTHENTICATE); -} - - -SM_STEP(REAUTH_TIMER) -{ - if (sm->portControl != Auto || sm->initialize || - sm->authPortStatus == Unauthorized || !sm->reAuthEnabled) { - SM_ENTER_GLOBAL(REAUTH_TIMER, INITIALIZE); - return; - } - - switch (sm->reauth_timer_state) { - case REAUTH_TIMER_INITIALIZE: - if (sm->reAuthWhen == 0) - SM_ENTER(REAUTH_TIMER, REAUTHENTICATE); - break; - case REAUTH_TIMER_REAUTHENTICATE: - SM_ENTER(REAUTH_TIMER, INITIALIZE); - break; - } -} - - - -/* Authenticator Key Transmit state machine */ - -SM_STATE(AUTH_KEY_TX, NO_KEY_TRANSMIT) -{ - SM_ENTRY_MA(AUTH_KEY_TX, NO_KEY_TRANSMIT, auth_key_tx); -} - - -SM_STATE(AUTH_KEY_TX, KEY_TRANSMIT) -{ - SM_ENTRY_MA(AUTH_KEY_TX, KEY_TRANSMIT, auth_key_tx); - - txKey(); - sm->eap_if->eapKeyAvailable = FALSE; - sm->keyDone = TRUE; -} - - -SM_STEP(AUTH_KEY_TX) -{ - if (sm->initialize || sm->portControl != Auto) { - SM_ENTER_GLOBAL(AUTH_KEY_TX, NO_KEY_TRANSMIT); - return; - } - - switch (sm->auth_key_tx_state) { - case AUTH_KEY_TX_NO_KEY_TRANSMIT: - if (sm->keyTxEnabled && sm->eap_if->eapKeyAvailable && - sm->keyRun && !(sm->flags & EAPOL_SM_USES_WPA)) - SM_ENTER(AUTH_KEY_TX, KEY_TRANSMIT); - break; - case AUTH_KEY_TX_KEY_TRANSMIT: - if (!sm->keyTxEnabled || !sm->keyRun) - SM_ENTER(AUTH_KEY_TX, NO_KEY_TRANSMIT); - else if (sm->eap_if->eapKeyAvailable) - SM_ENTER(AUTH_KEY_TX, KEY_TRANSMIT); - break; - } -} - - - -/* Key Receive state machine */ - -SM_STATE(KEY_RX, NO_KEY_RECEIVE) -{ - SM_ENTRY_MA(KEY_RX, NO_KEY_RECEIVE, key_rx); -} - - -SM_STATE(KEY_RX, KEY_RECEIVE) -{ - SM_ENTRY_MA(KEY_RX, KEY_RECEIVE, key_rx); - - processKey(); - sm->rxKey = FALSE; -} - - -SM_STEP(KEY_RX) -{ - if (sm->initialize || !sm->eap_if->portEnabled) { - SM_ENTER_GLOBAL(KEY_RX, NO_KEY_RECEIVE); - return; - } - - switch (sm->key_rx_state) { - case KEY_RX_NO_KEY_RECEIVE: - if (sm->rxKey) - SM_ENTER(KEY_RX, KEY_RECEIVE); - break; - case KEY_RX_KEY_RECEIVE: - if (sm->rxKey) - SM_ENTER(KEY_RX, KEY_RECEIVE); - break; - } -} - - - -/* Controlled Directions state machine */ - -SM_STATE(CTRL_DIR, FORCE_BOTH) -{ - SM_ENTRY_MA(CTRL_DIR, FORCE_BOTH, ctrl_dir); - sm->operControlledDirections = Both; -} - - -SM_STATE(CTRL_DIR, IN_OR_BOTH) -{ - SM_ENTRY_MA(CTRL_DIR, IN_OR_BOTH, ctrl_dir); - sm->operControlledDirections = sm->adminControlledDirections; -} - - -SM_STEP(CTRL_DIR) -{ - if (sm->initialize) { - SM_ENTER_GLOBAL(CTRL_DIR, IN_OR_BOTH); - return; - } - - switch (sm->ctrl_dir_state) { - case CTRL_DIR_FORCE_BOTH: - if (sm->eap_if->portEnabled && sm->operEdge) - SM_ENTER(CTRL_DIR, IN_OR_BOTH); - break; - case CTRL_DIR_IN_OR_BOTH: - if (sm->operControlledDirections != - sm->adminControlledDirections) - SM_ENTER(CTRL_DIR, IN_OR_BOTH); - if (!sm->eap_if->portEnabled || !sm->operEdge) - SM_ENTER(CTRL_DIR, FORCE_BOTH); - break; - } -} - - - -struct eapol_state_machine * -eapol_auth_alloc(struct eapol_authenticator *eapol, const u8 *addr, - int flags, const struct wpabuf *assoc_wps_ie, - const struct wpabuf *assoc_p2p_ie, void *sta_ctx) -{ - struct eapol_state_machine *sm; - struct eap_config eap_conf; - - if (eapol == NULL) - return NULL; - - sm = os_zalloc(sizeof(*sm)); - if (sm == NULL) { - wpa_printf(MSG_DEBUG, "IEEE 802.1X state machine allocation " - "failed"); - return NULL; - } - sm->radius_identifier = -1; - os_memcpy(sm->addr, addr, ETH_ALEN); - sm->flags = flags; - - sm->eapol = eapol; - sm->sta = sta_ctx; - - /* Set default values for state machine constants */ - sm->auth_pae_state = AUTH_PAE_INITIALIZE; - sm->quietPeriod = AUTH_PAE_DEFAULT_quietPeriod; - sm->reAuthMax = AUTH_PAE_DEFAULT_reAuthMax; - - sm->be_auth_state = BE_AUTH_INITIALIZE; - sm->serverTimeout = BE_AUTH_DEFAULT_serverTimeout; - - sm->reauth_timer_state = REAUTH_TIMER_INITIALIZE; - sm->reAuthPeriod = eapol->conf.eap_reauth_period; - sm->reAuthEnabled = eapol->conf.eap_reauth_period > 0 ? TRUE : FALSE; - - sm->auth_key_tx_state = AUTH_KEY_TX_NO_KEY_TRANSMIT; - - sm->key_rx_state = KEY_RX_NO_KEY_RECEIVE; - - sm->ctrl_dir_state = CTRL_DIR_IN_OR_BOTH; - - sm->portControl = Auto; - - if (!eapol->conf.wpa && - (eapol->default_wep_key || eapol->conf.individual_wep_key_len > 0)) - sm->keyTxEnabled = TRUE; - else - sm->keyTxEnabled = FALSE; - if (eapol->conf.wpa) - sm->portValid = FALSE; - else - sm->portValid = TRUE; - - os_memset(&eap_conf, 0, sizeof(eap_conf)); - eap_conf.eap_server = eapol->conf.eap_server; - eap_conf.ssl_ctx = eapol->conf.ssl_ctx; - eap_conf.msg_ctx = eapol->conf.msg_ctx; - eap_conf.eap_sim_db_priv = eapol->conf.eap_sim_db_priv; - eap_conf.pac_opaque_encr_key = eapol->conf.pac_opaque_encr_key; - eap_conf.eap_fast_a_id = eapol->conf.eap_fast_a_id; - eap_conf.eap_fast_a_id_len = eapol->conf.eap_fast_a_id_len; - eap_conf.eap_fast_a_id_info = eapol->conf.eap_fast_a_id_info; - eap_conf.eap_fast_prov = eapol->conf.eap_fast_prov; - eap_conf.pac_key_lifetime = eapol->conf.pac_key_lifetime; - eap_conf.pac_key_refresh_time = eapol->conf.pac_key_refresh_time; - eap_conf.eap_sim_aka_result_ind = eapol->conf.eap_sim_aka_result_ind; - eap_conf.tnc = eapol->conf.tnc; - eap_conf.wps = eapol->conf.wps; - eap_conf.assoc_wps_ie = assoc_wps_ie; - eap_conf.assoc_p2p_ie = assoc_p2p_ie; - eap_conf.peer_addr = addr; - eap_conf.fragment_size = eapol->conf.fragment_size; - eap_conf.pwd_group = eapol->conf.pwd_group; - sm->eap = eap_server_sm_init(sm, &eapol_cb, &eap_conf); - if (sm->eap == NULL) { - eapol_auth_free(sm); - return NULL; - } - sm->eap_if = eap_get_interface(sm->eap); - - eapol_auth_initialize(sm); - - return sm; -} - - -void eapol_auth_free(struct eapol_state_machine *sm) -{ - if (sm == NULL) - return; - - eloop_cancel_timeout(eapol_port_timers_tick, NULL, sm); - eloop_cancel_timeout(eapol_sm_step_cb, sm, NULL); - if (sm->eap) - eap_server_sm_deinit(sm->eap); - os_free(sm); -} - - -static int eapol_sm_sta_entry_alive(struct eapol_authenticator *eapol, - const u8 *addr) -{ - return eapol->cb.sta_entry_alive(eapol->conf.ctx, addr); -} - - -static void eapol_sm_step_run(struct eapol_state_machine *sm) -{ - struct eapol_authenticator *eapol = sm->eapol; - u8 addr[ETH_ALEN]; - unsigned int prev_auth_pae, prev_be_auth, prev_reauth_timer, - prev_auth_key_tx, prev_key_rx, prev_ctrl_dir; - int max_steps = 100; - - os_memcpy(addr, sm->addr, ETH_ALEN); - - /* - * Allow EAPOL state machines to run as long as there are state - * changes, but exit and return here through event loop if more than - * 100 steps is needed as a precaution against infinite loops inside - * eloop callback. - */ -restart: - prev_auth_pae = sm->auth_pae_state; - prev_be_auth = sm->be_auth_state; - prev_reauth_timer = sm->reauth_timer_state; - prev_auth_key_tx = sm->auth_key_tx_state; - prev_key_rx = sm->key_rx_state; - prev_ctrl_dir = sm->ctrl_dir_state; - - SM_STEP_RUN(AUTH_PAE); - if (sm->initializing || eapol_sm_sta_entry_alive(eapol, addr)) - SM_STEP_RUN(BE_AUTH); - if (sm->initializing || eapol_sm_sta_entry_alive(eapol, addr)) - SM_STEP_RUN(REAUTH_TIMER); - if (sm->initializing || eapol_sm_sta_entry_alive(eapol, addr)) - SM_STEP_RUN(AUTH_KEY_TX); - if (sm->initializing || eapol_sm_sta_entry_alive(eapol, addr)) - SM_STEP_RUN(KEY_RX); - if (sm->initializing || eapol_sm_sta_entry_alive(eapol, addr)) - SM_STEP_RUN(CTRL_DIR); - - if (prev_auth_pae != sm->auth_pae_state || - prev_be_auth != sm->be_auth_state || - prev_reauth_timer != sm->reauth_timer_state || - prev_auth_key_tx != sm->auth_key_tx_state || - prev_key_rx != sm->key_rx_state || - prev_ctrl_dir != sm->ctrl_dir_state) { - if (--max_steps > 0) - goto restart; - /* Re-run from eloop timeout */ - eapol_auth_step(sm); - return; - } - - if (eapol_sm_sta_entry_alive(eapol, addr) && sm->eap) { - if (eap_server_sm_step(sm->eap)) { - if (--max_steps > 0) - goto restart; - /* Re-run from eloop timeout */ - eapol_auth_step(sm); - return; - } - - /* TODO: find a better location for this */ - if (sm->eap_if->aaaEapResp) { - sm->eap_if->aaaEapResp = FALSE; - if (sm->eap_if->aaaEapRespData == NULL) { - wpa_printf(MSG_DEBUG, "EAPOL: aaaEapResp set, " - "but no aaaEapRespData available"); - return; - } - sm->eapol->cb.aaa_send( - sm->eapol->conf.ctx, sm->sta, - wpabuf_head(sm->eap_if->aaaEapRespData), - wpabuf_len(sm->eap_if->aaaEapRespData)); - } - } - - if (eapol_sm_sta_entry_alive(eapol, addr)) - sm->eapol->cb.eapol_event(sm->eapol->conf.ctx, sm->sta, - EAPOL_AUTH_SM_CHANGE); -} - - -static void eapol_sm_step_cb(void *eloop_ctx, void *timeout_ctx) -{ - struct eapol_state_machine *sm = eloop_ctx; - eapol_sm_step_run(sm); -} - - -/** - * eapol_auth_step - Advance EAPOL state machines - * @sm: EAPOL state machine - * - * This function is called to advance EAPOL state machines after any change - * that could affect their state. - */ -void eapol_auth_step(struct eapol_state_machine *sm) -{ - /* - * Run eapol_sm_step_run from a registered timeout to make sure that - * other possible timeouts/events are processed and to avoid long - * function call chains. - */ - - eloop_register_timeout(0, 0, eapol_sm_step_cb, sm, NULL); -} - - -static void eapol_auth_initialize(struct eapol_state_machine *sm) -{ - sm->initializing = TRUE; - /* Initialize the state machines by asserting initialize and then - * deasserting it after one step */ - sm->initialize = TRUE; - eapol_sm_step_run(sm); - sm->initialize = FALSE; - eapol_sm_step_run(sm); - sm->initializing = FALSE; - - /* Start one second tick for port timers state machine */ - eloop_cancel_timeout(eapol_port_timers_tick, NULL, sm); - eloop_register_timeout(1, 0, eapol_port_timers_tick, NULL, sm); -} - - -static int eapol_sm_get_eap_user(void *ctx, const u8 *identity, - size_t identity_len, int phase2, - struct eap_user *user) -{ - struct eapol_state_machine *sm = ctx; - return sm->eapol->cb.get_eap_user(sm->eapol->conf.ctx, identity, - identity_len, phase2, user); -} - - -static const char * eapol_sm_get_eap_req_id_text(void *ctx, size_t *len) -{ - struct eapol_state_machine *sm = ctx; - *len = sm->eapol->conf.eap_req_id_text_len; - return sm->eapol->conf.eap_req_id_text; -} - - -static struct eapol_callbacks eapol_cb = -{ - eapol_sm_get_eap_user, - eapol_sm_get_eap_req_id_text -}; - - -int eapol_auth_eap_pending_cb(struct eapol_state_machine *sm, void *ctx) -{ - if (sm == NULL || ctx != sm->eap) - return -1; - - eap_sm_pending_cb(sm->eap); - eapol_auth_step(sm); - - return 0; -} - - -static int eapol_auth_conf_clone(struct eapol_auth_config *dst, - struct eapol_auth_config *src) -{ - dst->ctx = src->ctx; - dst->eap_reauth_period = src->eap_reauth_period; - dst->wpa = src->wpa; - dst->individual_wep_key_len = src->individual_wep_key_len; - dst->eap_server = src->eap_server; - dst->ssl_ctx = src->ssl_ctx; - dst->msg_ctx = src->msg_ctx; - dst->eap_sim_db_priv = src->eap_sim_db_priv; - os_free(dst->eap_req_id_text); - dst->pwd_group = src->pwd_group; - if (src->eap_req_id_text) { - dst->eap_req_id_text = os_malloc(src->eap_req_id_text_len); - if (dst->eap_req_id_text == NULL) - return -1; - os_memcpy(dst->eap_req_id_text, src->eap_req_id_text, - src->eap_req_id_text_len); - dst->eap_req_id_text_len = src->eap_req_id_text_len; - } else { - dst->eap_req_id_text = NULL; - dst->eap_req_id_text_len = 0; - } - if (src->pac_opaque_encr_key) { - dst->pac_opaque_encr_key = os_malloc(16); - os_memcpy(dst->pac_opaque_encr_key, src->pac_opaque_encr_key, - 16); - } else - dst->pac_opaque_encr_key = NULL; - if (src->eap_fast_a_id) { - dst->eap_fast_a_id = os_malloc(src->eap_fast_a_id_len); - if (dst->eap_fast_a_id == NULL) { - os_free(dst->eap_req_id_text); - return -1; - } - os_memcpy(dst->eap_fast_a_id, src->eap_fast_a_id, - src->eap_fast_a_id_len); - dst->eap_fast_a_id_len = src->eap_fast_a_id_len; - } else - dst->eap_fast_a_id = NULL; - if (src->eap_fast_a_id_info) { - dst->eap_fast_a_id_info = os_strdup(src->eap_fast_a_id_info); - if (dst->eap_fast_a_id_info == NULL) { - os_free(dst->eap_req_id_text); - os_free(dst->eap_fast_a_id); - return -1; - } - } else - dst->eap_fast_a_id_info = NULL; - dst->eap_fast_prov = src->eap_fast_prov; - dst->pac_key_lifetime = src->pac_key_lifetime; - dst->pac_key_refresh_time = src->pac_key_refresh_time; - dst->eap_sim_aka_result_ind = src->eap_sim_aka_result_ind; - dst->tnc = src->tnc; - dst->wps = src->wps; - dst->fragment_size = src->fragment_size; - return 0; -} - - -static void eapol_auth_conf_free(struct eapol_auth_config *conf) -{ - os_free(conf->eap_req_id_text); - conf->eap_req_id_text = NULL; - os_free(conf->pac_opaque_encr_key); - conf->pac_opaque_encr_key = NULL; - os_free(conf->eap_fast_a_id); - conf->eap_fast_a_id = NULL; - os_free(conf->eap_fast_a_id_info); - conf->eap_fast_a_id_info = NULL; -} - - -struct eapol_authenticator * eapol_auth_init(struct eapol_auth_config *conf, - struct eapol_auth_cb *cb) -{ - struct eapol_authenticator *eapol; - - eapol = os_zalloc(sizeof(*eapol)); - if (eapol == NULL) - return NULL; - - if (eapol_auth_conf_clone(&eapol->conf, conf) < 0) { - os_free(eapol); - return NULL; - } - - if (conf->individual_wep_key_len > 0) { - /* use key0 in individual key and key1 in broadcast key */ - eapol->default_wep_key_idx = 1; - } - - eapol->cb.eapol_send = cb->eapol_send; - eapol->cb.aaa_send = cb->aaa_send; - eapol->cb.finished = cb->finished; - eapol->cb.get_eap_user = cb->get_eap_user; - eapol->cb.sta_entry_alive = cb->sta_entry_alive; - eapol->cb.logger = cb->logger; - eapol->cb.set_port_authorized = cb->set_port_authorized; - eapol->cb.abort_auth = cb->abort_auth; - eapol->cb.tx_key = cb->tx_key; - eapol->cb.eapol_event = cb->eapol_event; - - return eapol; -} - - -void eapol_auth_deinit(struct eapol_authenticator *eapol) -{ - if (eapol == NULL) - return; - - eapol_auth_conf_free(&eapol->conf); - os_free(eapol->default_wep_key); - os_free(eapol); -} diff --git a/hostapd-0.8/src/eapol_auth/eapol_auth_sm.h b/hostapd-0.8/src/eapol_auth/eapol_auth_sm.h deleted file mode 100644 index 59a10b4..0000000 --- a/hostapd-0.8/src/eapol_auth/eapol_auth_sm.h +++ /dev/null @@ -1,92 +0,0 @@ -/* - * IEEE 802.1X-2004 Authenticator - EAPOL state machine - * Copyright (c) 2002-2009, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#ifndef EAPOL_AUTH_SM_H -#define EAPOL_AUTH_SM_H - -#define EAPOL_SM_PREAUTH BIT(0) -#define EAPOL_SM_WAIT_START BIT(1) -#define EAPOL_SM_USES_WPA BIT(2) -#define EAPOL_SM_FROM_PMKSA_CACHE BIT(3) - -struct eapol_auth_config { - int eap_reauth_period; - int wpa; - int individual_wep_key_len; - int eap_server; - void *ssl_ctx; - void *msg_ctx; - void *eap_sim_db_priv; - char *eap_req_id_text; /* a copy of this will be allocated */ - size_t eap_req_id_text_len; - u8 *pac_opaque_encr_key; - u8 *eap_fast_a_id; - size_t eap_fast_a_id_len; - char *eap_fast_a_id_info; - int eap_fast_prov; - int pac_key_lifetime; - int pac_key_refresh_time; - int eap_sim_aka_result_ind; - int tnc; - struct wps_context *wps; - int fragment_size; - u16 pwd_group; - - /* Opaque context pointer to owner data for callback functions */ - void *ctx; -}; - -struct eap_user; - -typedef enum { - EAPOL_LOGGER_DEBUG, EAPOL_LOGGER_INFO, EAPOL_LOGGER_WARNING -} eapol_logger_level; - -enum eapol_event { - EAPOL_AUTH_SM_CHANGE, - EAPOL_AUTH_REAUTHENTICATE -}; - -struct eapol_auth_cb { - void (*eapol_send)(void *ctx, void *sta_ctx, u8 type, const u8 *data, - size_t datalen); - void (*aaa_send)(void *ctx, void *sta_ctx, const u8 *data, - size_t datalen); - void (*finished)(void *ctx, void *sta_ctx, int success, int preauth); - int (*get_eap_user)(void *ctx, const u8 *identity, size_t identity_len, - int phase2, struct eap_user *user); - int (*sta_entry_alive)(void *ctx, const u8 *addr); - void (*logger)(void *ctx, const u8 *addr, eapol_logger_level level, - const char *txt); - void (*set_port_authorized)(void *ctx, void *sta_ctx, int authorized); - void (*abort_auth)(void *ctx, void *sta_ctx); - void (*tx_key)(void *ctx, void *sta_ctx); - void (*eapol_event)(void *ctx, void *sta_ctx, enum eapol_event type); -}; - - -struct eapol_authenticator * eapol_auth_init(struct eapol_auth_config *conf, - struct eapol_auth_cb *cb); -void eapol_auth_deinit(struct eapol_authenticator *eapol); -struct eapol_state_machine * -eapol_auth_alloc(struct eapol_authenticator *eapol, const u8 *addr, - int flags, const struct wpabuf *assoc_wps_ie, - const struct wpabuf *assoc_p2p_ie, void *sta_ctx); -void eapol_auth_free(struct eapol_state_machine *sm); -void eapol_auth_step(struct eapol_state_machine *sm); -void eapol_auth_dump_state(FILE *f, const char *prefix, - struct eapol_state_machine *sm); -int eapol_auth_eap_pending_cb(struct eapol_state_machine *sm, void *ctx); - -#endif /* EAPOL_AUTH_SM_H */ diff --git a/hostapd-0.8/src/eapol_auth/eapol_auth_sm_i.h b/hostapd-0.8/src/eapol_auth/eapol_auth_sm_i.h deleted file mode 100644 index 1000da4..0000000 --- a/hostapd-0.8/src/eapol_auth/eapol_auth_sm_i.h +++ /dev/null @@ -1,183 +0,0 @@ -/* - * IEEE 802.1X-2004 Authenticator - EAPOL state machine (internal definitions) - * Copyright (c) 2002-2009, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#ifndef EAPOL_AUTH_SM_I_H -#define EAPOL_AUTH_SM_I_H - -#include "common/defs.h" -#include "radius/radius.h" - -/* IEEE Std 802.1X-2004, Ch. 8.2 */ - -typedef enum { ForceUnauthorized = 1, ForceAuthorized = 3, Auto = 2 } - PortTypes; -typedef enum { Unauthorized = 2, Authorized = 1 } PortState; -typedef enum { Both = 0, In = 1 } ControlledDirection; -typedef unsigned int Counter; - - -/** - * struct eapol_authenticator - Global EAPOL authenticator data - */ -struct eapol_authenticator { - struct eapol_auth_config conf; - struct eapol_auth_cb cb; - - u8 *default_wep_key; - u8 default_wep_key_idx; -}; - - -/** - * struct eapol_state_machine - Per-Supplicant Authenticator state machines - */ -struct eapol_state_machine { - /* timers */ - int aWhile; - int quietWhile; - int reAuthWhen; - - /* global variables */ - Boolean authAbort; - Boolean authFail; - PortState authPortStatus; - Boolean authStart; - Boolean authTimeout; - Boolean authSuccess; - Boolean eapolEap; - Boolean initialize; - Boolean keyDone; - Boolean keyRun; - Boolean keyTxEnabled; - PortTypes portControl; - Boolean portValid; - Boolean reAuthenticate; - - /* Port Timers state machine */ - /* 'Boolean tick' implicitly handled as registered timeout */ - - /* Authenticator PAE state machine */ - enum { AUTH_PAE_INITIALIZE, AUTH_PAE_DISCONNECTED, AUTH_PAE_CONNECTING, - AUTH_PAE_AUTHENTICATING, AUTH_PAE_AUTHENTICATED, - AUTH_PAE_ABORTING, AUTH_PAE_HELD, AUTH_PAE_FORCE_AUTH, - AUTH_PAE_FORCE_UNAUTH, AUTH_PAE_RESTART } auth_pae_state; - /* variables */ - Boolean eapolLogoff; - Boolean eapolStart; - PortTypes portMode; - unsigned int reAuthCount; - /* constants */ - unsigned int quietPeriod; /* default 60; 0..65535 */ -#define AUTH_PAE_DEFAULT_quietPeriod 60 - unsigned int reAuthMax; /* default 2 */ -#define AUTH_PAE_DEFAULT_reAuthMax 2 - /* counters */ - Counter authEntersConnecting; - Counter authEapLogoffsWhileConnecting; - Counter authEntersAuthenticating; - Counter authAuthSuccessesWhileAuthenticating; - Counter authAuthTimeoutsWhileAuthenticating; - Counter authAuthFailWhileAuthenticating; - Counter authAuthEapStartsWhileAuthenticating; - Counter authAuthEapLogoffWhileAuthenticating; - Counter authAuthReauthsWhileAuthenticated; - Counter authAuthEapStartsWhileAuthenticated; - Counter authAuthEapLogoffWhileAuthenticated; - - /* Backend Authentication state machine */ - enum { BE_AUTH_REQUEST, BE_AUTH_RESPONSE, BE_AUTH_SUCCESS, - BE_AUTH_FAIL, BE_AUTH_TIMEOUT, BE_AUTH_IDLE, BE_AUTH_INITIALIZE, - BE_AUTH_IGNORE - } be_auth_state; - /* constants */ - unsigned int serverTimeout; /* default 30; 1..X */ -#define BE_AUTH_DEFAULT_serverTimeout 30 - /* counters */ - Counter backendResponses; - Counter backendAccessChallenges; - Counter backendOtherRequestsToSupplicant; - Counter backendAuthSuccesses; - Counter backendAuthFails; - - /* Reauthentication Timer state machine */ - enum { REAUTH_TIMER_INITIALIZE, REAUTH_TIMER_REAUTHENTICATE - } reauth_timer_state; - /* constants */ - unsigned int reAuthPeriod; /* default 3600 s */ - Boolean reAuthEnabled; - - /* Authenticator Key Transmit state machine */ - enum { AUTH_KEY_TX_NO_KEY_TRANSMIT, AUTH_KEY_TX_KEY_TRANSMIT - } auth_key_tx_state; - - /* Key Receive state machine */ - enum { KEY_RX_NO_KEY_RECEIVE, KEY_RX_KEY_RECEIVE } key_rx_state; - /* variables */ - Boolean rxKey; - - /* Controlled Directions state machine */ - enum { CTRL_DIR_FORCE_BOTH, CTRL_DIR_IN_OR_BOTH } ctrl_dir_state; - /* variables */ - ControlledDirection adminControlledDirections; - ControlledDirection operControlledDirections; - Boolean operEdge; - - /* Authenticator Statistics Table */ - Counter dot1xAuthEapolFramesRx; - Counter dot1xAuthEapolFramesTx; - Counter dot1xAuthEapolStartFramesRx; - Counter dot1xAuthEapolLogoffFramesRx; - Counter dot1xAuthEapolRespIdFramesRx; - Counter dot1xAuthEapolRespFramesRx; - Counter dot1xAuthEapolReqIdFramesTx; - Counter dot1xAuthEapolReqFramesTx; - Counter dot1xAuthInvalidEapolFramesRx; - Counter dot1xAuthEapLengthErrorFramesRx; - Counter dot1xAuthLastEapolFrameVersion; - - /* Other variables - not defined in IEEE 802.1X */ - u8 addr[ETH_ALEN]; /* Supplicant address */ - int flags; /* EAPOL_SM_* */ - - /* EAPOL/AAA <-> EAP full authenticator interface */ - struct eap_eapol_interface *eap_if; - - int radius_identifier; - /* TODO: check when the last messages can be released */ - struct radius_msg *last_recv_radius; - u8 last_eap_id; /* last used EAP Identifier */ - u8 *identity; - size_t identity_len; - u8 eap_type_authsrv; /* EAP type of the last EAP packet from - * Authentication server */ - u8 eap_type_supp; /* EAP type of the last EAP packet from Supplicant */ - struct radius_class_data radius_class; - - /* Keys for encrypting and signing EAPOL-Key frames */ - u8 *eapol_key_sign; - size_t eapol_key_sign_len; - u8 *eapol_key_crypt; - size_t eapol_key_crypt_len; - - struct eap_sm *eap; - - Boolean initializing; /* in process of initializing state machines */ - Boolean changed; - - struct eapol_authenticator *eapol; - - void *sta; /* station context pointer to use in callbacks */ -}; - -#endif /* EAPOL_AUTH_SM_I_H */ diff --git a/hostapd-0.8/src/eapol_supp/Makefile b/hostapd-0.8/src/eapol_supp/Makefile deleted file mode 100644 index 9c41962..0000000 --- a/hostapd-0.8/src/eapol_supp/Makefile +++ /dev/null @@ -1,8 +0,0 @@ -all: - @echo Nothing to be made. - -clean: - rm -f *~ *.o *.d - -install: - @echo Nothing to be made. diff --git a/hostapd-0.8/src/eapol_supp/eapol_supp_sm.c b/hostapd-0.8/src/eapol_supp/eapol_supp_sm.c deleted file mode 100644 index 18abb4e..0000000 --- a/hostapd-0.8/src/eapol_supp/eapol_supp_sm.c +++ /dev/null @@ -1,1913 +0,0 @@ -/* - * EAPOL supplicant state machines - * Copyright (c) 2004-2008, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#include "includes.h" - -#include "common.h" -#include "state_machine.h" -#include "wpabuf.h" -#include "eloop.h" -#include "crypto/crypto.h" -#include "crypto/md5.h" -#include "common/eapol_common.h" -#include "eap_peer/eap.h" -#include "eapol_supp_sm.h" - -#define STATE_MACHINE_DATA struct eapol_sm -#define STATE_MACHINE_DEBUG_PREFIX "EAPOL" - - -/* IEEE 802.1X-2004 - Supplicant - EAPOL state machines */ - -/** - * struct eapol_sm - Internal data for EAPOL state machines - */ -struct eapol_sm { - /* Timers */ - unsigned int authWhile; - unsigned int heldWhile; - unsigned int startWhen; - unsigned int idleWhile; /* for EAP state machine */ - int timer_tick_enabled; - - /* Global variables */ - Boolean eapFail; - Boolean eapolEap; - Boolean eapSuccess; - Boolean initialize; - Boolean keyDone; - Boolean keyRun; - PortControl portControl; - Boolean portEnabled; - PortStatus suppPortStatus; /* dot1xSuppControlledPortStatus */ - Boolean portValid; - Boolean suppAbort; - Boolean suppFail; - Boolean suppStart; - Boolean suppSuccess; - Boolean suppTimeout; - - /* Supplicant PAE state machine */ - enum { - SUPP_PAE_UNKNOWN = 0, - SUPP_PAE_DISCONNECTED = 1, - SUPP_PAE_LOGOFF = 2, - SUPP_PAE_CONNECTING = 3, - SUPP_PAE_AUTHENTICATING = 4, - SUPP_PAE_AUTHENTICATED = 5, - /* unused(6) */ - SUPP_PAE_HELD = 7, - SUPP_PAE_RESTART = 8, - SUPP_PAE_S_FORCE_AUTH = 9, - SUPP_PAE_S_FORCE_UNAUTH = 10 - } SUPP_PAE_state; /* dot1xSuppPaeState */ - /* Variables */ - Boolean userLogoff; - Boolean logoffSent; - unsigned int startCount; - Boolean eapRestart; - PortControl sPortMode; - /* Constants */ - unsigned int heldPeriod; /* dot1xSuppHeldPeriod */ - unsigned int startPeriod; /* dot1xSuppStartPeriod */ - unsigned int maxStart; /* dot1xSuppMaxStart */ - - /* Key Receive state machine */ - enum { - KEY_RX_UNKNOWN = 0, - KEY_RX_NO_KEY_RECEIVE, KEY_RX_KEY_RECEIVE - } KEY_RX_state; - /* Variables */ - Boolean rxKey; - - /* Supplicant Backend state machine */ - enum { - SUPP_BE_UNKNOWN = 0, - SUPP_BE_INITIALIZE = 1, - SUPP_BE_IDLE = 2, - SUPP_BE_REQUEST = 3, - SUPP_BE_RECEIVE = 4, - SUPP_BE_RESPONSE = 5, - SUPP_BE_FAIL = 6, - SUPP_BE_TIMEOUT = 7, - SUPP_BE_SUCCESS = 8 - } SUPP_BE_state; /* dot1xSuppBackendPaeState */ - /* Variables */ - Boolean eapNoResp; - Boolean eapReq; - Boolean eapResp; - /* Constants */ - unsigned int authPeriod; /* dot1xSuppAuthPeriod */ - - /* Statistics */ - unsigned int dot1xSuppEapolFramesRx; - unsigned int dot1xSuppEapolFramesTx; - unsigned int dot1xSuppEapolStartFramesTx; - unsigned int dot1xSuppEapolLogoffFramesTx; - unsigned int dot1xSuppEapolRespFramesTx; - unsigned int dot1xSuppEapolReqIdFramesRx; - unsigned int dot1xSuppEapolReqFramesRx; - unsigned int dot1xSuppInvalidEapolFramesRx; - unsigned int dot1xSuppEapLengthErrorFramesRx; - unsigned int dot1xSuppLastEapolFrameVersion; - unsigned char dot1xSuppLastEapolFrameSource[6]; - - /* Miscellaneous variables (not defined in IEEE 802.1X-2004) */ - Boolean changed; - struct eap_sm *eap; - struct eap_peer_config *config; - Boolean initial_req; - u8 *last_rx_key; - size_t last_rx_key_len; - struct wpabuf *eapReqData; /* for EAP */ - Boolean altAccept; /* for EAP */ - Boolean altReject; /* for EAP */ - Boolean replay_counter_valid; - u8 last_replay_counter[16]; - struct eapol_config conf; - struct eapol_ctx *ctx; - enum { EAPOL_CB_IN_PROGRESS = 0, EAPOL_CB_SUCCESS, EAPOL_CB_FAILURE } - cb_status; - Boolean cached_pmk; - - Boolean unicast_key_received, broadcast_key_received; -}; - - -#define IEEE8021X_REPLAY_COUNTER_LEN 8 -#define IEEE8021X_KEY_SIGN_LEN 16 -#define IEEE8021X_KEY_IV_LEN 16 - -#define IEEE8021X_KEY_INDEX_FLAG 0x80 -#define IEEE8021X_KEY_INDEX_MASK 0x03 - -#ifdef _MSC_VER -#pragma pack(push, 1) -#endif /* _MSC_VER */ - -struct ieee802_1x_eapol_key { - u8 type; - /* Note: key_length is unaligned */ - u8 key_length[2]; - /* does not repeat within the life of the keying material used to - * encrypt the Key field; 64-bit NTP timestamp MAY be used here */ - u8 replay_counter[IEEE8021X_REPLAY_COUNTER_LEN]; - u8 key_iv[IEEE8021X_KEY_IV_LEN]; /* cryptographically random number */ - u8 key_index; /* key flag in the most significant bit: - * 0 = broadcast (default key), - * 1 = unicast (key mapping key); key index is in the - * 7 least significant bits */ - /* HMAC-MD5 message integrity check computed with MS-MPPE-Send-Key as - * the key */ - u8 key_signature[IEEE8021X_KEY_SIGN_LEN]; - - /* followed by key: if packet body length = 44 + key length, then the - * key field (of key_length bytes) contains the key in encrypted form; - * if packet body length = 44, key field is absent and key_length - * represents the number of least significant octets from - * MS-MPPE-Send-Key attribute to be used as the keying material; - * RC4 key used in encryption = Key-IV + MS-MPPE-Recv-Key */ -} STRUCT_PACKED; - -#ifdef _MSC_VER -#pragma pack(pop) -#endif /* _MSC_VER */ - - -static void eapol_sm_txLogoff(struct eapol_sm *sm); -static void eapol_sm_txStart(struct eapol_sm *sm); -static void eapol_sm_processKey(struct eapol_sm *sm); -static void eapol_sm_getSuppRsp(struct eapol_sm *sm); -static void eapol_sm_txSuppRsp(struct eapol_sm *sm); -static void eapol_sm_abortSupp(struct eapol_sm *sm); -static void eapol_sm_abort_cached(struct eapol_sm *sm); -static void eapol_sm_step_timeout(void *eloop_ctx, void *timeout_ctx); -static void eapol_sm_set_port_authorized(struct eapol_sm *sm); -static void eapol_sm_set_port_unauthorized(struct eapol_sm *sm); - - -/* Port Timers state machine - implemented as a function that will be called - * once a second as a registered event loop timeout */ -static void eapol_port_timers_tick(void *eloop_ctx, void *timeout_ctx) -{ - struct eapol_sm *sm = timeout_ctx; - - if (sm->authWhile > 0) { - sm->authWhile--; - if (sm->authWhile == 0) - wpa_printf(MSG_DEBUG, "EAPOL: authWhile --> 0"); - } - if (sm->heldWhile > 0) { - sm->heldWhile--; - if (sm->heldWhile == 0) - wpa_printf(MSG_DEBUG, "EAPOL: heldWhile --> 0"); - } - if (sm->startWhen > 0) { - sm->startWhen--; - if (sm->startWhen == 0) - wpa_printf(MSG_DEBUG, "EAPOL: startWhen --> 0"); - } - if (sm->idleWhile > 0) { - sm->idleWhile--; - if (sm->idleWhile == 0) - wpa_printf(MSG_DEBUG, "EAPOL: idleWhile --> 0"); - } - - if (sm->authWhile | sm->heldWhile | sm->startWhen | sm->idleWhile) { - eloop_register_timeout(1, 0, eapol_port_timers_tick, eloop_ctx, - sm); - } else { - wpa_printf(MSG_DEBUG, "EAPOL: disable timer tick"); - sm->timer_tick_enabled = 0; - } - eapol_sm_step(sm); -} - - -static void eapol_enable_timer_tick(struct eapol_sm *sm) -{ - if (sm->timer_tick_enabled) - return; - wpa_printf(MSG_DEBUG, "EAPOL: enable timer tick"); - sm->timer_tick_enabled = 1; - eloop_cancel_timeout(eapol_port_timers_tick, NULL, sm); - eloop_register_timeout(1, 0, eapol_port_timers_tick, NULL, sm); -} - - -SM_STATE(SUPP_PAE, LOGOFF) -{ - SM_ENTRY(SUPP_PAE, LOGOFF); - eapol_sm_txLogoff(sm); - sm->logoffSent = TRUE; - sm->suppPortStatus = Unauthorized; - eapol_sm_set_port_unauthorized(sm); -} - - -SM_STATE(SUPP_PAE, DISCONNECTED) -{ - SM_ENTRY(SUPP_PAE, DISCONNECTED); - sm->sPortMode = Auto; - sm->startCount = 0; - sm->logoffSent = FALSE; - sm->suppPortStatus = Unauthorized; - eapol_sm_set_port_unauthorized(sm); - sm->suppAbort = TRUE; - - sm->unicast_key_received = FALSE; - sm->broadcast_key_received = FALSE; -} - - -SM_STATE(SUPP_PAE, CONNECTING) -{ - int send_start = sm->SUPP_PAE_state == SUPP_PAE_CONNECTING; - SM_ENTRY(SUPP_PAE, CONNECTING); - if (send_start) { - sm->startWhen = sm->startPeriod; - sm->startCount++; - } else { - /* - * Do not send EAPOL-Start immediately since in most cases, - * Authenticator is going to start authentication immediately - * after association and an extra EAPOL-Start is just going to - * delay authentication. Use a short timeout to send the first - * EAPOL-Start if Authenticator does not start authentication. - */ -#ifdef CONFIG_WPS - /* Reduce latency on starting WPS negotiation. */ - sm->startWhen = 1; -#else /* CONFIG_WPS */ - sm->startWhen = 3; -#endif /* CONFIG_WPS */ - } - eapol_enable_timer_tick(sm); - sm->eapolEap = FALSE; - if (send_start) - eapol_sm_txStart(sm); -} - - -SM_STATE(SUPP_PAE, AUTHENTICATING) -{ - SM_ENTRY(SUPP_PAE, AUTHENTICATING); - sm->startCount = 0; - sm->suppSuccess = FALSE; - sm->suppFail = FALSE; - sm->suppTimeout = FALSE; - sm->keyRun = FALSE; - sm->keyDone = FALSE; - sm->suppStart = TRUE; -} - - -SM_STATE(SUPP_PAE, HELD) -{ - SM_ENTRY(SUPP_PAE, HELD); - sm->heldWhile = sm->heldPeriod; - eapol_enable_timer_tick(sm); - sm->suppPortStatus = Unauthorized; - eapol_sm_set_port_unauthorized(sm); - sm->cb_status = EAPOL_CB_FAILURE; -} - - -SM_STATE(SUPP_PAE, AUTHENTICATED) -{ - SM_ENTRY(SUPP_PAE, AUTHENTICATED); - sm->suppPortStatus = Authorized; - eapol_sm_set_port_authorized(sm); - sm->cb_status = EAPOL_CB_SUCCESS; -} - - -SM_STATE(SUPP_PAE, RESTART) -{ - SM_ENTRY(SUPP_PAE, RESTART); - sm->eapRestart = TRUE; -} - - -SM_STATE(SUPP_PAE, S_FORCE_AUTH) -{ - SM_ENTRY(SUPP_PAE, S_FORCE_AUTH); - sm->suppPortStatus = Authorized; - eapol_sm_set_port_authorized(sm); - sm->sPortMode = ForceAuthorized; -} - - -SM_STATE(SUPP_PAE, S_FORCE_UNAUTH) -{ - SM_ENTRY(SUPP_PAE, S_FORCE_UNAUTH); - sm->suppPortStatus = Unauthorized; - eapol_sm_set_port_unauthorized(sm); - sm->sPortMode = ForceUnauthorized; - eapol_sm_txLogoff(sm); -} - - -SM_STEP(SUPP_PAE) -{ - if ((sm->userLogoff && !sm->logoffSent) && - !(sm->initialize || !sm->portEnabled)) - SM_ENTER_GLOBAL(SUPP_PAE, LOGOFF); - else if (((sm->portControl == Auto) && - (sm->sPortMode != sm->portControl)) || - sm->initialize || !sm->portEnabled) - SM_ENTER_GLOBAL(SUPP_PAE, DISCONNECTED); - else if ((sm->portControl == ForceAuthorized) && - (sm->sPortMode != sm->portControl) && - !(sm->initialize || !sm->portEnabled)) - SM_ENTER_GLOBAL(SUPP_PAE, S_FORCE_AUTH); - else if ((sm->portControl == ForceUnauthorized) && - (sm->sPortMode != sm->portControl) && - !(sm->initialize || !sm->portEnabled)) - SM_ENTER_GLOBAL(SUPP_PAE, S_FORCE_UNAUTH); - else switch (sm->SUPP_PAE_state) { - case SUPP_PAE_UNKNOWN: - break; - case SUPP_PAE_LOGOFF: - if (!sm->userLogoff) - SM_ENTER(SUPP_PAE, DISCONNECTED); - break; - case SUPP_PAE_DISCONNECTED: - SM_ENTER(SUPP_PAE, CONNECTING); - break; - case SUPP_PAE_CONNECTING: - if (sm->startWhen == 0 && sm->startCount < sm->maxStart) - SM_ENTER(SUPP_PAE, CONNECTING); - else if (sm->startWhen == 0 && - sm->startCount >= sm->maxStart && - sm->portValid) - SM_ENTER(SUPP_PAE, AUTHENTICATED); - else if (sm->eapSuccess || sm->eapFail) - SM_ENTER(SUPP_PAE, AUTHENTICATING); - else if (sm->eapolEap) - SM_ENTER(SUPP_PAE, RESTART); - else if (sm->startWhen == 0 && - sm->startCount >= sm->maxStart && - !sm->portValid) - SM_ENTER(SUPP_PAE, HELD); - break; - case SUPP_PAE_AUTHENTICATING: - if (sm->eapSuccess && !sm->portValid && - sm->conf.accept_802_1x_keys && - sm->conf.required_keys == 0) { - wpa_printf(MSG_DEBUG, "EAPOL: IEEE 802.1X for " - "plaintext connection; no EAPOL-Key frames " - "required"); - sm->portValid = TRUE; - if (sm->ctx->eapol_done_cb) - sm->ctx->eapol_done_cb(sm->ctx->ctx); - } - if (sm->eapSuccess && sm->portValid) - SM_ENTER(SUPP_PAE, AUTHENTICATED); - else if (sm->eapFail || (sm->keyDone && !sm->portValid)) - SM_ENTER(SUPP_PAE, HELD); - else if (sm->suppTimeout) - SM_ENTER(SUPP_PAE, CONNECTING); - break; - case SUPP_PAE_HELD: - if (sm->heldWhile == 0) - SM_ENTER(SUPP_PAE, CONNECTING); - else if (sm->eapolEap) - SM_ENTER(SUPP_PAE, RESTART); - break; - case SUPP_PAE_AUTHENTICATED: - if (sm->eapolEap && sm->portValid) - SM_ENTER(SUPP_PAE, RESTART); - else if (!sm->portValid) - SM_ENTER(SUPP_PAE, DISCONNECTED); - break; - case SUPP_PAE_RESTART: - if (!sm->eapRestart) - SM_ENTER(SUPP_PAE, AUTHENTICATING); - break; - case SUPP_PAE_S_FORCE_AUTH: - break; - case SUPP_PAE_S_FORCE_UNAUTH: - break; - } -} - - -SM_STATE(KEY_RX, NO_KEY_RECEIVE) -{ - SM_ENTRY(KEY_RX, NO_KEY_RECEIVE); -} - - -SM_STATE(KEY_RX, KEY_RECEIVE) -{ - SM_ENTRY(KEY_RX, KEY_RECEIVE); - eapol_sm_processKey(sm); - sm->rxKey = FALSE; -} - - -SM_STEP(KEY_RX) -{ - if (sm->initialize || !sm->portEnabled) - SM_ENTER_GLOBAL(KEY_RX, NO_KEY_RECEIVE); - switch (sm->KEY_RX_state) { - case KEY_RX_UNKNOWN: - break; - case KEY_RX_NO_KEY_RECEIVE: - if (sm->rxKey) - SM_ENTER(KEY_RX, KEY_RECEIVE); - break; - case KEY_RX_KEY_RECEIVE: - if (sm->rxKey) - SM_ENTER(KEY_RX, KEY_RECEIVE); - break; - } -} - - -SM_STATE(SUPP_BE, REQUEST) -{ - SM_ENTRY(SUPP_BE, REQUEST); - sm->authWhile = 0; - sm->eapReq = TRUE; - eapol_sm_getSuppRsp(sm); -} - - -SM_STATE(SUPP_BE, RESPONSE) -{ - SM_ENTRY(SUPP_BE, RESPONSE); - eapol_sm_txSuppRsp(sm); - sm->eapResp = FALSE; -} - - -SM_STATE(SUPP_BE, SUCCESS) -{ - SM_ENTRY(SUPP_BE, SUCCESS); - sm->keyRun = TRUE; - sm->suppSuccess = TRUE; - - if (eap_key_available(sm->eap)) { - /* New key received - clear IEEE 802.1X EAPOL-Key replay - * counter */ - sm->replay_counter_valid = FALSE; - } -} - - -SM_STATE(SUPP_BE, FAIL) -{ - SM_ENTRY(SUPP_BE, FAIL); - sm->suppFail = TRUE; -} - - -SM_STATE(SUPP_BE, TIMEOUT) -{ - SM_ENTRY(SUPP_BE, TIMEOUT); - sm->suppTimeout = TRUE; -} - - -SM_STATE(SUPP_BE, IDLE) -{ - SM_ENTRY(SUPP_BE, IDLE); - sm->suppStart = FALSE; - sm->initial_req = TRUE; -} - - -SM_STATE(SUPP_BE, INITIALIZE) -{ - SM_ENTRY(SUPP_BE, INITIALIZE); - eapol_sm_abortSupp(sm); - sm->suppAbort = FALSE; -} - - -SM_STATE(SUPP_BE, RECEIVE) -{ - SM_ENTRY(SUPP_BE, RECEIVE); - sm->authWhile = sm->authPeriod; - eapol_enable_timer_tick(sm); - sm->eapolEap = FALSE; - sm->eapNoResp = FALSE; - sm->initial_req = FALSE; -} - - -SM_STEP(SUPP_BE) -{ - if (sm->initialize || sm->suppAbort) - SM_ENTER_GLOBAL(SUPP_BE, INITIALIZE); - else switch (sm->SUPP_BE_state) { - case SUPP_BE_UNKNOWN: - break; - case SUPP_BE_REQUEST: - /* - * IEEE Std 802.1X-2004 has transitions from REQUEST to FAIL - * and SUCCESS based on eapFail and eapSuccess, respectively. - * However, IEEE Std 802.1X-2004 is also specifying that - * eapNoResp should be set in conjuction with eapSuccess and - * eapFail which would mean that more than one of the - * transitions here would be activated at the same time. - * Skipping RESPONSE and/or RECEIVE states in these cases can - * cause problems and the direct transitions to do not seem - * correct. Because of this, the conditions for these - * transitions are verified only after eapNoResp. They are - * unlikely to be used since eapNoResp should always be set if - * either of eapSuccess or eapFail is set. - */ - if (sm->eapResp && sm->eapNoResp) { - wpa_printf(MSG_DEBUG, "EAPOL: SUPP_BE REQUEST: both " - "eapResp and eapNoResp set?!"); - } - if (sm->eapResp) - SM_ENTER(SUPP_BE, RESPONSE); - else if (sm->eapNoResp) - SM_ENTER(SUPP_BE, RECEIVE); - else if (sm->eapFail) - SM_ENTER(SUPP_BE, FAIL); - else if (sm->eapSuccess) - SM_ENTER(SUPP_BE, SUCCESS); - break; - case SUPP_BE_RESPONSE: - SM_ENTER(SUPP_BE, RECEIVE); - break; - case SUPP_BE_SUCCESS: - SM_ENTER(SUPP_BE, IDLE); - break; - case SUPP_BE_FAIL: - SM_ENTER(SUPP_BE, IDLE); - break; - case SUPP_BE_TIMEOUT: - SM_ENTER(SUPP_BE, IDLE); - break; - case SUPP_BE_IDLE: - if (sm->eapFail && sm->suppStart) - SM_ENTER(SUPP_BE, FAIL); - else if (sm->eapolEap && sm->suppStart) - SM_ENTER(SUPP_BE, REQUEST); - else if (sm->eapSuccess && sm->suppStart) - SM_ENTER(SUPP_BE, SUCCESS); - break; - case SUPP_BE_INITIALIZE: - SM_ENTER(SUPP_BE, IDLE); - break; - case SUPP_BE_RECEIVE: - if (sm->eapolEap) - SM_ENTER(SUPP_BE, REQUEST); - else if (sm->eapFail) - SM_ENTER(SUPP_BE, FAIL); - else if (sm->authWhile == 0) - SM_ENTER(SUPP_BE, TIMEOUT); - else if (sm->eapSuccess) - SM_ENTER(SUPP_BE, SUCCESS); - break; - } -} - - -static void eapol_sm_txLogoff(struct eapol_sm *sm) -{ - wpa_printf(MSG_DEBUG, "EAPOL: txLogoff"); - sm->ctx->eapol_send(sm->ctx->eapol_send_ctx, - IEEE802_1X_TYPE_EAPOL_LOGOFF, (u8 *) "", 0); - sm->dot1xSuppEapolLogoffFramesTx++; - sm->dot1xSuppEapolFramesTx++; -} - - -static void eapol_sm_txStart(struct eapol_sm *sm) -{ - wpa_printf(MSG_DEBUG, "EAPOL: txStart"); - sm->ctx->eapol_send(sm->ctx->eapol_send_ctx, - IEEE802_1X_TYPE_EAPOL_START, (u8 *) "", 0); - sm->dot1xSuppEapolStartFramesTx++; - sm->dot1xSuppEapolFramesTx++; -} - - -#define IEEE8021X_ENCR_KEY_LEN 32 -#define IEEE8021X_SIGN_KEY_LEN 32 - -struct eap_key_data { - u8 encr_key[IEEE8021X_ENCR_KEY_LEN]; - u8 sign_key[IEEE8021X_SIGN_KEY_LEN]; -}; - - -static void eapol_sm_processKey(struct eapol_sm *sm) -{ - struct ieee802_1x_hdr *hdr; - struct ieee802_1x_eapol_key *key; - struct eap_key_data keydata; - u8 orig_key_sign[IEEE8021X_KEY_SIGN_LEN], datakey[32]; - u8 ekey[IEEE8021X_KEY_IV_LEN + IEEE8021X_ENCR_KEY_LEN]; - int key_len, res, sign_key_len, encr_key_len; - u16 rx_key_length; - - wpa_printf(MSG_DEBUG, "EAPOL: processKey"); - if (sm->last_rx_key == NULL) - return; - - if (!sm->conf.accept_802_1x_keys) { - wpa_printf(MSG_WARNING, "EAPOL: Received IEEE 802.1X EAPOL-Key" - " even though this was not accepted - " - "ignoring this packet"); - return; - } - - hdr = (struct ieee802_1x_hdr *) sm->last_rx_key; - key = (struct ieee802_1x_eapol_key *) (hdr + 1); - if (sizeof(*hdr) + be_to_host16(hdr->length) > sm->last_rx_key_len) { - wpa_printf(MSG_WARNING, "EAPOL: Too short EAPOL-Key frame"); - return; - } - rx_key_length = WPA_GET_BE16(key->key_length); - wpa_printf(MSG_DEBUG, "EAPOL: RX IEEE 802.1X ver=%d type=%d len=%d " - "EAPOL-Key: type=%d key_length=%d key_index=0x%x", - hdr->version, hdr->type, be_to_host16(hdr->length), - key->type, rx_key_length, key->key_index); - - eapol_sm_notify_lower_layer_success(sm, 1); - sign_key_len = IEEE8021X_SIGN_KEY_LEN; - encr_key_len = IEEE8021X_ENCR_KEY_LEN; - res = eapol_sm_get_key(sm, (u8 *) &keydata, sizeof(keydata)); - if (res < 0) { - wpa_printf(MSG_DEBUG, "EAPOL: Could not get master key for " - "decrypting EAPOL-Key keys"); - return; - } - if (res == 16) { - /* LEAP derives only 16 bytes of keying material. */ - res = eapol_sm_get_key(sm, (u8 *) &keydata, 16); - if (res) { - wpa_printf(MSG_DEBUG, "EAPOL: Could not get LEAP " - "master key for decrypting EAPOL-Key keys"); - return; - } - sign_key_len = 16; - encr_key_len = 16; - os_memcpy(keydata.sign_key, keydata.encr_key, 16); - } else if (res) { - wpa_printf(MSG_DEBUG, "EAPOL: Could not get enough master key " - "data for decrypting EAPOL-Key keys (res=%d)", res); - return; - } - - /* The key replay_counter must increase when same master key */ - if (sm->replay_counter_valid && - os_memcmp(sm->last_replay_counter, key->replay_counter, - IEEE8021X_REPLAY_COUNTER_LEN) >= 0) { - wpa_printf(MSG_WARNING, "EAPOL: EAPOL-Key replay counter did " - "not increase - ignoring key"); - wpa_hexdump(MSG_DEBUG, "EAPOL: last replay counter", - sm->last_replay_counter, - IEEE8021X_REPLAY_COUNTER_LEN); - wpa_hexdump(MSG_DEBUG, "EAPOL: received replay counter", - key->replay_counter, IEEE8021X_REPLAY_COUNTER_LEN); - return; - } - - /* Verify key signature (HMAC-MD5) */ - os_memcpy(orig_key_sign, key->key_signature, IEEE8021X_KEY_SIGN_LEN); - os_memset(key->key_signature, 0, IEEE8021X_KEY_SIGN_LEN); - hmac_md5(keydata.sign_key, sign_key_len, - sm->last_rx_key, sizeof(*hdr) + be_to_host16(hdr->length), - key->key_signature); - if (os_memcmp(orig_key_sign, key->key_signature, - IEEE8021X_KEY_SIGN_LEN) != 0) { - wpa_printf(MSG_DEBUG, "EAPOL: Invalid key signature in " - "EAPOL-Key packet"); - os_memcpy(key->key_signature, orig_key_sign, - IEEE8021X_KEY_SIGN_LEN); - return; - } - wpa_printf(MSG_DEBUG, "EAPOL: EAPOL-Key key signature verified"); - - key_len = be_to_host16(hdr->length) - sizeof(*key); - if (key_len > 32 || rx_key_length > 32) { - wpa_printf(MSG_WARNING, "EAPOL: Too long key data length %d", - key_len ? key_len : rx_key_length); - return; - } - if (key_len == rx_key_length) { - os_memcpy(ekey, key->key_iv, IEEE8021X_KEY_IV_LEN); - os_memcpy(ekey + IEEE8021X_KEY_IV_LEN, keydata.encr_key, - encr_key_len); - os_memcpy(datakey, key + 1, key_len); - rc4_skip(ekey, IEEE8021X_KEY_IV_LEN + encr_key_len, 0, - datakey, key_len); - wpa_hexdump_key(MSG_DEBUG, "EAPOL: Decrypted(RC4) key", - datakey, key_len); - } else if (key_len == 0) { - /* - * IEEE 802.1X-2004 specifies that least significant Key Length - * octets from MS-MPPE-Send-Key are used as the key if the key - * data is not present. This seems to be meaning the beginning - * of the MS-MPPE-Send-Key. In addition, MS-MPPE-Send-Key in - * Supplicant corresponds to MS-MPPE-Recv-Key in Authenticator. - * Anyway, taking the beginning of the keying material from EAP - * seems to interoperate with Authenticators. - */ - key_len = rx_key_length; - os_memcpy(datakey, keydata.encr_key, key_len); - wpa_hexdump_key(MSG_DEBUG, "EAPOL: using part of EAP keying " - "material data encryption key", - datakey, key_len); - } else { - wpa_printf(MSG_DEBUG, "EAPOL: Invalid key data length %d " - "(key_length=%d)", key_len, rx_key_length); - return; - } - - sm->replay_counter_valid = TRUE; - os_memcpy(sm->last_replay_counter, key->replay_counter, - IEEE8021X_REPLAY_COUNTER_LEN); - - wpa_printf(MSG_DEBUG, "EAPOL: Setting dynamic WEP key: %s keyidx %d " - "len %d", - key->key_index & IEEE8021X_KEY_INDEX_FLAG ? - "unicast" : "broadcast", - key->key_index & IEEE8021X_KEY_INDEX_MASK, key_len); - - if (sm->ctx->set_wep_key && - sm->ctx->set_wep_key(sm->ctx->ctx, - key->key_index & IEEE8021X_KEY_INDEX_FLAG, - key->key_index & IEEE8021X_KEY_INDEX_MASK, - datakey, key_len) < 0) { - wpa_printf(MSG_WARNING, "EAPOL: Failed to set WEP key to the " - " driver."); - } else { - if (key->key_index & IEEE8021X_KEY_INDEX_FLAG) - sm->unicast_key_received = TRUE; - else - sm->broadcast_key_received = TRUE; - - if ((sm->unicast_key_received || - !(sm->conf.required_keys & EAPOL_REQUIRE_KEY_UNICAST)) && - (sm->broadcast_key_received || - !(sm->conf.required_keys & EAPOL_REQUIRE_KEY_BROADCAST))) - { - wpa_printf(MSG_DEBUG, "EAPOL: all required EAPOL-Key " - "frames received"); - sm->portValid = TRUE; - if (sm->ctx->eapol_done_cb) - sm->ctx->eapol_done_cb(sm->ctx->ctx); - } - } -} - - -static void eapol_sm_getSuppRsp(struct eapol_sm *sm) -{ - wpa_printf(MSG_DEBUG, "EAPOL: getSuppRsp"); - /* EAP layer processing; no special code is needed, since Supplicant - * Backend state machine is waiting for eapNoResp or eapResp to be set - * and these are only set in the EAP state machine when the processing - * has finished. */ -} - - -static void eapol_sm_txSuppRsp(struct eapol_sm *sm) -{ - struct wpabuf *resp; - - wpa_printf(MSG_DEBUG, "EAPOL: txSuppRsp"); - resp = eap_get_eapRespData(sm->eap); - if (resp == NULL) { - wpa_printf(MSG_WARNING, "EAPOL: txSuppRsp - EAP response data " - "not available"); - return; - } - - /* Send EAP-Packet from the EAP layer to the Authenticator */ - sm->ctx->eapol_send(sm->ctx->eapol_send_ctx, - IEEE802_1X_TYPE_EAP_PACKET, wpabuf_head(resp), - wpabuf_len(resp)); - - /* eapRespData is not used anymore, so free it here */ - wpabuf_free(resp); - - if (sm->initial_req) - sm->dot1xSuppEapolReqIdFramesRx++; - else - sm->dot1xSuppEapolReqFramesRx++; - sm->dot1xSuppEapolRespFramesTx++; - sm->dot1xSuppEapolFramesTx++; -} - - -static void eapol_sm_abortSupp(struct eapol_sm *sm) -{ - /* release system resources that may have been allocated for the - * authentication session */ - os_free(sm->last_rx_key); - sm->last_rx_key = NULL; - wpabuf_free(sm->eapReqData); - sm->eapReqData = NULL; - eap_sm_abort(sm->eap); -} - - -static void eapol_sm_step_timeout(void *eloop_ctx, void *timeout_ctx) -{ - eapol_sm_step(timeout_ctx); -} - - -static void eapol_sm_set_port_authorized(struct eapol_sm *sm) -{ - if (sm->ctx->port_cb) - sm->ctx->port_cb(sm->ctx->ctx, 1); -} - - -static void eapol_sm_set_port_unauthorized(struct eapol_sm *sm) -{ - if (sm->ctx->port_cb) - sm->ctx->port_cb(sm->ctx->ctx, 0); -} - - -/** - * eapol_sm_step - EAPOL state machine step function - * @sm: Pointer to EAPOL state machine allocated with eapol_sm_init() - * - * This function is called to notify the state machine about changed external - * variables. It will step through the EAPOL state machines in loop to process - * all triggered state changes. - */ -void eapol_sm_step(struct eapol_sm *sm) -{ - int i; - - /* In theory, it should be ok to run this in loop until !changed. - * However, it is better to use a limit on number of iterations to - * allow events (e.g., SIGTERM) to stop the program cleanly if the - * state machine were to generate a busy loop. */ - for (i = 0; i < 100; i++) { - sm->changed = FALSE; - SM_STEP_RUN(SUPP_PAE); - SM_STEP_RUN(KEY_RX); - SM_STEP_RUN(SUPP_BE); - if (eap_peer_sm_step(sm->eap)) - sm->changed = TRUE; - if (!sm->changed) - break; - } - - if (sm->changed) { - /* restart EAPOL state machine step from timeout call in order - * to allow other events to be processed. */ - eloop_cancel_timeout(eapol_sm_step_timeout, NULL, sm); - eloop_register_timeout(0, 0, eapol_sm_step_timeout, NULL, sm); - } - - if (sm->ctx->cb && sm->cb_status != EAPOL_CB_IN_PROGRESS) { - int success = sm->cb_status == EAPOL_CB_SUCCESS ? 1 : 0; - sm->cb_status = EAPOL_CB_IN_PROGRESS; - sm->ctx->cb(sm, success, sm->ctx->cb_ctx); - } -} - - -#ifdef CONFIG_CTRL_IFACE -static const char *eapol_supp_pae_state(int state) -{ - switch (state) { - case SUPP_PAE_LOGOFF: - return "LOGOFF"; - case SUPP_PAE_DISCONNECTED: - return "DISCONNECTED"; - case SUPP_PAE_CONNECTING: - return "CONNECTING"; - case SUPP_PAE_AUTHENTICATING: - return "AUTHENTICATING"; - case SUPP_PAE_HELD: - return "HELD"; - case SUPP_PAE_AUTHENTICATED: - return "AUTHENTICATED"; - case SUPP_PAE_RESTART: - return "RESTART"; - default: - return "UNKNOWN"; - } -} - - -static const char *eapol_supp_be_state(int state) -{ - switch (state) { - case SUPP_BE_REQUEST: - return "REQUEST"; - case SUPP_BE_RESPONSE: - return "RESPONSE"; - case SUPP_BE_SUCCESS: - return "SUCCESS"; - case SUPP_BE_FAIL: - return "FAIL"; - case SUPP_BE_TIMEOUT: - return "TIMEOUT"; - case SUPP_BE_IDLE: - return "IDLE"; - case SUPP_BE_INITIALIZE: - return "INITIALIZE"; - case SUPP_BE_RECEIVE: - return "RECEIVE"; - default: - return "UNKNOWN"; - } -} - - -static const char * eapol_port_status(PortStatus status) -{ - if (status == Authorized) - return "Authorized"; - else - return "Unauthorized"; -} -#endif /* CONFIG_CTRL_IFACE */ - - -#if defined(CONFIG_CTRL_IFACE) || !defined(CONFIG_NO_STDOUT_DEBUG) -static const char * eapol_port_control(PortControl ctrl) -{ - switch (ctrl) { - case Auto: - return "Auto"; - case ForceUnauthorized: - return "ForceUnauthorized"; - case ForceAuthorized: - return "ForceAuthorized"; - default: - return "Unknown"; - } -} -#endif /* CONFIG_CTRL_IFACE || !CONFIG_NO_STDOUT_DEBUG */ - - -/** - * eapol_sm_configure - Set EAPOL variables - * @sm: Pointer to EAPOL state machine allocated with eapol_sm_init() - * @heldPeriod: dot1xSuppHeldPeriod - * @authPeriod: dot1xSuppAuthPeriod - * @startPeriod: dot1xSuppStartPeriod - * @maxStart: dot1xSuppMaxStart - * - * Set configurable EAPOL state machine variables. Each variable can be set to - * the given value or ignored if set to -1 (to set only some of the variables). - */ -void eapol_sm_configure(struct eapol_sm *sm, int heldPeriod, int authPeriod, - int startPeriod, int maxStart) -{ - if (sm == NULL) - return; - if (heldPeriod >= 0) - sm->heldPeriod = heldPeriod; - if (authPeriod >= 0) - sm->authPeriod = authPeriod; - if (startPeriod >= 0) - sm->startPeriod = startPeriod; - if (maxStart >= 0) - sm->maxStart = maxStart; -} - - -/** - * eapol_sm_get_method_name - Get EAPOL method name - * @sm: Pointer to EAPOL state machine allocated with eapol_sm_init() - * Returns: Static string containing name of current eap method or NULL - */ -const char * eapol_sm_get_method_name(struct eapol_sm *sm) -{ - if (sm->SUPP_PAE_state != SUPP_PAE_AUTHENTICATED || - sm->suppPortStatus != Authorized) - return NULL; - - return eap_sm_get_method_name(sm->eap); -} - - -#ifdef CONFIG_CTRL_IFACE -/** - * eapol_sm_get_status - Get EAPOL state machine status - * @sm: Pointer to EAPOL state machine allocated with eapol_sm_init() - * @buf: Buffer for status information - * @buflen: Maximum buffer length - * @verbose: Whether to include verbose status information - * Returns: Number of bytes written to buf. - * - * Query EAPOL state machine for status information. This function fills in a - * text area with current status information from the EAPOL state machine. If - * the buffer (buf) is not large enough, status information will be truncated - * to fit the buffer. - */ -int eapol_sm_get_status(struct eapol_sm *sm, char *buf, size_t buflen, - int verbose) -{ - int len, ret; - if (sm == NULL) - return 0; - - len = os_snprintf(buf, buflen, - "Supplicant PAE state=%s\n" - "suppPortStatus=%s\n", - eapol_supp_pae_state(sm->SUPP_PAE_state), - eapol_port_status(sm->suppPortStatus)); - if (len < 0 || (size_t) len >= buflen) - return 0; - - if (verbose) { - ret = os_snprintf(buf + len, buflen - len, - "heldPeriod=%u\n" - "authPeriod=%u\n" - "startPeriod=%u\n" - "maxStart=%u\n" - "portControl=%s\n" - "Supplicant Backend state=%s\n", - sm->heldPeriod, - sm->authPeriod, - sm->startPeriod, - sm->maxStart, - eapol_port_control(sm->portControl), - eapol_supp_be_state(sm->SUPP_BE_state)); - if (ret < 0 || (size_t) ret >= buflen - len) - return len; - len += ret; - } - - len += eap_sm_get_status(sm->eap, buf + len, buflen - len, verbose); - - return len; -} - - -/** - * eapol_sm_get_mib - Get EAPOL state machine MIBs - * @sm: Pointer to EAPOL state machine allocated with eapol_sm_init() - * @buf: Buffer for MIB information - * @buflen: Maximum buffer length - * Returns: Number of bytes written to buf. - * - * Query EAPOL state machine for MIB information. This function fills in a - * text area with current MIB information from the EAPOL state machine. If - * the buffer (buf) is not large enough, MIB information will be truncated to - * fit the buffer. - */ -int eapol_sm_get_mib(struct eapol_sm *sm, char *buf, size_t buflen) -{ - size_t len; - int ret; - - if (sm == NULL) - return 0; - ret = os_snprintf(buf, buflen, - "dot1xSuppPaeState=%d\n" - "dot1xSuppHeldPeriod=%u\n" - "dot1xSuppAuthPeriod=%u\n" - "dot1xSuppStartPeriod=%u\n" - "dot1xSuppMaxStart=%u\n" - "dot1xSuppSuppControlledPortStatus=%s\n" - "dot1xSuppBackendPaeState=%d\n", - sm->SUPP_PAE_state, - sm->heldPeriod, - sm->authPeriod, - sm->startPeriod, - sm->maxStart, - sm->suppPortStatus == Authorized ? - "Authorized" : "Unauthorized", - sm->SUPP_BE_state); - - if (ret < 0 || (size_t) ret >= buflen) - return 0; - len = ret; - - ret = os_snprintf(buf + len, buflen - len, - "dot1xSuppEapolFramesRx=%u\n" - "dot1xSuppEapolFramesTx=%u\n" - "dot1xSuppEapolStartFramesTx=%u\n" - "dot1xSuppEapolLogoffFramesTx=%u\n" - "dot1xSuppEapolRespFramesTx=%u\n" - "dot1xSuppEapolReqIdFramesRx=%u\n" - "dot1xSuppEapolReqFramesRx=%u\n" - "dot1xSuppInvalidEapolFramesRx=%u\n" - "dot1xSuppEapLengthErrorFramesRx=%u\n" - "dot1xSuppLastEapolFrameVersion=%u\n" - "dot1xSuppLastEapolFrameSource=" MACSTR "\n", - sm->dot1xSuppEapolFramesRx, - sm->dot1xSuppEapolFramesTx, - sm->dot1xSuppEapolStartFramesTx, - sm->dot1xSuppEapolLogoffFramesTx, - sm->dot1xSuppEapolRespFramesTx, - sm->dot1xSuppEapolReqIdFramesRx, - sm->dot1xSuppEapolReqFramesRx, - sm->dot1xSuppInvalidEapolFramesRx, - sm->dot1xSuppEapLengthErrorFramesRx, - sm->dot1xSuppLastEapolFrameVersion, - MAC2STR(sm->dot1xSuppLastEapolFrameSource)); - - if (ret < 0 || (size_t) ret >= buflen - len) - return len; - len += ret; - - return len; -} -#endif /* CONFIG_CTRL_IFACE */ - - -/** - * eapol_sm_rx_eapol - Process received EAPOL frames - * @sm: Pointer to EAPOL state machine allocated with eapol_sm_init() - * @src: Source MAC address of the EAPOL packet - * @buf: Pointer to the beginning of the EAPOL data (EAPOL header) - * @len: Length of the EAPOL frame - * Returns: 1 = EAPOL frame processed, 0 = not for EAPOL state machine, - * -1 failure - */ -int eapol_sm_rx_eapol(struct eapol_sm *sm, const u8 *src, const u8 *buf, - size_t len) -{ - const struct ieee802_1x_hdr *hdr; - const struct ieee802_1x_eapol_key *key; - int data_len; - int res = 1; - size_t plen; - - if (sm == NULL) - return 0; - sm->dot1xSuppEapolFramesRx++; - if (len < sizeof(*hdr)) { - sm->dot1xSuppInvalidEapolFramesRx++; - return 0; - } - hdr = (const struct ieee802_1x_hdr *) buf; - sm->dot1xSuppLastEapolFrameVersion = hdr->version; - os_memcpy(sm->dot1xSuppLastEapolFrameSource, src, ETH_ALEN); - if (hdr->version < EAPOL_VERSION) { - /* TODO: backwards compatibility */ - } - plen = be_to_host16(hdr->length); - if (plen > len - sizeof(*hdr)) { - sm->dot1xSuppEapLengthErrorFramesRx++; - return 0; - } -#ifdef CONFIG_WPS - if (sm->conf.workaround && - plen < len - sizeof(*hdr) && - hdr->type == IEEE802_1X_TYPE_EAP_PACKET && - len - sizeof(*hdr) > sizeof(struct eap_hdr)) { - const struct eap_hdr *ehdr = - (const struct eap_hdr *) (hdr + 1); - u16 elen; - - elen = be_to_host16(ehdr->length); - if (elen > plen && elen <= len - sizeof(*hdr)) { - /* - * Buffalo WHR-G125 Ver.1.47 seems to send EAP-WPS - * packets with too short EAPOL header length field - * (14 octets). This is fixed in firmware Ver.1.49. - * As a workaround, fix the EAPOL header based on the - * correct length in the EAP packet. - */ - wpa_printf(MSG_DEBUG, "EAPOL: Workaround - fix EAPOL " - "payload length based on EAP header: " - "%d -> %d", (int) plen, elen); - plen = elen; - } - } -#endif /* CONFIG_WPS */ - data_len = plen + sizeof(*hdr); - - switch (hdr->type) { - case IEEE802_1X_TYPE_EAP_PACKET: - if (sm->cached_pmk) { - /* Trying to use PMKSA caching, but Authenticator did - * not seem to have a matching entry. Need to restart - * EAPOL state machines. - */ - eapol_sm_abort_cached(sm); - } - wpabuf_free(sm->eapReqData); - sm->eapReqData = wpabuf_alloc_copy(hdr + 1, plen); - if (sm->eapReqData) { - wpa_printf(MSG_DEBUG, "EAPOL: Received EAP-Packet " - "frame"); - sm->eapolEap = TRUE; - eapol_sm_step(sm); - } - break; - case IEEE802_1X_TYPE_EAPOL_KEY: - if (plen < sizeof(*key)) { - wpa_printf(MSG_DEBUG, "EAPOL: Too short EAPOL-Key " - "frame received"); - break; - } - key = (const struct ieee802_1x_eapol_key *) (hdr + 1); - if (key->type == EAPOL_KEY_TYPE_WPA || - key->type == EAPOL_KEY_TYPE_RSN) { - /* WPA Supplicant takes care of this frame. */ - wpa_printf(MSG_DEBUG, "EAPOL: Ignoring WPA EAPOL-Key " - "frame in EAPOL state machines"); - res = 0; - break; - } - if (key->type != EAPOL_KEY_TYPE_RC4) { - wpa_printf(MSG_DEBUG, "EAPOL: Ignored unknown " - "EAPOL-Key type %d", key->type); - break; - } - os_free(sm->last_rx_key); - sm->last_rx_key = os_malloc(data_len); - if (sm->last_rx_key) { - wpa_printf(MSG_DEBUG, "EAPOL: Received EAPOL-Key " - "frame"); - os_memcpy(sm->last_rx_key, buf, data_len); - sm->last_rx_key_len = data_len; - sm->rxKey = TRUE; - eapol_sm_step(sm); - } - break; - default: - wpa_printf(MSG_DEBUG, "EAPOL: Received unknown EAPOL type %d", - hdr->type); - sm->dot1xSuppInvalidEapolFramesRx++; - break; - } - - return res; -} - - -/** - * eapol_sm_notify_tx_eapol_key - Notification about transmitted EAPOL packet - * @sm: Pointer to EAPOL state machine allocated with eapol_sm_init() - * - * Notify EAPOL state machine about transmitted EAPOL packet from an external - * component, e.g., WPA. This will update the statistics. - */ -void eapol_sm_notify_tx_eapol_key(struct eapol_sm *sm) -{ - if (sm) - sm->dot1xSuppEapolFramesTx++; -} - - -/** - * eapol_sm_notify_portEnabled - Notification about portEnabled change - * @sm: Pointer to EAPOL state machine allocated with eapol_sm_init() - * @enabled: New portEnabled value - * - * Notify EAPOL state machine about new portEnabled value. - */ -void eapol_sm_notify_portEnabled(struct eapol_sm *sm, Boolean enabled) -{ - if (sm == NULL) - return; - wpa_printf(MSG_DEBUG, "EAPOL: External notification - " - "portEnabled=%d", enabled); - sm->portEnabled = enabled; - eapol_sm_step(sm); -} - - -/** - * eapol_sm_notify_portValid - Notification about portValid change - * @sm: Pointer to EAPOL state machine allocated with eapol_sm_init() - * @valid: New portValid value - * - * Notify EAPOL state machine about new portValid value. - */ -void eapol_sm_notify_portValid(struct eapol_sm *sm, Boolean valid) -{ - if (sm == NULL) - return; - wpa_printf(MSG_DEBUG, "EAPOL: External notification - " - "portValid=%d", valid); - sm->portValid = valid; - eapol_sm_step(sm); -} - - -/** - * eapol_sm_notify_eap_success - Notification of external EAP success trigger - * @sm: Pointer to EAPOL state machine allocated with eapol_sm_init() - * @success: %TRUE = set success, %FALSE = clear success - * - * Notify the EAPOL state machine that external event has forced EAP state to - * success (success = %TRUE). This can be cleared by setting success = %FALSE. - * - * This function is called to update EAP state when WPA-PSK key handshake has - * been completed successfully since WPA-PSK does not use EAP state machine. - */ -void eapol_sm_notify_eap_success(struct eapol_sm *sm, Boolean success) -{ - if (sm == NULL) - return; - wpa_printf(MSG_DEBUG, "EAPOL: External notification - " - "EAP success=%d", success); - sm->eapSuccess = success; - sm->altAccept = success; - if (success) - eap_notify_success(sm->eap); - eapol_sm_step(sm); -} - - -/** - * eapol_sm_notify_eap_fail - Notification of external EAP failure trigger - * @sm: Pointer to EAPOL state machine allocated with eapol_sm_init() - * @fail: %TRUE = set failure, %FALSE = clear failure - * - * Notify EAPOL state machine that external event has forced EAP state to - * failure (fail = %TRUE). This can be cleared by setting fail = %FALSE. - */ -void eapol_sm_notify_eap_fail(struct eapol_sm *sm, Boolean fail) -{ - if (sm == NULL) - return; - wpa_printf(MSG_DEBUG, "EAPOL: External notification - " - "EAP fail=%d", fail); - sm->eapFail = fail; - sm->altReject = fail; - eapol_sm_step(sm); -} - - -/** - * eapol_sm_notify_config - Notification of EAPOL configuration change - * @sm: Pointer to EAPOL state machine allocated with eapol_sm_init() - * @config: Pointer to current network EAP configuration - * @conf: Pointer to EAPOL configuration data - * - * Notify EAPOL state machine that configuration has changed. config will be - * stored as a backpointer to network configuration. This can be %NULL to clear - * the stored pointed. conf will be copied to local EAPOL/EAP configuration - * data. If conf is %NULL, this part of the configuration change will be - * skipped. - */ -void eapol_sm_notify_config(struct eapol_sm *sm, - struct eap_peer_config *config, - const struct eapol_config *conf) -{ - if (sm == NULL) - return; - - sm->config = config; - - if (conf == NULL) - return; - - sm->conf.accept_802_1x_keys = conf->accept_802_1x_keys; - sm->conf.required_keys = conf->required_keys; - sm->conf.fast_reauth = conf->fast_reauth; - sm->conf.workaround = conf->workaround; - if (sm->eap) { - eap_set_fast_reauth(sm->eap, conf->fast_reauth); - eap_set_workaround(sm->eap, conf->workaround); - eap_set_force_disabled(sm->eap, conf->eap_disabled); - } -} - - -/** - * eapol_sm_get_key - Get master session key (MSK) from EAP - * @sm: Pointer to EAPOL state machine allocated with eapol_sm_init() - * @key: Pointer for key buffer - * @len: Number of bytes to copy to key - * Returns: 0 on success (len of key available), maximum available key len - * (>0) if key is available but it is shorter than len, or -1 on failure. - * - * Fetch EAP keying material (MSK, eapKeyData) from EAP state machine. The key - * is available only after a successful authentication. - */ -int eapol_sm_get_key(struct eapol_sm *sm, u8 *key, size_t len) -{ - const u8 *eap_key; - size_t eap_len; - - if (sm == NULL || !eap_key_available(sm->eap)) { - wpa_printf(MSG_DEBUG, "EAPOL: EAP key not available"); - return -1; - } - eap_key = eap_get_eapKeyData(sm->eap, &eap_len); - if (eap_key == NULL) { - wpa_printf(MSG_DEBUG, "EAPOL: Failed to get eapKeyData"); - return -1; - } - if (len > eap_len) { - wpa_printf(MSG_DEBUG, "EAPOL: Requested key length (%lu) not " - "available (len=%lu)", - (unsigned long) len, (unsigned long) eap_len); - return eap_len; - } - os_memcpy(key, eap_key, len); - wpa_printf(MSG_DEBUG, "EAPOL: Successfully fetched key (len=%lu)", - (unsigned long) len); - return 0; -} - - -/** - * eapol_sm_notify_logoff - Notification of logon/logoff commands - * @sm: Pointer to EAPOL state machine allocated with eapol_sm_init() - * @logoff: Whether command was logoff - * - * Notify EAPOL state machines that user requested logon/logoff. - */ -void eapol_sm_notify_logoff(struct eapol_sm *sm, Boolean logoff) -{ - if (sm) { - sm->userLogoff = logoff; - eapol_sm_step(sm); - } -} - - -/** - * eapol_sm_notify_pmkid_attempt - Notification of successful PMKSA caching - * @sm: Pointer to EAPOL state machine allocated with eapol_sm_init() - * - * Notify EAPOL state machines that PMKSA caching was successful. This is used - * to move EAPOL and EAP state machines into authenticated/successful state. - */ -void eapol_sm_notify_cached(struct eapol_sm *sm) -{ - if (sm == NULL) - return; - wpa_printf(MSG_DEBUG, "EAPOL: PMKSA caching was used - skip EAPOL"); - sm->SUPP_PAE_state = SUPP_PAE_AUTHENTICATED; - sm->suppPortStatus = Authorized; - eapol_sm_set_port_authorized(sm); - sm->portValid = TRUE; - eap_notify_success(sm->eap); - eapol_sm_step(sm); -} - - -/** - * eapol_sm_notify_pmkid_attempt - Notification of PMKSA caching - * @sm: Pointer to EAPOL state machine allocated with eapol_sm_init() - * @attempt: Whether PMKSA caching is tried - * - * Notify EAPOL state machines whether PMKSA caching is used. - */ -void eapol_sm_notify_pmkid_attempt(struct eapol_sm *sm, int attempt) -{ - if (sm == NULL) - return; - if (attempt) { - wpa_printf(MSG_DEBUG, "RSN: Trying to use cached PMKSA"); - sm->cached_pmk = TRUE; - } else { - wpa_printf(MSG_DEBUG, "RSN: Do not try to use cached PMKSA"); - sm->cached_pmk = FALSE; - } -} - - -static void eapol_sm_abort_cached(struct eapol_sm *sm) -{ - wpa_printf(MSG_DEBUG, "RSN: Authenticator did not accept PMKID, " - "doing full EAP authentication"); - if (sm == NULL) - return; - sm->cached_pmk = FALSE; - sm->SUPP_PAE_state = SUPP_PAE_CONNECTING; - sm->suppPortStatus = Unauthorized; - eapol_sm_set_port_unauthorized(sm); - - /* Make sure we do not start sending EAPOL-Start frames first, but - * instead move to RESTART state to start EAPOL authentication. */ - sm->startWhen = 3; - eapol_enable_timer_tick(sm); - - if (sm->ctx->aborted_cached) - sm->ctx->aborted_cached(sm->ctx->ctx); -} - - -/** - * eapol_sm_register_scard_ctx - Notification of smart card context - * @sm: Pointer to EAPOL state machine allocated with eapol_sm_init() - * @ctx: Context data for smart card operations - * - * Notify EAPOL state machines of context data for smart card operations. This - * context data will be used as a parameter for scard_*() functions. - */ -void eapol_sm_register_scard_ctx(struct eapol_sm *sm, void *ctx) -{ - if (sm) { - sm->ctx->scard_ctx = ctx; - eap_register_scard_ctx(sm->eap, ctx); - } -} - - -/** - * eapol_sm_notify_portControl - Notification of portControl changes - * @sm: Pointer to EAPOL state machine allocated with eapol_sm_init() - * @portControl: New value for portControl variable - * - * Notify EAPOL state machines that portControl variable has changed. - */ -void eapol_sm_notify_portControl(struct eapol_sm *sm, PortControl portControl) -{ - if (sm == NULL) - return; - wpa_printf(MSG_DEBUG, "EAPOL: External notification - " - "portControl=%s", eapol_port_control(portControl)); - sm->portControl = portControl; - eapol_sm_step(sm); -} - - -/** - * eapol_sm_notify_ctrl_attached - Notification of attached monitor - * @sm: Pointer to EAPOL state machine allocated with eapol_sm_init() - * - * Notify EAPOL state machines that a monitor was attached to the control - * interface to trigger re-sending of pending requests for user input. - */ -void eapol_sm_notify_ctrl_attached(struct eapol_sm *sm) -{ - if (sm == NULL) - return; - eap_sm_notify_ctrl_attached(sm->eap); -} - - -/** - * eapol_sm_notify_ctrl_response - Notification of received user input - * @sm: Pointer to EAPOL state machine allocated with eapol_sm_init() - * - * Notify EAPOL state machines that a control response, i.e., user - * input, was received in order to trigger retrying of a pending EAP request. - */ -void eapol_sm_notify_ctrl_response(struct eapol_sm *sm) -{ - if (sm == NULL) - return; - if (sm->eapReqData && !sm->eapReq) { - wpa_printf(MSG_DEBUG, "EAPOL: received control response (user " - "input) notification - retrying pending EAP " - "Request"); - sm->eapolEap = TRUE; - sm->eapReq = TRUE; - eapol_sm_step(sm); - } -} - - -/** - * eapol_sm_request_reauth - Request reauthentication - * @sm: Pointer to EAPOL state machine allocated with eapol_sm_init() - * - * This function can be used to request EAPOL reauthentication, e.g., when the - * current PMKSA entry is nearing expiration. - */ -void eapol_sm_request_reauth(struct eapol_sm *sm) -{ - if (sm == NULL || sm->SUPP_PAE_state != SUPP_PAE_AUTHENTICATED) - return; - eapol_sm_txStart(sm); -} - - -/** - * eapol_sm_notify_lower_layer_success - Notification of lower layer success - * @sm: Pointer to EAPOL state machine allocated with eapol_sm_init() - * @in_eapol_sm: Whether the caller is already running inside EAPOL state - * machine loop (eapol_sm_step()) - * - * Notify EAPOL (and EAP) state machines that a lower layer has detected a - * successful authentication. This is used to recover from dropped EAP-Success - * messages. - */ -void eapol_sm_notify_lower_layer_success(struct eapol_sm *sm, int in_eapol_sm) -{ - if (sm == NULL) - return; - eap_notify_lower_layer_success(sm->eap); - if (!in_eapol_sm) - eapol_sm_step(sm); -} - - -/** - * eapol_sm_invalidate_cached_session - Mark cached EAP session data invalid - * @sm: Pointer to EAPOL state machine allocated with eapol_sm_init() - */ -void eapol_sm_invalidate_cached_session(struct eapol_sm *sm) -{ - if (sm) - eap_invalidate_cached_session(sm->eap); -} - - -static struct eap_peer_config * eapol_sm_get_config(void *ctx) -{ - struct eapol_sm *sm = ctx; - return sm ? sm->config : NULL; -} - - -static struct wpabuf * eapol_sm_get_eapReqData(void *ctx) -{ - struct eapol_sm *sm = ctx; - if (sm == NULL || sm->eapReqData == NULL) - return NULL; - - return sm->eapReqData; -} - - -static Boolean eapol_sm_get_bool(void *ctx, enum eapol_bool_var variable) -{ - struct eapol_sm *sm = ctx; - if (sm == NULL) - return FALSE; - switch (variable) { - case EAPOL_eapSuccess: - return sm->eapSuccess; - case EAPOL_eapRestart: - return sm->eapRestart; - case EAPOL_eapFail: - return sm->eapFail; - case EAPOL_eapResp: - return sm->eapResp; - case EAPOL_eapNoResp: - return sm->eapNoResp; - case EAPOL_eapReq: - return sm->eapReq; - case EAPOL_portEnabled: - return sm->portEnabled; - case EAPOL_altAccept: - return sm->altAccept; - case EAPOL_altReject: - return sm->altReject; - } - return FALSE; -} - - -static void eapol_sm_set_bool(void *ctx, enum eapol_bool_var variable, - Boolean value) -{ - struct eapol_sm *sm = ctx; - if (sm == NULL) - return; - switch (variable) { - case EAPOL_eapSuccess: - sm->eapSuccess = value; - break; - case EAPOL_eapRestart: - sm->eapRestart = value; - break; - case EAPOL_eapFail: - sm->eapFail = value; - break; - case EAPOL_eapResp: - sm->eapResp = value; - break; - case EAPOL_eapNoResp: - sm->eapNoResp = value; - break; - case EAPOL_eapReq: - sm->eapReq = value; - break; - case EAPOL_portEnabled: - sm->portEnabled = value; - break; - case EAPOL_altAccept: - sm->altAccept = value; - break; - case EAPOL_altReject: - sm->altReject = value; - break; - } -} - - -static unsigned int eapol_sm_get_int(void *ctx, enum eapol_int_var variable) -{ - struct eapol_sm *sm = ctx; - if (sm == NULL) - return 0; - switch (variable) { - case EAPOL_idleWhile: - return sm->idleWhile; - } - return 0; -} - - -static void eapol_sm_set_int(void *ctx, enum eapol_int_var variable, - unsigned int value) -{ - struct eapol_sm *sm = ctx; - if (sm == NULL) - return; - switch (variable) { - case EAPOL_idleWhile: - sm->idleWhile = value; - eapol_enable_timer_tick(sm); - break; - } -} - - -static void eapol_sm_set_config_blob(void *ctx, struct wpa_config_blob *blob) -{ -#ifndef CONFIG_NO_CONFIG_BLOBS - struct eapol_sm *sm = ctx; - if (sm && sm->ctx && sm->ctx->set_config_blob) - sm->ctx->set_config_blob(sm->ctx->ctx, blob); -#endif /* CONFIG_NO_CONFIG_BLOBS */ -} - - -static const struct wpa_config_blob * -eapol_sm_get_config_blob(void *ctx, const char *name) -{ -#ifndef CONFIG_NO_CONFIG_BLOBS - struct eapol_sm *sm = ctx; - if (sm && sm->ctx && sm->ctx->get_config_blob) - return sm->ctx->get_config_blob(sm->ctx->ctx, name); - else - return NULL; -#else /* CONFIG_NO_CONFIG_BLOBS */ - return NULL; -#endif /* CONFIG_NO_CONFIG_BLOBS */ -} - - -static void eapol_sm_notify_pending(void *ctx) -{ - struct eapol_sm *sm = ctx; - if (sm == NULL) - return; - if (sm->eapReqData && !sm->eapReq) { - wpa_printf(MSG_DEBUG, "EAPOL: received notification from EAP " - "state machine - retrying pending EAP Request"); - sm->eapolEap = TRUE; - sm->eapReq = TRUE; - eapol_sm_step(sm); - } -} - - -#if defined(CONFIG_CTRL_IFACE) || !defined(CONFIG_NO_STDOUT_DEBUG) -static void eapol_sm_eap_param_needed(void *ctx, const char *field, - const char *txt) -{ - struct eapol_sm *sm = ctx; - wpa_printf(MSG_DEBUG, "EAPOL: EAP parameter needed"); - if (sm->ctx->eap_param_needed) - sm->ctx->eap_param_needed(sm->ctx->ctx, field, txt); -} -#else /* CONFIG_CTRL_IFACE || !CONFIG_NO_STDOUT_DEBUG */ -#define eapol_sm_eap_param_needed NULL -#endif /* CONFIG_CTRL_IFACE || !CONFIG_NO_STDOUT_DEBUG */ - - -static struct eapol_callbacks eapol_cb = -{ - eapol_sm_get_config, - eapol_sm_get_bool, - eapol_sm_set_bool, - eapol_sm_get_int, - eapol_sm_set_int, - eapol_sm_get_eapReqData, - eapol_sm_set_config_blob, - eapol_sm_get_config_blob, - eapol_sm_notify_pending, - eapol_sm_eap_param_needed -}; - - -/** - * eapol_sm_init - Initialize EAPOL state machine - * @ctx: Pointer to EAPOL context data; this needs to be an allocated buffer - * and EAPOL state machine will free it in eapol_sm_deinit() - * Returns: Pointer to the allocated EAPOL state machine or %NULL on failure - * - * Allocate and initialize an EAPOL state machine. - */ -struct eapol_sm *eapol_sm_init(struct eapol_ctx *ctx) -{ - struct eapol_sm *sm; - struct eap_config conf; - sm = os_zalloc(sizeof(*sm)); - if (sm == NULL) - return NULL; - sm->ctx = ctx; - - sm->portControl = Auto; - - /* Supplicant PAE state machine */ - sm->heldPeriod = 60; - sm->startPeriod = 30; - sm->maxStart = 3; - - /* Supplicant Backend state machine */ - sm->authPeriod = 30; - - os_memset(&conf, 0, sizeof(conf)); - conf.opensc_engine_path = ctx->opensc_engine_path; - conf.pkcs11_engine_path = ctx->pkcs11_engine_path; - conf.pkcs11_module_path = ctx->pkcs11_module_path; - conf.wps = ctx->wps; - - sm->eap = eap_peer_sm_init(sm, &eapol_cb, sm->ctx->msg_ctx, &conf); - if (sm->eap == NULL) { - os_free(sm); - return NULL; - } - - /* Initialize EAPOL state machines */ - sm->initialize = TRUE; - eapol_sm_step(sm); - sm->initialize = FALSE; - eapol_sm_step(sm); - - sm->timer_tick_enabled = 1; - eloop_register_timeout(1, 0, eapol_port_timers_tick, NULL, sm); - - return sm; -} - - -/** - * eapol_sm_deinit - Deinitialize EAPOL state machine - * @sm: Pointer to EAPOL state machine allocated with eapol_sm_init() - * - * Deinitialize and free EAPOL state machine. - */ -void eapol_sm_deinit(struct eapol_sm *sm) -{ - if (sm == NULL) - return; - eloop_cancel_timeout(eapol_sm_step_timeout, NULL, sm); - eloop_cancel_timeout(eapol_port_timers_tick, NULL, sm); - eap_peer_sm_deinit(sm->eap); - os_free(sm->last_rx_key); - wpabuf_free(sm->eapReqData); - os_free(sm->ctx); - os_free(sm); -} diff --git a/hostapd-0.8/src/eapol_supp/eapol_supp_sm.h b/hostapd-0.8/src/eapol_supp/eapol_supp_sm.h deleted file mode 100644 index 1bdf8cd..0000000 --- a/hostapd-0.8/src/eapol_supp/eapol_supp_sm.h +++ /dev/null @@ -1,352 +0,0 @@ -/* - * EAPOL supplicant state machines - * Copyright (c) 2004-2008, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#ifndef EAPOL_SUPP_SM_H -#define EAPOL_SUPP_SM_H - -#include "common/defs.h" - -typedef enum { Unauthorized, Authorized } PortStatus; -typedef enum { Auto, ForceUnauthorized, ForceAuthorized } PortControl; - -/** - * struct eapol_config - Per network configuration for EAPOL state machines - */ -struct eapol_config { - /** - * accept_802_1x_keys - Accept IEEE 802.1X (non-WPA) EAPOL-Key frames - * - * This variable should be set to 1 when using EAPOL state machines - * with non-WPA security policy to generate dynamic WEP keys. When - * using WPA, this should be set to 0 so that WPA state machine can - * process the EAPOL-Key frames. - */ - int accept_802_1x_keys; - -#define EAPOL_REQUIRE_KEY_UNICAST BIT(0) -#define EAPOL_REQUIRE_KEY_BROADCAST BIT(1) - /** - * required_keys - Which EAPOL-Key packets are required - * - * This variable determines which EAPOL-Key packets are required before - * marking connection authenticated. This is a bit field of - * EAPOL_REQUIRE_KEY_UNICAST and EAPOL_REQUIRE_KEY_BROADCAST flags. - */ - int required_keys; - - /** - * fast_reauth - Whether fast EAP reauthentication is enabled - */ - int fast_reauth; - - /** - * workaround - Whether EAP workarounds are enabled - */ - unsigned int workaround; - - /** - * eap_disabled - Whether EAP is disabled - */ - int eap_disabled; -}; - -struct eapol_sm; -struct wpa_config_blob; - -/** - * struct eapol_ctx - Global (for all networks) EAPOL state machine context - */ -struct eapol_ctx { - /** - * ctx - Pointer to arbitrary upper level context - */ - void *ctx; - - /** - * preauth - IEEE 802.11i/RSN pre-authentication - * - * This EAPOL state machine is used for IEEE 802.11i/RSN - * pre-authentication - */ - int preauth; - - /** - * cb - Function to be called when EAPOL negotiation has been completed - * @eapol: Pointer to EAPOL state machine data - * @success: Whether the authentication was completed successfully - * @ctx: Pointer to context data (cb_ctx) - * - * This optional callback function will be called when the EAPOL - * authentication has been completed. This allows the owner of the - * EAPOL state machine to process the key and terminate the EAPOL state - * machine. Currently, this is used only in RSN pre-authentication. - */ - void (*cb)(struct eapol_sm *eapol, int success, void *ctx); - - /** - * cb_ctx - Callback context for cb() - */ - void *cb_ctx; - - /** - * msg_ctx - Callback context for wpa_msg() calls - */ - void *msg_ctx; - - /** - * scard_ctx - Callback context for PC/SC scard_*() function calls - * - * This context can be updated with eapol_sm_register_scard_ctx(). - */ - void *scard_ctx; - - /** - * eapol_send_ctx - Callback context for eapol_send() calls - */ - void *eapol_send_ctx; - - /** - * eapol_done_cb - Function to be called at successful completion - * @ctx: Callback context (ctx) - * - * This function is called at the successful completion of EAPOL - * authentication. If dynamic WEP keys are used, this is called only - * after all the expected keys have been received. - */ - void (*eapol_done_cb)(void *ctx); - - /** - * eapol_send - Send EAPOL packets - * @ctx: Callback context (eapol_send_ctx) - * @type: EAPOL type (IEEE802_1X_TYPE_*) - * @buf: Pointer to EAPOL payload - * @len: Length of the EAPOL payload - * Returns: 0 on success, -1 on failure - */ - int (*eapol_send)(void *ctx, int type, const u8 *buf, size_t len); - - /** - * set_wep_key - Configure WEP keys - * @ctx: Callback context (ctx) - * @unicast: Non-zero = unicast, 0 = multicast/broadcast key - * @keyidx: Key index (0..3) - * @key: WEP key - * @keylen: Length of the WEP key - * Returns: 0 on success, -1 on failure - */ - int (*set_wep_key)(void *ctx, int unicast, int keyidx, - const u8 *key, size_t keylen); - - /** - * set_config_blob - Set or add a named configuration blob - * @ctx: Callback context (ctx) - * @blob: New value for the blob - * - * Adds a new configuration blob or replaces the current value of an - * existing blob. - */ - void (*set_config_blob)(void *ctx, struct wpa_config_blob *blob); - - /** - * get_config_blob - Get a named configuration blob - * @ctx: Callback context (ctx) - * @name: Name of the blob - * Returns: Pointer to blob data or %NULL if not found - */ - const struct wpa_config_blob * (*get_config_blob)(void *ctx, - const char *name); - - /** - * aborted_cached - Notify that cached PMK attempt was aborted - * @ctx: Callback context (ctx) - */ - void (*aborted_cached)(void *ctx); - - /** - * opensc_engine_path - Path to the OpenSSL engine for opensc - * - * This is an OpenSSL specific configuration option for loading OpenSC - * engine (engine_opensc.so); if %NULL, this engine is not loaded. - */ - const char *opensc_engine_path; - - /** - * pkcs11_engine_path - Path to the OpenSSL engine for PKCS#11 - * - * This is an OpenSSL specific configuration option for loading PKCS#11 - * engine (engine_pkcs11.so); if %NULL, this engine is not loaded. - */ - const char *pkcs11_engine_path; - - /** - * pkcs11_module_path - Path to the OpenSSL OpenSC/PKCS#11 module - * - * This is an OpenSSL specific configuration option for configuring - * path to OpenSC/PKCS#11 engine (opensc-pkcs11.so); if %NULL, this - * module is not loaded. - */ - const char *pkcs11_module_path; - - /** - * wps - WPS context data - * - * This is only used by EAP-WSC and can be left %NULL if not available. - */ - struct wps_context *wps; - - /** - * eap_param_needed - Notify that EAP parameter is needed - * @ctx: Callback context (ctx) - * @field: Field name (e.g., "IDENTITY") - * @txt: User readable text describing the required parameter - */ - void (*eap_param_needed)(void *ctx, const char *field, - const char *txt); - - /** - * port_cb - Set port authorized/unauthorized callback (optional) - * @ctx: Callback context (ctx) - * @authorized: Whether the supplicant port is now in authorized state - */ - void (*port_cb)(void *ctx, int authorized); -}; - - -struct eap_peer_config; - -#ifdef IEEE8021X_EAPOL -struct eapol_sm *eapol_sm_init(struct eapol_ctx *ctx); -void eapol_sm_deinit(struct eapol_sm *sm); -void eapol_sm_step(struct eapol_sm *sm); -int eapol_sm_get_status(struct eapol_sm *sm, char *buf, size_t buflen, - int verbose); -int eapol_sm_get_mib(struct eapol_sm *sm, char *buf, size_t buflen); -void eapol_sm_configure(struct eapol_sm *sm, int heldPeriod, int authPeriod, - int startPeriod, int maxStart); -int eapol_sm_rx_eapol(struct eapol_sm *sm, const u8 *src, const u8 *buf, - size_t len); -void eapol_sm_notify_tx_eapol_key(struct eapol_sm *sm); -void eapol_sm_notify_portEnabled(struct eapol_sm *sm, Boolean enabled); -void eapol_sm_notify_portValid(struct eapol_sm *sm, Boolean valid); -void eapol_sm_notify_eap_success(struct eapol_sm *sm, Boolean success); -void eapol_sm_notify_eap_fail(struct eapol_sm *sm, Boolean fail); -void eapol_sm_notify_config(struct eapol_sm *sm, - struct eap_peer_config *config, - const struct eapol_config *conf); -int eapol_sm_get_key(struct eapol_sm *sm, u8 *key, size_t len); -void eapol_sm_notify_logoff(struct eapol_sm *sm, Boolean logoff); -void eapol_sm_notify_cached(struct eapol_sm *sm); -void eapol_sm_notify_pmkid_attempt(struct eapol_sm *sm, int attempt); -void eapol_sm_register_scard_ctx(struct eapol_sm *sm, void *ctx); -void eapol_sm_notify_portControl(struct eapol_sm *sm, PortControl portControl); -void eapol_sm_notify_ctrl_attached(struct eapol_sm *sm); -void eapol_sm_notify_ctrl_response(struct eapol_sm *sm); -void eapol_sm_request_reauth(struct eapol_sm *sm); -void eapol_sm_notify_lower_layer_success(struct eapol_sm *sm, int in_eapol_sm); -void eapol_sm_invalidate_cached_session(struct eapol_sm *sm); -const char * eapol_sm_get_method_name(struct eapol_sm *sm); -#else /* IEEE8021X_EAPOL */ -static inline struct eapol_sm *eapol_sm_init(struct eapol_ctx *ctx) -{ - free(ctx); - return (struct eapol_sm *) 1; -} -static inline void eapol_sm_deinit(struct eapol_sm *sm) -{ -} -static inline void eapol_sm_step(struct eapol_sm *sm) -{ -} -static inline int eapol_sm_get_status(struct eapol_sm *sm, char *buf, - size_t buflen, int verbose) -{ - return 0; -} -static inline int eapol_sm_get_mib(struct eapol_sm *sm, char *buf, - size_t buflen) -{ - return 0; -} -static inline void eapol_sm_configure(struct eapol_sm *sm, int heldPeriod, - int authPeriod, int startPeriod, - int maxStart) -{ -} -static inline int eapol_sm_rx_eapol(struct eapol_sm *sm, const u8 *src, - const u8 *buf, size_t len) -{ - return 0; -} -static inline void eapol_sm_notify_tx_eapol_key(struct eapol_sm *sm) -{ -} -static inline void eapol_sm_notify_portEnabled(struct eapol_sm *sm, - Boolean enabled) -{ -} -static inline void eapol_sm_notify_portValid(struct eapol_sm *sm, - Boolean valid) -{ -} -static inline void eapol_sm_notify_eap_success(struct eapol_sm *sm, - Boolean success) -{ -} -static inline void eapol_sm_notify_eap_fail(struct eapol_sm *sm, Boolean fail) -{ -} -static inline void eapol_sm_notify_config(struct eapol_sm *sm, - struct eap_peer_config *config, - struct eapol_config *conf) -{ -} -static inline int eapol_sm_get_key(struct eapol_sm *sm, u8 *key, size_t len) -{ - return -1; -} -static inline void eapol_sm_notify_logoff(struct eapol_sm *sm, Boolean logoff) -{ -} -static inline void eapol_sm_notify_cached(struct eapol_sm *sm) -{ -} -#define eapol_sm_notify_pmkid_attempt(sm, attempt) do { } while (0) -#define eapol_sm_register_scard_ctx(sm, ctx) do { } while (0) -static inline void eapol_sm_notify_portControl(struct eapol_sm *sm, - PortControl portControl) -{ -} -static inline void eapol_sm_notify_ctrl_attached(struct eapol_sm *sm) -{ -} -static inline void eapol_sm_notify_ctrl_response(struct eapol_sm *sm) -{ -} -static inline void eapol_sm_request_reauth(struct eapol_sm *sm) -{ -} -static inline void eapol_sm_notify_lower_layer_success(struct eapol_sm *sm, - int in_eapol_sm) -{ -} -static inline void eapol_sm_invalidate_cached_session(struct eapol_sm *sm) -{ -} -static inline const char * eapol_sm_get_method_name(struct eapol_sm *sm) -{ - return NULL; -} -#endif /* IEEE8021X_EAPOL */ - -#endif /* EAPOL_SUPP_SM_H */ diff --git a/hostapd-0.8/src/l2_packet/Makefile b/hostapd-0.8/src/l2_packet/Makefile deleted file mode 100644 index 9c41962..0000000 --- a/hostapd-0.8/src/l2_packet/Makefile +++ /dev/null @@ -1,8 +0,0 @@ -all: - @echo Nothing to be made. - -clean: - rm -f *~ *.o *.d - -install: - @echo Nothing to be made. diff --git a/hostapd-0.8/src/l2_packet/l2_packet.h b/hostapd-0.8/src/l2_packet/l2_packet.h deleted file mode 100644 index c7b5014..0000000 --- a/hostapd-0.8/src/l2_packet/l2_packet.h +++ /dev/null @@ -1,130 +0,0 @@ -/* - * WPA Supplicant - Layer2 packet interface definition - * Copyright (c) 2003-2005, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - * - * This file defines an interface for layer 2 (link layer) packet sending and - * receiving. l2_packet_linux.c is one implementation for such a layer 2 - * implementation using Linux packet sockets and l2_packet_pcap.c another one - * using libpcap and libdnet. When porting %wpa_supplicant to other operating - * systems, a new l2_packet implementation may need to be added. - */ - -#ifndef L2_PACKET_H -#define L2_PACKET_H - -/** - * struct l2_packet_data - Internal l2_packet data structure - * - * This structure is used by the l2_packet implementation to store its private - * data. Other files use a pointer to this data when calling the l2_packet - * functions, but the contents of this structure should not be used directly - * outside l2_packet implementation. - */ -struct l2_packet_data; - -#ifdef _MSC_VER -#pragma pack(push, 1) -#endif /* _MSC_VER */ - -struct l2_ethhdr { - u8 h_dest[ETH_ALEN]; - u8 h_source[ETH_ALEN]; - be16 h_proto; -} STRUCT_PACKED; - -#ifdef _MSC_VER -#pragma pack(pop) -#endif /* _MSC_VER */ - -/** - * l2_packet_init - Initialize l2_packet interface - * @ifname: Interface name - * @own_addr: Optional own MAC address if available from driver interface or - * %NULL if not available - * @protocol: Ethernet protocol number in host byte order - * @rx_callback: Callback function that will be called for each received packet - * @rx_callback_ctx: Callback data (ctx) for calls to rx_callback() - * @l2_hdr: 1 = include layer 2 header, 0 = do not include header - * Returns: Pointer to internal data or %NULL on failure - * - * rx_callback function will be called with src_addr pointing to the source - * address (MAC address) of the the packet. If l2_hdr is set to 0, buf - * points to len bytes of the payload after the layer 2 header and similarly, - * TX buffers start with payload. This behavior can be changed by setting - * l2_hdr=1 to include the layer 2 header in the data buffer. - */ -struct l2_packet_data * l2_packet_init( - const char *ifname, const u8 *own_addr, unsigned short protocol, - void (*rx_callback)(void *ctx, const u8 *src_addr, - const u8 *buf, size_t len), - void *rx_callback_ctx, int l2_hdr); - -/** - * l2_packet_deinit - Deinitialize l2_packet interface - * @l2: Pointer to internal l2_packet data from l2_packet_init() - */ -void l2_packet_deinit(struct l2_packet_data *l2); - -/** - * l2_packet_get_own_addr - Get own layer 2 address - * @l2: Pointer to internal l2_packet data from l2_packet_init() - * @addr: Buffer for the own address (6 bytes) - * Returns: 0 on success, -1 on failure - */ -int l2_packet_get_own_addr(struct l2_packet_data *l2, u8 *addr); - -/** - * l2_packet_send - Send a packet - * @l2: Pointer to internal l2_packet data from l2_packet_init() - * @dst_addr: Destination address for the packet (only used if l2_hdr == 0) - * @proto: Protocol/ethertype for the packet in host byte order (only used if - * l2_hdr == 0) - * @buf: Packet contents to be sent; including layer 2 header if l2_hdr was - * set to 1 in l2_packet_init() call. Otherwise, only the payload of the packet - * is included. - * @len: Length of the buffer (including l2 header only if l2_hdr == 1) - * Returns: >=0 on success, <0 on failure - */ -int l2_packet_send(struct l2_packet_data *l2, const u8 *dst_addr, u16 proto, - const u8 *buf, size_t len); - -/** - * l2_packet_get_ip_addr - Get the current IP address from the interface - * @l2: Pointer to internal l2_packet data from l2_packet_init() - * @buf: Buffer for the IP address in text format - * @len: Maximum buffer length - * Returns: 0 on success, -1 on failure - * - * This function can be used to get the current IP address from the interface - * bound to the l2_packet. This is mainly for status information and the IP - * address will be stored as an ASCII string. This function is not essential - * for %wpa_supplicant operation, so full implementation is not required. - * l2_packet implementation will need to define the function, but it can return - * -1 if the IP address information is not available. - */ -int l2_packet_get_ip_addr(struct l2_packet_data *l2, char *buf, size_t len); - - -/** - * l2_packet_notify_auth_start - Notify l2_packet about start of authentication - * @l2: Pointer to internal l2_packet data from l2_packet_init() - * - * This function is called when authentication is expected to start, e.g., when - * association has been completed, in order to prepare l2_packet implementation - * for EAPOL frames. This function is used mainly if the l2_packet code needs - * to do polling in which case it can increasing polling frequency. This can - * also be an empty function if the l2_packet implementation does not benefit - * from knowing about the starting authentication. - */ -void l2_packet_notify_auth_start(struct l2_packet_data *l2); - -#endif /* L2_PACKET_H */ diff --git a/hostapd-0.8/src/l2_packet/l2_packet_freebsd.c b/hostapd-0.8/src/l2_packet/l2_packet_freebsd.c deleted file mode 100644 index e24277c..0000000 --- a/hostapd-0.8/src/l2_packet/l2_packet_freebsd.c +++ /dev/null @@ -1,316 +0,0 @@ -/* - * WPA Supplicant - Layer2 packet handling with FreeBSD - * Copyright (c) 2003-2005, Jouni Malinen - * Copyright (c) 2005, Sam Leffler - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#include "includes.h" -#if defined(__APPLE__) || defined(__GLIBC__) -#include -#endif /* __APPLE__ */ -#include - -#include -#ifdef __sun__ -#include -#else /* __sun__ */ -#include -#endif /* __sun__ */ - -#include -#include -#include -#include - -#include "common.h" -#include "eloop.h" -#include "l2_packet.h" - - -static const u8 pae_group_addr[ETH_ALEN] = -{ 0x01, 0x80, 0xc2, 0x00, 0x00, 0x03 }; - -struct l2_packet_data { - pcap_t *pcap; - char ifname[100]; - u8 own_addr[ETH_ALEN]; - void (*rx_callback)(void *ctx, const u8 *src_addr, - const u8 *buf, size_t len); - void *rx_callback_ctx; - int l2_hdr; /* whether to include layer 2 (Ethernet) header data - * buffers */ -}; - - -int l2_packet_get_own_addr(struct l2_packet_data *l2, u8 *addr) -{ - os_memcpy(addr, l2->own_addr, ETH_ALEN); - return 0; -} - - -int l2_packet_send(struct l2_packet_data *l2, const u8 *dst_addr, u16 proto, - const u8 *buf, size_t len) -{ - if (!l2->l2_hdr) { - int ret; - struct l2_ethhdr *eth = os_malloc(sizeof(*eth) + len); - if (eth == NULL) - return -1; - os_memcpy(eth->h_dest, dst_addr, ETH_ALEN); - os_memcpy(eth->h_source, l2->own_addr, ETH_ALEN); - eth->h_proto = htons(proto); - os_memcpy(eth + 1, buf, len); - ret = pcap_inject(l2->pcap, (u8 *) eth, len + sizeof(*eth)); - os_free(eth); - return ret; - } else - return pcap_inject(l2->pcap, buf, len); -} - - -static void l2_packet_receive(int sock, void *eloop_ctx, void *sock_ctx) -{ - struct l2_packet_data *l2 = eloop_ctx; - pcap_t *pcap = sock_ctx; - struct pcap_pkthdr hdr; - const u_char *packet; - struct l2_ethhdr *ethhdr; - unsigned char *buf; - size_t len; - - packet = pcap_next(pcap, &hdr); - - if (packet == NULL || hdr.caplen < sizeof(*ethhdr)) - return; - - ethhdr = (struct l2_ethhdr *) packet; - if (l2->l2_hdr) { - buf = (unsigned char *) ethhdr; - len = hdr.caplen; - } else { - buf = (unsigned char *) (ethhdr + 1); - len = hdr.caplen - sizeof(*ethhdr); - } - l2->rx_callback(l2->rx_callback_ctx, ethhdr->h_source, buf, len); -} - - -static int l2_packet_init_libpcap(struct l2_packet_data *l2, - unsigned short protocol) -{ - bpf_u_int32 pcap_maskp, pcap_netp; - char pcap_filter[200], pcap_err[PCAP_ERRBUF_SIZE]; - struct bpf_program pcap_fp; - - pcap_lookupnet(l2->ifname, &pcap_netp, &pcap_maskp, pcap_err); - l2->pcap = pcap_open_live(l2->ifname, 2500, 0, 10, pcap_err); - if (l2->pcap == NULL) { - fprintf(stderr, "pcap_open_live: %s\n", pcap_err); - fprintf(stderr, "ifname='%s'\n", l2->ifname); - return -1; - } - if (pcap_datalink(l2->pcap) != DLT_EN10MB && - pcap_set_datalink(l2->pcap, DLT_EN10MB) < 0) { - fprintf(stderr, "pcap_set_datalink(DLT_EN10MB): %s\n", - pcap_geterr(l2->pcap)); - return -1; - } - os_snprintf(pcap_filter, sizeof(pcap_filter), - "not ether src " MACSTR " and " - "( ether dst " MACSTR " or ether dst " MACSTR " ) and " - "ether proto 0x%x", - MAC2STR(l2->own_addr), /* do not receive own packets */ - MAC2STR(l2->own_addr), MAC2STR(pae_group_addr), - protocol); - if (pcap_compile(l2->pcap, &pcap_fp, pcap_filter, 1, pcap_netp) < 0) { - fprintf(stderr, "pcap_compile: %s\n", pcap_geterr(l2->pcap)); - return -1; - } - - if (pcap_setfilter(l2->pcap, &pcap_fp) < 0) { - fprintf(stderr, "pcap_setfilter: %s\n", pcap_geterr(l2->pcap)); - return -1; - } - - pcap_freecode(&pcap_fp); -#ifndef __sun__ - /* - * When libpcap uses BPF we must enable "immediate mode" to - * receive frames right away; otherwise the system may - * buffer them for us. - */ - { - unsigned int on = 1; - if (ioctl(pcap_fileno(l2->pcap), BIOCIMMEDIATE, &on) < 0) { - fprintf(stderr, "%s: cannot enable immediate mode on " - "interface %s: %s\n", - __func__, l2->ifname, strerror(errno)); - /* XXX should we fail? */ - } - } -#endif /* __sun__ */ - - eloop_register_read_sock(pcap_get_selectable_fd(l2->pcap), - l2_packet_receive, l2, l2->pcap); - - return 0; -} - - -static int eth_get(const char *device, u8 ea[ETH_ALEN]) -{ -#ifdef __sun__ - dlpi_handle_t dh; - u32 physaddrlen = DLPI_PHYSADDR_MAX; - u8 physaddr[DLPI_PHYSADDR_MAX]; - int retval; - - retval = dlpi_open(device, &dh, 0); - if (retval != DLPI_SUCCESS) { - wpa_printf(MSG_ERROR, "dlpi_open error: %s", - dlpi_strerror(retval)); - return -1; - } - - retval = dlpi_get_physaddr(dh, DL_CURR_PHYS_ADDR, physaddr, - &physaddrlen); - if (retval != DLPI_SUCCESS) { - wpa_printf(MSG_ERROR, "dlpi_get_physaddr error: %s", - dlpi_strerror(retval)); - dlpi_close(dh); - return -1; - } - os_memcpy(ea, physaddr, ETH_ALEN); - dlpi_close(dh); -#else /* __sun__ */ - struct if_msghdr *ifm; - struct sockaddr_dl *sdl; - u_char *p, *buf; - size_t len; - int mib[] = { CTL_NET, AF_ROUTE, 0, AF_LINK, NET_RT_IFLIST, 0 }; - - if (sysctl(mib, 6, NULL, &len, NULL, 0) < 0) - return -1; - if ((buf = os_malloc(len)) == NULL) - return -1; - if (sysctl(mib, 6, buf, &len, NULL, 0) < 0) { - os_free(buf); - return -1; - } - for (p = buf; p < buf + len; p += ifm->ifm_msglen) { - ifm = (struct if_msghdr *)p; - sdl = (struct sockaddr_dl *)(ifm + 1); - if (ifm->ifm_type != RTM_IFINFO || - (ifm->ifm_addrs & RTA_IFP) == 0) - continue; - if (sdl->sdl_family != AF_LINK || sdl->sdl_nlen == 0 || - os_memcmp(sdl->sdl_data, device, sdl->sdl_nlen) != 0) - continue; - os_memcpy(ea, LLADDR(sdl), sdl->sdl_alen); - break; - } - os_free(buf); - - if (p >= buf + len) { - errno = ESRCH; - return -1; - } -#endif /* __sun__ */ - return 0; -} - - -struct l2_packet_data * l2_packet_init( - const char *ifname, const u8 *own_addr, unsigned short protocol, - void (*rx_callback)(void *ctx, const u8 *src_addr, - const u8 *buf, size_t len), - void *rx_callback_ctx, int l2_hdr) -{ - struct l2_packet_data *l2; - - l2 = os_zalloc(sizeof(struct l2_packet_data)); - if (l2 == NULL) - return NULL; - os_strlcpy(l2->ifname, ifname, sizeof(l2->ifname)); - l2->rx_callback = rx_callback; - l2->rx_callback_ctx = rx_callback_ctx; - l2->l2_hdr = l2_hdr; - - if (eth_get(l2->ifname, l2->own_addr) < 0) { - fprintf(stderr, "Failed to get link-level address for " - "interface '%s'.\n", l2->ifname); - os_free(l2); - return NULL; - } - - if (l2_packet_init_libpcap(l2, protocol)) { - os_free(l2); - return NULL; - } - - return l2; -} - - -void l2_packet_deinit(struct l2_packet_data *l2) -{ - if (l2 != NULL) { - if (l2->pcap) { - eloop_unregister_read_sock( - pcap_get_selectable_fd(l2->pcap)); - pcap_close(l2->pcap); - } - os_free(l2); - } -} - - -int l2_packet_get_ip_addr(struct l2_packet_data *l2, char *buf, size_t len) -{ - pcap_if_t *devs, *dev; - struct pcap_addr *addr; - struct sockaddr_in *saddr; - int found = 0; - char err[PCAP_ERRBUF_SIZE + 1]; - - if (pcap_findalldevs(&devs, err) < 0) { - wpa_printf(MSG_DEBUG, "pcap_findalldevs: %s\n", err); - return -1; - } - - for (dev = devs; dev && !found; dev = dev->next) { - if (os_strcmp(dev->name, l2->ifname) != 0) - continue; - - addr = dev->addresses; - while (addr) { - saddr = (struct sockaddr_in *) addr->addr; - if (saddr && saddr->sin_family == AF_INET) { - os_strlcpy(buf, inet_ntoa(saddr->sin_addr), - len); - found = 1; - break; - } - addr = addr->next; - } - } - - pcap_freealldevs(devs); - - return found ? 0 : -1; -} - - -void l2_packet_notify_auth_start(struct l2_packet_data *l2) -{ -} diff --git a/hostapd-0.8/src/l2_packet/l2_packet_linux.c b/hostapd-0.8/src/l2_packet/l2_packet_linux.c deleted file mode 100644 index 93e15eb..0000000 --- a/hostapd-0.8/src/l2_packet/l2_packet_linux.c +++ /dev/null @@ -1,210 +0,0 @@ -/* - * WPA Supplicant - Layer2 packet handling with Linux packet sockets - * Copyright (c) 2003-2005, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#include "includes.h" -#include -#include -#include - -#include "common.h" -#include "eloop.h" -#include "l2_packet.h" - - -struct l2_packet_data { - int fd; /* packet socket for EAPOL frames */ - char ifname[IFNAMSIZ + 1]; - int ifindex; - u8 own_addr[ETH_ALEN]; - void (*rx_callback)(void *ctx, const u8 *src_addr, - const u8 *buf, size_t len); - void *rx_callback_ctx; - int l2_hdr; /* whether to include layer 2 (Ethernet) header data - * buffers */ -}; - - -int l2_packet_get_own_addr(struct l2_packet_data *l2, u8 *addr) -{ - os_memcpy(addr, l2->own_addr, ETH_ALEN); - return 0; -} - - -int l2_packet_send(struct l2_packet_data *l2, const u8 *dst_addr, u16 proto, - const u8 *buf, size_t len) -{ - int ret; - if (l2 == NULL) - return -1; - if (l2->l2_hdr) { - ret = send(l2->fd, buf, len, 0); - if (ret < 0) - wpa_printf(MSG_ERROR, "l2_packet_send - send: %s", - strerror(errno)); - } else { - struct sockaddr_ll ll; - os_memset(&ll, 0, sizeof(ll)); - ll.sll_family = AF_PACKET; - ll.sll_ifindex = l2->ifindex; - ll.sll_protocol = htons(proto); - ll.sll_halen = ETH_ALEN; - os_memcpy(ll.sll_addr, dst_addr, ETH_ALEN); - ret = sendto(l2->fd, buf, len, 0, (struct sockaddr *) &ll, - sizeof(ll)); - if (ret < 0) { - wpa_printf(MSG_ERROR, "l2_packet_send - sendto: %s", - strerror(errno)); - } - } - return ret; -} - - -static void l2_packet_receive(int sock, void *eloop_ctx, void *sock_ctx) -{ - struct l2_packet_data *l2 = eloop_ctx; - u8 buf[2300]; - int res; - struct sockaddr_ll ll; - socklen_t fromlen; - - os_memset(&ll, 0, sizeof(ll)); - fromlen = sizeof(ll); - res = recvfrom(sock, buf, sizeof(buf), 0, (struct sockaddr *) &ll, - &fromlen); - if (res < 0) { - wpa_printf(MSG_DEBUG, "l2_packet_receive - recvfrom: %s", - strerror(errno)); - return; - } - - l2->rx_callback(l2->rx_callback_ctx, ll.sll_addr, buf, res); -} - - -struct l2_packet_data * l2_packet_init( - const char *ifname, const u8 *own_addr, unsigned short protocol, - void (*rx_callback)(void *ctx, const u8 *src_addr, - const u8 *buf, size_t len), - void *rx_callback_ctx, int l2_hdr) -{ - struct l2_packet_data *l2; - struct ifreq ifr; - struct sockaddr_ll ll; - - l2 = os_zalloc(sizeof(struct l2_packet_data)); - if (l2 == NULL) - return NULL; - os_strlcpy(l2->ifname, ifname, sizeof(l2->ifname)); - l2->rx_callback = rx_callback; - l2->rx_callback_ctx = rx_callback_ctx; - l2->l2_hdr = l2_hdr; - - l2->fd = socket(PF_PACKET, l2_hdr ? SOCK_RAW : SOCK_DGRAM, - htons(protocol)); - if (l2->fd < 0) { - wpa_printf(MSG_ERROR, "%s: socket(PF_PACKET): %s", - __func__, strerror(errno)); - os_free(l2); - return NULL; - } - os_memset(&ifr, 0, sizeof(ifr)); - os_strlcpy(ifr.ifr_name, l2->ifname, sizeof(ifr.ifr_name)); - if (ioctl(l2->fd, SIOCGIFINDEX, &ifr) < 0) { - wpa_printf(MSG_ERROR, "%s: ioctl[SIOCGIFINDEX]: %s", - __func__, strerror(errno)); - close(l2->fd); - os_free(l2); - return NULL; - } - l2->ifindex = ifr.ifr_ifindex; - - os_memset(&ll, 0, sizeof(ll)); - ll.sll_family = PF_PACKET; - ll.sll_ifindex = ifr.ifr_ifindex; - ll.sll_protocol = htons(protocol); - if (bind(l2->fd, (struct sockaddr *) &ll, sizeof(ll)) < 0) { - wpa_printf(MSG_ERROR, "%s: bind[PF_PACKET]: %s", - __func__, strerror(errno)); - close(l2->fd); - os_free(l2); - return NULL; - } - - if (ioctl(l2->fd, SIOCGIFHWADDR, &ifr) < 0) { - wpa_printf(MSG_ERROR, "%s: ioctl[SIOCGIFHWADDR]: %s", - __func__, strerror(errno)); - close(l2->fd); - os_free(l2); - return NULL; - } - os_memcpy(l2->own_addr, ifr.ifr_hwaddr.sa_data, ETH_ALEN); - - eloop_register_read_sock(l2->fd, l2_packet_receive, l2, NULL); - - return l2; -} - - -void l2_packet_deinit(struct l2_packet_data *l2) -{ - if (l2 == NULL) - return; - - if (l2->fd >= 0) { - eloop_unregister_read_sock(l2->fd); - close(l2->fd); - } - - os_free(l2); -} - - -int l2_packet_get_ip_addr(struct l2_packet_data *l2, char *buf, size_t len) -{ - int s; - struct ifreq ifr; - struct sockaddr_in *saddr; - size_t res; - - s = socket(PF_INET, SOCK_DGRAM, 0); - if (s < 0) { - wpa_printf(MSG_ERROR, "%s: socket: %s", - __func__, strerror(errno)); - return -1; - } - os_memset(&ifr, 0, sizeof(ifr)); - os_strlcpy(ifr.ifr_name, l2->ifname, sizeof(ifr.ifr_name)); - if (ioctl(s, SIOCGIFADDR, &ifr) < 0) { - if (errno != EADDRNOTAVAIL) - wpa_printf(MSG_ERROR, "%s: ioctl[SIOCGIFADDR]: %s", - __func__, strerror(errno)); - close(s); - return -1; - } - close(s); - saddr = aliasing_hide_typecast(&ifr.ifr_addr, struct sockaddr_in); - if (saddr->sin_family != AF_INET) - return -1; - res = os_strlcpy(buf, inet_ntoa(saddr->sin_addr), len); - if (res >= len) - return -1; - return 0; -} - - -void l2_packet_notify_auth_start(struct l2_packet_data *l2) -{ -} diff --git a/hostapd-0.8/src/l2_packet/l2_packet_ndis.c b/hostapd-0.8/src/l2_packet/l2_packet_ndis.c deleted file mode 100644 index 6ce29aa..0000000 --- a/hostapd-0.8/src/l2_packet/l2_packet_ndis.c +++ /dev/null @@ -1,522 +0,0 @@ -/* - * WPA Supplicant - Layer2 packet handling with Microsoft NDISUIO - * Copyright (c) 2003-2006, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - * - * This implementation requires Windows specific event loop implementation, - * i.e., eloop_win.c. In addition, the NDISUIO connection is shared with - * driver_ndis.c, so only that driver interface can be used and - * CONFIG_USE_NDISUIO must be defined. - * - * WinXP version of the code uses overlapped I/O and a single threaded design - * with callback functions from I/O code. WinCE version uses a separate RX - * thread that blocks on ReadFile() whenever the media status is connected. - */ - -#include "includes.h" -#include -#include - -#ifdef _WIN32_WCE -#include -#include -#endif /* _WIN32_WCE */ - -#include "common.h" -#include "eloop.h" -#include "l2_packet.h" - -#ifndef _WIN32_WCE -/* from nuiouser.h */ -#define FSCTL_NDISUIO_BASE FILE_DEVICE_NETWORK -#define _NDISUIO_CTL_CODE(_Function, _Method, _Access) \ - CTL_CODE(FSCTL_NDISUIO_BASE, _Function, _Method, _Access) -#define IOCTL_NDISUIO_SET_ETHER_TYPE \ - _NDISUIO_CTL_CODE(0x202, METHOD_BUFFERED, \ - FILE_READ_ACCESS | FILE_WRITE_ACCESS) -#endif /* _WIN32_WCE */ - -/* From driver_ndis.c to shared the handle to NDISUIO */ -HANDLE driver_ndis_get_ndisuio_handle(void); - -/* - * NDISUIO supports filtering of only one ethertype at the time, so we must - * fake support for two (EAPOL and RSN pre-auth) by switching to pre-auth - * whenever wpa_supplicant is trying to pre-authenticate and then switching - * back to EAPOL when pre-authentication has been completed. - */ - -struct l2_packet_data; - -struct l2_packet_ndisuio_global { - int refcount; - unsigned short first_proto; - struct l2_packet_data *l2[2]; -#ifdef _WIN32_WCE - HANDLE rx_thread; - HANDLE stop_request; - HANDLE ready_for_read; - HANDLE rx_processed; -#endif /* _WIN32_WCE */ -}; - -static struct l2_packet_ndisuio_global *l2_ndisuio_global = NULL; - -struct l2_packet_data { - char ifname[100]; - u8 own_addr[ETH_ALEN]; - void (*rx_callback)(void *ctx, const u8 *src_addr, - const u8 *buf, size_t len); - void *rx_callback_ctx; - int l2_hdr; /* whether to include layer 2 (Ethernet) header in calls to - * rx_callback and l2_packet_send() */ - HANDLE rx_avail; -#ifndef _WIN32_WCE - OVERLAPPED rx_overlapped; -#endif /* _WIN32_WCE */ - u8 rx_buf[1514]; - DWORD rx_written; -}; - - -int l2_packet_get_own_addr(struct l2_packet_data *l2, u8 *addr) -{ - os_memcpy(addr, l2->own_addr, ETH_ALEN); - return 0; -} - - -int l2_packet_send(struct l2_packet_data *l2, const u8 *dst_addr, u16 proto, - const u8 *buf, size_t len) -{ - BOOL res; - DWORD written; - struct l2_ethhdr *eth; -#ifndef _WIN32_WCE - OVERLAPPED overlapped; -#endif /* _WIN32_WCE */ - OVERLAPPED *o; - - if (l2 == NULL) - return -1; - -#ifdef _WIN32_WCE - o = NULL; -#else /* _WIN32_WCE */ - os_memset(&overlapped, 0, sizeof(overlapped)); - o = &overlapped; -#endif /* _WIN32_WCE */ - - if (l2->l2_hdr) { - res = WriteFile(driver_ndis_get_ndisuio_handle(), buf, len, - &written, o); - } else { - size_t mlen = sizeof(*eth) + len; - eth = os_malloc(mlen); - if (eth == NULL) - return -1; - - os_memcpy(eth->h_dest, dst_addr, ETH_ALEN); - os_memcpy(eth->h_source, l2->own_addr, ETH_ALEN); - eth->h_proto = htons(proto); - os_memcpy(eth + 1, buf, len); - res = WriteFile(driver_ndis_get_ndisuio_handle(), eth, mlen, - &written, o); - os_free(eth); - } - - if (!res) { - DWORD err = GetLastError(); -#ifndef _WIN32_WCE - if (err == ERROR_IO_PENDING) { - wpa_printf(MSG_DEBUG, "L2(NDISUIO): Wait for pending " - "write to complete"); - res = GetOverlappedResult( - driver_ndis_get_ndisuio_handle(), &overlapped, - &written, TRUE); - if (!res) { - wpa_printf(MSG_DEBUG, "L2(NDISUIO): " - "GetOverlappedResult failed: %d", - (int) GetLastError()); - return -1; - } - return 0; - } -#endif /* _WIN32_WCE */ - wpa_printf(MSG_DEBUG, "L2(NDISUIO): WriteFile failed: %d", - (int) GetLastError()); - return -1; - } - - return 0; -} - - -static void l2_packet_callback(struct l2_packet_data *l2); - -#ifdef _WIN32_WCE -static void l2_packet_rx_thread_try_read(struct l2_packet_data *l2) -{ - HANDLE handles[2]; - - wpa_printf(MSG_MSGDUMP, "l2_packet_rx_thread: -> ReadFile"); - if (!ReadFile(driver_ndis_get_ndisuio_handle(), l2->rx_buf, - sizeof(l2->rx_buf), &l2->rx_written, NULL)) { - DWORD err = GetLastError(); - wpa_printf(MSG_DEBUG, "l2_packet_rx_thread: ReadFile failed: " - "%d", (int) err); - /* - * ReadFile on NDISUIO/WinCE returns ERROR_DEVICE_NOT_CONNECTED - * error whenever the connection is not up. Yield the thread to - * avoid triggering a busy loop. Connection event should stop - * us from looping for long, but we need to allow enough CPU - * for the main thread to process the media disconnection. - */ - Sleep(100); - return; - } - - wpa_printf(MSG_DEBUG, "l2_packet_rx_thread: Read %d byte packet", - (int) l2->rx_written); - - /* - * Notify the main thread about the availability of a frame and wait - * for the frame to be processed. - */ - SetEvent(l2->rx_avail); - handles[0] = l2_ndisuio_global->stop_request; - handles[1] = l2_ndisuio_global->rx_processed; - WaitForMultipleObjects(2, handles, FALSE, INFINITE); - ResetEvent(l2_ndisuio_global->rx_processed); -} - - -static DWORD WINAPI l2_packet_rx_thread(LPVOID arg) -{ - struct l2_packet_data *l2 = arg; - DWORD res; - HANDLE handles[2]; - int run = 1; - - wpa_printf(MSG_DEBUG, "L2(NDISUIO): RX thread started"); - handles[0] = l2_ndisuio_global->stop_request; - handles[1] = l2_ndisuio_global->ready_for_read; - - /* - * Unfortunately, NDISUIO on WinCE does not seem to support waiting - * on the handle. There do not seem to be anything else that we could - * wait for either. If one were to modify NDISUIO to set a named event - * whenever packets are available, this event could be used here to - * avoid having to poll for new packets or we could even move to use a - * single threaded design. - * - * In addition, NDISUIO on WinCE is returning - * ERROR_DEVICE_NOT_CONNECTED whenever ReadFile() is attempted while - * the adapter is not in connected state. For now, we are just using a - * local event to allow ReadFile calls only after having received NDIS - * media connect event. This event could be easily converted to handle - * another event if the protocol driver is replaced with somewhat more - * useful design. - */ - - while (l2_ndisuio_global && run) { - res = WaitForMultipleObjects(2, handles, FALSE, INFINITE); - switch (res) { - case WAIT_OBJECT_0: - wpa_printf(MSG_DEBUG, "l2_packet_rx_thread: Received " - "request to stop RX thread"); - run = 0; - break; - case WAIT_OBJECT_0 + 1: - l2_packet_rx_thread_try_read(l2); - break; - case WAIT_FAILED: - default: - wpa_printf(MSG_DEBUG, "l2_packet_rx_thread: " - "WaitForMultipleObjects failed: %d", - (int) GetLastError()); - run = 0; - break; - } - } - - wpa_printf(MSG_DEBUG, "L2(NDISUIO): RX thread stopped"); - - return 0; -} -#else /* _WIN32_WCE */ -static int l2_ndisuio_start_read(struct l2_packet_data *l2, int recursive) -{ - os_memset(&l2->rx_overlapped, 0, sizeof(l2->rx_overlapped)); - l2->rx_overlapped.hEvent = l2->rx_avail; - if (!ReadFile(driver_ndis_get_ndisuio_handle(), l2->rx_buf, - sizeof(l2->rx_buf), &l2->rx_written, &l2->rx_overlapped)) - { - DWORD err = GetLastError(); - if (err != ERROR_IO_PENDING) { - wpa_printf(MSG_DEBUG, "L2(NDISUIO): ReadFile failed: " - "%d", (int) err); - return -1; - } - /* - * Once read is completed, l2_packet_rx_event() will be - * called. - */ - } else { - wpa_printf(MSG_DEBUG, "L2(NDISUIO): ReadFile returned data " - "without wait for completion"); - if (!recursive) - l2_packet_callback(l2); - } - - return 0; -} -#endif /* _WIN32_WCE */ - - -static void l2_packet_callback(struct l2_packet_data *l2) -{ - const u8 *rx_buf, *rx_src; - size_t rx_len; - struct l2_ethhdr *ethhdr = (struct l2_ethhdr *) l2->rx_buf; - - wpa_printf(MSG_DEBUG, "L2(NDISUIO): Read %d bytes", - (int) l2->rx_written); - - if (l2->l2_hdr || l2->rx_written < sizeof(*ethhdr)) { - rx_buf = (u8 *) ethhdr; - rx_len = l2->rx_written; - } else { - rx_buf = (u8 *) (ethhdr + 1); - rx_len = l2->rx_written - sizeof(*ethhdr); - } - rx_src = ethhdr->h_source; - - l2->rx_callback(l2->rx_callback_ctx, rx_src, rx_buf, rx_len); -#ifndef _WIN32_WCE - l2_ndisuio_start_read(l2, 1); -#endif /* _WIN32_WCE */ -} - - -static void l2_packet_rx_event(void *eloop_data, void *user_data) -{ - struct l2_packet_data *l2 = eloop_data; - - if (l2_ndisuio_global) - l2 = l2_ndisuio_global->l2[l2_ndisuio_global->refcount - 1]; - - ResetEvent(l2->rx_avail); - -#ifndef _WIN32_WCE - if (!GetOverlappedResult(driver_ndis_get_ndisuio_handle(), - &l2->rx_overlapped, &l2->rx_written, FALSE)) { - wpa_printf(MSG_DEBUG, "L2(NDISUIO): GetOverlappedResult " - "failed: %d", (int) GetLastError()); - return; - } -#endif /* _WIN32_WCE */ - - l2_packet_callback(l2); - -#ifdef _WIN32_WCE - SetEvent(l2_ndisuio_global->rx_processed); -#endif /* _WIN32_WCE */ -} - - -static int l2_ndisuio_set_ether_type(unsigned short protocol) -{ - USHORT proto = htons(protocol); - DWORD written; - - if (!DeviceIoControl(driver_ndis_get_ndisuio_handle(), - IOCTL_NDISUIO_SET_ETHER_TYPE, &proto, - sizeof(proto), NULL, 0, &written, NULL)) { - wpa_printf(MSG_ERROR, "L2(NDISUIO): " - "IOCTL_NDISUIO_SET_ETHER_TYPE failed: %d", - (int) GetLastError()); - return -1; - } - - return 0; -} - - -struct l2_packet_data * l2_packet_init( - const char *ifname, const u8 *own_addr, unsigned short protocol, - void (*rx_callback)(void *ctx, const u8 *src_addr, - const u8 *buf, size_t len), - void *rx_callback_ctx, int l2_hdr) -{ - struct l2_packet_data *l2; - - if (l2_ndisuio_global == NULL) { - l2_ndisuio_global = os_zalloc(sizeof(*l2_ndisuio_global)); - if (l2_ndisuio_global == NULL) - return NULL; - l2_ndisuio_global->first_proto = protocol; - } - if (l2_ndisuio_global->refcount >= 2) { - wpa_printf(MSG_ERROR, "L2(NDISUIO): Not more than two " - "simultaneous connections allowed"); - return NULL; - } - l2_ndisuio_global->refcount++; - - l2 = os_zalloc(sizeof(struct l2_packet_data)); - if (l2 == NULL) - return NULL; - l2_ndisuio_global->l2[l2_ndisuio_global->refcount - 1] = l2; - - os_strlcpy(l2->ifname, ifname, sizeof(l2->ifname)); - l2->rx_callback = rx_callback; - l2->rx_callback_ctx = rx_callback_ctx; - l2->l2_hdr = l2_hdr; - - if (own_addr) - os_memcpy(l2->own_addr, own_addr, ETH_ALEN); - - if (l2_ndisuio_set_ether_type(protocol) < 0) { - os_free(l2); - return NULL; - } - - if (l2_ndisuio_global->refcount > 1) { - wpa_printf(MSG_DEBUG, "L2(NDISUIO): Temporarily setting " - "filtering ethertype to %04x", protocol); - if (l2_ndisuio_global->l2[0]) - l2->rx_avail = l2_ndisuio_global->l2[0]->rx_avail; - return l2; - } - - l2->rx_avail = CreateEvent(NULL, TRUE, FALSE, NULL); - if (l2->rx_avail == NULL) { - os_free(l2); - return NULL; - } - - eloop_register_event(l2->rx_avail, sizeof(l2->rx_avail), - l2_packet_rx_event, l2, NULL); - -#ifdef _WIN32_WCE - l2_ndisuio_global->stop_request = CreateEvent(NULL, TRUE, FALSE, NULL); - /* - * This event is being set based on media connect/disconnect - * notifications in driver_ndis.c. - */ - l2_ndisuio_global->ready_for_read = - CreateEvent(NULL, TRUE, FALSE, TEXT("WpaSupplicantConnected")); - l2_ndisuio_global->rx_processed = CreateEvent(NULL, TRUE, FALSE, NULL); - if (l2_ndisuio_global->stop_request == NULL || - l2_ndisuio_global->ready_for_read == NULL || - l2_ndisuio_global->rx_processed == NULL) { - if (l2_ndisuio_global->stop_request) { - CloseHandle(l2_ndisuio_global->stop_request); - l2_ndisuio_global->stop_request = NULL; - } - if (l2_ndisuio_global->ready_for_read) { - CloseHandle(l2_ndisuio_global->ready_for_read); - l2_ndisuio_global->ready_for_read = NULL; - } - if (l2_ndisuio_global->rx_processed) { - CloseHandle(l2_ndisuio_global->rx_processed); - l2_ndisuio_global->rx_processed = NULL; - } - eloop_unregister_event(l2->rx_avail, sizeof(l2->rx_avail)); - os_free(l2); - return NULL; - } - - l2_ndisuio_global->rx_thread = CreateThread(NULL, 0, - l2_packet_rx_thread, l2, 0, - NULL); - if (l2_ndisuio_global->rx_thread == NULL) { - wpa_printf(MSG_INFO, "L2(NDISUIO): Failed to create RX " - "thread: %d", (int) GetLastError()); - eloop_unregister_event(l2->rx_avail, sizeof(l2->rx_avail)); - CloseHandle(l2_ndisuio_global->stop_request); - l2_ndisuio_global->stop_request = NULL; - os_free(l2); - return NULL; - } -#else /* _WIN32_WCE */ - l2_ndisuio_start_read(l2, 0); -#endif /* _WIN32_WCE */ - - return l2; -} - - -void l2_packet_deinit(struct l2_packet_data *l2) -{ - if (l2 == NULL) - return; - - if (l2_ndisuio_global) { - l2_ndisuio_global->refcount--; - l2_ndisuio_global->l2[l2_ndisuio_global->refcount] = NULL; - if (l2_ndisuio_global->refcount) { - wpa_printf(MSG_DEBUG, "L2(NDISUIO): restore filtering " - "ethertype to %04x", - l2_ndisuio_global->first_proto); - l2_ndisuio_set_ether_type( - l2_ndisuio_global->first_proto); - return; - } - -#ifdef _WIN32_WCE - wpa_printf(MSG_DEBUG, "L2(NDISUIO): Waiting for RX thread to " - "stop"); - SetEvent(l2_ndisuio_global->stop_request); - /* - * Cancel pending ReadFile() in the RX thread (if we were still - * connected at this point). - */ - if (!DeviceIoControl(driver_ndis_get_ndisuio_handle(), - IOCTL_CANCEL_READ, NULL, 0, NULL, 0, NULL, - NULL)) { - wpa_printf(MSG_DEBUG, "L2(NDISUIO): IOCTL_CANCEL_READ " - "failed: %d", (int) GetLastError()); - /* RX thread will exit blocking ReadFile once NDISUIO - * notices that the adapter is disconnected. */ - } - WaitForSingleObject(l2_ndisuio_global->rx_thread, INFINITE); - wpa_printf(MSG_DEBUG, "L2(NDISUIO): RX thread exited"); - CloseHandle(l2_ndisuio_global->rx_thread); - CloseHandle(l2_ndisuio_global->stop_request); - CloseHandle(l2_ndisuio_global->ready_for_read); - CloseHandle(l2_ndisuio_global->rx_processed); -#endif /* _WIN32_WCE */ - - os_free(l2_ndisuio_global); - l2_ndisuio_global = NULL; - } - -#ifndef _WIN32_WCE - CancelIo(driver_ndis_get_ndisuio_handle()); -#endif /* _WIN32_WCE */ - - eloop_unregister_event(l2->rx_avail, sizeof(l2->rx_avail)); - CloseHandle(l2->rx_avail); - os_free(l2); -} - - -int l2_packet_get_ip_addr(struct l2_packet_data *l2, char *buf, size_t len) -{ - return -1; -} - - -void l2_packet_notify_auth_start(struct l2_packet_data *l2) -{ -} diff --git a/hostapd-0.8/src/l2_packet/l2_packet_none.c b/hostapd-0.8/src/l2_packet/l2_packet_none.c deleted file mode 100644 index 5e3f6e9..0000000 --- a/hostapd-0.8/src/l2_packet/l2_packet_none.c +++ /dev/null @@ -1,123 +0,0 @@ -/* - * WPA Supplicant - Layer2 packet handling example with dummy functions - * Copyright (c) 2003-2005, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - * - * This file can be used as a starting point for layer2 packet implementation. - */ - -#include "includes.h" - -#include "common.h" -#include "eloop.h" -#include "l2_packet.h" - - -struct l2_packet_data { - char ifname[17]; - u8 own_addr[ETH_ALEN]; - void (*rx_callback)(void *ctx, const u8 *src_addr, - const u8 *buf, size_t len); - void *rx_callback_ctx; - int l2_hdr; /* whether to include layer 2 (Ethernet) header data - * buffers */ - int fd; -}; - - -int l2_packet_get_own_addr(struct l2_packet_data *l2, u8 *addr) -{ - os_memcpy(addr, l2->own_addr, ETH_ALEN); - return 0; -} - - -int l2_packet_send(struct l2_packet_data *l2, const u8 *dst_addr, u16 proto, - const u8 *buf, size_t len) -{ - if (l2 == NULL) - return -1; - - /* - * TODO: Send frame (may need different implementation depending on - * whether l2->l2_hdr is set). - */ - - return 0; -} - - -static void l2_packet_receive(int sock, void *eloop_ctx, void *sock_ctx) -{ - struct l2_packet_data *l2 = eloop_ctx; - u8 buf[2300]; - int res; - - /* TODO: receive frame (e.g., recv() using sock */ - buf[0] = 0; - res = 0; - - l2->rx_callback(l2->rx_callback_ctx, NULL /* TODO: src addr */, - buf, res); -} - - -struct l2_packet_data * l2_packet_init( - const char *ifname, const u8 *own_addr, unsigned short protocol, - void (*rx_callback)(void *ctx, const u8 *src_addr, - const u8 *buf, size_t len), - void *rx_callback_ctx, int l2_hdr) -{ - struct l2_packet_data *l2; - - l2 = os_zalloc(sizeof(struct l2_packet_data)); - if (l2 == NULL) - return NULL; - os_strlcpy(l2->ifname, ifname, sizeof(l2->ifname)); - l2->rx_callback = rx_callback; - l2->rx_callback_ctx = rx_callback_ctx; - l2->l2_hdr = l2_hdr; - - /* - * TODO: open connection for receiving frames - */ - l2->fd = -1; - eloop_register_read_sock(l2->fd, l2_packet_receive, l2, NULL); - - return l2; -} - - -void l2_packet_deinit(struct l2_packet_data *l2) -{ - if (l2 == NULL) - return; - - if (l2->fd >= 0) { - eloop_unregister_read_sock(l2->fd); - /* TODO: close connection */ - } - - os_free(l2); -} - - -int l2_packet_get_ip_addr(struct l2_packet_data *l2, char *buf, size_t len) -{ - /* TODO: get interface IP address */ - return -1; -} - - -void l2_packet_notify_auth_start(struct l2_packet_data *l2) -{ - /* This function can be left empty */ -} diff --git a/hostapd-0.8/src/l2_packet/l2_packet_pcap.c b/hostapd-0.8/src/l2_packet/l2_packet_pcap.c deleted file mode 100644 index 8156e29..0000000 --- a/hostapd-0.8/src/l2_packet/l2_packet_pcap.c +++ /dev/null @@ -1,386 +0,0 @@ -/* - * WPA Supplicant - Layer2 packet handling with libpcap/libdnet and WinPcap - * Copyright (c) 2003-2006, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#include "includes.h" -#ifndef CONFIG_NATIVE_WINDOWS -#include -#endif /* CONFIG_NATIVE_WINDOWS */ -#include -#ifndef CONFIG_WINPCAP -#include -#endif /* CONFIG_WINPCAP */ - -#include "common.h" -#include "eloop.h" -#include "l2_packet.h" - - -static const u8 pae_group_addr[ETH_ALEN] = -{ 0x01, 0x80, 0xc2, 0x00, 0x00, 0x03 }; - -struct l2_packet_data { - pcap_t *pcap; -#ifdef CONFIG_WINPCAP - unsigned int num_fast_poll; -#else /* CONFIG_WINPCAP */ - eth_t *eth; -#endif /* CONFIG_WINPCAP */ - char ifname[100]; - u8 own_addr[ETH_ALEN]; - void (*rx_callback)(void *ctx, const u8 *src_addr, - const u8 *buf, size_t len); - void *rx_callback_ctx; - int l2_hdr; /* whether to include layer 2 (Ethernet) header in calls - * to rx_callback */ -}; - - -int l2_packet_get_own_addr(struct l2_packet_data *l2, u8 *addr) -{ - os_memcpy(addr, l2->own_addr, ETH_ALEN); - return 0; -} - - -#ifndef CONFIG_WINPCAP -static int l2_packet_init_libdnet(struct l2_packet_data *l2) -{ - eth_addr_t own_addr; - - l2->eth = eth_open(l2->ifname); - if (!l2->eth) { - printf("Failed to open interface '%s'.\n", l2->ifname); - perror("eth_open"); - return -1; - } - - if (eth_get(l2->eth, &own_addr) < 0) { - printf("Failed to get own hw address from interface '%s'.\n", - l2->ifname); - perror("eth_get"); - eth_close(l2->eth); - l2->eth = NULL; - return -1; - } - os_memcpy(l2->own_addr, own_addr.data, ETH_ALEN); - - return 0; -} -#endif /* CONFIG_WINPCAP */ - - -int l2_packet_send(struct l2_packet_data *l2, const u8 *dst_addr, u16 proto, - const u8 *buf, size_t len) -{ - int ret; - struct l2_ethhdr *eth; - - if (l2 == NULL) - return -1; - - if (l2->l2_hdr) { -#ifdef CONFIG_WINPCAP - ret = pcap_sendpacket(l2->pcap, buf, len); -#else /* CONFIG_WINPCAP */ - ret = eth_send(l2->eth, buf, len); -#endif /* CONFIG_WINPCAP */ - } else { - size_t mlen = sizeof(*eth) + len; - eth = os_malloc(mlen); - if (eth == NULL) - return -1; - - os_memcpy(eth->h_dest, dst_addr, ETH_ALEN); - os_memcpy(eth->h_source, l2->own_addr, ETH_ALEN); - eth->h_proto = htons(proto); - os_memcpy(eth + 1, buf, len); - -#ifdef CONFIG_WINPCAP - ret = pcap_sendpacket(l2->pcap, (u8 *) eth, mlen); -#else /* CONFIG_WINPCAP */ - ret = eth_send(l2->eth, (u8 *) eth, mlen); -#endif /* CONFIG_WINPCAP */ - - os_free(eth); - } - - return ret; -} - - -#ifndef CONFIG_WINPCAP -static void l2_packet_receive(int sock, void *eloop_ctx, void *sock_ctx) -{ - struct l2_packet_data *l2 = eloop_ctx; - pcap_t *pcap = sock_ctx; - struct pcap_pkthdr hdr; - const u_char *packet; - struct l2_ethhdr *ethhdr; - unsigned char *buf; - size_t len; - - packet = pcap_next(pcap, &hdr); - - if (packet == NULL || hdr.caplen < sizeof(*ethhdr)) - return; - - ethhdr = (struct l2_ethhdr *) packet; - if (l2->l2_hdr) { - buf = (unsigned char *) ethhdr; - len = hdr.caplen; - } else { - buf = (unsigned char *) (ethhdr + 1); - len = hdr.caplen - sizeof(*ethhdr); - } - l2->rx_callback(l2->rx_callback_ctx, ethhdr->h_source, buf, len); -} -#endif /* CONFIG_WINPCAP */ - - -#ifdef CONFIG_WINPCAP -static void l2_packet_receive_cb(u_char *user, const struct pcap_pkthdr *hdr, - const u_char *pkt_data) -{ - struct l2_packet_data *l2 = (struct l2_packet_data *) user; - struct l2_ethhdr *ethhdr; - unsigned char *buf; - size_t len; - - if (pkt_data == NULL || hdr->caplen < sizeof(*ethhdr)) - return; - - ethhdr = (struct l2_ethhdr *) pkt_data; - if (l2->l2_hdr) { - buf = (unsigned char *) ethhdr; - len = hdr->caplen; - } else { - buf = (unsigned char *) (ethhdr + 1); - len = hdr->caplen - sizeof(*ethhdr); - } - l2->rx_callback(l2->rx_callback_ctx, ethhdr->h_source, buf, len); - /* - * Use shorter poll interval for 3 seconds to reduce latency during key - * handshake. - */ - l2->num_fast_poll = 3 * 50; -} - - -static void l2_packet_receive_timeout(void *eloop_ctx, void *timeout_ctx) -{ - struct l2_packet_data *l2 = eloop_ctx; - pcap_t *pcap = timeout_ctx; - int timeout; - - if (l2->num_fast_poll > 0) { - timeout = 20000; - l2->num_fast_poll--; - } else - timeout = 100000; - - /* Register new timeout before calling l2_packet_receive() since - * receive handler may free this l2_packet instance (which will - * cancel this timeout). */ - eloop_register_timeout(0, timeout, l2_packet_receive_timeout, - l2, pcap); - pcap_dispatch(pcap, 10, l2_packet_receive_cb, (u_char *) l2); -} -#endif /* CONFIG_WINPCAP */ - - -static int l2_packet_init_libpcap(struct l2_packet_data *l2, - unsigned short protocol) -{ - bpf_u_int32 pcap_maskp, pcap_netp; - char pcap_filter[200], pcap_err[PCAP_ERRBUF_SIZE]; - struct bpf_program pcap_fp; - -#ifdef CONFIG_WINPCAP - char ifname[128]; - os_snprintf(ifname, sizeof(ifname), "\\Device\\NPF_%s", l2->ifname); - pcap_lookupnet(ifname, &pcap_netp, &pcap_maskp, pcap_err); - l2->pcap = pcap_open_live(ifname, 2500, 0, 10, pcap_err); - if (l2->pcap == NULL) { - fprintf(stderr, "pcap_open_live: %s\n", pcap_err); - fprintf(stderr, "ifname='%s'\n", ifname); - return -1; - } - if (pcap_setnonblock(l2->pcap, 1, pcap_err) < 0) - fprintf(stderr, "pcap_setnonblock: %s\n", - pcap_geterr(l2->pcap)); -#else /* CONFIG_WINPCAP */ - pcap_lookupnet(l2->ifname, &pcap_netp, &pcap_maskp, pcap_err); - l2->pcap = pcap_open_live(l2->ifname, 2500, 0, 10, pcap_err); - if (l2->pcap == NULL) { - fprintf(stderr, "pcap_open_live: %s\n", pcap_err); - fprintf(stderr, "ifname='%s'\n", l2->ifname); - return -1; - } - if (pcap_datalink(l2->pcap) != DLT_EN10MB && - pcap_set_datalink(l2->pcap, DLT_EN10MB) < 0) { - fprintf(stderr, "pcap_set_datalink(DLT_EN10MB): %s\n", - pcap_geterr(l2->pcap)); - return -1; - } -#endif /* CONFIG_WINPCAP */ - os_snprintf(pcap_filter, sizeof(pcap_filter), - "not ether src " MACSTR " and " - "( ether dst " MACSTR " or ether dst " MACSTR " ) and " - "ether proto 0x%x", - MAC2STR(l2->own_addr), /* do not receive own packets */ - MAC2STR(l2->own_addr), MAC2STR(pae_group_addr), - protocol); - if (pcap_compile(l2->pcap, &pcap_fp, pcap_filter, 1, pcap_netp) < 0) { - fprintf(stderr, "pcap_compile: %s\n", pcap_geterr(l2->pcap)); - return -1; - } - - if (pcap_setfilter(l2->pcap, &pcap_fp) < 0) { - fprintf(stderr, "pcap_setfilter: %s\n", pcap_geterr(l2->pcap)); - return -1; - } - - pcap_freecode(&pcap_fp); -#ifdef BIOCIMMEDIATE - /* - * When libpcap uses BPF we must enable "immediate mode" to - * receive frames right away; otherwise the system may - * buffer them for us. - */ - { - unsigned int on = 1; - if (ioctl(pcap_fileno(l2->pcap), BIOCIMMEDIATE, &on) < 0) { - fprintf(stderr, "%s: cannot enable immediate mode on " - "interface %s: %s\n", - __func__, l2->ifname, strerror(errno)); - /* XXX should we fail? */ - } - } -#endif /* BIOCIMMEDIATE */ - -#ifdef CONFIG_WINPCAP - eloop_register_timeout(0, 100000, l2_packet_receive_timeout, - l2, l2->pcap); -#else /* CONFIG_WINPCAP */ - eloop_register_read_sock(pcap_get_selectable_fd(l2->pcap), - l2_packet_receive, l2, l2->pcap); -#endif /* CONFIG_WINPCAP */ - - return 0; -} - - -struct l2_packet_data * l2_packet_init( - const char *ifname, const u8 *own_addr, unsigned short protocol, - void (*rx_callback)(void *ctx, const u8 *src_addr, - const u8 *buf, size_t len), - void *rx_callback_ctx, int l2_hdr) -{ - struct l2_packet_data *l2; - - l2 = os_zalloc(sizeof(struct l2_packet_data)); - if (l2 == NULL) - return NULL; - os_strlcpy(l2->ifname, ifname, sizeof(l2->ifname)); - l2->rx_callback = rx_callback; - l2->rx_callback_ctx = rx_callback_ctx; - l2->l2_hdr = l2_hdr; - -#ifdef CONFIG_WINPCAP - if (own_addr) - os_memcpy(l2->own_addr, own_addr, ETH_ALEN); -#else /* CONFIG_WINPCAP */ - if (l2_packet_init_libdnet(l2)) - return NULL; -#endif /* CONFIG_WINPCAP */ - - if (l2_packet_init_libpcap(l2, protocol)) { -#ifndef CONFIG_WINPCAP - eth_close(l2->eth); -#endif /* CONFIG_WINPCAP */ - os_free(l2); - return NULL; - } - - return l2; -} - - -void l2_packet_deinit(struct l2_packet_data *l2) -{ - if (l2 == NULL) - return; - -#ifdef CONFIG_WINPCAP - eloop_cancel_timeout(l2_packet_receive_timeout, l2, l2->pcap); -#else /* CONFIG_WINPCAP */ - if (l2->eth) - eth_close(l2->eth); - eloop_unregister_read_sock(pcap_get_selectable_fd(l2->pcap)); -#endif /* CONFIG_WINPCAP */ - if (l2->pcap) - pcap_close(l2->pcap); - os_free(l2); -} - - -int l2_packet_get_ip_addr(struct l2_packet_data *l2, char *buf, size_t len) -{ - pcap_if_t *devs, *dev; - struct pcap_addr *addr; - struct sockaddr_in *saddr; - int found = 0; - char err[PCAP_ERRBUF_SIZE + 1]; - - if (pcap_findalldevs(&devs, err) < 0) { - wpa_printf(MSG_DEBUG, "pcap_findalldevs: %s\n", err); - return -1; - } - - for (dev = devs; dev && !found; dev = dev->next) { - if (os_strcmp(dev->name, l2->ifname) != 0) - continue; - - addr = dev->addresses; - while (addr) { - saddr = (struct sockaddr_in *) addr->addr; - if (saddr && saddr->sin_family == AF_INET) { - os_strlcpy(buf, inet_ntoa(saddr->sin_addr), - len); - found = 1; - break; - } - addr = addr->next; - } - } - - pcap_freealldevs(devs); - - return found ? 0 : -1; -} - - -void l2_packet_notify_auth_start(struct l2_packet_data *l2) -{ -#ifdef CONFIG_WINPCAP - /* - * Use shorter poll interval for 3 seconds to reduce latency during key - * handshake. - */ - l2->num_fast_poll = 3 * 50; - eloop_cancel_timeout(l2_packet_receive_timeout, l2, l2->pcap); - eloop_register_timeout(0, 10000, l2_packet_receive_timeout, - l2, l2->pcap); -#endif /* CONFIG_WINPCAP */ -} diff --git a/hostapd-0.8/src/l2_packet/l2_packet_privsep.c b/hostapd-0.8/src/l2_packet/l2_packet_privsep.c deleted file mode 100644 index 79d2968..0000000 --- a/hostapd-0.8/src/l2_packet/l2_packet_privsep.c +++ /dev/null @@ -1,267 +0,0 @@ -/* - * WPA Supplicant - Layer2 packet handling with privilege separation - * Copyright (c) 2007, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#include "includes.h" -#include - -#include "common.h" -#include "eloop.h" -#include "l2_packet.h" -#include "common/privsep_commands.h" - - -struct l2_packet_data { - int fd; /* UNIX domain socket for privsep access */ - void (*rx_callback)(void *ctx, const u8 *src_addr, - const u8 *buf, size_t len); - void *rx_callback_ctx; - u8 own_addr[ETH_ALEN]; - char *own_socket_path; - struct sockaddr_un priv_addr; -}; - - -static int wpa_priv_cmd(struct l2_packet_data *l2, int cmd, - const void *data, size_t data_len) -{ - struct msghdr msg; - struct iovec io[2]; - - io[0].iov_base = &cmd; - io[0].iov_len = sizeof(cmd); - io[1].iov_base = (u8 *) data; - io[1].iov_len = data_len; - - os_memset(&msg, 0, sizeof(msg)); - msg.msg_iov = io; - msg.msg_iovlen = data ? 2 : 1; - msg.msg_name = &l2->priv_addr; - msg.msg_namelen = sizeof(l2->priv_addr); - - if (sendmsg(l2->fd, &msg, 0) < 0) { - perror("L2: sendmsg(cmd)"); - return -1; - } - - return 0; -} - - -int l2_packet_get_own_addr(struct l2_packet_data *l2, u8 *addr) -{ - os_memcpy(addr, l2->own_addr, ETH_ALEN); - return 0; -} - - -int l2_packet_send(struct l2_packet_data *l2, const u8 *dst_addr, u16 proto, - const u8 *buf, size_t len) -{ - struct msghdr msg; - struct iovec io[4]; - int cmd = PRIVSEP_CMD_L2_SEND; - - io[0].iov_base = &cmd; - io[0].iov_len = sizeof(cmd); - io[1].iov_base = &dst_addr; - io[1].iov_len = ETH_ALEN; - io[2].iov_base = &proto; - io[2].iov_len = 2; - io[3].iov_base = (u8 *) buf; - io[3].iov_len = len; - - os_memset(&msg, 0, sizeof(msg)); - msg.msg_iov = io; - msg.msg_iovlen = 4; - msg.msg_name = &l2->priv_addr; - msg.msg_namelen = sizeof(l2->priv_addr); - - if (sendmsg(l2->fd, &msg, 0) < 0) { - perror("L2: sendmsg(packet_send)"); - return -1; - } - - return 0; -} - - -static void l2_packet_receive(int sock, void *eloop_ctx, void *sock_ctx) -{ - struct l2_packet_data *l2 = eloop_ctx; - u8 buf[2300]; - int res; - struct sockaddr_un from; - socklen_t fromlen = sizeof(from); - - os_memset(&from, 0, sizeof(from)); - res = recvfrom(sock, buf, sizeof(buf), 0, (struct sockaddr *) &from, - &fromlen); - if (res < 0) { - perror("l2_packet_receive - recvfrom"); - return; - } - if (res < ETH_ALEN) { - wpa_printf(MSG_DEBUG, "L2: Too show packet received"); - return; - } - - if (from.sun_family != AF_UNIX || - os_strncmp(from.sun_path, l2->priv_addr.sun_path, - sizeof(from.sun_path)) != 0) { - wpa_printf(MSG_DEBUG, "L2: Received message from unexpected " - "source"); - return; - } - - l2->rx_callback(l2->rx_callback_ctx, buf, buf + ETH_ALEN, - res - ETH_ALEN); -} - - -struct l2_packet_data * l2_packet_init( - const char *ifname, const u8 *own_addr, unsigned short protocol, - void (*rx_callback)(void *ctx, const u8 *src_addr, - const u8 *buf, size_t len), - void *rx_callback_ctx, int l2_hdr) -{ - struct l2_packet_data *l2; - char *own_dir = "/tmp"; - char *priv_dir = "/var/run/wpa_priv"; - size_t len; - static unsigned int counter = 0; - struct sockaddr_un addr; - fd_set rfds; - struct timeval tv; - int res; - u8 reply[ETH_ALEN + 1]; - int reg_cmd[2]; - - l2 = os_zalloc(sizeof(struct l2_packet_data)); - if (l2 == NULL) - return NULL; - l2->rx_callback = rx_callback; - l2->rx_callback_ctx = rx_callback_ctx; - - len = os_strlen(own_dir) + 50; - l2->own_socket_path = os_malloc(len); - if (l2->own_socket_path == NULL) { - os_free(l2); - return NULL; - } - os_snprintf(l2->own_socket_path, len, "%s/wpa_privsep-l2-%d-%d", - own_dir, getpid(), counter++); - - l2->priv_addr.sun_family = AF_UNIX; - os_snprintf(l2->priv_addr.sun_path, sizeof(l2->priv_addr.sun_path), - "%s/%s", priv_dir, ifname); - - l2->fd = socket(PF_UNIX, SOCK_DGRAM, 0); - if (l2->fd < 0) { - perror("socket(PF_UNIX)"); - os_free(l2->own_socket_path); - l2->own_socket_path = NULL; - os_free(l2); - return NULL; - } - - os_memset(&addr, 0, sizeof(addr)); - addr.sun_family = AF_UNIX; - os_strlcpy(addr.sun_path, l2->own_socket_path, sizeof(addr.sun_path)); - if (bind(l2->fd, (struct sockaddr *) &addr, sizeof(addr)) < 0) { - perror("bind(PF_UNIX)"); - goto fail; - } - - reg_cmd[0] = protocol; - reg_cmd[1] = l2_hdr; - if (wpa_priv_cmd(l2, PRIVSEP_CMD_L2_REGISTER, reg_cmd, sizeof(reg_cmd)) - < 0) { - wpa_printf(MSG_ERROR, "L2: Failed to register with wpa_priv"); - goto fail; - } - - FD_ZERO(&rfds); - FD_SET(l2->fd, &rfds); - tv.tv_sec = 5; - tv.tv_usec = 0; - res = select(l2->fd + 1, &rfds, NULL, NULL, &tv); - if (res < 0 && errno != EINTR) { - perror("select"); - goto fail; - } - - if (FD_ISSET(l2->fd, &rfds)) { - res = recv(l2->fd, reply, sizeof(reply), 0); - if (res < 0) { - perror("recv"); - goto fail; - } - } else { - wpa_printf(MSG_DEBUG, "L2: Timeout while waiting for " - "registration reply"); - goto fail; - } - - if (res != ETH_ALEN) { - wpa_printf(MSG_DEBUG, "L2: Unexpected registration reply " - "(len=%d)", res); - } - os_memcpy(l2->own_addr, reply, ETH_ALEN); - - eloop_register_read_sock(l2->fd, l2_packet_receive, l2, NULL); - - return l2; - -fail: - close(l2->fd); - l2->fd = -1; - unlink(l2->own_socket_path); - os_free(l2->own_socket_path); - l2->own_socket_path = NULL; - os_free(l2); - return NULL; -} - - -void l2_packet_deinit(struct l2_packet_data *l2) -{ - if (l2 == NULL) - return; - - if (l2->fd >= 0) { - wpa_priv_cmd(l2, PRIVSEP_CMD_L2_UNREGISTER, NULL, 0); - eloop_unregister_read_sock(l2->fd); - close(l2->fd); - } - - if (l2->own_socket_path) { - unlink(l2->own_socket_path); - os_free(l2->own_socket_path); - } - - os_free(l2); -} - - -int l2_packet_get_ip_addr(struct l2_packet_data *l2, char *buf, size_t len) -{ - /* TODO */ - return -1; -} - - -void l2_packet_notify_auth_start(struct l2_packet_data *l2) -{ - wpa_priv_cmd(l2, PRIVSEP_CMD_L2_NOTIFY_AUTH_START, NULL, 0); -} diff --git a/hostapd-0.8/src/l2_packet/l2_packet_winpcap.c b/hostapd-0.8/src/l2_packet/l2_packet_winpcap.c deleted file mode 100644 index f76b386..0000000 --- a/hostapd-0.8/src/l2_packet/l2_packet_winpcap.c +++ /dev/null @@ -1,341 +0,0 @@ -/* - * WPA Supplicant - Layer2 packet handling with WinPcap RX thread - * Copyright (c) 2003-2006, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - * - * This l2_packet implementation is explicitly for WinPcap and Windows events. - * l2_packet_pcap.c has support for WinPcap, but it requires polling to receive - * frames which means relatively long latency for EAPOL RX processing. The - * implementation here uses a separate thread to allow WinPcap to be receiving - * all the time to reduce latency for EAPOL receiving from about 100 ms to 3 ms - * when comparing l2_packet_pcap.c to l2_packet_winpcap.c. Extra sleep of 50 ms - * is added in to receive thread whenever no EAPOL frames has been received for - * a while. Whenever an EAPOL handshake is expected, this sleep is removed. - * - * The RX thread receives a frame and signals main thread through Windows event - * about the availability of a new frame. Processing the received frame is - * synchronized with pair of Windows events so that no extra buffer or queuing - * mechanism is needed. This implementation requires Windows specific event - * loop implementation, i.e., eloop_win.c. - * - * WinPcap has pcap_getevent() that could, in theory at least, be used to - * implement this kind of waiting with a simpler single-thread design. However, - * that event handle is not really signaled immediately when receiving each - * frame, so it does not really work for this kind of use. - */ - -#include "includes.h" -#include - -#include "common.h" -#include "eloop.h" -#include "l2_packet.h" - - -static const u8 pae_group_addr[ETH_ALEN] = -{ 0x01, 0x80, 0xc2, 0x00, 0x00, 0x03 }; - -/* - * Number of pcap_dispatch() iterations to do without extra wait after each - * received EAPOL packet or authentication notification. This is used to reduce - * latency for EAPOL receive. - */ -static const size_t no_wait_count = 750; - -struct l2_packet_data { - pcap_t *pcap; - unsigned int num_fast_poll; - char ifname[100]; - u8 own_addr[ETH_ALEN]; - void (*rx_callback)(void *ctx, const u8 *src_addr, - const u8 *buf, size_t len); - void *rx_callback_ctx; - int l2_hdr; /* whether to include layer 2 (Ethernet) header in calls to - * rx_callback and l2_packet_send() */ - int running; - HANDLE rx_avail, rx_done, rx_thread, rx_thread_done, rx_notify; - u8 *rx_buf, *rx_src; - size_t rx_len; - size_t rx_no_wait; -}; - - -int l2_packet_get_own_addr(struct l2_packet_data *l2, u8 *addr) -{ - os_memcpy(addr, l2->own_addr, ETH_ALEN); - return 0; -} - - -int l2_packet_send(struct l2_packet_data *l2, const u8 *dst_addr, u16 proto, - const u8 *buf, size_t len) -{ - int ret; - struct l2_ethhdr *eth; - - if (l2 == NULL) - return -1; - - if (l2->l2_hdr) { - ret = pcap_sendpacket(l2->pcap, buf, len); - } else { - size_t mlen = sizeof(*eth) + len; - eth = os_malloc(mlen); - if (eth == NULL) - return -1; - - os_memcpy(eth->h_dest, dst_addr, ETH_ALEN); - os_memcpy(eth->h_source, l2->own_addr, ETH_ALEN); - eth->h_proto = htons(proto); - os_memcpy(eth + 1, buf, len); - ret = pcap_sendpacket(l2->pcap, (u8 *) eth, mlen); - os_free(eth); - } - - return ret; -} - - -/* pcap_dispatch() callback for the RX thread */ -static void l2_packet_receive_cb(u_char *user, const struct pcap_pkthdr *hdr, - const u_char *pkt_data) -{ - struct l2_packet_data *l2 = (struct l2_packet_data *) user; - struct l2_ethhdr *ethhdr; - - if (pkt_data == NULL || hdr->caplen < sizeof(*ethhdr)) - return; - - ethhdr = (struct l2_ethhdr *) pkt_data; - if (l2->l2_hdr) { - l2->rx_buf = (u8 *) ethhdr; - l2->rx_len = hdr->caplen; - } else { - l2->rx_buf = (u8 *) (ethhdr + 1); - l2->rx_len = hdr->caplen - sizeof(*ethhdr); - } - l2->rx_src = ethhdr->h_source; - SetEvent(l2->rx_avail); - WaitForSingleObject(l2->rx_done, INFINITE); - ResetEvent(l2->rx_done); - l2->rx_no_wait = no_wait_count; -} - - -/* main RX loop that is running in a separate thread */ -static DWORD WINAPI l2_packet_receive_thread(LPVOID arg) -{ - struct l2_packet_data *l2 = arg; - - while (l2->running) { - pcap_dispatch(l2->pcap, 1, l2_packet_receive_cb, - (u_char *) l2); - if (l2->rx_no_wait > 0) - l2->rx_no_wait--; - if (WaitForSingleObject(l2->rx_notify, - l2->rx_no_wait ? 0 : 50) == - WAIT_OBJECT_0) { - l2->rx_no_wait = no_wait_count; - ResetEvent(l2->rx_notify); - } - } - SetEvent(l2->rx_thread_done); - ExitThread(0); - return 0; -} - - -/* main thread RX event handler */ -static void l2_packet_rx_event(void *eloop_data, void *user_data) -{ - struct l2_packet_data *l2 = eloop_data; - l2->rx_callback(l2->rx_callback_ctx, l2->rx_src, l2->rx_buf, - l2->rx_len); - ResetEvent(l2->rx_avail); - SetEvent(l2->rx_done); -} - - -static int l2_packet_init_libpcap(struct l2_packet_data *l2, - unsigned short protocol) -{ - bpf_u_int32 pcap_maskp, pcap_netp; - char pcap_filter[200], pcap_err[PCAP_ERRBUF_SIZE]; - struct bpf_program pcap_fp; - - pcap_lookupnet(l2->ifname, &pcap_netp, &pcap_maskp, pcap_err); - l2->pcap = pcap_open_live(l2->ifname, 2500, 0, 1, pcap_err); - if (l2->pcap == NULL) { - fprintf(stderr, "pcap_open_live: %s\n", pcap_err); - fprintf(stderr, "ifname='%s'\n", l2->ifname); - return -1; - } - os_snprintf(pcap_filter, sizeof(pcap_filter), - "not ether src " MACSTR " and " - "( ether dst " MACSTR " or ether dst " MACSTR " ) and " - "ether proto 0x%x", - MAC2STR(l2->own_addr), /* do not receive own packets */ - MAC2STR(l2->own_addr), MAC2STR(pae_group_addr), - protocol); - if (pcap_compile(l2->pcap, &pcap_fp, pcap_filter, 1, pcap_netp) < 0) { - fprintf(stderr, "pcap_compile: %s\n", pcap_geterr(l2->pcap)); - return -1; - } - - if (pcap_setfilter(l2->pcap, &pcap_fp) < 0) { - fprintf(stderr, "pcap_setfilter: %s\n", pcap_geterr(l2->pcap)); - return -1; - } - - pcap_freecode(&pcap_fp); - - return 0; -} - - -struct l2_packet_data * l2_packet_init( - const char *ifname, const u8 *own_addr, unsigned short protocol, - void (*rx_callback)(void *ctx, const u8 *src_addr, - const u8 *buf, size_t len), - void *rx_callback_ctx, int l2_hdr) -{ - struct l2_packet_data *l2; - DWORD thread_id; - - l2 = os_zalloc(sizeof(struct l2_packet_data)); - if (l2 == NULL) - return NULL; - if (os_strncmp(ifname, "\\Device\\NPF_", 12) == 0) - os_strlcpy(l2->ifname, ifname, sizeof(l2->ifname)); - else - os_snprintf(l2->ifname, sizeof(l2->ifname), "\\Device\\NPF_%s", - ifname); - l2->rx_callback = rx_callback; - l2->rx_callback_ctx = rx_callback_ctx; - l2->l2_hdr = l2_hdr; - - if (own_addr) - os_memcpy(l2->own_addr, own_addr, ETH_ALEN); - - if (l2_packet_init_libpcap(l2, protocol)) { - os_free(l2); - return NULL; - } - - l2->rx_avail = CreateEvent(NULL, TRUE, FALSE, NULL); - l2->rx_done = CreateEvent(NULL, TRUE, FALSE, NULL); - l2->rx_notify = CreateEvent(NULL, TRUE, FALSE, NULL); - if (l2->rx_avail == NULL || l2->rx_done == NULL || - l2->rx_notify == NULL) { - CloseHandle(l2->rx_avail); - CloseHandle(l2->rx_done); - CloseHandle(l2->rx_notify); - pcap_close(l2->pcap); - os_free(l2); - return NULL; - } - - eloop_register_event(l2->rx_avail, sizeof(l2->rx_avail), - l2_packet_rx_event, l2, NULL); - - l2->running = 1; - l2->rx_thread = CreateThread(NULL, 0, l2_packet_receive_thread, l2, 0, - &thread_id); - - return l2; -} - - -static void l2_packet_deinit_timeout(void *eloop_ctx, void *timeout_ctx) -{ - struct l2_packet_data *l2 = eloop_ctx; - - if (l2->rx_thread_done && - WaitForSingleObject(l2->rx_thread_done, 2000) != WAIT_OBJECT_0) { - wpa_printf(MSG_DEBUG, "l2_packet_winpcap: RX thread did not " - "exit - kill it\n"); - TerminateThread(l2->rx_thread, 0); - } - CloseHandle(l2->rx_thread_done); - CloseHandle(l2->rx_thread); - if (l2->pcap) - pcap_close(l2->pcap); - eloop_unregister_event(l2->rx_avail, sizeof(l2->rx_avail)); - CloseHandle(l2->rx_avail); - CloseHandle(l2->rx_done); - CloseHandle(l2->rx_notify); - os_free(l2); -} - - -void l2_packet_deinit(struct l2_packet_data *l2) -{ - if (l2 == NULL) - return; - - l2->rx_thread_done = CreateEvent(NULL, TRUE, FALSE, NULL); - - l2->running = 0; - pcap_breakloop(l2->pcap); - - /* - * RX thread may be waiting in l2_packet_receive_cb() for l2->rx_done - * event and this event is set in l2_packet_rx_event(). However, - * l2_packet_deinit() may end up being called from l2->rx_callback(), - * so we need to return from here and complete deinitialization in - * a registered timeout to avoid having to forcefully kill the RX - * thread. - */ - eloop_register_timeout(0, 0, l2_packet_deinit_timeout, l2, NULL); -} - - -int l2_packet_get_ip_addr(struct l2_packet_data *l2, char *buf, size_t len) -{ - pcap_if_t *devs, *dev; - struct pcap_addr *addr; - struct sockaddr_in *saddr; - int found = 0; - char err[PCAP_ERRBUF_SIZE + 1]; - - if (pcap_findalldevs(&devs, err) < 0) { - wpa_printf(MSG_DEBUG, "pcap_findalldevs: %s\n", err); - return -1; - } - - for (dev = devs; dev && !found; dev = dev->next) { - if (os_strcmp(dev->name, l2->ifname) != 0) - continue; - - addr = dev->addresses; - while (addr) { - saddr = (struct sockaddr_in *) addr->addr; - if (saddr && saddr->sin_family == AF_INET) { - os_strlcpy(buf, inet_ntoa(saddr->sin_addr), - len); - found = 1; - break; - } - addr = addr->next; - } - } - - pcap_freealldevs(devs); - - return found ? 0 : -1; -} - - -void l2_packet_notify_auth_start(struct l2_packet_data *l2) -{ - if (l2) - SetEvent(l2->rx_notify); -} diff --git a/hostapd-0.8/src/lib.rules b/hostapd-0.8/src/lib.rules deleted file mode 100644 index b260d25..0000000 --- a/hostapd-0.8/src/lib.rules +++ /dev/null @@ -1,21 +0,0 @@ -ifndef CC -CC=gcc -endif - -ifndef CFLAGS -CFLAGS = -MMD -O2 -Wall -g -endif - -CFLAGS += -I.. -I../utils - - -Q=@ -E=echo -ifeq ($(V), 1) -Q= -E=true -endif - -%.o: %.c - $(Q)$(CC) -c -o $@ $(CFLAGS) $< - @$(E) " CC " $< diff --git a/hostapd-0.8/src/p2p/Makefile b/hostapd-0.8/src/p2p/Makefile deleted file mode 100644 index cffba62..0000000 --- a/hostapd-0.8/src/p2p/Makefile +++ /dev/null @@ -1,9 +0,0 @@ -all: - @echo Nothing to be made. - -clean: - for d in $(SUBDIRS); do make -C $$d clean; done - rm -f *~ *.o *.d - -install: - @echo Nothing to be made. diff --git a/hostapd-0.8/src/p2p/p2p.c b/hostapd-0.8/src/p2p/p2p.c deleted file mode 100644 index 653609e..0000000 --- a/hostapd-0.8/src/p2p/p2p.c +++ /dev/null @@ -1,3490 +0,0 @@ -/* - * Wi-Fi Direct - P2P module - * Copyright (c) 2009-2010, Atheros Communications - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#include "includes.h" - -#include "common.h" -#include "eloop.h" -#include "common/ieee802_11_defs.h" -#include "common/ieee802_11_common.h" -#include "wps/wps_i.h" -#include "p2p_i.h" -#include "p2p.h" - - -static void p2p_state_timeout(void *eloop_ctx, void *timeout_ctx); -static void p2p_device_free(struct p2p_data *p2p, struct p2p_device *dev); -static void p2p_process_presence_req(struct p2p_data *p2p, const u8 *da, - const u8 *sa, const u8 *data, size_t len, - int rx_freq); -static void p2p_process_presence_resp(struct p2p_data *p2p, const u8 *da, - const u8 *sa, const u8 *data, - size_t len); -static void p2p_ext_listen_timeout(void *eloop_ctx, void *timeout_ctx); -static void p2p_scan_timeout(void *eloop_ctx, void *timeout_ctx); - - -/* - * p2p_scan recovery timeout - * - * Many drivers are using 30 second timeout on scan results. Allow a bit larger - * timeout for this to avoid hitting P2P timeout unnecessarily. - */ -#define P2P_SCAN_TIMEOUT 35 - -/** - * P2P_PEER_EXPIRATION_AGE - Number of seconds after which inactive peer - * entries will be removed - */ -#define P2P_PEER_EXPIRATION_AGE 300 - -#define P2P_PEER_EXPIRATION_INTERVAL (P2P_PEER_EXPIRATION_AGE / 2) - -static void p2p_expire_peers(struct p2p_data *p2p) -{ - struct p2p_device *dev, *n; - struct os_time now; - - os_get_time(&now); - dl_list_for_each_safe(dev, n, &p2p->devices, struct p2p_device, list) { - if (dev->last_seen.sec + P2P_PEER_EXPIRATION_AGE >= now.sec) - continue; - wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Expiring old peer " - "entry " MACSTR, MAC2STR(dev->info.p2p_device_addr)); - dl_list_del(&dev->list); - p2p_device_free(p2p, dev); - } -} - - -static void p2p_expiration_timeout(void *eloop_ctx, void *timeout_ctx) -{ - struct p2p_data *p2p = eloop_ctx; - p2p_expire_peers(p2p); - eloop_register_timeout(P2P_PEER_EXPIRATION_INTERVAL, 0, - p2p_expiration_timeout, p2p, NULL); -} - - -static const char * p2p_state_txt(int state) -{ - switch (state) { - case P2P_IDLE: - return "IDLE"; - case P2P_SEARCH: - return "SEARCH"; - case P2P_CONNECT: - return "CONNECT"; - case P2P_CONNECT_LISTEN: - return "CONNECT_LISTEN"; - case P2P_GO_NEG: - return "GO_NEG"; - case P2P_LISTEN_ONLY: - return "LISTEN_ONLY"; - case P2P_WAIT_PEER_CONNECT: - return "WAIT_PEER_CONNECT"; - case P2P_WAIT_PEER_IDLE: - return "WAIT_PEER_IDLE"; - case P2P_SD_DURING_FIND: - return "SD_DURING_FIND"; - case P2P_PROVISIONING: - return "PROVISIONING"; - case P2P_PD_DURING_FIND: - return "PD_DURING_FIND"; - case P2P_INVITE: - return "INVITE"; - case P2P_INVITE_LISTEN: - return "INVITE_LISTEN"; - default: - return "?"; - } -} - - -void p2p_set_state(struct p2p_data *p2p, int new_state) -{ - wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: State %s -> %s", - p2p_state_txt(p2p->state), p2p_state_txt(new_state)); - p2p->state = new_state; -} - - -void p2p_set_timeout(struct p2p_data *p2p, unsigned int sec, unsigned int usec) -{ - wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, - "P2P: Set timeout (state=%s): %u.%06u sec", - p2p_state_txt(p2p->state), sec, usec); - eloop_cancel_timeout(p2p_state_timeout, p2p, NULL); - eloop_register_timeout(sec, usec, p2p_state_timeout, p2p, NULL); -} - - -void p2p_clear_timeout(struct p2p_data *p2p) -{ - wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Clear timeout (state=%s)", - p2p_state_txt(p2p->state)); - eloop_cancel_timeout(p2p_state_timeout, p2p, NULL); -} - - -void p2p_go_neg_failed(struct p2p_data *p2p, struct p2p_device *peer, - int status) -{ - struct p2p_go_neg_results res; - p2p_clear_timeout(p2p); - p2p_set_state(p2p, P2P_IDLE); - p2p->go_neg_peer = NULL; - - os_memset(&res, 0, sizeof(res)); - res.status = status; - if (peer) { - os_memcpy(res.peer_device_addr, peer->info.p2p_device_addr, - ETH_ALEN); - os_memcpy(res.peer_interface_addr, peer->intended_addr, - ETH_ALEN); - } - p2p->cfg->go_neg_completed(p2p->cfg->cb_ctx, &res); -} - - -static void p2p_listen_in_find(struct p2p_data *p2p) -{ - unsigned int r, tu; - int freq; - struct wpabuf *ies; - - wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, - "P2P: Starting short listen state (state=%s)", - p2p_state_txt(p2p->state)); - - freq = p2p_channel_to_freq(p2p->cfg->country, p2p->cfg->reg_class, - p2p->cfg->channel); - if (freq < 0) { - wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, - "P2P: Unknown regulatory class/channel"); - return; - } - - os_get_random((u8 *) &r, sizeof(r)); - tu = (r % ((p2p->max_disc_int - p2p->min_disc_int) + 1) + - p2p->min_disc_int) * 100; - - p2p->pending_listen_freq = freq; - p2p->pending_listen_sec = 0; - p2p->pending_listen_usec = 1024 * tu; - - ies = p2p_build_probe_resp_ies(p2p); - if (ies == NULL) - return; - - if (p2p->cfg->start_listen(p2p->cfg->cb_ctx, freq, 1024 * tu / 1000, - ies) < 0) { - wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, - "P2P: Failed to start listen mode"); - p2p->pending_listen_freq = 0; - } - wpabuf_free(ies); -} - - -int p2p_listen(struct p2p_data *p2p, unsigned int timeout) -{ - int freq; - struct wpabuf *ies; - - wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, - "P2P: Going to listen(only) state"); - - freq = p2p_channel_to_freq(p2p->cfg->country, p2p->cfg->reg_class, - p2p->cfg->channel); - if (freq < 0) { - wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, - "P2P: Unknown regulatory class/channel"); - return -1; - } - - p2p->pending_listen_freq = freq; - p2p->pending_listen_sec = timeout / 1000; - p2p->pending_listen_usec = (timeout % 1000) * 1000; - - if (p2p->p2p_scan_running) { - wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, - "P2P: p2p_scan running - delay start of listen state"); - p2p->start_after_scan = P2P_AFTER_SCAN_LISTEN; - return 0; - } - - ies = p2p_build_probe_resp_ies(p2p); - if (ies == NULL) - return -1; - - if (p2p->cfg->start_listen(p2p->cfg->cb_ctx, freq, timeout, ies) < 0) { - wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, - "P2P: Failed to start listen mode"); - p2p->pending_listen_freq = 0; - wpabuf_free(ies); - return -1; - } - wpabuf_free(ies); - - p2p_set_state(p2p, P2P_LISTEN_ONLY); - - return 0; -} - - -static void p2p_device_clear_reported(struct p2p_data *p2p) -{ - struct p2p_device *dev; - dl_list_for_each(dev, &p2p->devices, struct p2p_device, list) - dev->flags &= ~P2P_DEV_REPORTED; -} - - -/** - * p2p_get_device - Fetch a peer entry - * @p2p: P2P module context from p2p_init() - * @addr: P2P Device Address of the peer - * Returns: Pointer to the device entry or %NULL if not found - */ -struct p2p_device * p2p_get_device(struct p2p_data *p2p, const u8 *addr) -{ - struct p2p_device *dev; - dl_list_for_each(dev, &p2p->devices, struct p2p_device, list) { - if (os_memcmp(dev->info.p2p_device_addr, addr, ETH_ALEN) == 0) - return dev; - } - return NULL; -} - - -/** - * p2p_get_device_interface - Fetch a peer entry based on P2P Interface Address - * @p2p: P2P module context from p2p_init() - * @addr: P2P Interface Address of the peer - * Returns: Pointer to the device entry or %NULL if not found - */ -struct p2p_device * p2p_get_device_interface(struct p2p_data *p2p, - const u8 *addr) -{ - struct p2p_device *dev; - dl_list_for_each(dev, &p2p->devices, struct p2p_device, list) { - if (os_memcmp(dev->interface_addr, addr, ETH_ALEN) == 0) - return dev; - } - return NULL; -} - - -/** - * p2p_create_device - Create a peer entry - * @p2p: P2P module context from p2p_init() - * @addr: P2P Device Address of the peer - * Returns: Pointer to the device entry or %NULL on failure - * - * If there is already an entry for the peer, it will be returned instead of - * creating a new one. - */ -static struct p2p_device * p2p_create_device(struct p2p_data *p2p, - const u8 *addr) -{ - struct p2p_device *dev, *oldest = NULL; - size_t count = 0; - - dev = p2p_get_device(p2p, addr); - if (dev) - return dev; - - dl_list_for_each(dev, &p2p->devices, struct p2p_device, list) { - count++; - if (oldest == NULL || - os_time_before(&dev->last_seen, &oldest->last_seen)) - oldest = dev; - } - if (count + 1 > p2p->cfg->max_peers && oldest) { - wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, - "P2P: Remove oldest peer entry to make room for a new " - "peer"); - dl_list_del(&oldest->list); - p2p_device_free(p2p, oldest); - } - - dev = os_zalloc(sizeof(*dev)); - if (dev == NULL) - return NULL; - dl_list_add(&p2p->devices, &dev->list); - os_memcpy(dev->info.p2p_device_addr, addr, ETH_ALEN); - - return dev; -} - - -static void p2p_copy_client_info(struct p2p_device *dev, - struct p2p_client_info *cli) -{ - os_memcpy(dev->info.device_name, cli->dev_name, cli->dev_name_len); - dev->info.device_name[cli->dev_name_len] = '\0'; - dev->info.dev_capab = cli->dev_capab; - dev->info.config_methods = cli->config_methods; - os_memcpy(dev->info.pri_dev_type, cli->pri_dev_type, 8); - dev->info.wps_sec_dev_type_list_len = 8 * cli->num_sec_dev_types; - os_memcpy(dev->info.wps_sec_dev_type_list, cli->sec_dev_types, - dev->info.wps_sec_dev_type_list_len); -} - - -static int p2p_add_group_clients(struct p2p_data *p2p, const u8 *go_dev_addr, - const u8 *go_interface_addr, int freq, - const u8 *gi, size_t gi_len) -{ - struct p2p_group_info info; - size_t c; - struct p2p_device *dev; - - if (gi == NULL) - return 0; - - if (p2p_group_info_parse(gi, gi_len, &info) < 0) - return -1; - - /* - * Clear old data for this group; if the devices are still in the - * group, the information will be restored in the loop following this. - */ - dl_list_for_each(dev, &p2p->devices, struct p2p_device, list) { - if (os_memcpy(dev->member_in_go_iface, go_interface_addr, - ETH_ALEN) == 0) { - os_memset(dev->member_in_go_iface, 0, ETH_ALEN); - os_memset(dev->member_in_go_dev, 0, ETH_ALEN); - } - } - - for (c = 0; c < info.num_clients; c++) { - struct p2p_client_info *cli = &info.client[c]; - dev = p2p_get_device(p2p, cli->p2p_device_addr); - if (dev) { - /* - * Update information only if we have not received this - * directly from the client. - */ - if (dev->flags & (P2P_DEV_GROUP_CLIENT_ONLY | - P2P_DEV_PROBE_REQ_ONLY)) - p2p_copy_client_info(dev, cli); - if (dev->flags & P2P_DEV_PROBE_REQ_ONLY) { - dev->flags &= ~P2P_DEV_PROBE_REQ_ONLY; - } - } else { - dev = p2p_create_device(p2p, cli->p2p_device_addr); - if (dev == NULL) - continue; - dev->flags |= P2P_DEV_GROUP_CLIENT_ONLY; - p2p_copy_client_info(dev, cli); - dev->oper_freq = freq; - p2p->cfg->dev_found(p2p->cfg->cb_ctx, - dev->info.p2p_device_addr, - &dev->info, 1); - dev->flags |= P2P_DEV_REPORTED | P2P_DEV_REPORTED_ONCE; - } - - os_memcpy(dev->interface_addr, cli->p2p_interface_addr, - ETH_ALEN); - os_get_time(&dev->last_seen); - os_memcpy(dev->member_in_go_dev, go_dev_addr, ETH_ALEN); - os_memcpy(dev->member_in_go_iface, go_interface_addr, - ETH_ALEN); - } - - return 0; -} - - -static void p2p_copy_wps_info(struct p2p_device *dev, int probe_req, - const struct p2p_message *msg) -{ - os_memcpy(dev->info.device_name, msg->device_name, - sizeof(dev->info.device_name)); - - if (msg->manufacturer && - msg->manufacturer_len < sizeof(dev->info.manufacturer)) { - os_memset(dev->info.manufacturer, 0, - sizeof(dev->info.manufacturer)); - os_memcpy(dev->info.manufacturer, msg->manufacturer, - msg->manufacturer_len); - } - - if (msg->model_name && - msg->model_name_len < sizeof(dev->info.model_name)) { - os_memset(dev->info.model_name, 0, - sizeof(dev->info.model_name)); - os_memcpy(dev->info.model_name, msg->model_name, - msg->model_name_len); - } - - if (msg->model_number && - msg->model_number_len < sizeof(dev->info.model_number)) { - os_memset(dev->info.model_number, 0, - sizeof(dev->info.model_number)); - os_memcpy(dev->info.model_number, msg->model_number, - msg->model_number_len); - } - - if (msg->serial_number && - msg->serial_number_len < sizeof(dev->info.serial_number)) { - os_memset(dev->info.serial_number, 0, - sizeof(dev->info.serial_number)); - os_memcpy(dev->info.serial_number, msg->serial_number, - msg->serial_number_len); - } - - if (msg->pri_dev_type) - os_memcpy(dev->info.pri_dev_type, msg->pri_dev_type, - sizeof(dev->info.pri_dev_type)); - else if (msg->wps_pri_dev_type) - os_memcpy(dev->info.pri_dev_type, msg->wps_pri_dev_type, - sizeof(dev->info.pri_dev_type)); - - if (msg->wps_sec_dev_type_list) { - os_memcpy(dev->info.wps_sec_dev_type_list, - msg->wps_sec_dev_type_list, - msg->wps_sec_dev_type_list_len); - dev->info.wps_sec_dev_type_list_len = - msg->wps_sec_dev_type_list_len; - } - - if (msg->capability) { - dev->info.dev_capab = msg->capability[0]; - dev->info.group_capab = msg->capability[1]; - } - - if (msg->ext_listen_timing) { - dev->ext_listen_period = WPA_GET_LE16(msg->ext_listen_timing); - dev->ext_listen_interval = - WPA_GET_LE16(msg->ext_listen_timing + 2); - } - - if (!probe_req) { - dev->info.config_methods = msg->config_methods ? - msg->config_methods : msg->wps_config_methods; - } -} - - -/** - * p2p_add_device - Add peer entries based on scan results - * @p2p: P2P module context from p2p_init() - * @addr: Source address of Beacon or Probe Response frame (may be either - * P2P Device Address or P2P Interface Address) - * @level: Signal level (signal strength of the received frame from the peer) - * @freq: Frequency on which the Beacon or Probe Response frame was received - * @ies: IEs from the Beacon or Probe Response frame - * @ies_len: Length of ies buffer in octets - * Returns: 0 on success, -1 on failure - * - * If the scan result is for a GO, the clients in the group will also be added - * to the peer table. This function can also be used with some other frames - * like Provision Discovery Request that contains P2P Capability and P2P Device - * Info attributes. - */ -int p2p_add_device(struct p2p_data *p2p, const u8 *addr, int freq, int level, - const u8 *ies, size_t ies_len) -{ - struct p2p_device *dev; - struct p2p_message msg; - const u8 *p2p_dev_addr; - int i; - - os_memset(&msg, 0, sizeof(msg)); - if (p2p_parse_ies(ies, ies_len, &msg)) { - wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, - "P2P: Failed to parse P2P IE for a device entry"); - p2p_parse_free(&msg); - return -1; - } - - if (msg.p2p_device_addr) - p2p_dev_addr = msg.p2p_device_addr; - else if (msg.device_id) - p2p_dev_addr = msg.device_id; - else { - wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, - "P2P: Ignore scan data without P2P Device Info or " - "P2P Device Id"); - p2p_parse_free(&msg); - return -1; - } - - if (!is_zero_ether_addr(p2p->peer_filter) && - os_memcmp(p2p_dev_addr, p2p->peer_filter, ETH_ALEN) != 0) { - wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Do not add peer " - "filter for " MACSTR " due to peer filter", - MAC2STR(p2p_dev_addr)); - return 0; - } - - dev = p2p_create_device(p2p, p2p_dev_addr); - if (dev == NULL) { - p2p_parse_free(&msg); - return -1; - } - os_get_time(&dev->last_seen); - dev->flags &= ~(P2P_DEV_PROBE_REQ_ONLY | P2P_DEV_GROUP_CLIENT_ONLY); - - if (os_memcmp(addr, p2p_dev_addr, ETH_ALEN) != 0) - os_memcpy(dev->interface_addr, addr, ETH_ALEN); - if (msg.ssid && - (msg.ssid[1] != P2P_WILDCARD_SSID_LEN || - os_memcmp(msg.ssid + 2, P2P_WILDCARD_SSID, P2P_WILDCARD_SSID_LEN) - != 0)) { - os_memcpy(dev->oper_ssid, msg.ssid + 2, msg.ssid[1]); - dev->oper_ssid_len = msg.ssid[1]; - } - - if (freq >= 2412 && freq <= 2484 && msg.ds_params && - *msg.ds_params >= 1 && *msg.ds_params <= 14) { - int ds_freq; - if (*msg.ds_params == 14) - ds_freq = 2484; - else - ds_freq = 2407 + *msg.ds_params * 5; - if (freq != ds_freq) { - wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, - "P2P: Update Listen frequency based on DS " - "Parameter Set IE: %d -> %d MHz", - freq, ds_freq); - freq = ds_freq; - } - } - - if (dev->listen_freq && dev->listen_freq != freq) { - wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, - "P2P: Update Listen frequency based on scan " - "results (" MACSTR " %d -> %d MHz (DS param %d)", - MAC2STR(dev->info.p2p_device_addr), dev->listen_freq, - freq, msg.ds_params ? *msg.ds_params : -1); - } - dev->listen_freq = freq; - if (msg.group_info) - dev->oper_freq = freq; - dev->level = level; - - p2p_copy_wps_info(dev, 0, &msg); - - for (i = 0; i < P2P_MAX_WPS_VENDOR_EXT; i++) { - wpabuf_free(dev->info.wps_vendor_ext[i]); - dev->info.wps_vendor_ext[i] = NULL; - } - - for (i = 0; i < P2P_MAX_WPS_VENDOR_EXT; i++) { - if (msg.wps_vendor_ext[i] == NULL) - break; - dev->info.wps_vendor_ext[i] = wpabuf_alloc_copy( - msg.wps_vendor_ext[i], msg.wps_vendor_ext_len[i]); - if (dev->info.wps_vendor_ext[i] == NULL) - break; - } - - p2p_add_group_clients(p2p, p2p_dev_addr, addr, freq, msg.group_info, - msg.group_info_len); - - p2p_parse_free(&msg); - - if (p2p_pending_sd_req(p2p, dev)) - dev->flags |= P2P_DEV_SD_SCHEDULE; - - if (dev->flags & P2P_DEV_REPORTED) - return 0; - - wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, - "P2P: Peer found with Listen frequency %d MHz", freq); - if (dev->flags & P2P_DEV_USER_REJECTED) { - wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, - "P2P: Do not report rejected device"); - return 0; - } - - p2p->cfg->dev_found(p2p->cfg->cb_ctx, addr, &dev->info, - !(dev->flags & P2P_DEV_REPORTED_ONCE)); - dev->flags |= P2P_DEV_REPORTED | P2P_DEV_REPORTED_ONCE; - - return 0; -} - - -static void p2p_device_free(struct p2p_data *p2p, struct p2p_device *dev) -{ - int i; - - if (p2p->go_neg_peer == dev) - p2p->go_neg_peer = NULL; - if (p2p->invite_peer == dev) - p2p->invite_peer = NULL; - if (p2p->sd_peer == dev) - p2p->sd_peer = NULL; - if (p2p->pending_client_disc_go == dev) - p2p->pending_client_disc_go = NULL; - - p2p->cfg->dev_lost(p2p->cfg->cb_ctx, dev->info.p2p_device_addr); - - for (i = 0; i < P2P_MAX_WPS_VENDOR_EXT; i++) { - wpabuf_free(dev->info.wps_vendor_ext[i]); - dev->info.wps_vendor_ext[i] = NULL; - } - - os_free(dev); -} - - -static int p2p_get_next_prog_freq(struct p2p_data *p2p) -{ - struct p2p_channels *c; - struct p2p_reg_class *cla; - size_t cl, ch; - int found = 0; - u8 reg_class; - u8 channel; - int freq; - - c = &p2p->cfg->channels; - for (cl = 0; cl < c->reg_classes; cl++) { - cla = &c->reg_class[cl]; - if (cla->reg_class != p2p->last_prog_scan_class) - continue; - for (ch = 0; ch < cla->channels; ch++) { - if (cla->channel[ch] == p2p->last_prog_scan_chan) { - found = 1; - break; - } - } - if (found) - break; - } - - if (!found) { - /* Start from beginning */ - reg_class = c->reg_class[0].reg_class; - channel = c->reg_class[0].channel[0]; - } else { - /* Pick the next channel */ - ch++; - if (ch == cla->channels) { - cl++; - if (cl == c->reg_classes) - cl = 0; - ch = 0; - } - reg_class = c->reg_class[cl].reg_class; - channel = c->reg_class[cl].channel[ch]; - } - - freq = p2p_channel_to_freq(p2p->cfg->country, reg_class, channel); - wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Next progressive search " - "channel: reg_class %u channel %u -> %d MHz", - reg_class, channel, freq); - p2p->last_prog_scan_class = reg_class; - p2p->last_prog_scan_chan = channel; - - if (freq == 2412 || freq == 2437 || freq == 2462) - return 0; /* No need to add social channels */ - return freq; -} - - -static void p2p_search(struct p2p_data *p2p) -{ - int freq = 0; - enum p2p_scan_type type; - - if (p2p->drv_in_listen) { - wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Driver is still " - "in Listen state - wait for it to end before " - "continuing"); - return; - } - p2p->cfg->stop_listen(p2p->cfg->cb_ctx); - - if (p2p->go_neg_peer) { - /* - * Only scan the known listen frequency of the peer - * during GO Negotiation start. - */ - freq = p2p->go_neg_peer->listen_freq; - if (freq <= 0) - freq = p2p->go_neg_peer->oper_freq; - type = P2P_SCAN_SPECIFIC; - wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Starting search " - "for freq %u (GO Neg)", freq); - } else if (p2p->invite_peer) { - /* - * Only scan the known listen frequency of the peer - * during Invite start. - */ - freq = p2p->invite_peer->listen_freq; - if (freq <= 0) - freq = p2p->invite_peer->oper_freq; - type = P2P_SCAN_SPECIFIC; - wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Starting search " - "for freq %u (Invite)", freq); - } else if (p2p->find_type == P2P_FIND_PROGRESSIVE && - (freq = p2p_get_next_prog_freq(p2p)) > 0) { - type = P2P_SCAN_SOCIAL_PLUS_ONE; - wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Starting search " - "(+ freq %u)", freq); - } else { - type = P2P_SCAN_SOCIAL; - wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Starting search"); - } - - if (p2p->cfg->p2p_scan(p2p->cfg->cb_ctx, type, freq, - p2p->num_req_dev_types, p2p->req_dev_types) < 0) - { - wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, - "P2P: Scan request failed"); - p2p_continue_find(p2p); - } else { - wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Running p2p_scan"); - p2p->p2p_scan_running = 1; - eloop_cancel_timeout(p2p_scan_timeout, p2p, NULL); - eloop_register_timeout(P2P_SCAN_TIMEOUT, 0, p2p_scan_timeout, - p2p, NULL); - } -} - - -static void p2p_find_timeout(void *eloop_ctx, void *timeout_ctx) -{ - struct p2p_data *p2p = eloop_ctx; - wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Find timeout -> stop"); - p2p_stop_find(p2p); -} - - -static int p2p_run_after_scan(struct p2p_data *p2p) -{ - struct p2p_device *dev; - enum p2p_after_scan op; - - if (p2p->after_scan_tx) { - int ret; - /* TODO: schedule p2p_run_after_scan to be called from TX - * status callback(?) */ - wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Send pending " - "Action frame at p2p_scan completion"); - ret = p2p->cfg->send_action(p2p->cfg->cb_ctx, - p2p->after_scan_tx->freq, - p2p->after_scan_tx->dst, - p2p->after_scan_tx->src, - p2p->after_scan_tx->bssid, - (u8 *) (p2p->after_scan_tx + 1), - p2p->after_scan_tx->len, - p2p->after_scan_tx->wait_time); - os_free(p2p->after_scan_tx); - p2p->after_scan_tx = NULL; - return 1; - } - - op = p2p->start_after_scan; - p2p->start_after_scan = P2P_AFTER_SCAN_NOTHING; - switch (op) { - case P2P_AFTER_SCAN_NOTHING: - break; - case P2P_AFTER_SCAN_LISTEN: - wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Start previously " - "requested Listen state"); - p2p_listen(p2p, p2p->pending_listen_sec * 1000 + - p2p->pending_listen_usec / 1000); - return 1; - case P2P_AFTER_SCAN_CONNECT: - wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Start previously " - "requested connect with " MACSTR, - MAC2STR(p2p->after_scan_peer)); - dev = p2p_get_device(p2p, p2p->after_scan_peer); - if (dev == NULL) { - wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Peer not " - "known anymore"); - break; - } - p2p_connect_send(p2p, dev); - return 1; - } - - return 0; -} - - -static void p2p_scan_timeout(void *eloop_ctx, void *timeout_ctx) -{ - struct p2p_data *p2p = eloop_ctx; - int running; - wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: p2p_scan timeout " - "(running=%d)", p2p->p2p_scan_running); - running = p2p->p2p_scan_running; - /* Make sure we recover from missed scan results callback */ - p2p->p2p_scan_running = 0; - - if (running) - p2p_run_after_scan(p2p); -} - - -static void p2p_free_req_dev_types(struct p2p_data *p2p) -{ - p2p->num_req_dev_types = 0; - os_free(p2p->req_dev_types); - p2p->req_dev_types = NULL; -} - - -int p2p_find(struct p2p_data *p2p, unsigned int timeout, - enum p2p_discovery_type type, - unsigned int num_req_dev_types, const u8 *req_dev_types) -{ - int res; - - wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Starting find (type=%d)", - type); - if (p2p->p2p_scan_running) { - wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: p2p_scan is " - "already running"); - } - - p2p_free_req_dev_types(p2p); - if (req_dev_types && num_req_dev_types) { - p2p->req_dev_types = os_malloc(num_req_dev_types * - WPS_DEV_TYPE_LEN); - if (p2p->req_dev_types == NULL) - return -1; - os_memcpy(p2p->req_dev_types, req_dev_types, - num_req_dev_types * WPS_DEV_TYPE_LEN); - p2p->num_req_dev_types = num_req_dev_types; - } - - p2p->start_after_scan = P2P_AFTER_SCAN_NOTHING; - p2p_clear_timeout(p2p); - p2p->cfg->stop_listen(p2p->cfg->cb_ctx); - p2p->find_type = type; - p2p_device_clear_reported(p2p); - p2p_set_state(p2p, P2P_SEARCH); - eloop_cancel_timeout(p2p_find_timeout, p2p, NULL); - if (timeout) - eloop_register_timeout(timeout, 0, p2p_find_timeout, - p2p, NULL); - switch (type) { - case P2P_FIND_START_WITH_FULL: - case P2P_FIND_PROGRESSIVE: - res = p2p->cfg->p2p_scan(p2p->cfg->cb_ctx, P2P_SCAN_FULL, 0, - p2p->num_req_dev_types, - p2p->req_dev_types); - break; - case P2P_FIND_ONLY_SOCIAL: - res = p2p->cfg->p2p_scan(p2p->cfg->cb_ctx, P2P_SCAN_SOCIAL, 0, - p2p->num_req_dev_types, - p2p->req_dev_types); - break; - default: - return -1; - } - - if (res == 0) { - wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Running p2p_scan"); - p2p->p2p_scan_running = 1; - eloop_cancel_timeout(p2p_scan_timeout, p2p, NULL); - eloop_register_timeout(P2P_SCAN_TIMEOUT, 0, p2p_scan_timeout, - p2p, NULL); - } else { - wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Failed to start " - "p2p_scan"); - } - - return res; -} - - -void p2p_stop_find_for_freq(struct p2p_data *p2p, int freq) -{ - wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Stopping find"); - eloop_cancel_timeout(p2p_find_timeout, p2p, NULL); - p2p_clear_timeout(p2p); - p2p_set_state(p2p, P2P_IDLE); - p2p_free_req_dev_types(p2p); - p2p->start_after_scan = P2P_AFTER_SCAN_NOTHING; - p2p->go_neg_peer = NULL; - p2p->sd_peer = NULL; - p2p->invite_peer = NULL; - if (freq > 0 && p2p->drv_in_listen == freq && p2p->in_listen) { - wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Skip stop_listen " - "since we are on correct channel for response"); - return; - } - p2p->cfg->stop_listen(p2p->cfg->cb_ctx); -} - - -void p2p_stop_find(struct p2p_data *p2p) -{ - p2p_stop_find_for_freq(p2p, 0); -} - - -static int p2p_prepare_channel(struct p2p_data *p2p, unsigned int force_freq) -{ - if (force_freq) { - u8 op_reg_class, op_channel; - if (p2p_freq_to_channel(p2p->cfg->country, force_freq, - &op_reg_class, &op_channel) < 0) { - wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, - "P2P: Unsupported frequency %u MHz", - force_freq); - return -1; - } - if (!p2p_channels_includes(&p2p->cfg->channels, op_reg_class, - op_channel)) { - wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, - "P2P: Frequency %u MHz (oper_class %u " - "channel %u) not allowed for P2P", - force_freq, op_reg_class, op_channel); - return -1; - } - p2p->op_reg_class = op_reg_class; - p2p->op_channel = op_channel; - p2p->channels.reg_classes = 1; - p2p->channels.reg_class[0].channels = 1; - p2p->channels.reg_class[0].reg_class = p2p->op_reg_class; - p2p->channels.reg_class[0].channel[0] = p2p->op_channel; - } else { - u8 op_reg_class, op_channel; - - if (!p2p->cfg->cfg_op_channel && p2p->best_freq_overall > 0 && - p2p_supported_freq(p2p, p2p->best_freq_overall) && - p2p_freq_to_channel(p2p->cfg->country, - p2p->best_freq_overall, - &op_reg_class, &op_channel) == 0) { - wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, - "P2P: Select best overall channel as " - "operating channel preference"); - p2p->op_reg_class = op_reg_class; - p2p->op_channel = op_channel; - } else if (!p2p->cfg->cfg_op_channel && p2p->best_freq_5 > 0 && - p2p_supported_freq(p2p, p2p->best_freq_5) && - p2p_freq_to_channel(p2p->cfg->country, - p2p->best_freq_5, - &op_reg_class, &op_channel) == - 0) { - wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, - "P2P: Select best 5 GHz channel as " - "operating channel preference"); - p2p->op_reg_class = op_reg_class; - p2p->op_channel = op_channel; - } else if (!p2p->cfg->cfg_op_channel && - p2p->best_freq_24 > 0 && - p2p_supported_freq(p2p, p2p->best_freq_24) && - p2p_freq_to_channel(p2p->cfg->country, - p2p->best_freq_24, - &op_reg_class, &op_channel) == - 0) { - wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, - "P2P: Select best 2.4 GHz channel as " - "operating channel preference"); - p2p->op_reg_class = op_reg_class; - p2p->op_channel = op_channel; - } else { - p2p->op_reg_class = p2p->cfg->op_reg_class; - p2p->op_channel = p2p->cfg->op_channel; - } - - os_memcpy(&p2p->channels, &p2p->cfg->channels, - sizeof(struct p2p_channels)); - } - wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, - "P2P: Own preference for operation channel: " - "Operating Class %u Channel %u%s", - p2p->op_reg_class, p2p->op_channel, - force_freq ? " (forced)" : ""); - - return 0; -} - - -int p2p_connect(struct p2p_data *p2p, const u8 *peer_addr, - enum p2p_wps_method wps_method, - int go_intent, const u8 *own_interface_addr, - unsigned int force_freq, int persistent_group) -{ - struct p2p_device *dev; - - wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, - "P2P: Request to start group negotiation - peer=" MACSTR - " GO Intent=%d Intended Interface Address=" MACSTR - " wps_method=%d persistent_group=%d", - MAC2STR(peer_addr), go_intent, MAC2STR(own_interface_addr), - wps_method, persistent_group); - - if (p2p_prepare_channel(p2p, force_freq) < 0) - return -1; - - dev = p2p_get_device(p2p, peer_addr); - if (dev == NULL || (dev->flags & P2P_DEV_PROBE_REQ_ONLY)) { - wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, - "P2P: Cannot connect to unknown P2P Device " MACSTR, - MAC2STR(peer_addr)); - return -1; - } - - if (dev->flags & P2P_DEV_GROUP_CLIENT_ONLY) { - if (!(dev->info.dev_capab & - P2P_DEV_CAPAB_CLIENT_DISCOVERABILITY)) { - wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, - "P2P: Cannot connect to P2P Device " MACSTR - " that is in a group and is not discoverable", - MAC2STR(peer_addr)); - return -1; - } - if (dev->oper_freq <= 0) { - wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, - "P2P: Cannot connect to P2P Device " MACSTR - " with incomplete information", - MAC2STR(peer_addr)); - return -1; - } - - /* - * First, try to connect directly. If the peer does not - * acknowledge frames, assume it is sleeping and use device - * discoverability via the GO at that point. - */ - } - - dev->flags &= ~P2P_DEV_NOT_YET_READY; - dev->flags &= ~P2P_DEV_USER_REJECTED; - dev->flags &= ~P2P_DEV_WAIT_GO_NEG_RESPONSE; - dev->flags &= ~P2P_DEV_WAIT_GO_NEG_CONFIRM; - dev->connect_reqs = 0; - dev->go_neg_req_sent = 0; - dev->go_state = UNKNOWN_GO; - if (persistent_group) - dev->flags |= P2P_DEV_PREFER_PERSISTENT_GROUP; - else - dev->flags &= ~P2P_DEV_PREFER_PERSISTENT_GROUP; - p2p->go_intent = go_intent; - os_memcpy(p2p->intended_addr, own_interface_addr, ETH_ALEN); - - if (p2p->state != P2P_IDLE) - p2p_stop_find(p2p); - - if (p2p->after_scan_tx) { - /* - * We need to drop the pending frame to avoid issues with the - * new GO Negotiation, e.g., when the pending frame was from a - * previous attempt at starting a GO Negotiation. - */ - wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Dropped " - "previous pending Action frame TX that was waiting " - "for p2p_scan completion"); - os_free(p2p->after_scan_tx); - p2p->after_scan_tx = NULL; - } - - dev->wps_method = wps_method; - dev->status = P2P_SC_SUCCESS; - - if (force_freq) - dev->flags |= P2P_DEV_FORCE_FREQ; - else - dev->flags &= ~P2P_DEV_FORCE_FREQ; - - if (p2p->p2p_scan_running) { - wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, - "P2P: p2p_scan running - delay connect send"); - p2p->start_after_scan = P2P_AFTER_SCAN_CONNECT; - os_memcpy(p2p->after_scan_peer, peer_addr, ETH_ALEN); - return 0; - } - p2p->start_after_scan = P2P_AFTER_SCAN_NOTHING; - - return p2p_connect_send(p2p, dev); -} - - -int p2p_authorize(struct p2p_data *p2p, const u8 *peer_addr, - enum p2p_wps_method wps_method, - int go_intent, const u8 *own_interface_addr, - unsigned int force_freq, int persistent_group) -{ - struct p2p_device *dev; - - wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, - "P2P: Request to authorize group negotiation - peer=" MACSTR - " GO Intent=%d Intended Interface Address=" MACSTR - " wps_method=%d persistent_group=%d", - MAC2STR(peer_addr), go_intent, MAC2STR(own_interface_addr), - wps_method, persistent_group); - - if (p2p_prepare_channel(p2p, force_freq) < 0) - return -1; - - dev = p2p_get_device(p2p, peer_addr); - if (dev == NULL) { - wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, - "P2P: Cannot authorize unknown P2P Device " MACSTR, - MAC2STR(peer_addr)); - return -1; - } - - dev->flags &= ~P2P_DEV_NOT_YET_READY; - dev->flags &= ~P2P_DEV_USER_REJECTED; - dev->go_neg_req_sent = 0; - dev->go_state = UNKNOWN_GO; - if (persistent_group) - dev->flags |= P2P_DEV_PREFER_PERSISTENT_GROUP; - else - dev->flags &= ~P2P_DEV_PREFER_PERSISTENT_GROUP; - p2p->go_intent = go_intent; - os_memcpy(p2p->intended_addr, own_interface_addr, ETH_ALEN); - - dev->wps_method = wps_method; - dev->status = P2P_SC_SUCCESS; - - if (force_freq) - dev->flags |= P2P_DEV_FORCE_FREQ; - else - dev->flags &= ~P2P_DEV_FORCE_FREQ; - - return 0; -} - - -void p2p_add_dev_info(struct p2p_data *p2p, const u8 *addr, - struct p2p_device *dev, struct p2p_message *msg) -{ - os_get_time(&dev->last_seen); - - p2p_copy_wps_info(dev, 0, msg); - - if (msg->listen_channel) { - int freq; - freq = p2p_channel_to_freq((char *) msg->listen_channel, - msg->listen_channel[3], - msg->listen_channel[4]); - if (freq < 0) { - wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, - "P2P: Unknown peer Listen channel: " - "country=%c%c(0x%02x) reg_class=%u channel=%u", - msg->listen_channel[0], - msg->listen_channel[1], - msg->listen_channel[2], - msg->listen_channel[3], - msg->listen_channel[4]); - } else { - wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Update " - "peer " MACSTR " Listen channel: %u -> %u MHz", - MAC2STR(dev->info.p2p_device_addr), - dev->listen_freq, freq); - dev->listen_freq = freq; - } - } - - if (dev->flags & P2P_DEV_PROBE_REQ_ONLY) { - dev->flags &= ~P2P_DEV_PROBE_REQ_ONLY; - wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, - "P2P: Completed device entry based on data from " - "GO Negotiation Request"); - } else { - wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, - "P2P: Created device entry based on GO Neg Req: " - MACSTR " dev_capab=0x%x group_capab=0x%x name='%s' " - "listen_freq=%d", - MAC2STR(dev->info.p2p_device_addr), - dev->info.dev_capab, dev->info.group_capab, - dev->info.device_name, dev->listen_freq); - } - - dev->flags &= ~P2P_DEV_GROUP_CLIENT_ONLY; - - if (dev->flags & P2P_DEV_USER_REJECTED) { - wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, - "P2P: Do not report rejected device"); - return; - } - - p2p->cfg->dev_found(p2p->cfg->cb_ctx, addr, &dev->info, - !(dev->flags & P2P_DEV_REPORTED_ONCE)); - dev->flags |= P2P_DEV_REPORTED | P2P_DEV_REPORTED_ONCE; -} - - -void p2p_build_ssid(struct p2p_data *p2p, u8 *ssid, size_t *ssid_len) -{ - os_memcpy(ssid, P2P_WILDCARD_SSID, P2P_WILDCARD_SSID_LEN); - p2p_random((char *) &ssid[P2P_WILDCARD_SSID_LEN], 2); - os_memcpy(&ssid[P2P_WILDCARD_SSID_LEN + 2], - p2p->cfg->ssid_postfix, p2p->cfg->ssid_postfix_len); - *ssid_len = P2P_WILDCARD_SSID_LEN + 2 + p2p->cfg->ssid_postfix_len; -} - - -int p2p_go_params(struct p2p_data *p2p, struct p2p_go_neg_results *params) -{ - p2p_build_ssid(p2p, params->ssid, ¶ms->ssid_len); - p2p_random(params->passphrase, 8); - return 0; -} - - -void p2p_go_complete(struct p2p_data *p2p, struct p2p_device *peer) -{ - struct p2p_go_neg_results res; - int go = peer->go_state == LOCAL_GO; - struct p2p_channels intersection; - int freqs; - size_t i, j; - - wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, - "P2P: GO Negotiation with " MACSTR " completed (%s will be " - "GO)", MAC2STR(peer->info.p2p_device_addr), - go ? "local end" : "peer"); - - os_memset(&res, 0, sizeof(res)); - res.role_go = go; - os_memcpy(res.peer_device_addr, peer->info.p2p_device_addr, ETH_ALEN); - os_memcpy(res.peer_interface_addr, peer->intended_addr, ETH_ALEN); - res.wps_method = peer->wps_method; - if (peer->flags & P2P_DEV_PREFER_PERSISTENT_GROUP) - res.persistent_group = 1; - - if (go) { - /* Setup AP mode for WPS provisioning */ - res.freq = p2p_channel_to_freq(p2p->cfg->country, - p2p->op_reg_class, - p2p->op_channel); - os_memcpy(res.ssid, p2p->ssid, p2p->ssid_len); - res.ssid_len = p2p->ssid_len; - p2p_random(res.passphrase, 8); - } else { - res.freq = peer->oper_freq; - if (p2p->ssid_len) { - os_memcpy(res.ssid, p2p->ssid, p2p->ssid_len); - res.ssid_len = p2p->ssid_len; - } - } - - p2p_channels_intersect(&p2p->channels, &peer->channels, - &intersection); - freqs = 0; - for (i = 0; i < intersection.reg_classes; i++) { - struct p2p_reg_class *c = &intersection.reg_class[i]; - if (freqs + 1 == P2P_MAX_CHANNELS) - break; - for (j = 0; j < c->channels; j++) { - int freq; - if (freqs + 1 == P2P_MAX_CHANNELS) - break; - freq = p2p_channel_to_freq(peer->country, c->reg_class, - c->channel[j]); - if (freq < 0) - continue; - res.freq_list[freqs++] = freq; - } - } - - res.peer_config_timeout = go ? peer->client_timeout : peer->go_timeout; - - p2p_clear_timeout(p2p); - peer->go_neg_req_sent = 0; - peer->wps_method = WPS_NOT_READY; - - p2p_set_state(p2p, P2P_PROVISIONING); - p2p->cfg->go_neg_completed(p2p->cfg->cb_ctx, &res); -} - - -static void p2p_rx_p2p_action(struct p2p_data *p2p, const u8 *sa, - const u8 *data, size_t len, int rx_freq) -{ - wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, - "P2P: RX P2P Public Action from " MACSTR, MAC2STR(sa)); - wpa_hexdump(MSG_MSGDUMP, "P2P: P2P Public Action contents", data, len); - - if (len < 1) - return; - - switch (data[0]) { - case P2P_GO_NEG_REQ: - p2p_process_go_neg_req(p2p, sa, data + 1, len - 1, rx_freq); - break; - case P2P_GO_NEG_RESP: - p2p_process_go_neg_resp(p2p, sa, data + 1, len - 1, rx_freq); - break; - case P2P_GO_NEG_CONF: - p2p_process_go_neg_conf(p2p, sa, data + 1, len - 1); - break; - case P2P_INVITATION_REQ: - p2p_process_invitation_req(p2p, sa, data + 1, len - 1, - rx_freq); - break; - case P2P_INVITATION_RESP: - p2p_process_invitation_resp(p2p, sa, data + 1, len - 1); - break; - case P2P_PROV_DISC_REQ: - p2p_process_prov_disc_req(p2p, sa, data + 1, len - 1, rx_freq); - break; - case P2P_PROV_DISC_RESP: - p2p_process_prov_disc_resp(p2p, sa, data + 1, len - 1); - break; - case P2P_DEV_DISC_REQ: - p2p_process_dev_disc_req(p2p, sa, data + 1, len - 1, rx_freq); - break; - case P2P_DEV_DISC_RESP: - p2p_process_dev_disc_resp(p2p, sa, data + 1, len - 1); - break; - default: - wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, - "P2P: Unsupported P2P Public Action frame type %d", - data[0]); - break; - } -} - - -void p2p_rx_action_public(struct p2p_data *p2p, const u8 *da, const u8 *sa, - const u8 *bssid, const u8 *data, size_t len, - int freq) -{ - if (len < 1) - return; - - switch (data[0]) { - case WLAN_PA_VENDOR_SPECIFIC: - data++; - len--; - if (len < 3) - return; - if (WPA_GET_BE24(data) != OUI_WFA) - return; - - data += 3; - len -= 3; - if (len < 1) - return; - - if (*data != P2P_OUI_TYPE) - return; - - p2p_rx_p2p_action(p2p, sa, data + 1, len - 1, freq); - break; - case WLAN_PA_GAS_INITIAL_REQ: - p2p_rx_gas_initial_req(p2p, sa, data + 1, len - 1, freq); - break; - case WLAN_PA_GAS_INITIAL_RESP: - p2p_rx_gas_initial_resp(p2p, sa, data + 1, len - 1, freq); - break; - case WLAN_PA_GAS_COMEBACK_REQ: - p2p_rx_gas_comeback_req(p2p, sa, data + 1, len - 1, freq); - break; - case WLAN_PA_GAS_COMEBACK_RESP: - p2p_rx_gas_comeback_resp(p2p, sa, data + 1, len - 1, freq); - break; - } -} - - -void p2p_rx_action(struct p2p_data *p2p, const u8 *da, const u8 *sa, - const u8 *bssid, u8 category, - const u8 *data, size_t len, int freq) -{ - if (category == WLAN_ACTION_PUBLIC) { - p2p_rx_action_public(p2p, da, sa, bssid, data, len, freq); - return; - } - - if (category != WLAN_ACTION_VENDOR_SPECIFIC) - return; - - if (len < 4) - return; - - if (WPA_GET_BE24(data) != OUI_WFA) - return; - data += 3; - len -= 3; - - if (*data != P2P_OUI_TYPE) - return; - data++; - len--; - - /* P2P action frame */ - wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, - "P2P: RX P2P Action from " MACSTR, MAC2STR(sa)); - wpa_hexdump(MSG_MSGDUMP, "P2P: P2P Action contents", data, len); - - if (len < 1) - return; - switch (data[0]) { - case P2P_NOA: - wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, - "P2P: Received P2P Action - Notice of Absence"); - /* TODO */ - break; - case P2P_PRESENCE_REQ: - p2p_process_presence_req(p2p, da, sa, data + 1, len - 1, freq); - break; - case P2P_PRESENCE_RESP: - p2p_process_presence_resp(p2p, da, sa, data + 1, len - 1); - break; - case P2P_GO_DISC_REQ: - p2p_process_go_disc_req(p2p, da, sa, data + 1, len - 1, freq); - break; - default: - wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, - "P2P: Received P2P Action - unknown type %u", data[0]); - break; - } -} - - -static void p2p_go_neg_start(void *eloop_ctx, void *timeout_ctx) -{ - struct p2p_data *p2p = eloop_ctx; - if (p2p->go_neg_peer == NULL) - return; - p2p->cfg->stop_listen(p2p->cfg->cb_ctx); - p2p->go_neg_peer->status = P2P_SC_SUCCESS; - p2p_connect_send(p2p, p2p->go_neg_peer); -} - - -static void p2p_invite_start(void *eloop_ctx, void *timeout_ctx) -{ - struct p2p_data *p2p = eloop_ctx; - if (p2p->invite_peer == NULL) - return; - p2p->cfg->stop_listen(p2p->cfg->cb_ctx); - p2p_invite_send(p2p, p2p->invite_peer, p2p->invite_go_dev_addr); -} - - -static void p2p_add_dev_from_probe_req(struct p2p_data *p2p, const u8 *addr, - const u8 *ie, size_t ie_len) -{ - struct p2p_message msg; - struct p2p_device *dev; - - os_memset(&msg, 0, sizeof(msg)); - if (p2p_parse_ies(ie, ie_len, &msg) < 0 || msg.p2p_attributes == NULL) - { - p2p_parse_free(&msg); - return; /* not a P2P probe */ - } - - if (msg.ssid == NULL || msg.ssid[1] != P2P_WILDCARD_SSID_LEN || - os_memcmp(msg.ssid + 2, P2P_WILDCARD_SSID, P2P_WILDCARD_SSID_LEN) - != 0) { - /* The Probe Request is not part of P2P Device Discovery. It is - * not known whether the source address of the frame is the P2P - * Device Address or P2P Interface Address. Do not add a new - * peer entry based on this frames. - */ - p2p_parse_free(&msg); - return; - } - - dev = p2p_get_device(p2p, addr); - if (dev) { - if (dev->country[0] == 0 && msg.listen_channel) - os_memcpy(dev->country, msg.listen_channel, 3); - p2p_parse_free(&msg); - return; /* already known */ - } - - dev = p2p_create_device(p2p, addr); - if (dev == NULL) { - p2p_parse_free(&msg); - return; - } - - os_get_time(&dev->last_seen); - dev->flags |= P2P_DEV_PROBE_REQ_ONLY; - - if (msg.listen_channel) { - os_memcpy(dev->country, msg.listen_channel, 3); - dev->listen_freq = p2p_channel_to_freq(dev->country, - msg.listen_channel[3], - msg.listen_channel[4]); - } - - p2p_copy_wps_info(dev, 1, &msg); - - p2p_parse_free(&msg); - - wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, - "P2P: Created device entry based on Probe Req: " MACSTR - " dev_capab=0x%x group_capab=0x%x name='%s' listen_freq=%d", - MAC2STR(dev->info.p2p_device_addr), dev->info.dev_capab, - dev->info.group_capab, dev->info.device_name, - dev->listen_freq); -} - - -struct p2p_device * p2p_add_dev_from_go_neg_req(struct p2p_data *p2p, - const u8 *addr, - struct p2p_message *msg) -{ - struct p2p_device *dev; - - dev = p2p_get_device(p2p, addr); - if (dev) { - os_get_time(&dev->last_seen); - return dev; /* already known */ - } - - dev = p2p_create_device(p2p, addr); - if (dev == NULL) - return NULL; - - p2p_add_dev_info(p2p, addr, dev, msg); - - return dev; -} - - -static int dev_type_match(const u8 *dev_type, const u8 *req_dev_type) -{ - if (os_memcmp(dev_type, req_dev_type, WPS_DEV_TYPE_LEN) == 0) - return 1; - if (os_memcmp(dev_type, req_dev_type, 2) == 0 && - WPA_GET_BE32(&req_dev_type[2]) == 0 && - WPA_GET_BE16(&req_dev_type[6]) == 0) - return 1; /* Category match with wildcard OUI/sub-category */ - return 0; -} - - -int dev_type_list_match(const u8 *dev_type, const u8 *req_dev_type[], - size_t num_req_dev_type) -{ - size_t i; - for (i = 0; i < num_req_dev_type; i++) { - if (dev_type_match(dev_type, req_dev_type[i])) - return 1; - } - return 0; -} - - -/** - * p2p_match_dev_type - Match local device type with requested type - * @p2p: P2P module context from p2p_init() - * @wps: WPS TLVs from Probe Request frame (concatenated WPS IEs) - * Returns: 1 on match, 0 on mismatch - * - * This function can be used to match the Requested Device Type attribute in - * WPS IE with the local device types for deciding whether to reply to a Probe - * Request frame. - */ -int p2p_match_dev_type(struct p2p_data *p2p, struct wpabuf *wps) -{ - struct wps_parse_attr attr; - size_t i; - - if (wps_parse_msg(wps, &attr)) - return 1; /* assume no Requested Device Type attributes */ - - if (attr.num_req_dev_type == 0) - return 1; /* no Requested Device Type attributes -> match */ - - if (dev_type_list_match(p2p->cfg->pri_dev_type, attr.req_dev_type, - attr.num_req_dev_type)) - return 1; /* Own Primary Device Type matches */ - - for (i = 0; i < p2p->cfg->num_sec_dev_types; i++) - if (dev_type_list_match(p2p->cfg->sec_dev_type[i], - attr.req_dev_type, - attr.num_req_dev_type)) - return 1; /* Own Secondary Device Type matches */ - - /* No matching device type found */ - return 0; -} - - -struct wpabuf * p2p_build_probe_resp_ies(struct p2p_data *p2p) -{ - struct wpabuf *buf; - u8 *len; - - buf = wpabuf_alloc(1000); - if (buf == NULL) - return NULL; - - p2p_build_wps_ie(p2p, buf, DEV_PW_DEFAULT, 1); - - /* P2P IE */ - len = p2p_buf_add_ie_hdr(buf); - p2p_buf_add_capability(buf, p2p->dev_capab, 0); - if (p2p->ext_listen_interval) - p2p_buf_add_ext_listen_timing(buf, p2p->ext_listen_period, - p2p->ext_listen_interval); - p2p_buf_add_device_info(buf, p2p, NULL); - p2p_buf_update_ie_hdr(buf, len); - - return buf; -} - - -static void p2p_reply_probe(struct p2p_data *p2p, const u8 *addr, const u8 *ie, - size_t ie_len) -{ - struct ieee802_11_elems elems; - struct wpabuf *buf; - struct ieee80211_mgmt *resp; - struct wpabuf *wps; - struct wpabuf *ies; - - if (!p2p->in_listen || !p2p->drv_in_listen) { - /* not in Listen state - ignore Probe Request */ - return; - } - - if (ieee802_11_parse_elems((u8 *) ie, ie_len, &elems, 0) == - ParseFailed) { - /* Ignore invalid Probe Request frames */ - return; - } - - if (elems.p2p == NULL) { - /* not a P2P probe - ignore it */ - return; - } - - if (elems.ssid == NULL || elems.ssid_len != P2P_WILDCARD_SSID_LEN || - os_memcmp(elems.ssid, P2P_WILDCARD_SSID, P2P_WILDCARD_SSID_LEN) != - 0) { - /* not using P2P Wildcard SSID - ignore */ - return; - } - - /* Check Requested Device Type match */ - wps = ieee802_11_vendor_ie_concat(ie, ie_len, WPS_DEV_OUI_WFA); - if (wps && !p2p_match_dev_type(p2p, wps)) { - wpabuf_free(wps); - /* No match with Requested Device Type */ - return; - } - wpabuf_free(wps); - - if (!p2p->cfg->send_probe_resp) - return; /* Response generated elsewhere */ - - wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, - "P2P: Reply to P2P Probe Request in Listen state"); - - /* - * We do not really have a specific BSS that this frame is advertising, - * so build a frame that has some information in valid format. This is - * really only used for discovery purposes, not to learn exact BSS - * parameters. - */ - ies = p2p_build_probe_resp_ies(p2p); - if (ies == NULL) - return; - - buf = wpabuf_alloc(200 + wpabuf_len(ies)); - if (buf == NULL) { - wpabuf_free(ies); - return; - } - - resp = NULL; - resp = wpabuf_put(buf, resp->u.probe_resp.variable - (u8 *) resp); - - resp->frame_control = host_to_le16((WLAN_FC_TYPE_MGMT << 2) | - (WLAN_FC_STYPE_PROBE_RESP << 4)); - os_memcpy(resp->da, addr, ETH_ALEN); - os_memcpy(resp->sa, p2p->cfg->dev_addr, ETH_ALEN); - os_memcpy(resp->bssid, p2p->cfg->dev_addr, ETH_ALEN); - resp->u.probe_resp.beacon_int = host_to_le16(100); - /* hardware or low-level driver will setup seq_ctrl and timestamp */ - resp->u.probe_resp.capab_info = - host_to_le16(WLAN_CAPABILITY_SHORT_PREAMBLE | - WLAN_CAPABILITY_PRIVACY | - WLAN_CAPABILITY_SHORT_SLOT_TIME); - - wpabuf_put_u8(buf, WLAN_EID_SSID); - wpabuf_put_u8(buf, P2P_WILDCARD_SSID_LEN); - wpabuf_put_data(buf, P2P_WILDCARD_SSID, P2P_WILDCARD_SSID_LEN); - - wpabuf_put_u8(buf, WLAN_EID_SUPP_RATES); - wpabuf_put_u8(buf, 8); - wpabuf_put_u8(buf, (60 / 5) | 0x80); - wpabuf_put_u8(buf, 90 / 5); - wpabuf_put_u8(buf, (120 / 5) | 0x80); - wpabuf_put_u8(buf, 180 / 5); - wpabuf_put_u8(buf, (240 / 5) | 0x80); - wpabuf_put_u8(buf, 360 / 5); - wpabuf_put_u8(buf, 480 / 5); - wpabuf_put_u8(buf, 540 / 5); - - wpabuf_put_u8(buf, WLAN_EID_DS_PARAMS); - wpabuf_put_u8(buf, 1); - wpabuf_put_u8(buf, p2p->cfg->channel); - - wpabuf_put_buf(buf, ies); - wpabuf_free(ies); - - p2p->cfg->send_probe_resp(p2p->cfg->cb_ctx, buf); - - wpabuf_free(buf); -} - - -int p2p_probe_req_rx(struct p2p_data *p2p, const u8 *addr, const u8 *ie, - size_t ie_len) -{ - p2p_add_dev_from_probe_req(p2p, addr, ie, ie_len); - - p2p_reply_probe(p2p, addr, ie, ie_len); - - if ((p2p->state == P2P_CONNECT || p2p->state == P2P_CONNECT_LISTEN) && - p2p->go_neg_peer && - os_memcmp(addr, p2p->go_neg_peer->info.p2p_device_addr, ETH_ALEN) - == 0) { - /* Received a Probe Request from GO Negotiation peer */ - wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, - "P2P: Found GO Negotiation peer - try to start GO " - "negotiation from timeout"); - eloop_register_timeout(0, 0, p2p_go_neg_start, p2p, NULL); - return 1; - } - - if ((p2p->state == P2P_INVITE || p2p->state == P2P_INVITE_LISTEN) && - p2p->invite_peer && - os_memcmp(addr, p2p->invite_peer->info.p2p_device_addr, ETH_ALEN) - == 0) { - /* Received a Probe Request from Invite peer */ - wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, - "P2P: Found Invite peer - try to start Invite from " - "timeout"); - eloop_register_timeout(0, 0, p2p_invite_start, p2p, NULL); - return 1; - } - - return 0; -} - - -static int p2p_assoc_req_ie_wlan_ap(struct p2p_data *p2p, const u8 *bssid, - u8 *buf, size_t len, struct wpabuf *p2p_ie) -{ - struct wpabuf *tmp; - u8 *lpos; - size_t tmplen; - int res; - u8 group_capab; - - if (p2p_ie == NULL) - return 0; /* WLAN AP is not a P2P manager */ - - /* - * (Re)Association Request - P2P IE - * P2P Capability attribute (shall be present) - * P2P Interface attribute (present if concurrent device and - * P2P Management is enabled) - */ - tmp = wpabuf_alloc(200); - if (tmp == NULL) - return -1; - - lpos = p2p_buf_add_ie_hdr(tmp); - group_capab = 0; - if (p2p->num_groups > 0) { - group_capab |= P2P_GROUP_CAPAB_GROUP_OWNER; - if ((p2p->dev_capab & P2P_DEV_CAPAB_CONCURRENT_OPER) && - (p2p->dev_capab & P2P_DEV_CAPAB_INFRA_MANAGED) && - p2p->cross_connect) - group_capab |= P2P_GROUP_CAPAB_CROSS_CONN; - } - p2p_buf_add_capability(tmp, p2p->dev_capab, group_capab); - if ((p2p->dev_capab & P2P_DEV_CAPAB_CONCURRENT_OPER) && - (p2p->dev_capab & P2P_DEV_CAPAB_INFRA_MANAGED)) - p2p_buf_add_p2p_interface(tmp, p2p); - p2p_buf_update_ie_hdr(tmp, lpos); - - tmplen = wpabuf_len(tmp); - if (tmplen > len) - res = -1; - else { - os_memcpy(buf, wpabuf_head(tmp), tmplen); - res = tmplen; - } - wpabuf_free(tmp); - - return res; -} - - -int p2p_assoc_req_ie(struct p2p_data *p2p, const u8 *bssid, u8 *buf, - size_t len, int p2p_group, struct wpabuf *p2p_ie) -{ - struct wpabuf *tmp; - u8 *lpos; - struct p2p_device *peer; - size_t tmplen; - int res; - - if (!p2p_group) - return p2p_assoc_req_ie_wlan_ap(p2p, bssid, buf, len, p2p_ie); - - /* - * (Re)Association Request - P2P IE - * P2P Capability attribute (shall be present) - * Extended Listen Timing (may be present) - * P2P Device Info attribute (shall be present) - */ - tmp = wpabuf_alloc(200); - if (tmp == NULL) - return -1; - - peer = bssid ? p2p_get_device(p2p, bssid) : NULL; - - lpos = p2p_buf_add_ie_hdr(tmp); - p2p_buf_add_capability(tmp, p2p->dev_capab, 0); - if (p2p->ext_listen_interval) - p2p_buf_add_ext_listen_timing(tmp, p2p->ext_listen_period, - p2p->ext_listen_interval); - p2p_buf_add_device_info(tmp, p2p, peer); - p2p_buf_update_ie_hdr(tmp, lpos); - - tmplen = wpabuf_len(tmp); - if (tmplen > len) - res = -1; - else { - os_memcpy(buf, wpabuf_head(tmp), tmplen); - res = tmplen; - } - wpabuf_free(tmp); - - return res; -} - - -int p2p_scan_result_text(const u8 *ies, size_t ies_len, char *buf, char *end) -{ - struct wpabuf *p2p_ie; - int ret; - - p2p_ie = ieee802_11_vendor_ie_concat(ies, ies_len, P2P_IE_VENDOR_TYPE); - if (p2p_ie == NULL) - return 0; - - ret = p2p_attr_text(p2p_ie, buf, end); - wpabuf_free(p2p_ie); - return ret; -} - - -static void p2p_clear_go_neg(struct p2p_data *p2p) -{ - p2p->go_neg_peer = NULL; - p2p_clear_timeout(p2p); - p2p_set_state(p2p, P2P_IDLE); -} - - -void p2p_wps_success_cb(struct p2p_data *p2p, const u8 *mac_addr) -{ - if (p2p->go_neg_peer == NULL) { - wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, - "P2P: No pending Group Formation - " - "ignore WPS registration success notification"); - return; /* No pending Group Formation */ - } - - if (os_memcmp(mac_addr, p2p->go_neg_peer->intended_addr, ETH_ALEN) != - 0) { - wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, - "P2P: Ignore WPS registration success notification " - "for " MACSTR " (GO Negotiation peer " MACSTR ")", - MAC2STR(mac_addr), - MAC2STR(p2p->go_neg_peer->intended_addr)); - return; /* Ignore unexpected peer address */ - } - - wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, - "P2P: Group Formation completed successfully with " MACSTR, - MAC2STR(mac_addr)); - - p2p_clear_go_neg(p2p); -} - - -void p2p_group_formation_failed(struct p2p_data *p2p) -{ - if (p2p->go_neg_peer == NULL) { - wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, - "P2P: No pending Group Formation - " - "ignore group formation failure notification"); - return; /* No pending Group Formation */ - } - - wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, - "P2P: Group Formation failed with " MACSTR, - MAC2STR(p2p->go_neg_peer->intended_addr)); - - p2p_clear_go_neg(p2p); -} - - -struct p2p_data * p2p_init(const struct p2p_config *cfg) -{ - struct p2p_data *p2p; - - if (cfg->max_peers < 1) - return NULL; - - p2p = os_zalloc(sizeof(*p2p) + sizeof(*cfg)); - if (p2p == NULL) - return NULL; - p2p->cfg = (struct p2p_config *) (p2p + 1); - os_memcpy(p2p->cfg, cfg, sizeof(*cfg)); - if (cfg->dev_name) - p2p->cfg->dev_name = os_strdup(cfg->dev_name); - if (cfg->manufacturer) - p2p->cfg->manufacturer = os_strdup(cfg->manufacturer); - if (cfg->model_name) - p2p->cfg->model_name = os_strdup(cfg->model_name); - if (cfg->model_number) - p2p->cfg->model_number = os_strdup(cfg->model_number); - if (cfg->serial_number) - p2p->cfg->serial_number = os_strdup(cfg->serial_number); - - p2p->min_disc_int = 1; - p2p->max_disc_int = 3; - - os_get_random(&p2p->next_tie_breaker, 1); - p2p->next_tie_breaker &= 0x01; - if (cfg->sd_request) - p2p->dev_capab |= P2P_DEV_CAPAB_SERVICE_DISCOVERY; - p2p->dev_capab |= P2P_DEV_CAPAB_INVITATION_PROCEDURE; - if (cfg->concurrent_operations) - p2p->dev_capab |= P2P_DEV_CAPAB_CONCURRENT_OPER; - p2p->dev_capab |= P2P_DEV_CAPAB_CLIENT_DISCOVERABILITY; - - dl_list_init(&p2p->devices); - - eloop_register_timeout(P2P_PEER_EXPIRATION_INTERVAL, 0, - p2p_expiration_timeout, p2p, NULL); - - return p2p; -} - - -void p2p_deinit(struct p2p_data *p2p) -{ - eloop_cancel_timeout(p2p_expiration_timeout, p2p, NULL); - eloop_cancel_timeout(p2p_ext_listen_timeout, p2p, NULL); - eloop_cancel_timeout(p2p_scan_timeout, p2p, NULL); - p2p_flush(p2p); - p2p_free_req_dev_types(p2p); - os_free(p2p->cfg->dev_name); - os_free(p2p->cfg->manufacturer); - os_free(p2p->cfg->model_name); - os_free(p2p->cfg->model_number); - os_free(p2p->cfg->serial_number); - os_free(p2p->groups); - wpabuf_free(p2p->sd_resp); - os_free(p2p->after_scan_tx); - p2p_remove_wps_vendor_extensions(p2p); - os_free(p2p); -} - - -void p2p_flush(struct p2p_data *p2p) -{ - struct p2p_device *dev, *prev; - p2p_clear_timeout(p2p); - p2p_set_state(p2p, P2P_IDLE); - p2p->start_after_scan = P2P_AFTER_SCAN_NOTHING; - p2p->go_neg_peer = NULL; - eloop_cancel_timeout(p2p_find_timeout, p2p, NULL); - dl_list_for_each_safe(dev, prev, &p2p->devices, struct p2p_device, - list) { - dl_list_del(&dev->list); - p2p_device_free(p2p, dev); - } - p2p_free_sd_queries(p2p); - os_free(p2p->after_scan_tx); - p2p->after_scan_tx = NULL; -} - - -int p2p_unauthorize(struct p2p_data *p2p, const u8 *addr) -{ - struct p2p_device *dev; - - dev = p2p_get_device(p2p, addr); - if (dev == NULL) - return -1; - - wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Unauthorizing " MACSTR, - MAC2STR(addr)); - - if (p2p->go_neg_peer == dev) - p2p->go_neg_peer = NULL; - - dev->wps_method = WPS_NOT_READY; - dev->flags &= ~P2P_DEV_WAIT_GO_NEG_RESPONSE; - dev->flags &= ~P2P_DEV_WAIT_GO_NEG_CONFIRM; - - /* Check if after_scan_tx is for this peer. If so free it */ - if (p2p->after_scan_tx && - os_memcmp(addr, p2p->after_scan_tx->dst, ETH_ALEN) == 0) { - os_free(p2p->after_scan_tx); - p2p->after_scan_tx = NULL; - } - - return 0; -} - - -int p2p_set_dev_name(struct p2p_data *p2p, const char *dev_name) -{ - os_free(p2p->cfg->dev_name); - if (dev_name) { - p2p->cfg->dev_name = os_strdup(dev_name); - if (p2p->cfg->dev_name == NULL) - return -1; - } else - p2p->cfg->dev_name = NULL; - return 0; -} - - -int p2p_set_manufacturer(struct p2p_data *p2p, const char *manufacturer) -{ - os_free(p2p->cfg->manufacturer); - p2p->cfg->manufacturer = NULL; - if (manufacturer) { - p2p->cfg->manufacturer = os_strdup(manufacturer); - if (p2p->cfg->manufacturer == NULL) - return -1; - } - - return 0; -} - - -int p2p_set_model_name(struct p2p_data *p2p, const char *model_name) -{ - os_free(p2p->cfg->model_name); - p2p->cfg->model_name = NULL; - if (model_name) { - p2p->cfg->model_name = os_strdup(model_name); - if (p2p->cfg->model_name == NULL) - return -1; - } - - return 0; -} - - -int p2p_set_model_number(struct p2p_data *p2p, const char *model_number) -{ - os_free(p2p->cfg->model_number); - p2p->cfg->model_number = NULL; - if (model_number) { - p2p->cfg->model_number = os_strdup(model_number); - if (p2p->cfg->model_number == NULL) - return -1; - } - - return 0; -} - - -int p2p_set_serial_number(struct p2p_data *p2p, const char *serial_number) -{ - os_free(p2p->cfg->serial_number); - p2p->cfg->serial_number = NULL; - if (serial_number) { - p2p->cfg->serial_number = os_strdup(serial_number); - if (p2p->cfg->serial_number == NULL) - return -1; - } - - return 0; -} - - -void p2p_set_config_methods(struct p2p_data *p2p, u16 config_methods) -{ - p2p->cfg->config_methods = config_methods; -} - - -void p2p_set_uuid(struct p2p_data *p2p, const u8 *uuid) -{ - os_memcpy(p2p->cfg->uuid, uuid, 16); -} - - -int p2p_set_pri_dev_type(struct p2p_data *p2p, const u8 *pri_dev_type) -{ - os_memcpy(p2p->cfg->pri_dev_type, pri_dev_type, 8); - return 0; -} - - -int p2p_set_sec_dev_types(struct p2p_data *p2p, const u8 dev_types[][8], - size_t num_dev_types) -{ - if (num_dev_types > P2P_SEC_DEVICE_TYPES) - num_dev_types = P2P_SEC_DEVICE_TYPES; - p2p->cfg->num_sec_dev_types = num_dev_types; - os_memcpy(p2p->cfg->sec_dev_type, dev_types, num_dev_types * 8); - return 0; -} - - -void p2p_remove_wps_vendor_extensions(struct p2p_data *p2p) -{ - int i; - - for (i = 0; i < P2P_MAX_WPS_VENDOR_EXT; i++) { - wpabuf_free(p2p->wps_vendor_ext[i]); - p2p->wps_vendor_ext[i] = NULL; - } -} - - -int p2p_add_wps_vendor_extension(struct p2p_data *p2p, - const struct wpabuf *vendor_ext) -{ - int i; - - if (vendor_ext == NULL) - return -1; - - for (i = 0; i < P2P_MAX_WPS_VENDOR_EXT; i++) { - if (p2p->wps_vendor_ext[i] == NULL) - break; - } - if (i >= P2P_MAX_WPS_VENDOR_EXT) - return -1; - - p2p->wps_vendor_ext[i] = wpabuf_dup(vendor_ext); - if (p2p->wps_vendor_ext[i] == NULL) - return -1; - - return 0; -} - - -int p2p_set_country(struct p2p_data *p2p, const char *country) -{ - os_memcpy(p2p->cfg->country, country, 3); - return 0; -} - - -void p2p_continue_find(struct p2p_data *p2p) -{ - struct p2p_device *dev; - p2p_set_state(p2p, P2P_SEARCH); - dl_list_for_each(dev, &p2p->devices, struct p2p_device, list) { - if (dev->flags & P2P_DEV_SD_SCHEDULE) { - if (p2p_start_sd(p2p, dev) == 0) - return; - else - break; - } else if (dev->req_config_methods && - !(dev->flags & P2P_DEV_PD_FOR_JOIN)) { - wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Send " - "pending Provisioning Discovery Request to " - MACSTR " (config methods 0x%x)", - MAC2STR(dev->info.p2p_device_addr), - dev->req_config_methods); - if (p2p_send_prov_disc_req(p2p, dev, 0) == 0) - return; - } - } - - p2p_listen_in_find(p2p); -} - - -static void p2p_sd_cb(struct p2p_data *p2p, int success) -{ - wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, - "P2P: Service Discovery Query TX callback: success=%d", - success); - p2p->pending_action_state = P2P_NO_PENDING_ACTION; - - if (!success) { - if (p2p->sd_peer) { - p2p->sd_peer->flags &= ~P2P_DEV_SD_SCHEDULE; - p2p->sd_peer = NULL; - } - p2p_continue_find(p2p); - return; - } - - if (p2p->sd_peer == NULL) { - wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, - "P2P: No SD peer entry known"); - p2p_continue_find(p2p); - return; - } - - /* Wait for response from the peer */ - p2p_set_state(p2p, P2P_SD_DURING_FIND); - p2p_set_timeout(p2p, 0, 200000); -} - -static void p2p_prov_disc_cb(struct p2p_data *p2p, int success) -{ - wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, - "P2P: Provision Discovery Request TX callback: success=%d", - success); - p2p->pending_action_state = P2P_NO_PENDING_ACTION; - - if (!success) { - if (p2p->state != P2P_IDLE) - p2p_continue_find(p2p); - return; - } - - /* Wait for response from the peer */ - if (p2p->state == P2P_SEARCH) - p2p_set_state(p2p, P2P_PD_DURING_FIND); - p2p_set_timeout(p2p, 0, 200000); -} - - -int p2p_scan_res_handler(struct p2p_data *p2p, const u8 *bssid, int freq, - int level, const u8 *ies, size_t ies_len) -{ - p2p_add_device(p2p, bssid, freq, level, ies, ies_len); - - if (p2p->go_neg_peer && p2p->state == P2P_SEARCH && - os_memcmp(p2p->go_neg_peer->info.p2p_device_addr, bssid, ETH_ALEN) - == 0) { - wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, - "P2P: Found GO Negotiation peer - try to start GO " - "negotiation"); - p2p_connect_send(p2p, p2p->go_neg_peer); - return 1; - } - - return 0; -} - - -void p2p_scan_res_handled(struct p2p_data *p2p) -{ - if (!p2p->p2p_scan_running) { - wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: p2p_scan was not " - "running, but scan results received"); - } - p2p->p2p_scan_running = 0; - eloop_cancel_timeout(p2p_scan_timeout, p2p, NULL); - - if (p2p_run_after_scan(p2p)) - return; - if (p2p->state == P2P_SEARCH) - p2p_continue_find(p2p); -} - - -void p2p_scan_ie(struct p2p_data *p2p, struct wpabuf *ies) -{ - u8 *len = p2p_buf_add_ie_hdr(ies); - p2p_buf_add_capability(ies, p2p->dev_capab, 0); - if (p2p->cfg->reg_class && p2p->cfg->channel) - p2p_buf_add_listen_channel(ies, p2p->cfg->country, - p2p->cfg->reg_class, - p2p->cfg->channel); - if (p2p->ext_listen_interval) - p2p_buf_add_ext_listen_timing(ies, p2p->ext_listen_period, - p2p->ext_listen_interval); - /* TODO: p2p_buf_add_operating_channel() if GO */ - p2p_buf_update_ie_hdr(ies, len); -} - - -int p2p_ie_text(struct wpabuf *p2p_ie, char *buf, char *end) -{ - return p2p_attr_text(p2p_ie, buf, end); -} - - -static void p2p_go_neg_req_cb(struct p2p_data *p2p, int success) -{ - struct p2p_device *dev = p2p->go_neg_peer; - - wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, - "P2P: GO Negotiation Request TX callback: success=%d", - success); - - if (dev == NULL) { - wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, - "P2P: No pending GO Negotiation"); - return; - } - - if (success) { - dev->go_neg_req_sent++; - if (dev->flags & P2P_DEV_USER_REJECTED) { - p2p_set_state(p2p, P2P_IDLE); - return; - } - } - - if (!success && - (dev->info.dev_capab & P2P_DEV_CAPAB_CLIENT_DISCOVERABILITY) && - !is_zero_ether_addr(dev->member_in_go_dev)) { - wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, - "P2P: Peer " MACSTR " did not acknowledge request - " - "try to use device discoverability through its GO", - MAC2STR(dev->info.p2p_device_addr)); - p2p->cfg->send_action_done(p2p->cfg->cb_ctx); - p2p_send_dev_disc_req(p2p, dev); - return; - } - - /* - * Use P2P find, if needed, to find the other device from its listen - * channel. - */ - p2p_set_state(p2p, P2P_CONNECT); - p2p_set_timeout(p2p, 0, 100000); -} - - -static void p2p_go_neg_resp_cb(struct p2p_data *p2p, int success) -{ - wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, - "P2P: GO Negotiation Response TX callback: success=%d", - success); - if (!p2p->go_neg_peer && p2p->state == P2P_PROVISIONING) { - wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, - "P2P: Ignore TX callback event - GO Negotiation is " - "not running anymore"); - return; - } - p2p_set_state(p2p, P2P_CONNECT); - p2p_set_timeout(p2p, 0, 100000); -} - - -static void p2p_go_neg_resp_failure_cb(struct p2p_data *p2p, int success) -{ - wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, - "P2P: GO Negotiation Response (failure) TX callback: " - "success=%d", success); - if (p2p->go_neg_peer && p2p->go_neg_peer->status != P2P_SC_SUCCESS) { - p2p_go_neg_failed(p2p, p2p->go_neg_peer, - p2p->go_neg_peer->status); - } -} - - -static void p2p_go_neg_conf_cb(struct p2p_data *p2p, - enum p2p_send_action_result result) -{ - struct p2p_device *dev; - - wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, - "P2P: GO Negotiation Confirm TX callback: result=%d", - result); - p2p->cfg->send_action_done(p2p->cfg->cb_ctx); - if (result == P2P_SEND_ACTION_FAILED) { - p2p_go_neg_failed(p2p, p2p->go_neg_peer, -1); - return; - } - if (result == P2P_SEND_ACTION_NO_ACK) { - /* - * It looks like the TX status for GO Negotiation Confirm is - * often showing failure even when the peer has actually - * received the frame. Since the peer may change channels - * immediately after having received the frame, we may not see - * an Ack for retries, so just dropping a single frame may - * trigger this. To allow the group formation to succeed if the - * peer did indeed receive the frame, continue regardless of - * the TX status. - */ - wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, - "P2P: Assume GO Negotiation Confirm TX was actually " - "received by the peer even though Ack was not " - "reported"); - } - - dev = p2p->go_neg_peer; - if (dev == NULL) - return; - - p2p_go_complete(p2p, dev); -} - - -void p2p_send_action_cb(struct p2p_data *p2p, unsigned int freq, const u8 *dst, - const u8 *src, const u8 *bssid, - enum p2p_send_action_result result) -{ - enum p2p_pending_action_state state; - int success; - - wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, - "P2P: Action frame TX callback (state=%d freq=%u dst=" MACSTR - " src=" MACSTR " bssid=" MACSTR " result=%d", - p2p->pending_action_state, freq, MAC2STR(dst), MAC2STR(src), - MAC2STR(bssid), result); - success = result == P2P_SEND_ACTION_SUCCESS; - state = p2p->pending_action_state; - p2p->pending_action_state = P2P_NO_PENDING_ACTION; - switch (state) { - case P2P_NO_PENDING_ACTION: - break; - case P2P_PENDING_GO_NEG_REQUEST: - p2p_go_neg_req_cb(p2p, success); - break; - case P2P_PENDING_GO_NEG_RESPONSE: - p2p_go_neg_resp_cb(p2p, success); - break; - case P2P_PENDING_GO_NEG_RESPONSE_FAILURE: - p2p_go_neg_resp_failure_cb(p2p, success); - break; - case P2P_PENDING_GO_NEG_CONFIRM: - p2p_go_neg_conf_cb(p2p, result); - break; - case P2P_PENDING_SD: - p2p_sd_cb(p2p, success); - break; - case P2P_PENDING_PD: - p2p_prov_disc_cb(p2p, success); - break; - case P2P_PENDING_INVITATION_REQUEST: - p2p_invitation_req_cb(p2p, success); - break; - case P2P_PENDING_INVITATION_RESPONSE: - p2p_invitation_resp_cb(p2p, success); - break; - case P2P_PENDING_DEV_DISC_REQUEST: - p2p_dev_disc_req_cb(p2p, success); - break; - case P2P_PENDING_DEV_DISC_RESPONSE: - p2p_dev_disc_resp_cb(p2p, success); - break; - case P2P_PENDING_GO_DISC_REQ: - p2p_go_disc_req_cb(p2p, success); - break; - } -} - - -void p2p_listen_cb(struct p2p_data *p2p, unsigned int freq, - unsigned int duration) -{ - if (freq == p2p->pending_client_disc_freq) { - wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, - "P2P: Client discoverability remain-awake completed"); - p2p->pending_client_disc_freq = 0; - return; - } - - if (freq != p2p->pending_listen_freq) { - wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, - "P2P: Unexpected listen callback for freq=%u " - "duration=%u (pending_listen_freq=%u)", - freq, duration, p2p->pending_listen_freq); - return; - } - - wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, - "P2P: Starting Listen timeout(%u,%u) on freq=%u based on " - "callback", - p2p->pending_listen_sec, p2p->pending_listen_usec, - p2p->pending_listen_freq); - p2p->in_listen = 1; - p2p->drv_in_listen = freq; - if (p2p->pending_listen_sec || p2p->pending_listen_usec) { - /* - * Add 20 msec extra wait to avoid race condition with driver - * remain-on-channel end event, i.e., give driver more time to - * complete the operation before our timeout expires. - */ - p2p_set_timeout(p2p, p2p->pending_listen_sec, - p2p->pending_listen_usec + 20000); - } - - p2p->pending_listen_freq = 0; -} - - -int p2p_listen_end(struct p2p_data *p2p, unsigned int freq) -{ - wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Driver ended Listen " - "state (freq=%u)", freq); - p2p->drv_in_listen = 0; - if (p2p->in_listen) - return 0; /* Internal timeout will trigger the next step */ - - if (p2p->state == P2P_CONNECT_LISTEN && p2p->go_neg_peer) { - if (p2p->go_neg_peer->connect_reqs >= 120) { - wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, - "P2P: Timeout on sending GO Negotiation " - "Request without getting response"); - p2p_go_neg_failed(p2p, p2p->go_neg_peer, -1); - return 0; - } - - p2p_set_state(p2p, P2P_CONNECT); - p2p_connect_send(p2p, p2p->go_neg_peer); - return 1; - } else if (p2p->state == P2P_SEARCH) { - p2p_search(p2p); - return 1; - } - - return 0; -} - - -static void p2p_timeout_connect(struct p2p_data *p2p) -{ - p2p->cfg->send_action_done(p2p->cfg->cb_ctx); - p2p_set_state(p2p, P2P_CONNECT_LISTEN); - p2p_listen_in_find(p2p); -} - - -static void p2p_timeout_connect_listen(struct p2p_data *p2p) -{ - if (p2p->go_neg_peer) { - if (p2p->drv_in_listen) { - wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Driver is " - "still in Listen state; wait for it to " - "complete"); - return; - } - - if (p2p->go_neg_peer->connect_reqs >= 120) { - wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, - "P2P: Timeout on sending GO Negotiation " - "Request without getting response"); - p2p_go_neg_failed(p2p, p2p->go_neg_peer, -1); - return; - } - - p2p_set_state(p2p, P2P_CONNECT); - p2p_connect_send(p2p, p2p->go_neg_peer); - } else - p2p_set_state(p2p, P2P_IDLE); -} - - -static void p2p_timeout_wait_peer_connect(struct p2p_data *p2p) -{ - /* - * TODO: could remain constantly in Listen state for some time if there - * are no other concurrent uses for the radio. For now, go to listen - * state once per second to give other uses a chance to use the radio. - */ - p2p_set_state(p2p, P2P_WAIT_PEER_IDLE); - p2p_set_timeout(p2p, 1, 0); -} - - -static void p2p_timeout_wait_peer_idle(struct p2p_data *p2p) -{ - struct p2p_device *dev = p2p->go_neg_peer; - - if (dev == NULL) { - wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, - "P2P: Unknown GO Neg peer - stop GO Neg wait"); - return; - } - - dev->wait_count++; - if (dev->wait_count >= 120) { - wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, - "P2P: Timeout on waiting peer to become ready for GO " - "Negotiation"); - p2p_go_neg_failed(p2p, dev, -1); - return; - } - - wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, - "P2P: Go to Listen state while waiting for the peer to become " - "ready for GO Negotiation"); - p2p_set_state(p2p, P2P_WAIT_PEER_CONNECT); - p2p_listen_in_find(p2p); -} - - -static void p2p_timeout_sd_during_find(struct p2p_data *p2p) -{ - wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, - "P2P: Service Discovery Query timeout"); - if (p2p->sd_peer) { - p2p->cfg->send_action_done(p2p->cfg->cb_ctx); - p2p->sd_peer->flags &= ~P2P_DEV_SD_SCHEDULE; - p2p->sd_peer = NULL; - } - p2p_continue_find(p2p); -} - - -static void p2p_timeout_prov_disc_during_find(struct p2p_data *p2p) -{ - wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, - "P2P: Provision Discovery Request timeout"); - p2p->cfg->send_action_done(p2p->cfg->cb_ctx); - p2p_continue_find(p2p); -} - - -static void p2p_timeout_invite(struct p2p_data *p2p) -{ - p2p->cfg->send_action_done(p2p->cfg->cb_ctx); - p2p_set_state(p2p, P2P_INVITE_LISTEN); - if (p2p->inv_role == P2P_INVITE_ROLE_ACTIVE_GO) { - /* - * Better remain on operating channel instead of listen channel - * when running a group. - */ - wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Inviting in " - "active GO role - wait on operating channel"); - p2p_set_timeout(p2p, 0, 100000); - return; - } - p2p_listen_in_find(p2p); -} - - -static void p2p_timeout_invite_listen(struct p2p_data *p2p) -{ - if (p2p->invite_peer && p2p->invite_peer->invitation_reqs < 100) { - p2p_set_state(p2p, P2P_INVITE); - p2p_invite_send(p2p, p2p->invite_peer, - p2p->invite_go_dev_addr); - } else { - if (p2p->invite_peer) { - wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, - "P2P: Invitation Request retry limit reached"); - if (p2p->cfg->invitation_result) - p2p->cfg->invitation_result( - p2p->cfg->cb_ctx, -1, NULL); - } - p2p_set_state(p2p, P2P_IDLE); - } -} - - -static void p2p_state_timeout(void *eloop_ctx, void *timeout_ctx) -{ - struct p2p_data *p2p = eloop_ctx; - - wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Timeout (state=%s)", - p2p_state_txt(p2p->state)); - - p2p->in_listen = 0; - - switch (p2p->state) { - case P2P_IDLE: - break; - case P2P_SEARCH: - p2p_search(p2p); - break; - case P2P_CONNECT: - p2p_timeout_connect(p2p); - break; - case P2P_CONNECT_LISTEN: - p2p_timeout_connect_listen(p2p); - break; - case P2P_GO_NEG: - break; - case P2P_LISTEN_ONLY: - if (p2p->ext_listen_only) { - wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, - "P2P: Extended Listen Timing - Listen State " - "completed"); - p2p->ext_listen_only = 0; - p2p_set_state(p2p, P2P_IDLE); - } - break; - case P2P_WAIT_PEER_CONNECT: - p2p_timeout_wait_peer_connect(p2p); - break; - case P2P_WAIT_PEER_IDLE: - p2p_timeout_wait_peer_idle(p2p); - break; - case P2P_SD_DURING_FIND: - p2p_timeout_sd_during_find(p2p); - break; - case P2P_PROVISIONING: - break; - case P2P_PD_DURING_FIND: - p2p_timeout_prov_disc_during_find(p2p); - break; - case P2P_INVITE: - p2p_timeout_invite(p2p); - break; - case P2P_INVITE_LISTEN: - p2p_timeout_invite_listen(p2p); - break; - } -} - - -int p2p_reject(struct p2p_data *p2p, const u8 *peer_addr) -{ - struct p2p_device *dev; - - dev = p2p_get_device(p2p, peer_addr); - wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Local request to reject " - "connection attempts by peer " MACSTR, MAC2STR(peer_addr)); - if (dev == NULL) { - wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Peer " MACSTR - " unknown", MAC2STR(peer_addr)); - return -1; - } - dev->status = P2P_SC_FAIL_REJECTED_BY_USER; - dev->flags |= P2P_DEV_USER_REJECTED; - return 0; -} - - -static const char * p2p_wps_method_text(enum p2p_wps_method method) -{ - switch (method) { - case WPS_NOT_READY: - return "not-ready"; - case WPS_PIN_LABEL: - return "Label"; - case WPS_PIN_DISPLAY: - return "Display"; - case WPS_PIN_KEYPAD: - return "Keypad"; - case WPS_PBC: - return "PBC"; - } - - return "??"; -} - - -static const char * p2p_go_state_text(enum p2p_go_state go_state) -{ - switch (go_state) { - case UNKNOWN_GO: - return "unknown"; - case LOCAL_GO: - return "local"; - case REMOTE_GO: - return "remote"; - } - - return "??"; -} - - -int p2p_get_peer_info(struct p2p_data *p2p, const u8 *addr, int next, - char *buf, size_t buflen) -{ - struct p2p_device *dev; - int res; - char *pos, *end; - struct os_time now; - char devtype[WPS_DEV_TYPE_BUFSIZE]; - - if (addr) - dev = p2p_get_device(p2p, addr); - else - dev = dl_list_first(&p2p->devices, struct p2p_device, list); - - if (dev && next) { - dev = dl_list_first(&dev->list, struct p2p_device, list); - if (&dev->list == &p2p->devices) - dev = NULL; - } - - if (dev == NULL) - return -1; - - pos = buf; - end = buf + buflen; - - res = os_snprintf(pos, end - pos, MACSTR "\n", - MAC2STR(dev->info.p2p_device_addr)); - if (res < 0 || res >= end - pos) - return pos - buf; - pos += res; - - os_get_time(&now); - res = os_snprintf(pos, end - pos, - "age=%d\n" - "listen_freq=%d\n" - "level=%d\n" - "wps_method=%s\n" - "interface_addr=" MACSTR "\n" - "member_in_go_dev=" MACSTR "\n" - "member_in_go_iface=" MACSTR "\n" - "pri_dev_type=%s\n" - "device_name=%s\n" - "manufacturer=%s\n" - "model_name=%s\n" - "model_number=%s\n" - "serial_number=%s\n" - "config_methods=0x%x\n" - "dev_capab=0x%x\n" - "group_capab=0x%x\n" - "go_neg_req_sent=%d\n" - "go_state=%s\n" - "dialog_token=%u\n" - "intended_addr=" MACSTR "\n" - "country=%c%c\n" - "oper_freq=%d\n" - "req_config_methods=0x%x\n" - "flags=%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s\n" - "status=%d\n" - "wait_count=%u\n" - "invitation_reqs=%u\n", - (int) (now.sec - dev->last_seen.sec), - dev->listen_freq, - dev->level, - p2p_wps_method_text(dev->wps_method), - MAC2STR(dev->interface_addr), - MAC2STR(dev->member_in_go_dev), - MAC2STR(dev->member_in_go_iface), - wps_dev_type_bin2str(dev->info.pri_dev_type, - devtype, sizeof(devtype)), - dev->info.device_name, - dev->info.manufacturer, - dev->info.model_name, - dev->info.model_number, - dev->info.serial_number, - dev->info.config_methods, - dev->info.dev_capab, - dev->info.group_capab, - dev->go_neg_req_sent, - p2p_go_state_text(dev->go_state), - dev->dialog_token, - MAC2STR(dev->intended_addr), - dev->country[0] ? dev->country[0] : '_', - dev->country[1] ? dev->country[1] : '_', - dev->oper_freq, - dev->req_config_methods, - dev->flags & P2P_DEV_PROBE_REQ_ONLY ? - "[PROBE_REQ_ONLY]" : "", - dev->flags & P2P_DEV_REPORTED ? "[REPORTED]" : "", - dev->flags & P2P_DEV_NOT_YET_READY ? - "[NOT_YET_READY]" : "", - dev->flags & P2P_DEV_SD_INFO ? "[SD_INFO]" : "", - dev->flags & P2P_DEV_SD_SCHEDULE ? "[SD_SCHEDULE]" : - "", - dev->flags & P2P_DEV_PD_PEER_DISPLAY ? - "[PD_PEER_DISPLAY]" : "", - dev->flags & P2P_DEV_PD_PEER_KEYPAD ? - "[PD_PEER_KEYPAD]" : "", - dev->flags & P2P_DEV_USER_REJECTED ? - "[USER_REJECTED]" : "", - dev->flags & P2P_DEV_PEER_WAITING_RESPONSE ? - "[PEER_WAITING_RESPONSE]" : "", - dev->flags & P2P_DEV_PREFER_PERSISTENT_GROUP ? - "[PREFER_PERSISTENT_GROUP]" : "", - dev->flags & P2P_DEV_WAIT_GO_NEG_RESPONSE ? - "[WAIT_GO_NEG_RESPONSE]" : "", - dev->flags & P2P_DEV_WAIT_GO_NEG_CONFIRM ? - "[WAIT_GO_NEG_CONFIRM]" : "", - dev->flags & P2P_DEV_GROUP_CLIENT_ONLY ? - "[GROUP_CLIENT_ONLY]" : "", - dev->flags & P2P_DEV_FORCE_FREQ ? - "[FORCE_FREQ]" : "", - dev->flags & P2P_DEV_PD_FOR_JOIN ? - "[PD_FOR_JOIN]" : "", - dev->status, - dev->wait_count, - dev->invitation_reqs); - if (res < 0 || res >= end - pos) - return pos - buf; - pos += res; - - if (dev->ext_listen_period) { - res = os_snprintf(pos, end - pos, - "ext_listen_period=%u\n" - "ext_listen_interval=%u\n", - dev->ext_listen_period, - dev->ext_listen_interval); - if (res < 0 || res >= end - pos) - return pos - buf; - pos += res; - } - - if (dev->oper_ssid_len) { - res = os_snprintf(pos, end - pos, - "oper_ssid=%s\n", - wpa_ssid_txt(dev->oper_ssid, - dev->oper_ssid_len)); - if (res < 0 || res >= end - pos) - return pos - buf; - pos += res; - } - - return pos - buf; -} - - -void p2p_set_client_discoverability(struct p2p_data *p2p, int enabled) -{ - if (enabled) { - wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Client " - "discoverability enabled"); - p2p->dev_capab |= P2P_DEV_CAPAB_CLIENT_DISCOVERABILITY; - } else { - wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Client " - "discoverability disabled"); - p2p->dev_capab &= ~P2P_DEV_CAPAB_CLIENT_DISCOVERABILITY; - } -} - - -static struct wpabuf * p2p_build_presence_req(u32 duration1, u32 interval1, - u32 duration2, u32 interval2) -{ - struct wpabuf *req; - struct p2p_noa_desc desc1, desc2, *ptr1 = NULL, *ptr2 = NULL; - u8 *len; - - req = wpabuf_alloc(100); - if (req == NULL) - return NULL; - - if (duration1 || interval1) { - os_memset(&desc1, 0, sizeof(desc1)); - desc1.count_type = 1; - desc1.duration = duration1; - desc1.interval = interval1; - ptr1 = &desc1; - - if (duration2 || interval2) { - os_memset(&desc2, 0, sizeof(desc2)); - desc2.count_type = 2; - desc2.duration = duration2; - desc2.interval = interval2; - ptr2 = &desc2; - } - } - - p2p_buf_add_action_hdr(req, P2P_PRESENCE_REQ, 1); - len = p2p_buf_add_ie_hdr(req); - p2p_buf_add_noa(req, 0, 0, 0, ptr1, ptr2); - p2p_buf_update_ie_hdr(req, len); - - return req; -} - - -int p2p_presence_req(struct p2p_data *p2p, const u8 *go_interface_addr, - const u8 *own_interface_addr, unsigned int freq, - u32 duration1, u32 interval1, u32 duration2, - u32 interval2) -{ - struct wpabuf *req; - - wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Send Presence Request to " - "GO " MACSTR " (own interface " MACSTR ") freq=%u dur1=%u " - "int1=%u dur2=%u int2=%u", - MAC2STR(go_interface_addr), MAC2STR(own_interface_addr), - freq, duration1, interval1, duration2, interval2); - - req = p2p_build_presence_req(duration1, interval1, duration2, - interval2); - if (req == NULL) - return -1; - - p2p->pending_action_state = P2P_NO_PENDING_ACTION; - if (p2p_send_action(p2p, freq, go_interface_addr, own_interface_addr, - go_interface_addr, - wpabuf_head(req), wpabuf_len(req), 200) < 0) { - wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, - "P2P: Failed to send Action frame"); - } - wpabuf_free(req); - - return 0; -} - - -static struct wpabuf * p2p_build_presence_resp(u8 status, const u8 *noa, - size_t noa_len, u8 dialog_token) -{ - struct wpabuf *resp; - u8 *len; - - resp = wpabuf_alloc(100 + noa_len); - if (resp == NULL) - return NULL; - - p2p_buf_add_action_hdr(resp, P2P_PRESENCE_RESP, dialog_token); - len = p2p_buf_add_ie_hdr(resp); - p2p_buf_add_status(resp, status); - if (noa) { - wpabuf_put_u8(resp, P2P_ATTR_NOTICE_OF_ABSENCE); - wpabuf_put_le16(resp, noa_len); - wpabuf_put_data(resp, noa, noa_len); - } else - p2p_buf_add_noa(resp, 0, 0, 0, NULL, NULL); - p2p_buf_update_ie_hdr(resp, len); - - return resp; -} - - -static void p2p_process_presence_req(struct p2p_data *p2p, const u8 *da, - const u8 *sa, const u8 *data, size_t len, - int rx_freq) -{ - struct p2p_message msg; - u8 status; - struct wpabuf *resp; - size_t g; - struct p2p_group *group = NULL; - int parsed = 0; - u8 noa[50]; - int noa_len; - - wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, - "P2P: Received P2P Action - P2P Presence Request"); - - for (g = 0; g < p2p->num_groups; g++) { - if (os_memcmp(da, p2p_group_get_interface_addr(p2p->groups[g]), - ETH_ALEN) == 0) { - group = p2p->groups[g]; - break; - } - } - if (group == NULL) { - wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, - "P2P: Ignore P2P Presence Request for unknown group " - MACSTR, MAC2STR(da)); - return; - } - - if (p2p_parse(data, len, &msg) < 0) { - wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, - "P2P: Failed to parse P2P Presence Request"); - status = P2P_SC_FAIL_INVALID_PARAMS; - goto fail; - } - parsed = 1; - - if (msg.noa == NULL) { - wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, - "P2P: No NoA attribute in P2P Presence Request"); - status = P2P_SC_FAIL_INVALID_PARAMS; - goto fail; - } - - status = p2p_group_presence_req(group, sa, msg.noa, msg.noa_len); - -fail: - if (p2p->cfg->get_noa) - noa_len = p2p->cfg->get_noa(p2p->cfg->cb_ctx, da, noa, - sizeof(noa)); - else - noa_len = -1; - resp = p2p_build_presence_resp(status, noa_len > 0 ? noa : NULL, - noa_len > 0 ? noa_len : 0, - msg.dialog_token); - if (parsed) - p2p_parse_free(&msg); - if (resp == NULL) - return; - - p2p->pending_action_state = P2P_NO_PENDING_ACTION; - if (p2p_send_action(p2p, rx_freq, sa, da, da, - wpabuf_head(resp), wpabuf_len(resp), 200) < 0) { - wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, - "P2P: Failed to send Action frame"); - } - wpabuf_free(resp); -} - - -static void p2p_process_presence_resp(struct p2p_data *p2p, const u8 *da, - const u8 *sa, const u8 *data, size_t len) -{ - struct p2p_message msg; - - wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, - "P2P: Received P2P Action - P2P Presence Response"); - - if (p2p_parse(data, len, &msg) < 0) { - wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, - "P2P: Failed to parse P2P Presence Response"); - return; - } - - if (msg.status == NULL || msg.noa == NULL) { - wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, - "P2P: No Status or NoA attribute in P2P Presence " - "Response"); - p2p_parse_free(&msg); - return; - } - - if (*msg.status) { - wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, - "P2P: P2P Presence Request was rejected: status %u", - *msg.status); - p2p_parse_free(&msg); - return; - } - - wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, - "P2P: P2P Presence Request was accepted"); - wpa_hexdump(MSG_DEBUG, "P2P: P2P Presence Response - NoA", - msg.noa, msg.noa_len); - /* TODO: process NoA */ - p2p_parse_free(&msg); -} - - -static void p2p_ext_listen_timeout(void *eloop_ctx, void *timeout_ctx) -{ - struct p2p_data *p2p = eloop_ctx; - - if (p2p->ext_listen_interval) { - /* Schedule next extended listen timeout */ - eloop_register_timeout(p2p->ext_listen_interval_sec, - p2p->ext_listen_interval_usec, - p2p_ext_listen_timeout, p2p, NULL); - } - - if (p2p->state == P2P_LISTEN_ONLY && p2p->ext_listen_only) { - /* - * This should not really happen, but it looks like the Listen - * command may fail is something else (e.g., a scan) was - * running at an inconvenient time. As a workaround, allow new - * Extended Listen operation to be started. - */ - wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Previous " - "Extended Listen operation had not been completed - " - "try again"); - p2p->ext_listen_only = 0; - p2p_set_state(p2p, P2P_IDLE); - } - - if (p2p->state != P2P_IDLE) { - wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Skip Extended " - "Listen timeout in active state (%s)", - p2p_state_txt(p2p->state)); - return; - } - - wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Extended Listen timeout"); - p2p->ext_listen_only = 1; - if (p2p_listen(p2p, p2p->ext_listen_period) < 0) { - wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Failed to start " - "Listen state for Extended Listen Timing"); - p2p->ext_listen_only = 0; - } -} - - -int p2p_ext_listen(struct p2p_data *p2p, unsigned int period, - unsigned int interval) -{ - if (period > 65535 || interval > 65535 || period > interval || - (period == 0 && interval > 0) || (period > 0 && interval == 0)) { - wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, - "P2P: Invalid Extended Listen Timing request: " - "period=%u interval=%u", period, interval); - return -1; - } - - eloop_cancel_timeout(p2p_ext_listen_timeout, p2p, NULL); - - if (interval == 0) { - wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, - "P2P: Disabling Extended Listen Timing"); - p2p->ext_listen_period = 0; - p2p->ext_listen_interval = 0; - return 0; - } - - wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, - "P2P: Enabling Extended Listen Timing: period %u msec, " - "interval %u msec", period, interval); - p2p->ext_listen_period = period; - p2p->ext_listen_interval = interval; - p2p->ext_listen_interval_sec = interval / 1000; - p2p->ext_listen_interval_usec = (interval % 1000) * 1000; - - eloop_register_timeout(p2p->ext_listen_interval_sec, - p2p->ext_listen_interval_usec, - p2p_ext_listen_timeout, p2p, NULL); - - return 0; -} - - -void p2p_deauth_notif(struct p2p_data *p2p, const u8 *bssid, u16 reason_code, - const u8 *ie, size_t ie_len) -{ - struct p2p_message msg; - - if (bssid == NULL || ie == NULL) - return; - - os_memset(&msg, 0, sizeof(msg)); - if (p2p_parse_ies(ie, ie_len, &msg)) - return; - if (msg.minor_reason_code == NULL) - return; - - wpa_msg(p2p->cfg->msg_ctx, MSG_INFO, - "P2P: Deauthentication notification BSSID " MACSTR - " reason_code=%u minor_reason_code=%u", - MAC2STR(bssid), reason_code, *msg.minor_reason_code); - - p2p_parse_free(&msg); -} - - -void p2p_disassoc_notif(struct p2p_data *p2p, const u8 *bssid, u16 reason_code, - const u8 *ie, size_t ie_len) -{ - struct p2p_message msg; - - if (bssid == NULL || ie == NULL) - return; - - os_memset(&msg, 0, sizeof(msg)); - if (p2p_parse_ies(ie, ie_len, &msg)) - return; - if (msg.minor_reason_code == NULL) - return; - - wpa_msg(p2p->cfg->msg_ctx, MSG_INFO, - "P2P: Disassociation notification BSSID " MACSTR - " reason_code=%u minor_reason_code=%u", - MAC2STR(bssid), reason_code, *msg.minor_reason_code); - - p2p_parse_free(&msg); -} - - -void p2p_set_managed_oper(struct p2p_data *p2p, int enabled) -{ - if (enabled) { - wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Managed P2P " - "Device operations enabled"); - p2p->dev_capab |= P2P_DEV_CAPAB_INFRA_MANAGED; - } else { - wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Managed P2P " - "Device operations disabled"); - p2p->dev_capab &= ~P2P_DEV_CAPAB_INFRA_MANAGED; - } -} - - -int p2p_set_listen_channel(struct p2p_data *p2p, u8 reg_class, u8 channel) -{ - if (p2p_channel_to_freq(p2p->cfg->country, reg_class, channel) < 0) - return -1; - - wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Set Listen channel: " - "reg_class %u channel %u", reg_class, channel); - p2p->cfg->reg_class = reg_class; - p2p->cfg->channel = channel; - - return 0; -} - - -int p2p_set_ssid_postfix(struct p2p_data *p2p, const u8 *postfix, size_t len) -{ - wpa_hexdump_ascii(MSG_DEBUG, "P2P: New SSID postfix", postfix, len); - if (postfix == NULL) { - p2p->cfg->ssid_postfix_len = 0; - return 0; - } - if (len > sizeof(p2p->cfg->ssid_postfix)) - return -1; - os_memcpy(p2p->cfg->ssid_postfix, postfix, len); - p2p->cfg->ssid_postfix_len = len; - return 0; -} - - -int p2p_get_interface_addr(struct p2p_data *p2p, const u8 *dev_addr, - u8 *iface_addr) -{ - struct p2p_device *dev = p2p_get_device(p2p, dev_addr); - if (dev == NULL || is_zero_ether_addr(dev->interface_addr)) - return -1; - os_memcpy(iface_addr, dev->interface_addr, ETH_ALEN); - return 0; -} - - -int p2p_get_dev_addr(struct p2p_data *p2p, const u8 *iface_addr, - u8 *dev_addr) -{ - struct p2p_device *dev = p2p_get_device_interface(p2p, iface_addr); - if (dev == NULL) - return -1; - os_memcpy(dev_addr, dev->info.p2p_device_addr, ETH_ALEN); - return 0; -} - - -void p2p_set_peer_filter(struct p2p_data *p2p, const u8 *addr) -{ - os_memcpy(p2p->peer_filter, addr, ETH_ALEN); - if (is_zero_ether_addr(p2p->peer_filter)) - wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Disable peer " - "filter"); - else - wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Enable peer " - "filter for " MACSTR, MAC2STR(p2p->peer_filter)); -} - - -void p2p_set_cross_connect(struct p2p_data *p2p, int enabled) -{ - wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Cross connection %s", - enabled ? "enabled" : "disabled"); - if (p2p->cross_connect == enabled) - return; - p2p->cross_connect = enabled; - /* TODO: may need to tear down any action group where we are GO(?) */ -} - - -int p2p_get_oper_freq(struct p2p_data *p2p, const u8 *iface_addr) -{ - struct p2p_device *dev = p2p_get_device_interface(p2p, iface_addr); - if (dev == NULL) - return -1; - if (dev->oper_freq <= 0) - return -1; - return dev->oper_freq; -} - - -void p2p_set_intra_bss_dist(struct p2p_data *p2p, int enabled) -{ - wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Intra BSS distribution %s", - enabled ? "enabled" : "disabled"); - p2p->cfg->p2p_intra_bss = enabled; -} - - -void p2p_update_channel_list(struct p2p_data *p2p, struct p2p_channels *chan) -{ - wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Update channel list"); - os_memcpy(&p2p->cfg->channels, chan, sizeof(struct p2p_channels)); -} - - -int p2p_send_action(struct p2p_data *p2p, unsigned int freq, const u8 *dst, - const u8 *src, const u8 *bssid, const u8 *buf, - size_t len, unsigned int wait_time) -{ - if (p2p->p2p_scan_running) { - wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Delay Action " - "frame TX until p2p_scan completes"); - if (p2p->after_scan_tx) { - wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Dropped " - "previous pending Action frame TX"); - os_free(p2p->after_scan_tx); - } - p2p->after_scan_tx = os_malloc(sizeof(*p2p->after_scan_tx) + - len); - if (p2p->after_scan_tx == NULL) - return -1; - p2p->after_scan_tx->freq = freq; - os_memcpy(p2p->after_scan_tx->dst, dst, ETH_ALEN); - os_memcpy(p2p->after_scan_tx->src, src, ETH_ALEN); - os_memcpy(p2p->after_scan_tx->bssid, bssid, ETH_ALEN); - p2p->after_scan_tx->len = len; - p2p->after_scan_tx->wait_time = wait_time; - os_memcpy(p2p->after_scan_tx + 1, buf, len); - return 0; - } - - return p2p->cfg->send_action(p2p->cfg->cb_ctx, freq, dst, src, bssid, - buf, len, wait_time); -} - - -void p2p_set_best_channels(struct p2p_data *p2p, int freq_24, int freq_5, - int freq_overall) -{ - wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Best channel: 2.4 GHz: %d," - " 5 GHz: %d, overall: %d", freq_24, freq_5, freq_overall); - p2p->best_freq_24 = freq_24; - p2p->best_freq_5 = freq_5; - p2p->best_freq_overall = freq_overall; -} - - -const u8 * p2p_get_go_neg_peer(struct p2p_data *p2p) -{ - if (p2p == NULL || p2p->go_neg_peer == NULL) - return NULL; - return p2p->go_neg_peer->info.p2p_device_addr; -} - - -const struct p2p_peer_info * -p2p_get_peer_found(struct p2p_data *p2p, const u8 *addr, int next) -{ - struct p2p_device *dev; - - if (addr) { - dev = p2p_get_device(p2p, addr); - if (!dev) - return NULL; - - if (!next) { - if (dev->flags & P2P_DEV_PROBE_REQ_ONLY) - return NULL; - - return &dev->info; - } else { - do { - dev = dl_list_first(&dev->list, - struct p2p_device, - list); - if (&dev->list == &p2p->devices) - return NULL; - } while (dev->flags & P2P_DEV_PROBE_REQ_ONLY); - } - } else { - dev = dl_list_first(&p2p->devices, struct p2p_device, list); - if (!dev) - return NULL; - while (dev->flags & P2P_DEV_PROBE_REQ_ONLY) { - dev = dl_list_first(&dev->list, - struct p2p_device, - list); - if (&dev->list == &p2p->devices) - return NULL; - } - } - - return &dev->info; -} diff --git a/hostapd-0.8/src/p2p/p2p.h b/hostapd-0.8/src/p2p/p2p.h deleted file mode 100644 index 954f562..0000000 --- a/hostapd-0.8/src/p2p/p2p.h +++ /dev/null @@ -1,1473 +0,0 @@ -/* - * Wi-Fi Direct - P2P module - * Copyright (c) 2009-2010, Atheros Communications - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#ifndef P2P_H -#define P2P_H - -/** - * P2P_MAX_REG_CLASSES - Maximum number of regulatory classes - */ -#define P2P_MAX_REG_CLASSES 10 - -/** - * P2P_MAX_REG_CLASS_CHANNELS - Maximum number of channels per regulatory class - */ -#define P2P_MAX_REG_CLASS_CHANNELS 20 - -/** - * struct p2p_channels - List of supported channels - */ -struct p2p_channels { - /** - * struct p2p_reg_class - Supported regulatory class - */ - struct p2p_reg_class { - /** - * reg_class - Regulatory class (IEEE 802.11-2007, Annex J) - */ - u8 reg_class; - - /** - * channel - Supported channels - */ - u8 channel[P2P_MAX_REG_CLASS_CHANNELS]; - - /** - * channels - Number of channel entries in use - */ - size_t channels; - } reg_class[P2P_MAX_REG_CLASSES]; - - /** - * reg_classes - Number of reg_class entries in use - */ - size_t reg_classes; -}; - -enum p2p_wps_method { - WPS_NOT_READY, WPS_PIN_LABEL, WPS_PIN_DISPLAY, WPS_PIN_KEYPAD, WPS_PBC -}; - -/** - * struct p2p_go_neg_results - P2P Group Owner Negotiation results - */ -struct p2p_go_neg_results { - /** - * status - Negotiation result (Status Code) - * - * 0 (P2P_SC_SUCCESS) indicates success. Non-zero values indicate - * failed negotiation. - */ - int status; - - /** - * role_go - Whether local end is Group Owner - */ - int role_go; - - /** - * freq - Frequency of the group operational channel in MHz - */ - int freq; - - /** - * ssid - SSID of the group - */ - u8 ssid[32]; - - /** - * ssid_len - Length of SSID in octets - */ - size_t ssid_len; - - /** - * passphrase - WPA2-Personal passphrase for the group (GO only) - */ - char passphrase[64]; - - /** - * peer_device_addr - P2P Device Address of the peer - */ - u8 peer_device_addr[ETH_ALEN]; - - /** - * peer_interface_addr - P2P Interface Address of the peer - */ - u8 peer_interface_addr[ETH_ALEN]; - - /** - * wps_method - WPS method to be used during provisioning - */ - enum p2p_wps_method wps_method; - -#define P2P_MAX_CHANNELS 50 - - /** - * freq_list - Zero-terminated list of possible operational channels - */ - int freq_list[P2P_MAX_CHANNELS]; - - /** - * persistent_group - Whether the group should be made persistent - */ - int persistent_group; - - /** - * peer_config_timeout - Peer configuration timeout (in 10 msec units) - */ - unsigned int peer_config_timeout; -}; - -struct p2p_data; - -enum p2p_scan_type { - P2P_SCAN_SOCIAL, - P2P_SCAN_FULL, - P2P_SCAN_SPECIFIC, - P2P_SCAN_SOCIAL_PLUS_ONE -}; - -#define P2P_MAX_WPS_VENDOR_EXT 10 - -/** - * struct p2p_peer_info - P2P peer information - */ -struct p2p_peer_info { - /** - * p2p_device_addr - P2P Device Address of the peer - */ - u8 p2p_device_addr[ETH_ALEN]; - - /** - * pri_dev_type - Primary Device Type - */ - u8 pri_dev_type[8]; - - /** - * device_name - Device Name (0..32 octets encoded in UTF-8) - */ - char device_name[33]; - - /** - * manufacturer - Manufacturer (0..64 octets encoded in UTF-8) - */ - char manufacturer[65]; - - /** - * model_name - Model Name (0..32 octets encoded in UTF-8) - */ - char model_name[33]; - - /** - * model_number - Model Number (0..32 octets encoded in UTF-8) - */ - char model_number[33]; - - /** - * serial_number - Serial Number (0..32 octets encoded in UTF-8) - */ - char serial_number[33]; - - /** - * config_methods - WPS Configuration Methods - */ - u16 config_methods; - - /** - * dev_capab - Device Capabilities - */ - u8 dev_capab; - - /** - * group_capab - Group Capabilities - */ - u8 group_capab; - - /** - * wps_sec_dev_type_list - WPS secondary device type list - * - * This list includes from 0 to 16 Secondary Device Types as indicated - * by wps_sec_dev_type_list_len (8 * number of types). - */ - u8 wps_sec_dev_type_list[128]; - - /** - * wps_sec_dev_type_list_len - Length of secondary device type list - */ - size_t wps_sec_dev_type_list_len; - - struct wpabuf *wps_vendor_ext[P2P_MAX_WPS_VENDOR_EXT]; -}; - -/** - * struct p2p_config - P2P configuration - * - * This configuration is provided to the P2P module during initialization with - * p2p_init(). - */ -struct p2p_config { - /** - * country - Country code to use in P2P operations - */ - char country[3]; - - /** - * reg_class - Regulatory class for own listen channel - */ - u8 reg_class; - - /** - * channel - Own listen channel - */ - u8 channel; - - /** - * Regulatory class for own operational channel - */ - u8 op_reg_class; - - /** - * op_channel - Own operational channel - */ - u8 op_channel; - - /** - * cfg_op_channel - Whether op_channel is hardcoded in configuration - */ - u8 cfg_op_channel; - - /** - * channels - Own supported regulatory classes and channels - * - * List of supposerted channels per regulatory class. The regulatory - * classes are defined in IEEE Std 802.11-2007 Annex J and the - * numbering of the clases depends on the configured country code. - */ - struct p2p_channels channels; - - /** - * pri_dev_type - Primary Device Type (see WPS) - */ - u8 pri_dev_type[8]; - - /** - * P2P_SEC_DEVICE_TYPES - Maximum number of secondary device types - */ -#define P2P_SEC_DEVICE_TYPES 5 - - /** - * sec_dev_type - Optional secondary device types - */ - u8 sec_dev_type[P2P_SEC_DEVICE_TYPES][8]; - - /** - * num_sec_dev_types - Number of sec_dev_type entries - */ - size_t num_sec_dev_types; - - /** - * dev_addr - P2P Device Address - */ - u8 dev_addr[ETH_ALEN]; - - /** - * dev_name - Device Name - */ - char *dev_name; - - char *manufacturer; - char *model_name; - char *model_number; - char *serial_number; - - u8 uuid[16]; - u16 config_methods; - - /** - * concurrent_operations - Whether concurrent operations are supported - */ - int concurrent_operations; - - /** - * max_peers - Maximum number of discovered peers to remember - * - * If more peers are discovered, older entries will be removed to make - * room for the new ones. - */ - size_t max_peers; - - /** - * p2p_intra_bss - Intra BSS communication is supported - */ - int p2p_intra_bss; - - /** - * ssid_postfix - Postfix data to add to the SSID - * - * This data will be added to the end of the SSID after the - * DIRECT- prefix. - */ - u8 ssid_postfix[32 - 9]; - - /** - * ssid_postfix_len - Length of the ssid_postfix data - */ - size_t ssid_postfix_len; - - /** - * msg_ctx - Context to use with wpa_msg() calls - */ - void *msg_ctx; - - /** - * cb_ctx - Context to use with callback functions - */ - void *cb_ctx; - - - /* Callbacks to request lower layer driver operations */ - - /** - * p2p_scan - Request a P2P scan/search - * @ctx: Callback context from cb_ctx - * @type: Scan type - * @freq: Specific frequency (MHz) to scan or 0 for no restriction - * @num_req_dev_types: Number of requested device types - * @req_dev_types: Array containing requested device types - * Returns: 0 on success, -1 on failure - * - * This callback function is used to request a P2P scan or search - * operation to be completed. Type type argument specifies which type - * of scan is to be done. @P2P_SCAN_SOCIAL indicates that only the - * social channels (1, 6, 11) should be scanned. @P2P_SCAN_FULL - * indicates that all channels are to be scanned. @P2P_SCAN_SPECIFIC - * request a scan of a single channel specified by freq. - * @P2P_SCAN_SOCIAL_PLUS_ONE request scan of all the social channels - * plus one extra channel specified by freq. - * - * The full scan is used for the initial scan to find group owners from - * all. The other types are used during search phase scan of the social - * channels (with potential variation if the Listen channel of the - * target peer is known or if other channels are scanned in steps). - * - * The scan results are returned after this call by calling - * p2p_scan_res_handler() for each scan result that has a P2P IE and - * then calling p2p_scan_res_handled() to indicate that all scan - * results have been indicated. - */ - int (*p2p_scan)(void *ctx, enum p2p_scan_type type, int freq, - unsigned int num_req_dev_types, - const u8 *req_dev_types); - - /** - * send_probe_resp - Transmit a Probe Response frame - * @ctx: Callback context from cb_ctx - * @buf: Probe Response frame (including the header and body) - * Returns: 0 on success, -1 on failure - * - * This function is used to reply to Probe Request frames that were - * indicated with a call to p2p_probe_req_rx(). The response is to be - * sent on the same channel or to be dropped if the driver is not - * anymore listening to Probe Request frames. - * - * Alternatively, the responsibility for building the Probe Response - * frames in Listen state may be in another system component in which - * case this function need to be implemented (i.e., the function - * pointer can be %NULL). The WPS and P2P IEs to be added for Probe - * Response frames in such a case are available from the - * start_listen() callback. It should be noted that the received Probe - * Request frames must be indicated by calling p2p_probe_req_rx() even - * if this send_probe_resp() is not used. - */ - int (*send_probe_resp)(void *ctx, const struct wpabuf *buf); - - /** - * send_action - Transmit an Action frame - * @ctx: Callback context from cb_ctx - * @freq: Frequency in MHz for the channel on which to transmit - * @dst: Destination MAC address (Address 1) - * @src: Source MAC address (Address 2) - * @bssid: BSSID (Address 3) - * @buf: Frame body (starting from Category field) - * @len: Length of buf in octets - * @wait_time: How many msec to wait for a response frame - * Returns: 0 on success, -1 on failure - * - * The Action frame may not be transmitted immediately and the status - * of the transmission must be reported by calling - * p2p_send_action_cb() once the frame has either been transmitted or - * it has been dropped due to excessive retries or other failure to - * transmit. - */ - int (*send_action)(void *ctx, unsigned int freq, const u8 *dst, - const u8 *src, const u8 *bssid, const u8 *buf, - size_t len, unsigned int wait_time); - - /** - * send_action_done - Notify that Action frame sequence was completed - * @ctx: Callback context from cb_ctx - * - * This function is called when the Action frame sequence that was - * started with send_action() has been completed, i.e., when there is - * no need to wait for a response from the destination peer anymore. - */ - void (*send_action_done)(void *ctx); - - /** - * start_listen - Start Listen state - * @ctx: Callback context from cb_ctx - * @freq: Frequency of the listen channel in MHz - * @duration: Duration for the Listen state in milliseconds - * @probe_resp_ie: IE(s) to be added to Probe Response frames - * Returns: 0 on success, -1 on failure - * - * This Listen state may not start immediately since the driver may - * have other pending operations to complete first. Once the Listen - * state has started, p2p_listen_cb() must be called to notify the P2P - * module. Once the Listen state is stopped, p2p_listen_end() must be - * called to notify the P2P module that the driver is not in the Listen - * state anymore. - * - * If the send_probe_resp() is not used for generating the response, - * the IEs from probe_resp_ie need to be added to the end of the Probe - * Response frame body. If send_probe_resp() is used, the probe_resp_ie - * information can be ignored. - */ - int (*start_listen)(void *ctx, unsigned int freq, - unsigned int duration, - const struct wpabuf *probe_resp_ie); - /** - * stop_listen - Stop Listen state - * @ctx: Callback context from cb_ctx - * - * This callback can be used to stop a Listen state operation that was - * previously requested with start_listen(). - */ - void (*stop_listen)(void *ctx); - - /** - * get_noa - Get current Notice of Absence attribute payload - * @ctx: Callback context from cb_ctx - * @interface_addr: P2P Interface Address of the GO - * @buf: Buffer for returning NoA - * @buf_len: Buffer length in octets - * Returns: Number of octets used in buf, 0 to indicate no NoA is being - * advertized, or -1 on failure - * - * This function is used to fetch the current Notice of Absence - * attribute value from GO. - */ - int (*get_noa)(void *ctx, const u8 *interface_addr, u8 *buf, - size_t buf_len); - - /* Callbacks to notify events to upper layer management entity */ - - /** - * dev_found - Notification of a found P2P Device - * @ctx: Callback context from cb_ctx - * @addr: Source address of the message triggering this notification - * @info: P2P peer information - * @new_device: Inform if the peer is newly found - * - * This callback is used to notify that a new P2P Device has been - * found. This may happen, e.g., during Search state based on scan - * results or during Listen state based on receive Probe Request and - * Group Owner Negotiation Request. - */ - void (*dev_found)(void *ctx, const u8 *addr, - const struct p2p_peer_info *info, - int new_device); - - /** - * dev_lost - Notification of a lost P2P Device - * @ctx: Callback context from cb_ctx - * @dev_addr: P2P Device Address of the lost P2P Device - * - * This callback is used to notify that a P2P Device has been deleted. - */ - void (*dev_lost)(void *ctx, const u8 *dev_addr); - - /** - * go_neg_req_rx - Notification of a receive GO Negotiation Request - * @ctx: Callback context from cb_ctx - * @src: Source address of the message triggering this notification - * @dev_passwd_id: WPS Device Password ID - * - * This callback is used to notify that a P2P Device is requesting - * group owner negotiation with us, but we do not have all the - * necessary information to start GO Negotiation. This indicates that - * the local user has not authorized the connection yet by providing a - * PIN or PBC button press. This information can be provided with a - * call to p2p_connect(). - */ - void (*go_neg_req_rx)(void *ctx, const u8 *src, u16 dev_passwd_id); - - /** - * go_neg_completed - Notification of GO Negotiation results - * @ctx: Callback context from cb_ctx - * @res: GO Negotiation results - * - * This callback is used to notify that Group Owner Negotiation has - * been completed. Non-zero struct p2p_go_neg_results::status indicates - * failed negotiation. In case of success, this function is responsible - * for creating a new group interface (or using the existing interface - * depending on driver features), setting up the group interface in - * proper mode based on struct p2p_go_neg_results::role_go and - * initializing WPS provisioning either as a Registrar (if GO) or as an - * Enrollee. Successful WPS provisioning must be indicated by calling - * p2p_wps_success_cb(). The callee is responsible for timing out group - * formation if WPS provisioning cannot be completed successfully - * within 15 seconds. - */ - void (*go_neg_completed)(void *ctx, struct p2p_go_neg_results *res); - - /** - * sd_request - Callback on Service Discovery Request - * @ctx: Callback context from cb_ctx - * @freq: Frequency (in MHz) of the channel - * @sa: Source address of the request - * @dialog_token: Dialog token - * @update_indic: Service Update Indicator from the source of request - * @tlvs: P2P Service Request TLV(s) - * @tlvs_len: Length of tlvs buffer in octets - * - * This callback is used to indicate reception of a service discovery - * request. Response to the query must be indicated by calling - * p2p_sd_response() with the context information from the arguments to - * this callback function. - * - * This callback handler can be set to %NULL to indicate that service - * discovery is not supported. - */ - void (*sd_request)(void *ctx, int freq, const u8 *sa, u8 dialog_token, - u16 update_indic, const u8 *tlvs, size_t tlvs_len); - - /** - * sd_response - Callback on Service Discovery Response - * @ctx: Callback context from cb_ctx - * @sa: Source address of the request - * @update_indic: Service Update Indicator from the source of response - * @tlvs: P2P Service Response TLV(s) - * @tlvs_len: Length of tlvs buffer in octets - * - * This callback is used to indicate reception of a service discovery - * response. This callback handler can be set to %NULL if no service - * discovery requests are used. The information provided with this call - * is replies to the queries scheduled with p2p_sd_request(). - */ - void (*sd_response)(void *ctx, const u8 *sa, u16 update_indic, - const u8 *tlvs, size_t tlvs_len); - - /** - * prov_disc_req - Callback on Provisiong Discovery Request - * @ctx: Callback context from cb_ctx - * @peer: Source address of the request - * @config_methods: Requested WPS Config Method - * @dev_addr: P2P Device Address of the found P2P Device - * @pri_dev_type: Primary Device Type - * @dev_name: Device Name - * @supp_config_methods: Supported configuration Methods - * @dev_capab: Device Capabilities - * @group_capab: Group Capabilities - * - * This callback is used to indicate reception of a Provision Discovery - * Request frame that the P2P module accepted. - */ - void (*prov_disc_req)(void *ctx, const u8 *peer, u16 config_methods, - const u8 *dev_addr, const u8 *pri_dev_type, - const char *dev_name, u16 supp_config_methods, - u8 dev_capab, u8 group_capab); - - /** - * prov_disc_resp - Callback on Provisiong Discovery Response - * @ctx: Callback context from cb_ctx - * @peer: Source address of the response - * @config_methods: Value from p2p_prov_disc_req() or 0 on failure - * - * This callback is used to indicate reception of a Provision Discovery - * Response frame for a pending request scheduled with - * p2p_prov_disc_req(). This callback handler can be set to %NULL if - * provision discovery is not used. - */ - void (*prov_disc_resp)(void *ctx, const u8 *peer, u16 config_methods); - - /** - * invitation_process - Optional callback for processing Invitations - * @ctx: Callback context from cb_ctx - * @sa: Source address of the Invitation Request - * @bssid: P2P Group BSSID from the request or %NULL if not included - * @go_dev_addr: GO Device Address from P2P Group ID - * @ssid: SSID from P2P Group ID - * @ssid_len: Length of ssid buffer in octets - * @go: Variable for returning whether the local end is GO in the group - * @group_bssid: Buffer for returning P2P Group BSSID (if local end GO) - * @force_freq: Variable for returning forced frequency for the group - * @persistent_group: Whether this is an invitation to reinvoke a - * persistent group (instead of invitation to join an active - * group) - * Returns: Status code (P2P_SC_*) - * - * This optional callback can be used to implement persistent reconnect - * by allowing automatic restarting of persistent groups without user - * interaction. If this callback is not implemented (i.e., is %NULL), - * the received Invitation Request frames are replied with - * %P2P_SC_REQ_RECEIVED status and indicated to upper layer with the - * invitation_result() callback. - * - * If the requested parameters are acceptable and the group is known, - * %P2P_SC_SUCCESS may be returned. If the requested group is unknown, - * %P2P_SC_FAIL_UNKNOWN_GROUP should be returned. %P2P_SC_REQ_RECEIVED - * can be returned if there is not enough data to provide immediate - * response, i.e., if some sort of user interaction is needed. The - * invitation_received() callback will be called in that case - * immediately after this call. - */ - u8 (*invitation_process)(void *ctx, const u8 *sa, const u8 *bssid, - const u8 *go_dev_addr, const u8 *ssid, - size_t ssid_len, int *go, u8 *group_bssid, - int *force_freq, int persistent_group); - - /** - * invitation_received - Callback on Invitation Request RX - * @ctx: Callback context from cb_ctx - * @sa: Source address of the Invitation Request - * @bssid: P2P Group BSSID or %NULL if not received - * @ssid: SSID of the group - * @ssid_len: Length of ssid in octets - * @go_dev_addr: GO Device Address - * @status: Response Status - * @op_freq: Operational frequency for the group - * - * This callback is used to indicate sending of an Invitation Response - * for a received Invitation Request. If status == 0 (success), the - * upper layer code is responsible for starting the group. status == 1 - * indicates need to get user authorization for the group. Other status - * values indicate that the invitation request was rejected. - */ - void (*invitation_received)(void *ctx, const u8 *sa, const u8 *bssid, - const u8 *ssid, size_t ssid_len, - const u8 *go_dev_addr, u8 status, - int op_freq); - - /** - * invitation_result - Callback on Invitation result - * @ctx: Callback context from cb_ctx - * @status: Negotiation result (Status Code) - * @bssid: P2P Group BSSID or %NULL if not received - * - * This callback is used to indicate result of an Invitation procedure - * started with a call to p2p_invite(). The indicated status code is - * the value received from the peer in Invitation Response with 0 - * (P2P_SC_SUCCESS) indicating success or -1 to indicate a timeout or a - * local failure in transmitting the Invitation Request. - */ - void (*invitation_result)(void *ctx, int status, const u8 *bssid); -}; - - -/* P2P module initialization/deinitialization */ - -/** - * p2p_init - Initialize P2P module - * @cfg: P2P module configuration - * Returns: Pointer to private data or %NULL on failure - * - * This function is used to initialize global P2P module context (one per - * device). The P2P module will keep a copy of the configuration data, so the - * caller does not need to maintain this structure. However, the callback - * functions and the context parameters to them must be kept available until - * the P2P module is deinitialized with p2p_deinit(). - */ -struct p2p_data * p2p_init(const struct p2p_config *cfg); - -/** - * p2p_deinit - Deinitialize P2P module - * @p2p: P2P module context from p2p_init() - */ -void p2p_deinit(struct p2p_data *p2p); - -/** - * p2p_flush - Flush P2P module state - * @p2p: P2P module context from p2p_init() - * - * This command removes the P2P module state like peer device entries. - */ -void p2p_flush(struct p2p_data *p2p); - -/** - * p2p_unauthorize - Unauthorize the specified peer device - * @p2p: P2P module context from p2p_init() - * @addr: P2P peer entry to be unauthorized - * Returns: 0 on success, -1 on failure - * - * This command removes any connection authorization from the specified P2P - * peer device address. This can be used, e.g., to cancel effect of a previous - * p2p_authorize() or p2p_connect() call that has not yet resulted in completed - * GO Negotiation. - */ -int p2p_unauthorize(struct p2p_data *p2p, const u8 *addr); - -/** - * p2p_set_dev_name - Set device name - * @p2p: P2P module context from p2p_init() - * Returns: 0 on success, -1 on failure - * - * This function can be used to update the P2P module configuration with - * information that was not available at the time of the p2p_init() call. - */ -int p2p_set_dev_name(struct p2p_data *p2p, const char *dev_name); - -int p2p_set_manufacturer(struct p2p_data *p2p, const char *manufacturer); -int p2p_set_model_name(struct p2p_data *p2p, const char *model_name); -int p2p_set_model_number(struct p2p_data *p2p, const char *model_number); -int p2p_set_serial_number(struct p2p_data *p2p, const char *serial_number); - -void p2p_set_config_methods(struct p2p_data *p2p, u16 config_methods); -void p2p_set_uuid(struct p2p_data *p2p, const u8 *uuid); - -/** - * p2p_set_pri_dev_type - Set primary device type - * @p2p: P2P module context from p2p_init() - * Returns: 0 on success, -1 on failure - * - * This function can be used to update the P2P module configuration with - * information that was not available at the time of the p2p_init() call. - */ -int p2p_set_pri_dev_type(struct p2p_data *p2p, const u8 *pri_dev_type); - -/** - * p2p_set_sec_dev_types - Set secondary device types - * @p2p: P2P module context from p2p_init() - * Returns: 0 on success, -1 on failure - * - * This function can be used to update the P2P module configuration with - * information that was not available at the time of the p2p_init() call. - */ -int p2p_set_sec_dev_types(struct p2p_data *p2p, const u8 dev_types[][8], - size_t num_dev_types); - -int p2p_set_country(struct p2p_data *p2p, const char *country); - - -/* Commands from upper layer management entity */ - -enum p2p_discovery_type { - P2P_FIND_START_WITH_FULL, - P2P_FIND_ONLY_SOCIAL, - P2P_FIND_PROGRESSIVE -}; - -/** - * p2p_find - Start P2P Find (Device Discovery) - * @p2p: P2P module context from p2p_init() - * @timeout: Timeout for find operation in seconds or 0 for no timeout - * @type: Device Discovery type - * @num_req_dev_types: Number of requested device types - * @req_dev_types: Requested device types array, must be an array - * containing num_req_dev_types * WPS_DEV_TYPE_LEN bytes; %NULL if no - * requested device types. - * Returns: 0 on success, -1 on failure - */ -int p2p_find(struct p2p_data *p2p, unsigned int timeout, - enum p2p_discovery_type type, - unsigned int num_req_dev_types, const u8 *req_dev_types); - -/** - * p2p_stop_find - Stop P2P Find (Device Discovery) - * @p2p: P2P module context from p2p_init() - */ -void p2p_stop_find(struct p2p_data *p2p); - -/** - * p2p_stop_find_for_freq - Stop P2P Find for next oper on specific freq - * @p2p: P2P module context from p2p_init() - * @freq: Frequency in MHz for next operation - * - * This is like p2p_stop_find(), but Listen state is not stopped if we are - * already on the same frequency. - */ -void p2p_stop_find_for_freq(struct p2p_data *p2p, int freq); - -/** - * p2p_listen - Start P2P Listen state for specified duration - * @p2p: P2P module context from p2p_init() - * @timeout: Listen state duration in milliseconds - * Returns: 0 on success, -1 on failure - * - * This function can be used to request the P2P module to keep the device - * discoverable on the listen channel for an extended set of time. At least in - * its current form, this is mainly used for testing purposes and may not be of - * much use for normal P2P operations. - */ -int p2p_listen(struct p2p_data *p2p, unsigned int timeout); - -/** - * p2p_connect - Start P2P group formation (GO negotiation) - * @p2p: P2P module context from p2p_init() - * @peer_addr: MAC address of the peer P2P client - * @wps_method: WPS method to be used in provisioning - * @go_intent: Local GO intent value (1..15) - * @own_interface_addr: Intended interface address to use with the group - * @force_freq: The only allowed channel frequency in MHz or 0 - * @persistent_group: Whether to create a persistent group - * Returns: 0 on success, -1 on failure - */ -int p2p_connect(struct p2p_data *p2p, const u8 *peer_addr, - enum p2p_wps_method wps_method, - int go_intent, const u8 *own_interface_addr, - unsigned int force_freq, int persistent_group); - -/** - * p2p_authorize - Authorize P2P group formation (GO negotiation) - * @p2p: P2P module context from p2p_init() - * @peer_addr: MAC address of the peer P2P client - * @wps_method: WPS method to be used in provisioning - * @go_intent: Local GO intent value (1..15) - * @own_interface_addr: Intended interface address to use with the group - * @force_freq: The only allowed channel frequency in MHz or 0 - * @persistent_group: Whether to create a persistent group - * Returns: 0 on success, -1 on failure - * - * This is like p2p_connect(), but the actual group negotiation is not - * initiated automatically, i.e., the other end is expected to do that. - */ -int p2p_authorize(struct p2p_data *p2p, const u8 *peer_addr, - enum p2p_wps_method wps_method, - int go_intent, const u8 *own_interface_addr, - unsigned int force_freq, int persistent_group); - -/** - * p2p_reject - Reject peer device (explicitly block connection attempts) - * @p2p: P2P module context from p2p_init() - * @peer_addr: MAC address of the peer P2P client - * Returns: 0 on success, -1 on failure - */ -int p2p_reject(struct p2p_data *p2p, const u8 *peer_addr); - -/** - * p2p_prov_disc_req - Send Provision Discovery Request - * @p2p: P2P module context from p2p_init() - * @peer_addr: MAC address of the peer P2P client - * @config_methods: WPS Config Methods value (only one bit set) - * @join: Whether this is used by a client joining an active group - * Returns: 0 on success, -1 on failure - * - * This function can be used to request a discovered P2P peer to display a PIN - * (config_methods = WPS_CONFIG_DISPLAY) or be prepared to enter a PIN from us - * (config_methods = WPS_CONFIG_KEYPAD). The Provision Discovery Request frame - * is transmitted once immediately and if no response is received, the frame - * will be sent again whenever the target device is discovered during device - * dsicovery (start with a p2p_find() call). Response from the peer is - * indicated with the p2p_config::prov_disc_resp() callback. - */ -int p2p_prov_disc_req(struct p2p_data *p2p, const u8 *peer_addr, - u16 config_methods, int join); - -/** - * p2p_sd_request - Schedule a service discovery query - * @p2p: P2P module context from p2p_init() - * @dst: Destination peer or %NULL to apply for all peers - * @tlvs: P2P Service Query TLV(s) - * Returns: Reference to the query or %NULL on failure - * - * Response to the query is indicated with the p2p_config::sd_response() - * callback. - */ -void * p2p_sd_request(struct p2p_data *p2p, const u8 *dst, - const struct wpabuf *tlvs); - -/** - * p2p_sd_cancel_request - Cancel a pending service discovery query - * @p2p: P2P module context from p2p_init() - * @req: Query reference from p2p_sd_request() - * Returns: 0 if request for cancelled; -1 if not found - */ -int p2p_sd_cancel_request(struct p2p_data *p2p, void *req); - -/** - * p2p_sd_response - Send response to a service discovery query - * @p2p: P2P module context from p2p_init() - * @freq: Frequency from p2p_config::sd_request() callback - * @dst: Destination address from p2p_config::sd_request() callback - * @dialog_token: Dialog token from p2p_config::sd_request() callback - * @resp_tlvs: P2P Service Response TLV(s) - * - * This function is called as a response to the request indicated with - * p2p_config::sd_request() callback. - */ -void p2p_sd_response(struct p2p_data *p2p, int freq, const u8 *dst, - u8 dialog_token, const struct wpabuf *resp_tlvs); - -/** - * p2p_sd_service_update - Indicate a change in local services - * @p2p: P2P module context from p2p_init() - * - * This function needs to be called whenever there is a change in availability - * of the local services. This will increment the Service Update Indicator - * value which will be used in SD Request and Response frames. - */ -void p2p_sd_service_update(struct p2p_data *p2p); - - -enum p2p_invite_role { - P2P_INVITE_ROLE_GO, - P2P_INVITE_ROLE_ACTIVE_GO, - P2P_INVITE_ROLE_CLIENT -}; - -/** - * p2p_invite - Invite a P2P Device into a group - * @p2p: P2P module context from p2p_init() - * @peer: Device Address of the peer P2P Device - * @role: Local role in the group - * @bssid: Group BSSID or %NULL if not known - * @ssid: Group SSID - * @ssid_len: Length of ssid in octets - * @force_freq: The only allowed channel frequency in MHz or 0 - * @go_dev_addr: Forced GO Device Address or %NULL if none - * @persistent_group: Whether this is to reinvoke a persistent group - * Returns: 0 on success, -1 on failure - */ -int p2p_invite(struct p2p_data *p2p, const u8 *peer, enum p2p_invite_role role, - const u8 *bssid, const u8 *ssid, size_t ssid_len, - unsigned int force_freq, const u8 *go_dev_addr, - int persistent_group); - -/** - * p2p_presence_req - Request GO presence - * @p2p: P2P module context from p2p_init() - * @go_interface_addr: GO P2P Interface Address - * @own_interface_addr: Own P2P Interface Address for this group - * @freq: Group operating frequence (in MHz) - * @duration1: Preferred presence duration in microseconds - * @interval1: Preferred presence interval in microseconds - * @duration2: Acceptable presence duration in microseconds - * @interval2: Acceptable presence interval in microseconds - * Returns: 0 on success, -1 on failure - * - * If both duration and interval values are zero, the parameter pair is not - * specified (i.e., to remove Presence Request, use duration1 = interval1 = 0). - */ -int p2p_presence_req(struct p2p_data *p2p, const u8 *go_interface_addr, - const u8 *own_interface_addr, unsigned int freq, - u32 duration1, u32 interval1, u32 duration2, - u32 interval2); - -/** - * p2p_ext_listen - Set Extended Listen Timing - * @p2p: P2P module context from p2p_init() - * @freq: Group operating frequence (in MHz) - * @period: Availability period in milliseconds (1-65535; 0 to disable) - * @interval: Availability interval in milliseconds (1-65535; 0 to disable) - * Returns: 0 on success, -1 on failure - * - * This function can be used to enable or disable (period = interval = 0) - * Extended Listen Timing. When enabled, the P2P Device will become - * discoverable (go into Listen State) every @interval milliseconds for at - * least @period milliseconds. - */ -int p2p_ext_listen(struct p2p_data *p2p, unsigned int period, - unsigned int interval); - -/* Event notifications from upper layer management operations */ - -/** - * p2p_wps_success_cb - Report successfully completed WPS provisioning - * @p2p: P2P module context from p2p_init() - * @mac_addr: Peer address - * - * This function is used to report successfully completed WPS provisioning - * during group formation in both GO/Registrar and client/Enrollee roles. - */ -void p2p_wps_success_cb(struct p2p_data *p2p, const u8 *mac_addr); - -/** - * p2p_group_formation_failed - Report failed WPS provisioning - * @p2p: P2P module context from p2p_init() - * - * This function is used to report failed group formation. This can happen - * either due to failed WPS provisioning or due to 15 second timeout during - * the provisioning phase. - */ -void p2p_group_formation_failed(struct p2p_data *p2p); - - -/* Event notifications from lower layer driver operations */ - -/** - * p2p_probe_req_rx - Report reception of a Probe Request frame - * @p2p: P2P module context from p2p_init() - * @addr: Source MAC address - * @ie: Information elements from the Probe Request frame body - * @ie_len: Length of ie buffer in octets - * Returns: 0 to indicate the frame was not processed or 1 if it was - */ -int p2p_probe_req_rx(struct p2p_data *p2p, const u8 *addr, const u8 *ie, - size_t ie_len); - -/** - * p2p_rx_action - Report received Action frame - * @p2p: P2P module context from p2p_init() - * @da: Destination address of the received Action frame - * @sa: Source address of the received Action frame - * @bssid: Address 3 of the received Action frame - * @category: Category of the received Action frame - * @data: Action frame body after the Category field - * @len: Length of the data buffer in octets - * @freq: Frequency (in MHz) on which the frame was received - */ -void p2p_rx_action(struct p2p_data *p2p, const u8 *da, const u8 *sa, - const u8 *bssid, u8 category, - const u8 *data, size_t len, int freq); - -/** - * p2p_scan_res_handler - Indicate a P2P scan results - * @p2p: P2P module context from p2p_init() - * @bssid: BSSID of the scan result - * @freq: Frequency of the channel on which the device was found in MHz - * @level: Signal level (signal strength of the received Beacon/Probe Response - * frame) - * @ies: Pointer to IEs from the scan result - * @ies_len: Length of the ies buffer - * Returns: 0 to continue or 1 to stop scan result indication - * - * This function is called to indicate a scan result entry with P2P IE from a - * scan requested with struct p2p_config::p2p_scan(). This can be called during - * the actual scan process (i.e., whenever a new device is found) or as a - * sequence of calls after the full scan has been completed. The former option - * can result in optimized operations, but may not be supported by all - * driver/firmware designs. The ies buffer need to include at least the P2P IE, - * but it is recommended to include all IEs received from the device. The - * caller does not need to check that the IEs contain a P2P IE before calling - * this function since frames will be filtered internally if needed. - * - * This function will return 1 if it wants to stop scan result iteration (and - * scan in general if it is still in progress). This is used to allow faster - * start of a pending operation, e.g., to start a pending GO negotiation. - */ -int p2p_scan_res_handler(struct p2p_data *p2p, const u8 *bssid, int freq, - int level, const u8 *ies, size_t ies_len); - -/** - * p2p_scan_res_handled - Indicate end of scan results - * @p2p: P2P module context from p2p_init() - * - * This function is called to indicate that all P2P scan results from a scan - * have been reported with zero or more calls to p2p_scan_res_handler(). This - * function must be called as a response to successful - * struct p2p_config::p2p_scan() call if none of the p2p_scan_res_handler() - * calls stopped iteration. - */ -void p2p_scan_res_handled(struct p2p_data *p2p); - -enum p2p_send_action_result { - P2P_SEND_ACTION_SUCCESS /* Frame was send and acknowledged */, - P2P_SEND_ACTION_NO_ACK /* Frame was sent, but not acknowledged */, - P2P_SEND_ACTION_FAILED /* Frame was not sent due to a failure */ -}; - -/** - * p2p_send_action_cb - Notify TX status of an Action frame - * @p2p: P2P module context from p2p_init() - * @freq: Channel frequency in MHz - * @dst: Destination MAC address (Address 1) - * @src: Source MAC address (Address 2) - * @bssid: BSSID (Address 3) - * @result: Result of the transmission attempt - * - * This function is used to indicate the result of an Action frame transmission - * that was requested with struct p2p_config::send_action() callback. - */ -void p2p_send_action_cb(struct p2p_data *p2p, unsigned int freq, const u8 *dst, - const u8 *src, const u8 *bssid, - enum p2p_send_action_result result); - -/** - * p2p_listen_cb - Indicate the start of a requested Listen state - * @p2p: P2P module context from p2p_init() - * @freq: Listen channel frequency in MHz - * @duration: Duration for the Listen state in milliseconds - * - * This function is used to indicate that a Listen state requested with - * struct p2p_config::start_listen() callback has started. - */ -void p2p_listen_cb(struct p2p_data *p2p, unsigned int freq, - unsigned int duration); - -/** - * p2p_listen_end - Indicate the end of a requested Listen state - * @p2p: P2P module context from p2p_init() - * @freq: Listen channel frequency in MHz - * Returns: 0 if no operations were started, 1 if an operation was started - * - * This function is used to indicate that a Listen state requested with - * struct p2p_config::start_listen() callback has ended. - */ -int p2p_listen_end(struct p2p_data *p2p, unsigned int freq); - -void p2p_deauth_notif(struct p2p_data *p2p, const u8 *bssid, u16 reason_code, - const u8 *ie, size_t ie_len); - -void p2p_disassoc_notif(struct p2p_data *p2p, const u8 *bssid, u16 reason_code, - const u8 *ie, size_t ie_len); - - -/* Per-group P2P state for GO */ - -struct p2p_group; - -/** - * struct p2p_group_config - P2P group configuration - * - * This configuration is provided to the P2P module during initialization of - * the per-group information with p2p_group_init(). - */ -struct p2p_group_config { - /** - * persistent_group - Whether the group is persistent - */ - int persistent_group; - - /** - * interface_addr - P2P Interface Address of the group - */ - u8 interface_addr[ETH_ALEN]; - - /** - * max_clients - Maximum number of clients in the group - */ - unsigned int max_clients; - - /** - * cb_ctx - Context to use with callback functions - */ - void *cb_ctx; - - /** - * ie_update - Notification of IE update - * @ctx: Callback context from cb_ctx - * @beacon_ies: P2P IE for Beacon frames or %NULL if no change - * @proberesp_ies: P2P Ie for Probe Response frames - * - * P2P module uses this callback function to notify whenever the P2P IE - * in Beacon or Probe Response frames should be updated based on group - * events. - * - * The callee is responsible for freeing the returned buffer(s) with - * wpabuf_free(). - */ - void (*ie_update)(void *ctx, struct wpabuf *beacon_ies, - struct wpabuf *proberesp_ies); - - /** - * idle_update - Notification of changes in group idle state - * @ctx: Callback context from cb_ctx - * @idle: Whether the group is idle (no associated stations) - */ - void (*idle_update)(void *ctx, int idle); -}; - -/** - * p2p_group_init - Initialize P2P group - * @p2p: P2P module context from p2p_init() - * @config: P2P group configuration (will be freed by p2p_group_deinit()) - * Returns: Pointer to private data or %NULL on failure - * - * This function is used to initialize per-group P2P module context. Currently, - * this is only used to manage GO functionality and P2P clients do not need to - * create an instance of this per-group information. - */ -struct p2p_group * p2p_group_init(struct p2p_data *p2p, - struct p2p_group_config *config); - -/** - * p2p_group_deinit - Deinitialize P2P group - * @group: P2P group context from p2p_group_init() - */ -void p2p_group_deinit(struct p2p_group *group); - -/** - * p2p_group_notif_assoc - Notification of P2P client association with GO - * @group: P2P group context from p2p_group_init() - * @addr: Interface address of the P2P client - * @ie: IEs from the (Re)association Request frame - * @len: Length of the ie buffer in octets - * Returns: 0 on success, -1 on failure - */ -int p2p_group_notif_assoc(struct p2p_group *group, const u8 *addr, - const u8 *ie, size_t len); - -/** - * p2p_group_assoc_resp_ie - Build P2P IE for (re)association response - * @group: P2P group context from p2p_group_init() - * @status: Status value (P2P_SC_SUCCESS if association succeeded) - * Returns: P2P IE for (Re)association Response or %NULL on failure - * - * The caller is responsible for freeing the returned buffer with - * wpabuf_free(). - */ -struct wpabuf * p2p_group_assoc_resp_ie(struct p2p_group *group, u8 status); - -/** - * p2p_group_notif_disassoc - Notification of P2P client disassociation from GO - * @group: P2P group context from p2p_group_init() - * @addr: Interface address of the P2P client - */ -void p2p_group_notif_disassoc(struct p2p_group *group, const u8 *addr); - -/** - * p2p_group_notif_formation_done - Notification of completed group formation - * @group: P2P group context from p2p_group_init() - */ -void p2p_group_notif_formation_done(struct p2p_group *group); - -/** - * p2p_group_notif_noa - Notification of NoA change - * @group: P2P group context from p2p_group_init() - * @noa: Notice of Absence attribute payload, %NULL if none - * @noa_len: Length of noa buffer in octets - * Returns: 0 on success, -1 on failure - * - * Notify the P2P group management about a new NoA contents. This will be - * inserted into the P2P IEs in Beacon and Probe Response frames with rest of - * the group information. - */ -int p2p_group_notif_noa(struct p2p_group *group, const u8 *noa, - size_t noa_len); - -/** - * p2p_group_match_dev_type - Match device types in group with requested type - * @group: P2P group context from p2p_group_init() - * @wps: WPS TLVs from Probe Request frame (concatenated WPS IEs) - * Returns: 1 on match, 0 on mismatch - * - * This function can be used to match the Requested Device Type attribute in - * WPS IE with the device types of a group member for deciding whether a GO - * should reply to a Probe Request frame. Match will be reported if the WPS IE - * is not requested any specific device type. - */ -int p2p_group_match_dev_type(struct p2p_group *group, struct wpabuf *wps); - -/** - * p2p_group_go_discover - Send GO Discoverability Request to a group client - * @group: P2P group context from p2p_group_init() - * Returns: 0 on success (frame scheduled); -1 if client was not found - */ -int p2p_group_go_discover(struct p2p_group *group, const u8 *dev_id, - const u8 *searching_dev, int rx_freq); - - -/* Generic helper functions */ - -/** - * p2p_ie_text - Build text format description of P2P IE - * @p2p_ie: P2P IE - * @buf: Buffer for returning text - * @end: Pointer to the end of the buf area - * Returns: Number of octets written to the buffer or -1 on failure - * - * This function can be used to parse P2P IE contents into text format - * field=value lines. - */ -int p2p_ie_text(struct wpabuf *p2p_ie, char *buf, char *end); - -/** - * p2p_scan_result_text - Build text format description of P2P IE - * @ies: Information elements from scan results - * @ies_len: ies buffer length in octets - * @buf: Buffer for returning text - * @end: Pointer to the end of the buf area - * Returns: Number of octets written to the buffer or -1 on failure - * - * This function can be used to parse P2P IE contents into text format - * field=value lines. - */ -int p2p_scan_result_text(const u8 *ies, size_t ies_len, char *buf, char *end); - -/** - * p2p_assoc_req_ie - Build P2P IE for (Re)Association Request frame - * @p2p: P2P module context from p2p_init() - * @bssid: BSSID - * @buf: Buffer for writing the P2P IE - * @len: Maximum buf length in octets - * @p2p_group: Whether this is for association with a P2P GO - * @p2p_ie: Reassembled P2P IE data from scan results or %NULL if none - * Returns: Number of octets written into buf or -1 on failure - */ -int p2p_assoc_req_ie(struct p2p_data *p2p, const u8 *bssid, u8 *buf, - size_t len, int p2p_group, struct wpabuf *p2p_ie); - -/** - * p2p_scan_ie - Build P2P IE for Probe Request - * @p2p: P2P module context from p2p_init() - * @ies: Buffer for writing P2P IE - */ -void p2p_scan_ie(struct p2p_data *p2p, struct wpabuf *ies); - -/** - * p2p_go_params - Generate random P2P group parameters - * @p2p: P2P module context from p2p_init() - * @params: Buffer for parameters - * Returns: 0 on success, -1 on failure - */ -int p2p_go_params(struct p2p_data *p2p, struct p2p_go_neg_results *params); - -/** - * p2p_get_group_capab - Get Group Capability from P2P IE data - * @p2p_ie: P2P IE(s) contents - * Returns: Group Capability - */ -u8 p2p_get_group_capab(const struct wpabuf *p2p_ie); - -/** - * p2p_get_cross_connect_disallowed - Does WLAN AP disallows cross connection - * @p2p_ie: P2P IE(s) contents - * Returns: 0 if cross connection is allow, 1 if not - */ -int p2p_get_cross_connect_disallowed(const struct wpabuf *p2p_ie); - -/** - * p2p_get_go_dev_addr - Get P2P Device Address from P2P IE data - * @p2p_ie: P2P IE(s) contents - * Returns: Pointer to P2P Device Address or %NULL if not included - */ -const u8 * p2p_get_go_dev_addr(const struct wpabuf *p2p_ie); - -/** - * p2p_get_peer_info - Get P2P peer information in text format - * @p2p: P2P module context from p2p_init() - * @addr: P2P Device Address of the peer or %NULL to indicate the first peer - * @next: Whether to select the peer entry following the one indicated by addr - * @buf: Buffer for returning text - * @buflen: Maximum buffer length - * Returns: Number of octets written to the buffer or -1 on failure - */ -int p2p_get_peer_info(struct p2p_data *p2p, const u8 *addr, int next, - char *buf, size_t buflen); - -/** - * p2p_set_client_discoverability - Set client discoverability capability - * @p2p: P2P module context from p2p_init() - * @enabled: Whether client discoverability will be enabled - * - * This function can be used to disable (and re-enable) client discoverability. - * This capability is enabled by default and should not be disabled in normal - * use cases, i.e., this is mainly for testing purposes. - */ -void p2p_set_client_discoverability(struct p2p_data *p2p, int enabled); - -/** - * p2p_set_manageD_oper - Set managed P2P Device operations capability - * @p2p: P2P module context from p2p_init() - * @enabled: Whether managed P2P Device operations will be enabled - */ -void p2p_set_managed_oper(struct p2p_data *p2p, int enabled); - -int p2p_set_listen_channel(struct p2p_data *p2p, u8 reg_class, u8 channel); - -int p2p_set_ssid_postfix(struct p2p_data *p2p, const u8 *postfix, size_t len); - -int p2p_get_interface_addr(struct p2p_data *p2p, const u8 *dev_addr, - u8 *iface_addr); -int p2p_get_dev_addr(struct p2p_data *p2p, const u8 *iface_addr, - u8 *dev_addr); - -void p2p_set_peer_filter(struct p2p_data *p2p, const u8 *addr); - -/** - * p2p_set_cross_connect - Set cross connection capability - * @p2p: P2P module context from p2p_init() - * @enabled: Whether cross connection will be enabled - */ -void p2p_set_cross_connect(struct p2p_data *p2p, int enabled); - -int p2p_get_oper_freq(struct p2p_data *p2p, const u8 *iface_addr); - -int p2p_add_device(struct p2p_data *p2p, const u8 *addr, int freq, int level, - const u8 *ies, size_t ies_len); - -/** - * p2p_set_intra_bss_dist - Set intra BSS distribution - * @p2p: P2P module context from p2p_init() - * @enabled: Whether intra BSS distribution will be enabled - */ -void p2p_set_intra_bss_dist(struct p2p_data *p2p, int enabled); - -/** - * p2p_supported_freq - Check whether channel is supported for P2P - * @p2p: P2P module context from p2p_init() - * @freq: Channel frequency in MHz - * Returns: 0 if channel not usable for P2P, 1 if usable for P2P - */ -int p2p_supported_freq(struct p2p_data *p2p, unsigned int freq); - -void p2p_update_channel_list(struct p2p_data *p2p, struct p2p_channels *chan); - -/** - * p2p_set_best_channels - Update best channel information - * @p2p: P2P module context from p2p_init() - * @freq_24: Frequency (MHz) of best channel in 2.4 GHz band - * @freq_5: Frequency (MHz) of best channel in 5 GHz band - * @freq_overall: Frequency (MHz) of best channel overall - */ -void p2p_set_best_channels(struct p2p_data *p2p, int freq_24, int freq_5, - int freq_overall); - -const u8 * p2p_get_go_neg_peer(struct p2p_data *p2p); - -/** - * p2p_get_group_num_members - Get number of members in group - * @group: P2P group context from p2p_group_init() - * Returns: Number of members in the group - */ -unsigned int p2p_get_group_num_members(struct p2p_group *group); - -/** - * p2p_iterate_group_members - Iterate group members - * @group: P2P group context from p2p_group_init() - * @next: iteration pointer, must be a pointer to a void * that is set to %NULL - * on the first call and not modified later - * Returns: A P2P Interface Address for each call and %NULL for no more members - */ -const u8 * p2p_iterate_group_members(struct p2p_group *group, void **next); - -/** - * p2p_get_peer_found - Get P2P peer info structure of a found peer - * @p2p: P2P module context from p2p_init() - * @addr: P2P Device Address of the peer or %NULL to indicate the first peer - * @next: Whether to select the peer entry following the one indicated by addr - * Returns: The first P2P peer info available or %NULL if no such peer exists - */ -const struct p2p_peer_info * -p2p_get_peer_found(struct p2p_data *p2p, const u8 *addr, int next); - -/** - * p2p_remove_wps_vendor_extensions - Remove WPS vendor extensions - * @p2p: P2P module context from p2p_init() - */ -void p2p_remove_wps_vendor_extensions(struct p2p_data *p2p); - -/** - * p2p_add_wps_vendor_extension - Add a WPS vendor extension - * @p2p: P2P module context from p2p_init() - * @vendor_ext: The vendor extensions to add - * Returns: 0 on success, -1 on failure - * - * The wpabuf structures in the array are owned by the P2P - * module after this call. - */ -int p2p_add_wps_vendor_extension(struct p2p_data *p2p, - const struct wpabuf *vendor_ext); - -#endif /* P2P_H */ diff --git a/hostapd-0.8/src/p2p/p2p_build.c b/hostapd-0.8/src/p2p/p2p_build.c deleted file mode 100644 index c34db91..0000000 --- a/hostapd-0.8/src/p2p/p2p_build.c +++ /dev/null @@ -1,431 +0,0 @@ -/* - * P2P - IE builder - * Copyright (c) 2009-2010, Atheros Communications - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#include "includes.h" - -#include "common.h" -#include "common/ieee802_11_defs.h" -#include "wps/wps_i.h" -#include "p2p_i.h" - - -void p2p_buf_add_action_hdr(struct wpabuf *buf, u8 subtype, u8 dialog_token) -{ - wpabuf_put_u8(buf, WLAN_ACTION_VENDOR_SPECIFIC); - wpabuf_put_be24(buf, OUI_WFA); - wpabuf_put_u8(buf, P2P_OUI_TYPE); - - wpabuf_put_u8(buf, subtype); /* OUI Subtype */ - wpabuf_put_u8(buf, dialog_token); - wpa_printf(MSG_DEBUG, "P2P: * Dialog Token: %d", dialog_token); -} - - -void p2p_buf_add_public_action_hdr(struct wpabuf *buf, u8 subtype, - u8 dialog_token) -{ - wpabuf_put_u8(buf, WLAN_ACTION_PUBLIC); - wpabuf_put_u8(buf, WLAN_PA_VENDOR_SPECIFIC); - wpabuf_put_be24(buf, OUI_WFA); - wpabuf_put_u8(buf, P2P_OUI_TYPE); - - wpabuf_put_u8(buf, subtype); /* OUI Subtype */ - wpabuf_put_u8(buf, dialog_token); - wpa_printf(MSG_DEBUG, "P2P: * Dialog Token: %d", dialog_token); -} - - -u8 * p2p_buf_add_ie_hdr(struct wpabuf *buf) -{ - u8 *len; - - /* P2P IE header */ - wpabuf_put_u8(buf, WLAN_EID_VENDOR_SPECIFIC); - len = wpabuf_put(buf, 1); /* IE length to be filled */ - wpabuf_put_be24(buf, OUI_WFA); - wpabuf_put_u8(buf, P2P_OUI_TYPE); - wpa_printf(MSG_DEBUG, "P2P: * P2P IE header"); - return len; -} - - -void p2p_buf_update_ie_hdr(struct wpabuf *buf, u8 *len) -{ - /* Update P2P IE Length */ - *len = (u8 *) wpabuf_put(buf, 0) - len - 1; -} - - -void p2p_buf_add_capability(struct wpabuf *buf, u8 dev_capab, u8 group_capab) -{ - /* P2P Capability */ - wpabuf_put_u8(buf, P2P_ATTR_CAPABILITY); - wpabuf_put_le16(buf, 2); - wpabuf_put_u8(buf, dev_capab); /* Device Capabilities */ - wpabuf_put_u8(buf, group_capab); /* Group Capabilities */ - wpa_printf(MSG_DEBUG, "P2P: * Capability dev=%02x group=%02x", - dev_capab, group_capab); -} - - -void p2p_buf_add_go_intent(struct wpabuf *buf, u8 go_intent) -{ - /* Group Owner Intent */ - wpabuf_put_u8(buf, P2P_ATTR_GROUP_OWNER_INTENT); - wpabuf_put_le16(buf, 1); - wpabuf_put_u8(buf, go_intent); - wpa_printf(MSG_DEBUG, "P2P: * GO Intent: Intent %u Tie breaker %u", - go_intent >> 1, go_intent & 0x01); -} - - -void p2p_buf_add_listen_channel(struct wpabuf *buf, const char *country, - u8 reg_class, u8 channel) -{ - /* Listen Channel */ - wpabuf_put_u8(buf, P2P_ATTR_LISTEN_CHANNEL); - wpabuf_put_le16(buf, 5); - wpabuf_put_data(buf, country, 3); - wpabuf_put_u8(buf, reg_class); /* Regulatory Class */ - wpabuf_put_u8(buf, channel); /* Channel Number */ - wpa_printf(MSG_DEBUG, "P2P: * Listen Channel: Regulatory Class %u " - "Channel %u", reg_class, channel); -} - - -void p2p_buf_add_operating_channel(struct wpabuf *buf, const char *country, - u8 reg_class, u8 channel) -{ - /* Operating Channel */ - wpabuf_put_u8(buf, P2P_ATTR_OPERATING_CHANNEL); - wpabuf_put_le16(buf, 5); - wpabuf_put_data(buf, country, 3); - wpabuf_put_u8(buf, reg_class); /* Regulatory Class */ - wpabuf_put_u8(buf, channel); /* Channel Number */ - wpa_printf(MSG_DEBUG, "P2P: * Operating Channel: Regulatory Class %u " - "Channel %u", reg_class, channel); -} - - -void p2p_buf_add_channel_list(struct wpabuf *buf, const char *country, - struct p2p_channels *chan) -{ - u8 *len; - size_t i; - - /* Channel List */ - wpabuf_put_u8(buf, P2P_ATTR_CHANNEL_LIST); - len = wpabuf_put(buf, 2); /* IE length to be filled */ - wpabuf_put_data(buf, country, 3); /* Country String */ - - for (i = 0; i < chan->reg_classes; i++) { - struct p2p_reg_class *c = &chan->reg_class[i]; - wpabuf_put_u8(buf, c->reg_class); - wpabuf_put_u8(buf, c->channels); - wpabuf_put_data(buf, c->channel, c->channels); - } - - /* Update attribute length */ - WPA_PUT_LE16(len, (u8 *) wpabuf_put(buf, 0) - len - 2); - wpa_printf(MSG_DEBUG, "P2P: * Channel List"); -} - - -void p2p_buf_add_status(struct wpabuf *buf, u8 status) -{ - /* Status */ - wpabuf_put_u8(buf, P2P_ATTR_STATUS); - wpabuf_put_le16(buf, 1); - wpabuf_put_u8(buf, status); - wpa_printf(MSG_DEBUG, "P2P: * Status: %d", status); -} - - -void p2p_buf_add_device_info(struct wpabuf *buf, struct p2p_data *p2p, - struct p2p_device *peer) -{ - u8 *len; - u16 methods; - size_t nlen, i; - - /* P2P Device Info */ - wpabuf_put_u8(buf, P2P_ATTR_DEVICE_INFO); - len = wpabuf_put(buf, 2); /* IE length to be filled */ - - /* P2P Device address */ - wpabuf_put_data(buf, p2p->cfg->dev_addr, ETH_ALEN); - - /* Config Methods */ - methods = 0; - if (peer && peer->wps_method != WPS_NOT_READY) { - if (peer->wps_method == WPS_PBC) - methods |= WPS_CONFIG_PUSHBUTTON; - else if (peer->wps_method == WPS_PIN_LABEL) - methods |= WPS_CONFIG_LABEL; - else if (peer->wps_method == WPS_PIN_DISPLAY || - peer->wps_method == WPS_PIN_KEYPAD) - methods |= WPS_CONFIG_DISPLAY | WPS_CONFIG_KEYPAD; - } else { - methods |= WPS_CONFIG_PUSHBUTTON; - methods |= WPS_CONFIG_DISPLAY | WPS_CONFIG_KEYPAD; - } - wpabuf_put_be16(buf, methods); - - /* Primary Device Type */ - wpabuf_put_data(buf, p2p->cfg->pri_dev_type, - sizeof(p2p->cfg->pri_dev_type)); - - /* Number of Secondary Device Types */ - wpabuf_put_u8(buf, p2p->cfg->num_sec_dev_types); - - /* Secondary Device Type List */ - for (i = 0; i < p2p->cfg->num_sec_dev_types; i++) - wpabuf_put_data(buf, p2p->cfg->sec_dev_type[i], - WPS_DEV_TYPE_LEN); - - /* Device Name */ - nlen = p2p->cfg->dev_name ? os_strlen(p2p->cfg->dev_name) : 0; - wpabuf_put_be16(buf, ATTR_DEV_NAME); - wpabuf_put_be16(buf, nlen); - wpabuf_put_data(buf, p2p->cfg->dev_name, nlen); - - /* Update attribute length */ - WPA_PUT_LE16(len, (u8 *) wpabuf_put(buf, 0) - len - 2); - wpa_printf(MSG_DEBUG, "P2P: * Device Info"); -} - - -void p2p_buf_add_device_id(struct wpabuf *buf, const u8 *dev_addr) -{ - /* P2P Device ID */ - wpabuf_put_u8(buf, P2P_ATTR_DEVICE_ID); - wpabuf_put_le16(buf, ETH_ALEN); - wpabuf_put_data(buf, dev_addr, ETH_ALEN); - wpa_printf(MSG_DEBUG, "P2P: * Device ID: " MACSTR, MAC2STR(dev_addr)); -} - - -void p2p_buf_add_config_timeout(struct wpabuf *buf, u8 go_timeout, - u8 client_timeout) -{ - /* Configuration Timeout */ - wpabuf_put_u8(buf, P2P_ATTR_CONFIGURATION_TIMEOUT); - wpabuf_put_le16(buf, 2); - wpabuf_put_u8(buf, go_timeout); - wpabuf_put_u8(buf, client_timeout); - wpa_printf(MSG_DEBUG, "P2P: * Configuration Timeout: GO %d (*10ms) " - "client %d (*10ms)", go_timeout, client_timeout); -} - - -void p2p_buf_add_intended_addr(struct wpabuf *buf, const u8 *interface_addr) -{ - /* Intended P2P Interface Address */ - wpabuf_put_u8(buf, P2P_ATTR_INTENDED_INTERFACE_ADDR); - wpabuf_put_le16(buf, ETH_ALEN); - wpabuf_put_data(buf, interface_addr, ETH_ALEN); - wpa_printf(MSG_DEBUG, "P2P: * Intended P2P Interface Address " MACSTR, - MAC2STR(interface_addr)); -} - - -void p2p_buf_add_group_bssid(struct wpabuf *buf, const u8 *bssid) -{ - /* P2P Group BSSID */ - wpabuf_put_u8(buf, P2P_ATTR_GROUP_BSSID); - wpabuf_put_le16(buf, ETH_ALEN); - wpabuf_put_data(buf, bssid, ETH_ALEN); - wpa_printf(MSG_DEBUG, "P2P: * P2P Group BSSID " MACSTR, - MAC2STR(bssid)); -} - - -void p2p_buf_add_group_id(struct wpabuf *buf, const u8 *dev_addr, - const u8 *ssid, size_t ssid_len) -{ - /* P2P Group ID */ - wpabuf_put_u8(buf, P2P_ATTR_GROUP_ID); - wpabuf_put_le16(buf, ETH_ALEN + ssid_len); - wpabuf_put_data(buf, dev_addr, ETH_ALEN); - wpabuf_put_data(buf, ssid, ssid_len); - wpa_printf(MSG_DEBUG, "P2P: * P2P Group ID " MACSTR, - MAC2STR(dev_addr)); -} - - -void p2p_buf_add_invitation_flags(struct wpabuf *buf, u8 flags) -{ - /* Invitation Flags */ - wpabuf_put_u8(buf, P2P_ATTR_INVITATION_FLAGS); - wpabuf_put_le16(buf, 1); - wpabuf_put_u8(buf, flags); - wpa_printf(MSG_DEBUG, "P2P: * Invitation Flags: bitmap 0x%x", flags); -} - - -static void p2p_buf_add_noa_desc(struct wpabuf *buf, struct p2p_noa_desc *desc) -{ - if (desc == NULL) - return; - - wpabuf_put_u8(buf, desc->count_type); - wpabuf_put_le32(buf, desc->duration); - wpabuf_put_le32(buf, desc->interval); - wpabuf_put_le32(buf, desc->start_time); -} - - -void p2p_buf_add_noa(struct wpabuf *buf, u8 noa_index, u8 opp_ps, u8 ctwindow, - struct p2p_noa_desc *desc1, struct p2p_noa_desc *desc2) -{ - /* Notice of Absence */ - wpabuf_put_u8(buf, P2P_ATTR_NOTICE_OF_ABSENCE); - wpabuf_put_le16(buf, 2 + (desc1 ? 13 : 0) + (desc2 ? 13 : 0)); - wpabuf_put_u8(buf, noa_index); - wpabuf_put_u8(buf, (opp_ps ? 0x80 : 0) | (ctwindow & 0x7f)); - p2p_buf_add_noa_desc(buf, desc1); - p2p_buf_add_noa_desc(buf, desc2); - wpa_printf(MSG_DEBUG, "P2P: * Notice of Absence"); -} - - -void p2p_buf_add_ext_listen_timing(struct wpabuf *buf, u16 period, - u16 interval) -{ - /* Extended Listen Timing */ - wpabuf_put_u8(buf, P2P_ATTR_EXT_LISTEN_TIMING); - wpabuf_put_le16(buf, 4); - wpabuf_put_le16(buf, period); - wpabuf_put_le16(buf, interval); - wpa_printf(MSG_DEBUG, "P2P: * Extended Listen Timing (period %u msec " - "interval %u msec)", period, interval); -} - - -void p2p_buf_add_p2p_interface(struct wpabuf *buf, struct p2p_data *p2p) -{ - /* P2P Interface */ - wpabuf_put_u8(buf, P2P_ATTR_INTERFACE); - wpabuf_put_le16(buf, ETH_ALEN + 1 + ETH_ALEN); - /* P2P Device address */ - wpabuf_put_data(buf, p2p->cfg->dev_addr, ETH_ALEN); - /* - * FIX: Fetch interface address list from driver. Do not include - * the P2P Device address if it is never used as interface address. - */ - /* P2P Interface Address Count */ - wpabuf_put_u8(buf, 1); - wpabuf_put_data(buf, p2p->cfg->dev_addr, ETH_ALEN); -} - - -static void p2p_add_wps_string(struct wpabuf *buf, enum wps_attribute attr, - const char *val) -{ - size_t len; - - wpabuf_put_be16(buf, attr); - len = val ? os_strlen(val) : 0; -#ifndef CONFIG_WPS_STRICT - if (len == 0) { - /* - * Some deployed WPS implementations fail to parse zeor-length - * attributes. As a workaround, send a space character if the - * device attribute string is empty. - */ - wpabuf_put_be16(buf, 1); - wpabuf_put_u8(buf, ' '); - return; - } -#endif /* CONFIG_WPS_STRICT */ - wpabuf_put_be16(buf, len); - if (val) - wpabuf_put_data(buf, val, len); -} - - -void p2p_build_wps_ie(struct p2p_data *p2p, struct wpabuf *buf, u16 pw_id, - int all_attr) -{ - u8 *len; - int i; - - wpabuf_put_u8(buf, WLAN_EID_VENDOR_SPECIFIC); - len = wpabuf_put(buf, 1); - wpabuf_put_be32(buf, WPS_DEV_OUI_WFA); - - wps_build_version(buf); - - if (all_attr) { - wpabuf_put_be16(buf, ATTR_WPS_STATE); - wpabuf_put_be16(buf, 1); - wpabuf_put_u8(buf, WPS_STATE_NOT_CONFIGURED); - } - - /* Device Password ID */ - wpabuf_put_be16(buf, ATTR_DEV_PASSWORD_ID); - wpabuf_put_be16(buf, 2); - wpa_printf(MSG_DEBUG, "P2P: WPS IE Device Password ID: %d", pw_id); - wpabuf_put_be16(buf, pw_id); - - if (all_attr) { - wpabuf_put_be16(buf, ATTR_RESPONSE_TYPE); - wpabuf_put_be16(buf, 1); - wpabuf_put_u8(buf, WPS_RESP_ENROLLEE_INFO); - - wps_build_uuid_e(buf, p2p->cfg->uuid); - p2p_add_wps_string(buf, ATTR_MANUFACTURER, - p2p->cfg->manufacturer); - p2p_add_wps_string(buf, ATTR_MODEL_NAME, p2p->cfg->model_name); - p2p_add_wps_string(buf, ATTR_MODEL_NUMBER, - p2p->cfg->model_number); - p2p_add_wps_string(buf, ATTR_SERIAL_NUMBER, - p2p->cfg->serial_number); - - wpabuf_put_be16(buf, ATTR_PRIMARY_DEV_TYPE); - wpabuf_put_be16(buf, WPS_DEV_TYPE_LEN); - wpabuf_put_data(buf, p2p->cfg->pri_dev_type, WPS_DEV_TYPE_LEN); - - p2p_add_wps_string(buf, ATTR_DEV_NAME, p2p->cfg->dev_name); - - wpabuf_put_be16(buf, ATTR_CONFIG_METHODS); - wpabuf_put_be16(buf, 2); - wpabuf_put_be16(buf, p2p->cfg->config_methods); - } - - wps_build_wfa_ext(buf, 0, NULL, 0); - - if (all_attr && p2p->cfg->num_sec_dev_types) { - wpabuf_put_be16(buf, ATTR_SECONDARY_DEV_TYPE_LIST); - wpabuf_put_be16(buf, WPS_DEV_TYPE_LEN * - p2p->cfg->num_sec_dev_types); - wpabuf_put_data(buf, p2p->cfg->sec_dev_type, - WPS_DEV_TYPE_LEN * - p2p->cfg->num_sec_dev_types); - } - - /* Add the WPS vendor extensions */ - for (i = 0; i < P2P_MAX_WPS_VENDOR_EXT; i++) { - if (p2p->wps_vendor_ext[i] == NULL) - break; - if (wpabuf_tailroom(buf) < - 4 + wpabuf_len(p2p->wps_vendor_ext[i])) - continue; - wpabuf_put_be16(buf, ATTR_VENDOR_EXT); - wpabuf_put_be16(buf, wpabuf_len(p2p->wps_vendor_ext[i])); - wpabuf_put_buf(buf, p2p->wps_vendor_ext[i]); - } - - p2p_buf_update_ie_hdr(buf, len); -} diff --git a/hostapd-0.8/src/p2p/p2p_dev_disc.c b/hostapd-0.8/src/p2p/p2p_dev_disc.c deleted file mode 100644 index 47cc0fd..0000000 --- a/hostapd-0.8/src/p2p/p2p_dev_disc.c +++ /dev/null @@ -1,365 +0,0 @@ -/* - * Wi-Fi Direct - P2P Device Discoverability procedure - * Copyright (c) 2010, Atheros Communications - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#include "includes.h" - -#include "common.h" -#include "common/ieee802_11_defs.h" -#include "p2p_i.h" -#include "p2p.h" - - -static struct wpabuf * p2p_build_dev_disc_req(struct p2p_data *p2p, - struct p2p_device *go, - const u8 *dev_id) -{ - struct wpabuf *buf; - u8 *len; - - buf = wpabuf_alloc(100); - if (buf == NULL) - return NULL; - - go->dialog_token++; - if (go->dialog_token == 0) - go->dialog_token = 1; - p2p_buf_add_public_action_hdr(buf, P2P_DEV_DISC_REQ, go->dialog_token); - - len = p2p_buf_add_ie_hdr(buf); - p2p_buf_add_device_id(buf, dev_id); - p2p_buf_add_group_id(buf, go->info.p2p_device_addr, go->oper_ssid, - go->oper_ssid_len); - p2p_buf_update_ie_hdr(buf, len); - - return buf; -} - - -void p2p_dev_disc_req_cb(struct p2p_data *p2p, int success) -{ - wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, - "P2P: Device Discoverability Request TX callback: success=%d", - success); - - if (!success) { - /* - * Use P2P find, if needed, to find the other device or to - * retry device discoverability. - */ - p2p_set_state(p2p, P2P_CONNECT); - p2p_set_timeout(p2p, 0, 100000); - return; - } - - wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, - "P2P: GO acknowledged Device Discoverability Request - wait " - "for response"); - /* - * TODO: is the remain-on-channel from Action frame TX long enough for - * most cases or should we try to increase its duration and/or start - * another remain-on-channel if needed once the previous one expires? - */ -} - - -int p2p_send_dev_disc_req(struct p2p_data *p2p, struct p2p_device *dev) -{ - struct p2p_device *go; - struct wpabuf *req; - - go = p2p_get_device(p2p, dev->member_in_go_dev); - if (go == NULL || dev->oper_freq <= 0) { - wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, - "P2P: Could not find peer entry for GO and frequency " - "to send Device Discoverability Request"); - return -1; - } - - req = p2p_build_dev_disc_req(p2p, go, dev->info.p2p_device_addr); - if (req == NULL) - return -1; - - wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, - "P2P: Sending Device Discoverability Request to GO " MACSTR - " for client " MACSTR, - MAC2STR(go->info.p2p_device_addr), - MAC2STR(dev->info.p2p_device_addr)); - - p2p->pending_client_disc_go = go; - os_memcpy(p2p->pending_client_disc_addr, dev->info.p2p_device_addr, - ETH_ALEN); - p2p->pending_action_state = P2P_PENDING_DEV_DISC_REQUEST; - if (p2p_send_action(p2p, dev->oper_freq, go->info.p2p_device_addr, - p2p->cfg->dev_addr, go->info.p2p_device_addr, - wpabuf_head(req), wpabuf_len(req), 1000) < 0) { - wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, - "P2P: Failed to send Action frame"); - wpabuf_free(req); - /* TODO: how to recover from failure? */ - return -1; - } - - wpabuf_free(req); - - return 0; -} - - -static struct wpabuf * p2p_build_dev_disc_resp(u8 dialog_token, u8 status) -{ - struct wpabuf *buf; - u8 *len; - - buf = wpabuf_alloc(100); - if (buf == NULL) - return NULL; - - p2p_buf_add_public_action_hdr(buf, P2P_DEV_DISC_RESP, dialog_token); - - len = p2p_buf_add_ie_hdr(buf); - p2p_buf_add_status(buf, status); - p2p_buf_update_ie_hdr(buf, len); - - return buf; -} - - -void p2p_dev_disc_resp_cb(struct p2p_data *p2p, int success) -{ - wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, - "P2P: Device Discoverability Response TX callback: success=%d", - success); - p2p->cfg->send_action_done(p2p->cfg->cb_ctx); -} - - -static void p2p_send_dev_disc_resp(struct p2p_data *p2p, u8 dialog_token, - const u8 *addr, int freq, u8 status) -{ - struct wpabuf *resp; - - resp = p2p_build_dev_disc_resp(dialog_token, status); - if (resp == NULL) - return; - - wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, - "P2P: Sending Device Discoverability Response to " MACSTR - " (status %u freq %d)", - MAC2STR(addr), status, freq); - - p2p->pending_action_state = P2P_PENDING_DEV_DISC_RESPONSE; - if (p2p_send_action(p2p, freq, addr, p2p->cfg->dev_addr, - p2p->cfg->dev_addr, - wpabuf_head(resp), wpabuf_len(resp), 200) < 0) { - wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, - "P2P: Failed to send Action frame"); - } - - wpabuf_free(resp); -} - - -void p2p_process_dev_disc_req(struct p2p_data *p2p, const u8 *sa, - const u8 *data, size_t len, int rx_freq) -{ - struct p2p_message msg; - size_t g; - - wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, - "P2P: Received Device Discoverability Request from " MACSTR - " (freq=%d)", MAC2STR(sa), rx_freq); - - if (p2p_parse(data, len, &msg)) - return; - - if (msg.dialog_token == 0) { - wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, - "P2P: Invalid Dialog Token 0 (must be nonzero) in " - "Device Discoverability Request"); - p2p_send_dev_disc_resp(p2p, msg.dialog_token, sa, rx_freq, - P2P_SC_FAIL_INVALID_PARAMS); - p2p_parse_free(&msg); - return; - } - - if (msg.device_id == NULL) { - wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, - "P2P: P2P Device ID attribute missing from Device " - "Discoverability Request"); - p2p_send_dev_disc_resp(p2p, msg.dialog_token, sa, rx_freq, - P2P_SC_FAIL_INVALID_PARAMS); - p2p_parse_free(&msg); - return; - } - - for (g = 0; g < p2p->num_groups; g++) { - if (p2p_group_go_discover(p2p->groups[g], msg.device_id, sa, - rx_freq) == 0) { - wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Scheduled " - "GO Discoverability Request for the target " - "device"); - /* - * P2P group code will use a callback to indicate TX - * status, so that we can reply to the request once the - * target client has acknowledged the request or it has - * timed out. - */ - p2p->pending_dev_disc_dialog_token = msg.dialog_token; - os_memcpy(p2p->pending_dev_disc_addr, sa, ETH_ALEN); - p2p->pending_dev_disc_freq = rx_freq; - p2p_parse_free(&msg); - return; - } - } - - wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Requested client " - "was not found in any group or did not support client " - "discoverability"); - p2p_send_dev_disc_resp(p2p, msg.dialog_token, sa, rx_freq, - P2P_SC_FAIL_UNABLE_TO_ACCOMMODATE); - p2p_parse_free(&msg); -} - - -void p2p_process_dev_disc_resp(struct p2p_data *p2p, const u8 *sa, - const u8 *data, size_t len) -{ - struct p2p_message msg; - struct p2p_device *go; - u8 status; - - wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, - "P2P: Received Device Discoverability Response from " MACSTR, - MAC2STR(sa)); - - go = p2p->pending_client_disc_go; - if (go == NULL || - os_memcmp(sa, go->info.p2p_device_addr, ETH_ALEN) != 0) { - wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Ignore unexpected " - "Device Discoverability Response"); - return; - } - - if (p2p_parse(data, len, &msg)) - return; - - if (msg.status == NULL) { - p2p_parse_free(&msg); - return; - } - - if (msg.dialog_token != go->dialog_token) { - wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Ignore Device " - "Discoverability Response with unexpected dialog " - "token %u (expected %u)", - msg.dialog_token, go->dialog_token); - p2p_parse_free(&msg); - return; - } - - status = *msg.status; - p2p_parse_free(&msg); - - wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, - "P2P: Device Discoverability Response status %u", status); - - if (p2p->go_neg_peer == NULL || - os_memcmp(p2p->pending_client_disc_addr, - p2p->go_neg_peer->info.p2p_device_addr, ETH_ALEN) != 0 || - os_memcmp(p2p->go_neg_peer->member_in_go_dev, - go->info.p2p_device_addr, ETH_ALEN) != 0) { - wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: No pending " - "operation with the client discoverability peer " - "anymore"); - return; - } - - if (status == 0) { - /* - * Peer is expected to be awake for at least 100 TU; try to - * connect immediately. - */ - wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, - "P2P: Client discoverability request succeeded"); - if (p2p->state == P2P_CONNECT) { - /* - * Change state to force the timeout to start in - * P2P_CONNECT again without going through the short - * Listen state. - */ - p2p_set_state(p2p, P2P_CONNECT_LISTEN); - p2p->cfg->send_action_done(p2p->cfg->cb_ctx); - } - p2p_set_timeout(p2p, 0, 0); - } else { - /* - * Client discoverability request failed; try to connect from - * timeout. - */ - wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, - "P2P: Client discoverability request failed"); - p2p_set_timeout(p2p, 0, 500000); - } - -} - - -void p2p_go_disc_req_cb(struct p2p_data *p2p, int success) -{ - wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, - "P2P: GO Discoverability Request TX callback: success=%d", - success); - p2p->cfg->send_action_done(p2p->cfg->cb_ctx); - - if (p2p->pending_dev_disc_dialog_token == 0) { - wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: No pending Device " - "Discoverability Request"); - return; - } - - p2p_send_dev_disc_resp(p2p, p2p->pending_dev_disc_dialog_token, - p2p->pending_dev_disc_addr, - p2p->pending_dev_disc_freq, - success ? P2P_SC_SUCCESS : - P2P_SC_FAIL_UNABLE_TO_ACCOMMODATE); - - p2p->pending_dev_disc_dialog_token = 0; -} - - -void p2p_process_go_disc_req(struct p2p_data *p2p, const u8 *da, const u8 *sa, - const u8 *data, size_t len, int rx_freq) -{ - unsigned int tu; - struct wpabuf *ies; - - wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, - "P2P: Received GO Discoverability Request - remain awake for " - "100 TU"); - - ies = p2p_build_probe_resp_ies(p2p); - if (ies == NULL) - return; - - /* Remain awake 100 TU on operating channel */ - p2p->pending_client_disc_freq = rx_freq; - tu = 100; - if (p2p->cfg->start_listen(p2p->cfg->cb_ctx, rx_freq, 1024 * tu / 1000, - ies) < 0) { - wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, - "P2P: Failed to start listen mode for client " - "discoverability"); - } - wpabuf_free(ies); -} diff --git a/hostapd-0.8/src/p2p/p2p_go_neg.c b/hostapd-0.8/src/p2p/p2p_go_neg.c deleted file mode 100644 index 1c96486..0000000 --- a/hostapd-0.8/src/p2p/p2p_go_neg.c +++ /dev/null @@ -1,1127 +0,0 @@ -/* - * Wi-Fi Direct - P2P Group Owner Negotiation - * Copyright (c) 2009-2010, Atheros Communications - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#include "includes.h" - -#include "common.h" -#include "common/ieee802_11_defs.h" -#include "wps/wps_defs.h" -#include "p2p_i.h" -#include "p2p.h" - - -static int p2p_go_det(u8 own_intent, u8 peer_value) -{ - u8 peer_intent = peer_value >> 1; - if (own_intent == peer_intent) { - if (own_intent == P2P_MAX_GO_INTENT) - return -1; /* both devices want to become GO */ - - /* Use tie breaker bit to determine GO */ - return (peer_value & 0x01) ? 0 : 1; - } - - return own_intent > peer_intent; -} - - -int p2p_peer_channels_check(struct p2p_data *p2p, struct p2p_channels *own, - struct p2p_device *dev, - const u8 *channel_list, size_t channel_list_len) -{ - const u8 *pos, *end; - struct p2p_channels *ch; - size_t channels; - struct p2p_channels intersection; - - ch = &dev->channels; - os_memset(ch, 0, sizeof(*ch)); - pos = channel_list; - end = channel_list + channel_list_len; - - if (end - pos < 3) - return -1; - os_memcpy(dev->country, pos, 3); - wpa_hexdump_ascii(MSG_DEBUG, "P2P: Peer country", pos, 3); - if (pos[2] != 0x04 && os_memcmp(pos, p2p->cfg->country, 2) != 0) { - wpa_msg(p2p->cfg->msg_ctx, MSG_INFO, - "P2P: Mismatching country (ours=%c%c peer's=%c%c)", - p2p->cfg->country[0], p2p->cfg->country[1], - pos[0], pos[1]); - return -1; - } - pos += 3; - - while (pos + 2 < end) { - struct p2p_reg_class *cl = &ch->reg_class[ch->reg_classes]; - cl->reg_class = *pos++; - if (pos + 1 + pos[0] > end) { - wpa_msg(p2p->cfg->msg_ctx, MSG_INFO, - "P2P: Invalid peer Channel List"); - return -1; - } - channels = *pos++; - cl->channels = channels > P2P_MAX_REG_CLASS_CHANNELS ? - P2P_MAX_REG_CLASS_CHANNELS : channels; - os_memcpy(cl->channel, pos, cl->channels); - pos += channels; - ch->reg_classes++; - if (ch->reg_classes == P2P_MAX_REG_CLASSES) - break; - } - - p2p_channels_intersect(own, &dev->channels, &intersection); - wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Own reg_classes %d " - "peer reg_classes %d intersection reg_classes %d", - (int) own->reg_classes, - (int) dev->channels.reg_classes, - (int) intersection.reg_classes); - if (intersection.reg_classes == 0) { - wpa_msg(p2p->cfg->msg_ctx, MSG_INFO, - "P2P: No common channels found"); - return -1; - } - return 0; -} - - -static int p2p_peer_channels(struct p2p_data *p2p, struct p2p_device *dev, - const u8 *channel_list, size_t channel_list_len) -{ - return p2p_peer_channels_check(p2p, &p2p->channels, dev, - channel_list, channel_list_len); -} - - -static u16 p2p_wps_method_pw_id(enum p2p_wps_method wps_method) -{ - switch (wps_method) { - case WPS_PIN_LABEL: - return DEV_PW_DEFAULT; - case WPS_PIN_DISPLAY: - return DEV_PW_REGISTRAR_SPECIFIED; - case WPS_PIN_KEYPAD: - return DEV_PW_USER_SPECIFIED; - case WPS_PBC: - return DEV_PW_PUSHBUTTON; - default: - return DEV_PW_DEFAULT; - } -} - - -static const char * p2p_wps_method_str(enum p2p_wps_method wps_method) -{ - switch (wps_method) { - case WPS_PIN_LABEL: - return "Label"; - case WPS_PIN_DISPLAY: - return "Display"; - case WPS_PIN_KEYPAD: - return "Keypad"; - case WPS_PBC: - return "PBC"; - default: - return "??"; - } -} - - -static struct wpabuf * p2p_build_go_neg_req(struct p2p_data *p2p, - struct p2p_device *peer) -{ - struct wpabuf *buf; - u8 *len; - u8 group_capab; - - buf = wpabuf_alloc(1000); - if (buf == NULL) - return NULL; - - peer->dialog_token++; - if (peer->dialog_token == 0) - peer->dialog_token = 1; - p2p_buf_add_public_action_hdr(buf, P2P_GO_NEG_REQ, peer->dialog_token); - - len = p2p_buf_add_ie_hdr(buf); - group_capab = 0; - if (peer->flags & P2P_DEV_PREFER_PERSISTENT_GROUP) - group_capab |= P2P_GROUP_CAPAB_PERSISTENT_GROUP; - if (p2p->cross_connect) - group_capab |= P2P_GROUP_CAPAB_CROSS_CONN; - if (p2p->cfg->p2p_intra_bss) - group_capab |= P2P_GROUP_CAPAB_INTRA_BSS_DIST; - p2p_buf_add_capability(buf, p2p->dev_capab, group_capab); - p2p_buf_add_go_intent(buf, (p2p->go_intent << 1) | - p2p->next_tie_breaker); - p2p->next_tie_breaker = !p2p->next_tie_breaker; - p2p_buf_add_config_timeout(buf, 100, 20); - p2p_buf_add_listen_channel(buf, p2p->cfg->country, p2p->cfg->reg_class, - p2p->cfg->channel); - if (p2p->ext_listen_interval) - p2p_buf_add_ext_listen_timing(buf, p2p->ext_listen_period, - p2p->ext_listen_interval); - p2p_buf_add_intended_addr(buf, p2p->intended_addr); - p2p_buf_add_channel_list(buf, p2p->cfg->country, &p2p->channels); - p2p_buf_add_device_info(buf, p2p, peer); - p2p_buf_add_operating_channel(buf, p2p->cfg->country, - p2p->op_reg_class, p2p->op_channel); - p2p_buf_update_ie_hdr(buf, len); - - /* WPS IE with Device Password ID attribute */ - p2p_build_wps_ie(p2p, buf, p2p_wps_method_pw_id(peer->wps_method), 0); - - return buf; -} - - -int p2p_connect_send(struct p2p_data *p2p, struct p2p_device *dev) -{ - struct wpabuf *req; - int freq; - - freq = dev->listen_freq > 0 ? dev->listen_freq : dev->oper_freq; - if (freq <= 0) { - wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, - "P2P: No Listen/Operating frequency known for the " - "peer " MACSTR " to send GO Negotiation Request", - MAC2STR(dev->info.p2p_device_addr)); - return -1; - } - - req = p2p_build_go_neg_req(p2p, dev); - if (req == NULL) - return -1; - wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, - "P2P: Sending GO Negotiation Request"); - p2p_set_state(p2p, P2P_CONNECT); - p2p->pending_action_state = P2P_PENDING_GO_NEG_REQUEST; - p2p->go_neg_peer = dev; - dev->flags |= P2P_DEV_WAIT_GO_NEG_RESPONSE; - dev->connect_reqs++; - if (p2p_send_action(p2p, freq, dev->info.p2p_device_addr, - p2p->cfg->dev_addr, dev->info.p2p_device_addr, - wpabuf_head(req), wpabuf_len(req), 200) < 0) { - wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, - "P2P: Failed to send Action frame"); - /* Use P2P find to recover and retry */ - p2p_set_timeout(p2p, 0, 0); - } - - wpabuf_free(req); - - return 0; -} - - -static struct wpabuf * p2p_build_go_neg_resp(struct p2p_data *p2p, - struct p2p_device *peer, - u8 dialog_token, u8 status, - u8 tie_breaker) -{ - struct wpabuf *buf; - u8 *len; - u8 group_capab; - - wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, - "P2P: Building GO Negotiation Response"); - buf = wpabuf_alloc(1000); - if (buf == NULL) - return NULL; - - p2p_buf_add_public_action_hdr(buf, P2P_GO_NEG_RESP, dialog_token); - - len = p2p_buf_add_ie_hdr(buf); - p2p_buf_add_status(buf, status); - group_capab = 0; - if (peer && peer->go_state == LOCAL_GO) { - if (peer->flags & P2P_DEV_PREFER_PERSISTENT_GROUP) - group_capab |= P2P_GROUP_CAPAB_PERSISTENT_GROUP; - if (p2p->cross_connect) - group_capab |= P2P_GROUP_CAPAB_CROSS_CONN; - if (p2p->cfg->p2p_intra_bss) - group_capab |= P2P_GROUP_CAPAB_INTRA_BSS_DIST; - } - p2p_buf_add_capability(buf, p2p->dev_capab, group_capab); - p2p_buf_add_go_intent(buf, (p2p->go_intent << 1) | tie_breaker); - p2p_buf_add_config_timeout(buf, 100, 20); - if (peer && peer->go_state == REMOTE_GO) { - wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Omit Operating " - "Channel attribute"); - } else { - p2p_buf_add_operating_channel(buf, p2p->cfg->country, - p2p->op_reg_class, - p2p->op_channel); - } - p2p_buf_add_intended_addr(buf, p2p->intended_addr); - if (status || peer == NULL) { - p2p_buf_add_channel_list(buf, p2p->cfg->country, - &p2p->channels); - } else if (peer->go_state == REMOTE_GO) { - p2p_buf_add_channel_list(buf, p2p->cfg->country, - &p2p->channels); - } else { - struct p2p_channels res; - p2p_channels_intersect(&p2p->channels, &peer->channels, - &res); - p2p_buf_add_channel_list(buf, p2p->cfg->country, &res); - } - p2p_buf_add_device_info(buf, p2p, peer); - if (peer && peer->go_state == LOCAL_GO) { - p2p_buf_add_group_id(buf, p2p->cfg->dev_addr, p2p->ssid, - p2p->ssid_len); - } - p2p_buf_update_ie_hdr(buf, len); - - /* WPS IE with Device Password ID attribute */ - p2p_build_wps_ie(p2p, buf, - p2p_wps_method_pw_id(peer ? peer->wps_method : - WPS_NOT_READY), 0); - - return buf; -} - - -static void p2p_reselect_channel(struct p2p_data *p2p, - struct p2p_channels *intersection) -{ - struct p2p_reg_class *cl; - int freq; - u8 op_reg_class, op_channel; - - wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Selected operating " - "channel (reg_class %u channel %u) not acceptable to the " - "peer", p2p->op_reg_class, p2p->op_channel); - - /* First, try to pick the best channel from another band */ - freq = p2p_channel_to_freq(p2p->cfg->country, p2p->op_reg_class, - p2p->op_channel); - if (freq >= 2400 && freq < 2500 && p2p->best_freq_5 > 0 && - p2p_freq_to_channel(p2p->cfg->country, p2p->best_freq_5, - &op_reg_class, &op_channel) == 0 && - p2p_channels_includes(intersection, op_reg_class, op_channel)) { - wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Pick best 5 GHz " - "channel (reg_class %u channel %u) from intersection", - op_reg_class, op_channel); - p2p->op_reg_class = op_reg_class; - p2p->op_channel = op_channel; - return; - } - - if (freq >= 4900 && freq < 6000 && p2p->best_freq_24 > 0 && - p2p_freq_to_channel(p2p->cfg->country, p2p->best_freq_24, - &op_reg_class, &op_channel) == 0 && - p2p_channels_includes(intersection, op_reg_class, op_channel)) { - wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Pick best 2.4 GHz " - "channel (reg_class %u channel %u) from intersection", - op_reg_class, op_channel); - p2p->op_reg_class = op_reg_class; - p2p->op_channel = op_channel; - return; - } - - /* - * Fall back to whatever is included in the channel intersection since - * no better options seems to be available. - */ - cl = &intersection->reg_class[0]; - wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Pick another channel " - "(reg_class %u channel %u) from intersection", - cl->reg_class, cl->channel[0]); - p2p->op_reg_class = cl->reg_class; - p2p->op_channel = cl->channel[0]; -} - - -void p2p_process_go_neg_req(struct p2p_data *p2p, const u8 *sa, - const u8 *data, size_t len, int rx_freq) -{ - struct p2p_device *dev = NULL; - struct wpabuf *resp; - struct p2p_message msg; - u8 status = P2P_SC_FAIL_INVALID_PARAMS; - int tie_breaker = 0; - int freq; - - wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, - "P2P: Received GO Negotiation Request from " MACSTR - "(freq=%d)", MAC2STR(sa), rx_freq); - - if (p2p_parse(data, len, &msg)) - return; - - if (!msg.capability) { - wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, - "P2P: Mandatory Capability attribute missing from GO " - "Negotiation Request"); -#ifdef CONFIG_P2P_STRICT - goto fail; -#endif /* CONFIG_P2P_STRICT */ - } - - if (msg.go_intent) - tie_breaker = *msg.go_intent & 0x01; - else { - wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, - "P2P: Mandatory GO Intent attribute missing from GO " - "Negotiation Request"); -#ifdef CONFIG_P2P_STRICT - goto fail; -#endif /* CONFIG_P2P_STRICT */ - } - - if (!msg.config_timeout) { - wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, - "P2P: Mandatory Configuration Timeout attribute " - "missing from GO Negotiation Request"); -#ifdef CONFIG_P2P_STRICT - goto fail; -#endif /* CONFIG_P2P_STRICT */ - } - - if (!msg.listen_channel) { - wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, - "P2P: No Listen Channel attribute received"); - goto fail; - } - if (!msg.operating_channel) { - wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, - "P2P: No Operating Channel attribute received"); - goto fail; - } - if (!msg.channel_list) { - wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, - "P2P: No Channel List attribute received"); - goto fail; - } - if (!msg.intended_addr) { - wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, - "P2P: No Intended P2P Interface Address attribute " - "received"); - goto fail; - } - if (!msg.p2p_device_info) { - wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, - "P2P: No P2P Device Info attribute received"); - goto fail; - } - - if (os_memcmp(msg.p2p_device_addr, sa, ETH_ALEN) != 0) { - wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, - "P2P: Unexpected GO Negotiation Request SA=" MACSTR - " != dev_addr=" MACSTR, - MAC2STR(sa), MAC2STR(msg.p2p_device_addr)); - goto fail; - } - - dev = p2p_get_device(p2p, sa); - - if (msg.status && *msg.status) { - wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, - "P2P: Unexpected Status attribute (%d) in GO " - "Negotiation Request", *msg.status); - goto fail; - } - - if (dev == NULL) - dev = p2p_add_dev_from_go_neg_req(p2p, sa, &msg); - else if (dev->flags & P2P_DEV_PROBE_REQ_ONLY) - p2p_add_dev_info(p2p, sa, dev, &msg); - if (dev && dev->flags & P2P_DEV_USER_REJECTED) { - wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, - "P2P: User has rejected this peer"); - status = P2P_SC_FAIL_REJECTED_BY_USER; - } else if (dev == NULL || dev->wps_method == WPS_NOT_READY) { - wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, - "P2P: Not ready for GO negotiation with " MACSTR, - MAC2STR(sa)); - status = P2P_SC_FAIL_INFO_CURRENTLY_UNAVAILABLE; - if (dev) - dev->flags |= P2P_DEV_PEER_WAITING_RESPONSE; - p2p->cfg->go_neg_req_rx(p2p->cfg->cb_ctx, sa, - msg.dev_password_id); - } else if (p2p->go_neg_peer && p2p->go_neg_peer != dev) { - wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, - "P2P: Already in Group Formation with another peer"); - status = P2P_SC_FAIL_UNABLE_TO_ACCOMMODATE; - } else { - int go; - - if (!p2p->go_neg_peer) { - wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Starting " - "GO Negotiation with previously authorized " - "peer"); - if (!(dev->flags & P2P_DEV_FORCE_FREQ)) { - wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, - "P2P: Use default channel settings"); - p2p->op_reg_class = p2p->cfg->op_reg_class; - p2p->op_channel = p2p->cfg->op_channel; - os_memcpy(&p2p->channels, &p2p->cfg->channels, - sizeof(struct p2p_channels)); - } else { - wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, - "P2P: Use previously configured " - "forced channel settings"); - } - } - - dev->flags &= ~P2P_DEV_NOT_YET_READY; - - if (!msg.go_intent) { - wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, - "P2P: No GO Intent attribute received"); - goto fail; - } - if ((*msg.go_intent >> 1) > P2P_MAX_GO_INTENT) { - wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, - "P2P: Invalid GO Intent value (%u) received", - *msg.go_intent >> 1); - goto fail; - } - - if (dev->go_neg_req_sent && - os_memcmp(sa, p2p->cfg->dev_addr, ETH_ALEN) > 0) { - wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, - "P2P: Do not reply since peer has higher " - "address and GO Neg Request already sent"); - p2p_parse_free(&msg); - return; - } - - go = p2p_go_det(p2p->go_intent, *msg.go_intent); - if (go < 0) { - wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, - "P2P: Incompatible GO Intent"); - status = P2P_SC_FAIL_BOTH_GO_INTENT_15; - goto fail; - } - - if (p2p_peer_channels(p2p, dev, msg.channel_list, - msg.channel_list_len) < 0) { - wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, - "P2P: No common channels found"); - status = P2P_SC_FAIL_NO_COMMON_CHANNELS; - goto fail; - } - - switch (msg.dev_password_id) { - case DEV_PW_DEFAULT: - wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, - "P2P: PIN from peer Label"); - if (dev->wps_method != WPS_PIN_KEYPAD) { - wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, - "P2P: We have wps_method=%s -> " - "incompatible", - p2p_wps_method_str(dev->wps_method)); - status = P2P_SC_FAIL_INCOMPATIBLE_PROV_METHOD; - goto fail; - } - break; - case DEV_PW_REGISTRAR_SPECIFIED: - wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, - "P2P: PIN from peer Display"); - if (dev->wps_method != WPS_PIN_KEYPAD) { - wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, - "P2P: We have wps_method=%s -> " - "incompatible", - p2p_wps_method_str(dev->wps_method)); - status = P2P_SC_FAIL_INCOMPATIBLE_PROV_METHOD; - goto fail; - } - break; - case DEV_PW_USER_SPECIFIED: - wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, - "P2P: Peer entered PIN on Keypad"); - if (dev->wps_method != WPS_PIN_LABEL && - dev->wps_method != WPS_PIN_DISPLAY) { - wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, - "P2P: We have wps_method=%s -> " - "incompatible", - p2p_wps_method_str(dev->wps_method)); - status = P2P_SC_FAIL_INCOMPATIBLE_PROV_METHOD; - goto fail; - } - break; - case DEV_PW_PUSHBUTTON: - wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, - "P2P: Peer using pushbutton"); - if (dev->wps_method != WPS_PBC) { - wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, - "P2P: We have wps_method=%s -> " - "incompatible", - p2p_wps_method_str(dev->wps_method)); - status = P2P_SC_FAIL_INCOMPATIBLE_PROV_METHOD; - goto fail; - } - break; - default: - wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, - "P2P: Unsupported Device Password ID %d", - msg.dev_password_id); - status = P2P_SC_FAIL_INCOMPATIBLE_PROV_METHOD; - goto fail; - } - - if (go) { - struct p2p_channels intersection; - size_t i; - p2p_channels_intersect(&p2p->channels, &dev->channels, - &intersection); - if (intersection.reg_classes == 0 || - intersection.reg_class[0].channels == 0) { - status = P2P_SC_FAIL_NO_COMMON_CHANNELS; - wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, - "P2P: No common channels found"); - goto fail; - } - for (i = 0; i < intersection.reg_classes; i++) { - struct p2p_reg_class *c; - c = &intersection.reg_class[i]; - wpa_printf(MSG_DEBUG, "P2P: reg_class %u", - c->reg_class); - wpa_hexdump(MSG_DEBUG, "P2P: channels", - c->channel, c->channels); - } - if (!p2p_channels_includes(&intersection, - p2p->op_reg_class, - p2p->op_channel)) - p2p_reselect_channel(p2p, &intersection); - - p2p_build_ssid(p2p, p2p->ssid, &p2p->ssid_len); - } - - dev->go_state = go ? LOCAL_GO : REMOTE_GO; - dev->oper_freq = p2p_channel_to_freq((const char *) - msg.operating_channel, - msg.operating_channel[3], - msg.operating_channel[4]); - wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Peer operating " - "channel preference: %d MHz", dev->oper_freq); - - if (msg.config_timeout) { - dev->go_timeout = msg.config_timeout[0]; - dev->client_timeout = msg.config_timeout[1]; - } - - wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, - "P2P: GO Negotiation with " MACSTR, MAC2STR(sa)); - if (p2p->state != P2P_IDLE) - p2p_stop_find_for_freq(p2p, rx_freq); - p2p_set_state(p2p, P2P_GO_NEG); - p2p_clear_timeout(p2p); - dev->dialog_token = msg.dialog_token; - os_memcpy(dev->intended_addr, msg.intended_addr, ETH_ALEN); - p2p->go_neg_peer = dev; - status = P2P_SC_SUCCESS; - } - -fail: - if (dev) - dev->status = status; - resp = p2p_build_go_neg_resp(p2p, dev, msg.dialog_token, status, - !tie_breaker); - p2p_parse_free(&msg); - if (resp == NULL) - return; - wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, - "P2P: Sending GO Negotiation Response"); - if (rx_freq > 0) - freq = rx_freq; - else - freq = p2p_channel_to_freq(p2p->cfg->country, - p2p->cfg->reg_class, - p2p->cfg->channel); - if (freq < 0) { - wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, - "P2P: Unknown regulatory class/channel"); - wpabuf_free(resp); - return; - } - if (status == P2P_SC_SUCCESS) { - p2p->pending_action_state = P2P_PENDING_GO_NEG_RESPONSE; - dev->flags |= P2P_DEV_WAIT_GO_NEG_CONFIRM; - } else - p2p->pending_action_state = - P2P_PENDING_GO_NEG_RESPONSE_FAILURE; - if (p2p_send_action(p2p, freq, sa, p2p->cfg->dev_addr, - p2p->cfg->dev_addr, - wpabuf_head(resp), wpabuf_len(resp), 200) < 0) { - wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, - "P2P: Failed to send Action frame"); - } - - wpabuf_free(resp); -} - - -static struct wpabuf * p2p_build_go_neg_conf(struct p2p_data *p2p, - struct p2p_device *peer, - u8 dialog_token, u8 status, - const u8 *resp_chan, int go) -{ - struct wpabuf *buf; - u8 *len; - struct p2p_channels res; - u8 group_capab; - - wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, - "P2P: Building GO Negotiation Confirm"); - buf = wpabuf_alloc(1000); - if (buf == NULL) - return NULL; - - p2p_buf_add_public_action_hdr(buf, P2P_GO_NEG_CONF, dialog_token); - - len = p2p_buf_add_ie_hdr(buf); - p2p_buf_add_status(buf, status); - group_capab = 0; - if (peer->go_state == LOCAL_GO) { - if (peer->flags & P2P_DEV_PREFER_PERSISTENT_GROUP) - group_capab |= P2P_GROUP_CAPAB_PERSISTENT_GROUP; - if (p2p->cross_connect) - group_capab |= P2P_GROUP_CAPAB_CROSS_CONN; - if (p2p->cfg->p2p_intra_bss) - group_capab |= P2P_GROUP_CAPAB_INTRA_BSS_DIST; - } - p2p_buf_add_capability(buf, p2p->dev_capab, group_capab); - if (go || resp_chan == NULL) - p2p_buf_add_operating_channel(buf, p2p->cfg->country, - p2p->op_reg_class, - p2p->op_channel); - else - p2p_buf_add_operating_channel(buf, (const char *) resp_chan, - resp_chan[3], resp_chan[4]); - p2p_channels_intersect(&p2p->channels, &peer->channels, &res); - p2p_buf_add_channel_list(buf, p2p->cfg->country, &res); - if (go) { - p2p_buf_add_group_id(buf, p2p->cfg->dev_addr, p2p->ssid, - p2p->ssid_len); - } - p2p_buf_update_ie_hdr(buf, len); - - return buf; -} - - -void p2p_process_go_neg_resp(struct p2p_data *p2p, const u8 *sa, - const u8 *data, size_t len, int rx_freq) -{ - struct p2p_device *dev; - struct wpabuf *conf; - int go = -1; - struct p2p_message msg; - u8 status = P2P_SC_SUCCESS; - int freq; - - wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, - "P2P: Received GO Negotiation Response from " MACSTR - " (freq=%d)", MAC2STR(sa), rx_freq); - dev = p2p_get_device(p2p, sa); - if (dev == NULL || dev->wps_method == WPS_NOT_READY || - dev != p2p->go_neg_peer) { - wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, - "P2P: Not ready for GO negotiation with " MACSTR, - MAC2STR(sa)); - return; - } - - if (p2p_parse(data, len, &msg)) - return; - - if (!(dev->flags & P2P_DEV_WAIT_GO_NEG_RESPONSE)) { - wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, - "P2P: Was not expecting GO Negotiation Response - " - "ignore"); - p2p_parse_free(&msg); - return; - } - dev->flags &= ~P2P_DEV_WAIT_GO_NEG_RESPONSE; - - if (msg.dialog_token != dev->dialog_token) { - wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, - "P2P: Unexpected Dialog Token %u (expected %u)", - msg.dialog_token, dev->dialog_token); - p2p_parse_free(&msg); - return; - } - - if (!msg.status) { - wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, - "P2P: No Status attribute received"); - status = P2P_SC_FAIL_INVALID_PARAMS; - goto fail; - } - if (*msg.status) { - wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, - "P2P: GO Negotiation rejected: status %d", - *msg.status); - dev->go_neg_req_sent = 0; - if (*msg.status == P2P_SC_FAIL_INFO_CURRENTLY_UNAVAILABLE) { - wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, - "P2P: Wait for the peer to become ready for " - "GO Negotiation"); - dev->flags |= P2P_DEV_NOT_YET_READY; - dev->wait_count = 0; - p2p_set_state(p2p, P2P_WAIT_PEER_IDLE); - p2p_set_timeout(p2p, 0, 0); - } else { - wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, - "P2P: Stop GO Negotiation attempt"); - p2p_go_neg_failed(p2p, dev, *msg.status); - } - p2p->cfg->send_action_done(p2p->cfg->cb_ctx); - p2p_parse_free(&msg); - return; - } - - if (!msg.capability) { - wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, - "P2P: Mandatory Capability attribute missing from GO " - "Negotiation Response"); -#ifdef CONFIG_P2P_STRICT - status = P2P_SC_FAIL_INVALID_PARAMS; - goto fail; -#endif /* CONFIG_P2P_STRICT */ - } - - if (!msg.p2p_device_info) { - wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, - "P2P: Mandatory P2P Device Info attribute missing " - "from GO Negotiation Response"); -#ifdef CONFIG_P2P_STRICT - status = P2P_SC_FAIL_INVALID_PARAMS; - goto fail; -#endif /* CONFIG_P2P_STRICT */ - } - - if (!msg.intended_addr) { - wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, - "P2P: No Intended P2P Interface Address attribute " - "received"); - status = P2P_SC_FAIL_INVALID_PARAMS; - goto fail; - } - - if (!msg.go_intent) { - wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, - "P2P: No GO Intent attribute received"); - status = P2P_SC_FAIL_INVALID_PARAMS; - goto fail; - } - if ((*msg.go_intent >> 1) > P2P_MAX_GO_INTENT) { - wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, - "P2P: Invalid GO Intent value (%u) received", - *msg.go_intent >> 1); - status = P2P_SC_FAIL_INVALID_PARAMS; - goto fail; - } - - go = p2p_go_det(p2p->go_intent, *msg.go_intent); - if (go < 0) { - wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, - "P2P: Incompatible GO Intent"); - status = P2P_SC_FAIL_INCOMPATIBLE_PARAMS; - goto fail; - } - - if (!go && msg.group_id) { - /* Store SSID for Provisioning step */ - p2p->ssid_len = msg.group_id_len - ETH_ALEN; - os_memcpy(p2p->ssid, msg.group_id + ETH_ALEN, p2p->ssid_len); - } else if (!go) { - wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, - "P2P: Mandatory P2P Group ID attribute missing from " - "GO Negotiation Response"); - p2p->ssid_len = 0; -#ifdef CONFIG_P2P_STRICT - status = P2P_SC_FAIL_INVALID_PARAMS; - goto fail; -#endif /* CONFIG_P2P_STRICT */ - } - - if (!msg.config_timeout) { - wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, - "P2P: Mandatory Configuration Timeout attribute " - "missing from GO Negotiation Response"); -#ifdef CONFIG_P2P_STRICT - status = P2P_SC_FAIL_INVALID_PARAMS; - goto fail; -#endif /* CONFIG_P2P_STRICT */ - } else { - dev->go_timeout = msg.config_timeout[0]; - dev->client_timeout = msg.config_timeout[1]; - } - - if (!msg.operating_channel && !go) { - /* - * Note: P2P Client may omit Operating Channel attribute to - * indicate it does not have a preference. - */ - wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, - "P2P: No Operating Channel attribute received"); - status = P2P_SC_FAIL_INVALID_PARAMS; - goto fail; - } - if (!msg.channel_list) { - wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, - "P2P: No Channel List attribute received"); - status = P2P_SC_FAIL_INVALID_PARAMS; - goto fail; - } - - if (p2p_peer_channels(p2p, dev, msg.channel_list, - msg.channel_list_len) < 0) { - wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, - "P2P: No common channels found"); - status = P2P_SC_FAIL_NO_COMMON_CHANNELS; - goto fail; - } - - if (msg.operating_channel) { - dev->oper_freq = p2p_channel_to_freq((const char *) - msg.operating_channel, - msg.operating_channel[3], - msg.operating_channel[4]); - wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Peer operating " - "channel preference: %d MHz", dev->oper_freq); - } else - dev->oper_freq = 0; - - switch (msg.dev_password_id) { - case DEV_PW_DEFAULT: - wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, - "P2P: PIN from peer Label"); - if (dev->wps_method != WPS_PIN_KEYPAD) { - wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, - "P2P: We have wps_method=%s -> " - "incompatible", - p2p_wps_method_str(dev->wps_method)); - status = P2P_SC_FAIL_INCOMPATIBLE_PROV_METHOD; - goto fail; - } - break; - case DEV_PW_REGISTRAR_SPECIFIED: - wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, - "P2P: PIN from peer Display"); - if (dev->wps_method != WPS_PIN_KEYPAD) { - wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, - "P2P: We have wps_method=%s -> " - "incompatible", - p2p_wps_method_str(dev->wps_method)); - status = P2P_SC_FAIL_INCOMPATIBLE_PROV_METHOD; - goto fail; - } - break; - case DEV_PW_USER_SPECIFIED: - wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, - "P2P: Peer entered PIN on Keypad"); - if (dev->wps_method != WPS_PIN_LABEL && - dev->wps_method != WPS_PIN_DISPLAY) { - wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, - "P2P: We have wps_method=%s -> " - "incompatible", - p2p_wps_method_str(dev->wps_method)); - status = P2P_SC_FAIL_INCOMPATIBLE_PROV_METHOD; - goto fail; - } - break; - case DEV_PW_PUSHBUTTON: - wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, - "P2P: Peer using pushbutton"); - if (dev->wps_method != WPS_PBC) { - wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, - "P2P: We have wps_method=%s -> " - "incompatible", - p2p_wps_method_str(dev->wps_method)); - status = P2P_SC_FAIL_INCOMPATIBLE_PROV_METHOD; - goto fail; - } - break; - default: - wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, - "P2P: Unsupported Device Password ID %d", - msg.dev_password_id); - status = P2P_SC_FAIL_INCOMPATIBLE_PROV_METHOD; - goto fail; - } - - if (go) { - struct p2p_channels intersection; - size_t i; - p2p_channels_intersect(&p2p->channels, &dev->channels, - &intersection); - if (intersection.reg_classes == 0 || - intersection.reg_class[0].channels == 0) { - status = P2P_SC_FAIL_NO_COMMON_CHANNELS; - wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, - "P2P: No common channels found"); - goto fail; - } - for (i = 0; i < intersection.reg_classes; i++) { - struct p2p_reg_class *c; - c = &intersection.reg_class[i]; - wpa_printf(MSG_DEBUG, "P2P: reg_class %u", - c->reg_class); - wpa_hexdump(MSG_DEBUG, "P2P: channels", - c->channel, c->channels); - } - if (!p2p_channels_includes(&intersection, p2p->op_reg_class, - p2p->op_channel)) - p2p_reselect_channel(p2p, &intersection); - - p2p_build_ssid(p2p, p2p->ssid, &p2p->ssid_len); - } - - p2p_set_state(p2p, P2P_GO_NEG); - p2p_clear_timeout(p2p); - - wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, - "P2P: GO Negotiation with " MACSTR, MAC2STR(sa)); - os_memcpy(dev->intended_addr, msg.intended_addr, ETH_ALEN); - -fail: - conf = p2p_build_go_neg_conf(p2p, dev, msg.dialog_token, status, - msg.operating_channel, go); - p2p_parse_free(&msg); - if (conf == NULL) - return; - wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, - "P2P: Sending GO Negotiation Confirm"); - if (status == P2P_SC_SUCCESS) { - p2p->pending_action_state = P2P_PENDING_GO_NEG_CONFIRM; - dev->go_state = go ? LOCAL_GO : REMOTE_GO; - } else - p2p->pending_action_state = P2P_NO_PENDING_ACTION; - if (rx_freq > 0) - freq = rx_freq; - else - freq = dev->listen_freq; - if (p2p_send_action(p2p, freq, sa, p2p->cfg->dev_addr, sa, - wpabuf_head(conf), wpabuf_len(conf), 200) < 0) { - wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, - "P2P: Failed to send Action frame"); - p2p_go_neg_failed(p2p, dev, -1); - } - wpabuf_free(conf); -} - - -void p2p_process_go_neg_conf(struct p2p_data *p2p, const u8 *sa, - const u8 *data, size_t len) -{ - struct p2p_device *dev; - struct p2p_message msg; - - wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, - "P2P: Received GO Negotiation Confirm from " MACSTR, - MAC2STR(sa)); - dev = p2p_get_device(p2p, sa); - if (dev == NULL || dev->wps_method == WPS_NOT_READY || - dev != p2p->go_neg_peer) { - wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, - "P2P: Not ready for GO negotiation with " MACSTR, - MAC2STR(sa)); - return; - } - - if (p2p->pending_action_state == P2P_PENDING_GO_NEG_RESPONSE) { - wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Stopped waiting " - "for TX status on GO Negotiation Response since we " - "already received Confirmation"); - p2p->pending_action_state = P2P_NO_PENDING_ACTION; - } - - if (p2p_parse(data, len, &msg)) - return; - - if (!(dev->flags & P2P_DEV_WAIT_GO_NEG_CONFIRM)) { - wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, - "P2P: Was not expecting GO Negotiation Confirm - " - "ignore"); - return; - } - dev->flags &= ~P2P_DEV_WAIT_GO_NEG_CONFIRM; - - if (msg.dialog_token != dev->dialog_token) { - wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, - "P2P: Unexpected Dialog Token %u (expected %u)", - msg.dialog_token, dev->dialog_token); - p2p_parse_free(&msg); - return; - } - - if (!msg.status) { - wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, - "P2P: No Status attribute received"); - p2p_parse_free(&msg); - return; - } - if (*msg.status) { - wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, - "P2P: GO Negotiation rejected: status %d", - *msg.status); - p2p_parse_free(&msg); - return; - } - - if (dev->go_state == REMOTE_GO && msg.group_id) { - /* Store SSID for Provisioning step */ - p2p->ssid_len = msg.group_id_len - ETH_ALEN; - os_memcpy(p2p->ssid, msg.group_id + ETH_ALEN, p2p->ssid_len); - } else if (dev->go_state == REMOTE_GO) { - wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, - "P2P: Mandatory P2P Group ID attribute missing from " - "GO Negotiation Confirmation"); - p2p->ssid_len = 0; -#ifdef CONFIG_P2P_STRICT - p2p_parse_free(&msg); - return; -#endif /* CONFIG_P2P_STRICT */ - } - - if (!msg.operating_channel) { - wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, - "P2P: Mandatory Operating Channel attribute missing " - "from GO Negotiation Confirmation"); -#ifdef CONFIG_P2P_STRICT - p2p_parse_free(&msg); - return; -#endif /* CONFIG_P2P_STRICT */ - } - - if (!msg.channel_list) { - wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, - "P2P: Mandatory Operating Channel attribute missing " - "from GO Negotiation Confirmation"); -#ifdef CONFIG_P2P_STRICT - p2p_parse_free(&msg); - return; -#endif /* CONFIG_P2P_STRICT */ - } - - p2p_parse_free(&msg); - - if (dev->go_state == UNKNOWN_GO) { - /* - * This should not happen since GO negotiation has already - * been completed. - */ - wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, - "P2P: Unexpected GO Neg state - do not know which end " - "becomes GO"); - return; - } - - p2p_go_complete(p2p, dev); -} diff --git a/hostapd-0.8/src/p2p/p2p_group.c b/hostapd-0.8/src/p2p/p2p_group.c deleted file mode 100644 index 14a475d..0000000 --- a/hostapd-0.8/src/p2p/p2p_group.c +++ /dev/null @@ -1,673 +0,0 @@ -/* - * Wi-Fi Direct - P2P group operations - * Copyright (c) 2009-2010, Atheros Communications - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#include "includes.h" - -#include "common.h" -#include "common/ieee802_11_defs.h" -#include "common/ieee802_11_common.h" -#include "wps/wps_defs.h" -#include "wps/wps_i.h" -#include "p2p_i.h" -#include "p2p.h" - - -struct p2p_group_member { - struct p2p_group_member *next; - u8 addr[ETH_ALEN]; /* P2P Interface Address */ - u8 dev_addr[ETH_ALEN]; /* P2P Device Address */ - struct wpabuf *p2p_ie; - struct wpabuf *client_info; - u8 dev_capab; -}; - -/** - * struct p2p_group - Internal P2P module per-group data - */ -struct p2p_group { - struct p2p_data *p2p; - struct p2p_group_config *cfg; - struct p2p_group_member *members; - unsigned int num_members; - int group_formation; - int beacon_update; - struct wpabuf *noa; -}; - - -static void p2p_group_update_ies(struct p2p_group *group); - - -struct p2p_group * p2p_group_init(struct p2p_data *p2p, - struct p2p_group_config *config) -{ - struct p2p_group *group, **groups; - - group = os_zalloc(sizeof(*group)); - if (group == NULL) - return NULL; - - groups = os_realloc(p2p->groups, (p2p->num_groups + 1) * - sizeof(struct p2p_group *)); - if (groups == NULL) { - os_free(group); - return NULL; - } - groups[p2p->num_groups++] = group; - p2p->groups = groups; - - group->p2p = p2p; - group->cfg = config; - group->group_formation = 1; - group->beacon_update = 1; - p2p_group_update_ies(group); - group->cfg->idle_update(group->cfg->cb_ctx, 1); - - return group; -} - - -static void p2p_group_free_member(struct p2p_group_member *m) -{ - wpabuf_free(m->p2p_ie); - wpabuf_free(m->client_info); - os_free(m); -} - - -static void p2p_group_free_members(struct p2p_group *group) -{ - struct p2p_group_member *m, *prev; - m = group->members; - group->members = NULL; - group->num_members = 0; - while (m) { - prev = m; - m = m->next; - p2p_group_free_member(prev); - } -} - - -void p2p_group_deinit(struct p2p_group *group) -{ - size_t g; - struct p2p_data *p2p; - - if (group == NULL) - return; - - p2p = group->p2p; - - for (g = 0; g < p2p->num_groups; g++) { - if (p2p->groups[g] == group) { - while (g + 1 < p2p->num_groups) { - p2p->groups[g] = p2p->groups[g + 1]; - g++; - } - p2p->num_groups--; - break; - } - } - - p2p_group_free_members(group); - os_free(group->cfg); - wpabuf_free(group->noa); - os_free(group); -} - - -static void p2p_client_info(struct wpabuf *ie, struct p2p_group_member *m) -{ - if (m->client_info == NULL) - return; - if (wpabuf_tailroom(ie) < wpabuf_len(m->client_info) + 1) - return; - wpabuf_put_buf(ie, m->client_info); -} - - -static void p2p_group_add_common_ies(struct p2p_group *group, - struct wpabuf *ie) -{ - u8 dev_capab = 0, group_capab = 0; - - /* P2P Capability */ - dev_capab |= P2P_DEV_CAPAB_SERVICE_DISCOVERY; - dev_capab |= P2P_DEV_CAPAB_INVITATION_PROCEDURE; - group_capab |= P2P_GROUP_CAPAB_GROUP_OWNER; - if (group->cfg->persistent_group) - group_capab |= P2P_GROUP_CAPAB_PERSISTENT_GROUP; - if (group->p2p->cfg->p2p_intra_bss) - group_capab |= P2P_GROUP_CAPAB_INTRA_BSS_DIST; - if (group->group_formation) - group_capab |= P2P_GROUP_CAPAB_GROUP_FORMATION; - if (group->p2p->cross_connect) - group_capab |= P2P_GROUP_CAPAB_CROSS_CONN; - if (group->num_members >= group->cfg->max_clients) - group_capab |= P2P_GROUP_CAPAB_GROUP_LIMIT; - p2p_buf_add_capability(ie, dev_capab, group_capab); -} - - -static void p2p_group_add_noa(struct wpabuf *ie, struct wpabuf *noa) -{ - if (noa == NULL) - return; - /* Notice of Absence */ - wpabuf_put_u8(ie, P2P_ATTR_NOTICE_OF_ABSENCE); - wpabuf_put_le16(ie, wpabuf_len(noa)); - wpabuf_put_buf(ie, noa); -} - - -static struct wpabuf * p2p_group_build_beacon_ie(struct p2p_group *group) -{ - struct wpabuf *ie; - u8 *len; - - ie = wpabuf_alloc(257); - if (ie == NULL) - return NULL; - - len = p2p_buf_add_ie_hdr(ie); - p2p_group_add_common_ies(group, ie); - p2p_buf_add_device_id(ie, group->p2p->cfg->dev_addr); - p2p_group_add_noa(ie, group->noa); - p2p_buf_update_ie_hdr(ie, len); - - return ie; -} - - -static struct wpabuf * p2p_group_build_probe_resp_ie(struct p2p_group *group) -{ - u8 *group_info; - struct wpabuf *ie; - struct p2p_group_member *m; - u8 *len; - - ie = wpabuf_alloc(257); - if (ie == NULL) - return NULL; - - len = p2p_buf_add_ie_hdr(ie); - - p2p_group_add_common_ies(group, ie); - p2p_group_add_noa(ie, group->noa); - - /* P2P Device Info */ - p2p_buf_add_device_info(ie, group->p2p, NULL); - - /* P2P Group Info */ - group_info = wpabuf_put(ie, 0); - wpabuf_put_u8(ie, P2P_ATTR_GROUP_INFO); - wpabuf_put_le16(ie, 0); /* Length to be filled */ - for (m = group->members; m; m = m->next) - p2p_client_info(ie, m); - WPA_PUT_LE16(group_info + 1, - (u8 *) wpabuf_put(ie, 0) - group_info - 3); - - p2p_buf_update_ie_hdr(ie, len); - return ie; -} - - -static void p2p_group_update_ies(struct p2p_group *group) -{ - struct wpabuf *beacon_ie; - struct wpabuf *probe_resp_ie; - - probe_resp_ie = p2p_group_build_probe_resp_ie(group); - if (probe_resp_ie == NULL) - return; - wpa_hexdump_buf(MSG_MSGDUMP, "P2P: Update GO Probe Response P2P IE", - probe_resp_ie); - - if (group->beacon_update) { - beacon_ie = p2p_group_build_beacon_ie(group); - if (beacon_ie) - group->beacon_update = 0; - wpa_hexdump_buf(MSG_MSGDUMP, "P2P: Update GO Beacon P2P IE", - beacon_ie); - } else - beacon_ie = NULL; - - group->cfg->ie_update(group->cfg->cb_ctx, beacon_ie, probe_resp_ie); -} - - -/** - * p2p_build_client_info - Build P2P Client Info Descriptor - * @addr: MAC address of the peer device - * @p2p_ie: P2P IE from (Re)Association Request - * @dev_capab: Buffer for returning Device Capability - * @dev_addr: Buffer for returning P2P Device Address - * Returns: P2P Client Info Descriptor or %NULL on failure - * - * This function builds P2P Client Info Descriptor based on the information - * available from (Re)Association Request frame. Group owner can use this to - * build the P2P Group Info attribute for Probe Response frames. - */ -static struct wpabuf * p2p_build_client_info(const u8 *addr, - struct wpabuf *p2p_ie, - u8 *dev_capab, u8 *dev_addr) -{ - const u8 *spos; - struct p2p_message msg; - u8 *len_pos; - struct wpabuf *buf; - - if (p2p_ie == NULL) - return NULL; - - os_memset(&msg, 0, sizeof(msg)); - if (p2p_parse_p2p_ie(p2p_ie, &msg) || - msg.capability == NULL || msg.p2p_device_info == NULL) - return NULL; - - buf = wpabuf_alloc(ETH_ALEN + 1 + 1 + msg.p2p_device_info_len); - if (buf == NULL) - return NULL; - - *dev_capab = msg.capability[0]; - os_memcpy(dev_addr, msg.p2p_device_addr, ETH_ALEN); - - spos = msg.p2p_device_info; /* P2P Device address */ - - /* P2P Client Info Descriptor */ - /* Length to be set */ - len_pos = wpabuf_put(buf, 1); - /* P2P Device address */ - wpabuf_put_data(buf, spos, ETH_ALEN); - /* P2P Interface address */ - wpabuf_put_data(buf, addr, ETH_ALEN); - /* Device Capability Bitmap */ - wpabuf_put_u8(buf, msg.capability[0]); - /* - * Config Methods, Primary Device Type, Number of Secondary Device - * Types, Secondary Device Type List, Device Name copied from - * Device Info - */ - wpabuf_put_data(buf, spos + ETH_ALEN, - msg.p2p_device_info_len - ETH_ALEN); - - *len_pos = wpabuf_len(buf) - 1; - - - return buf; -} - - -int p2p_group_notif_assoc(struct p2p_group *group, const u8 *addr, - const u8 *ie, size_t len) -{ - struct p2p_group_member *m; - - if (group == NULL) - return -1; - - m = os_zalloc(sizeof(*m)); - if (m == NULL) - return -1; - os_memcpy(m->addr, addr, ETH_ALEN); - m->p2p_ie = ieee802_11_vendor_ie_concat(ie, len, P2P_IE_VENDOR_TYPE); - if (m->p2p_ie) { - m->client_info = p2p_build_client_info(addr, m->p2p_ie, - &m->dev_capab, - m->dev_addr); - } - - m->next = group->members; - group->members = m; - group->num_members++; - wpa_msg(group->p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Add client " MACSTR - " to group (p2p=%d client_info=%d); num_members=%u/%u", - MAC2STR(addr), m->p2p_ie ? 1 : 0, m->client_info ? 1 : 0, - group->num_members, group->cfg->max_clients); - if (group->num_members == group->cfg->max_clients) - group->beacon_update = 1; - p2p_group_update_ies(group); - if (group->num_members == 1) - group->cfg->idle_update(group->cfg->cb_ctx, 0); - - return 0; -} - - -struct wpabuf * p2p_group_assoc_resp_ie(struct p2p_group *group, u8 status) -{ - struct wpabuf *resp; - u8 *rlen; - - /* - * (Re)Association Response - P2P IE - * Status attribute (shall be present when association request is - * denied) - * Extended Listen Timing (may be present) - */ - resp = wpabuf_alloc(20); - if (resp == NULL) - return NULL; - rlen = p2p_buf_add_ie_hdr(resp); - if (status != P2P_SC_SUCCESS) - p2p_buf_add_status(resp, status); - p2p_buf_update_ie_hdr(resp, rlen); - - return resp; -} - - -void p2p_group_notif_disassoc(struct p2p_group *group, const u8 *addr) -{ - struct p2p_group_member *m, *prev; - - if (group == NULL) - return; - - m = group->members; - prev = NULL; - while (m) { - if (os_memcmp(m->addr, addr, ETH_ALEN) == 0) - break; - prev = m; - m = m->next; - } - - if (m) { - if (prev) - prev->next = m->next; - else - group->members = m->next; - p2p_group_free_member(m); - group->num_members--; - wpa_msg(group->p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Remove " - "client " MACSTR " from group; num_members=%u/%u", - MAC2STR(addr), group->num_members, - group->cfg->max_clients); - if (group->num_members == group->cfg->max_clients - 1) - group->beacon_update = 1; - p2p_group_update_ies(group); - if (group->num_members == 0) - group->cfg->idle_update(group->cfg->cb_ctx, 1); - } -} - - -/** - * p2p_match_dev_type_member - Match client device type with requested type - * @m: Group member - * @wps: WPS TLVs from Probe Request frame (concatenated WPS IEs) - * Returns: 1 on match, 0 on mismatch - * - * This function can be used to match the Requested Device Type attribute in - * WPS IE with the device types of a group member for deciding whether a GO - * should reply to a Probe Request frame. - */ -static int p2p_match_dev_type_member(struct p2p_group_member *m, - struct wpabuf *wps) -{ - const u8 *pos, *end; - struct wps_parse_attr attr; - u8 num_sec; - - if (m->client_info == NULL || wps == NULL) - return 0; - - pos = wpabuf_head(m->client_info); - end = pos + wpabuf_len(m->client_info); - - pos += 1 + 2 * ETH_ALEN + 1 + 2; - if (end - pos < WPS_DEV_TYPE_LEN + 1) - return 0; - - if (wps_parse_msg(wps, &attr)) - return 1; /* assume no Requested Device Type attributes */ - - if (attr.num_req_dev_type == 0) - return 1; /* no Requested Device Type attributes -> match */ - - if (dev_type_list_match(pos, attr.req_dev_type, attr.num_req_dev_type)) - return 1; /* Match with client Primary Device Type */ - - pos += WPS_DEV_TYPE_LEN; - num_sec = *pos++; - if (end - pos < num_sec * WPS_DEV_TYPE_LEN) - return 0; - while (num_sec > 0) { - num_sec--; - if (dev_type_list_match(pos, attr.req_dev_type, - attr.num_req_dev_type)) - return 1; /* Match with client Secondary Device Type */ - pos += WPS_DEV_TYPE_LEN; - } - - /* No matching device type found */ - return 0; -} - - -int p2p_group_match_dev_type(struct p2p_group *group, struct wpabuf *wps) -{ - struct p2p_group_member *m; - - if (p2p_match_dev_type(group->p2p, wps)) - return 1; /* Match with own device type */ - - for (m = group->members; m; m = m->next) { - if (p2p_match_dev_type_member(m, wps)) - return 1; /* Match with group client device type */ - } - - /* No match with Requested Device Type */ - return 0; -} - - -void p2p_group_notif_formation_done(struct p2p_group *group) -{ - if (group == NULL) - return; - group->group_formation = 0; - group->beacon_update = 1; - p2p_group_update_ies(group); -} - - -int p2p_group_notif_noa(struct p2p_group *group, const u8 *noa, - size_t noa_len) -{ - if (noa == NULL) { - wpabuf_free(group->noa); - group->noa = NULL; - } else { - if (group->noa) { - if (wpabuf_size(group->noa) >= noa_len) { - group->noa->size = 0; - wpabuf_put_data(group->noa, noa, noa_len); - } else { - wpabuf_free(group->noa); - group->noa = NULL; - } - } - - if (!group->noa) { - group->noa = wpabuf_alloc_copy(noa, noa_len); - if (group->noa == NULL) - return -1; - } - } - - group->beacon_update = 1; - p2p_group_update_ies(group); - return 0; -} - - -static struct p2p_group_member * p2p_group_get_client(struct p2p_group *group, - const u8 *dev_id) -{ - struct p2p_group_member *m; - - for (m = group->members; m; m = m->next) { - if (os_memcmp(dev_id, m->dev_addr, ETH_ALEN) == 0) - return m; - } - - return NULL; -} - - -static struct p2p_group_member * p2p_group_get_client_iface( - struct p2p_group *group, const u8 *interface_addr) -{ - struct p2p_group_member *m; - - for (m = group->members; m; m = m->next) { - if (os_memcmp(interface_addr, m->addr, ETH_ALEN) == 0) - return m; - } - - return NULL; -} - - -static struct wpabuf * p2p_build_go_disc_req(void) -{ - struct wpabuf *buf; - - buf = wpabuf_alloc(100); - if (buf == NULL) - return NULL; - - p2p_buf_add_action_hdr(buf, P2P_GO_DISC_REQ, 0); - - return buf; -} - - -int p2p_group_go_discover(struct p2p_group *group, const u8 *dev_id, - const u8 *searching_dev, int rx_freq) -{ - struct p2p_group_member *m; - struct wpabuf *req; - struct p2p_data *p2p = group->p2p; - int freq; - - m = p2p_group_get_client(group, dev_id); - if (m == NULL || m->client_info == NULL) { - wpa_printf(MSG_DEBUG, "P2P: Requested client was not in this " - "group " MACSTR, - MAC2STR(group->cfg->interface_addr)); - return -1; - } - - if (!(m->dev_capab & P2P_DEV_CAPAB_CLIENT_DISCOVERABILITY)) { - wpa_printf(MSG_DEBUG, "P2P: Requested client does not support " - "client discoverability"); - return -1; - } - - wpa_printf(MSG_DEBUG, "P2P: Schedule GO Discoverability Request to be " - "sent to " MACSTR, MAC2STR(dev_id)); - - req = p2p_build_go_disc_req(); - if (req == NULL) - return -1; - - /* TODO: Should really use group operating frequency here */ - freq = rx_freq; - - p2p->pending_action_state = P2P_PENDING_GO_DISC_REQ; - if (p2p->cfg->send_action(p2p->cfg->cb_ctx, freq, m->addr, - group->cfg->interface_addr, - group->cfg->interface_addr, - wpabuf_head(req), wpabuf_len(req), 200) < 0) - { - wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, - "P2P: Failed to send Action frame"); - } - - wpabuf_free(req); - - return 0; -} - - -const u8 * p2p_group_get_interface_addr(struct p2p_group *group) -{ - return group->cfg->interface_addr; -} - - -u8 p2p_group_presence_req(struct p2p_group *group, - const u8 *client_interface_addr, - const u8 *noa, size_t noa_len) -{ - struct p2p_group_member *m; - u8 curr_noa[50]; - int curr_noa_len; - - m = p2p_group_get_client_iface(group, client_interface_addr); - if (m == NULL || m->client_info == NULL) { - wpa_printf(MSG_DEBUG, "P2P: Client was not in this group"); - return P2P_SC_FAIL_UNABLE_TO_ACCOMMODATE; - } - - wpa_hexdump(MSG_DEBUG, "P2P: Presence Request NoA", noa, noa_len); - - if (group->p2p->cfg->get_noa) - curr_noa_len = group->p2p->cfg->get_noa( - group->p2p->cfg->cb_ctx, group->cfg->interface_addr, - curr_noa, sizeof(curr_noa)); - else - curr_noa_len = -1; - if (curr_noa_len < 0) - wpa_printf(MSG_DEBUG, "P2P: Failed to fetch current NoA"); - else if (curr_noa_len == 0) - wpa_printf(MSG_DEBUG, "P2P: No NoA being advertized"); - else - wpa_hexdump(MSG_DEBUG, "P2P: Current NoA", curr_noa, - curr_noa_len); - - /* TODO: properly process request and store copy */ - if (curr_noa_len > 0) - return P2P_SC_FAIL_UNABLE_TO_ACCOMMODATE; - - return P2P_SC_SUCCESS; -} - - -unsigned int p2p_get_group_num_members(struct p2p_group *group) -{ - return group->num_members; -} - - -const u8 * p2p_iterate_group_members(struct p2p_group *group, void **next) -{ - struct p2p_group_member *iter = *next; - - if (!iter) - iter = group->members; - else - iter = iter->next; - - *next = iter; - - if (!iter) - return NULL; - - return iter->addr; -} diff --git a/hostapd-0.8/src/p2p/p2p_i.h b/hostapd-0.8/src/p2p/p2p_i.h deleted file mode 100644 index 68b1194..0000000 --- a/hostapd-0.8/src/p2p/p2p_i.h +++ /dev/null @@ -1,638 +0,0 @@ -/* - * P2P - Internal definitions for P2P module - * Copyright (c) 2009-2010, Atheros Communications - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#ifndef P2P_I_H -#define P2P_I_H - -#include "utils/list.h" -#include "p2p.h" - -/* TODO: add removal of expired P2P device entries */ - -enum p2p_go_state { - UNKNOWN_GO, - LOCAL_GO, - REMOTE_GO -}; - -/** - * struct p2p_device - P2P Device data (internal to P2P module) - */ -struct p2p_device { - struct dl_list list; - struct os_time last_seen; - int listen_freq; - int level; - enum p2p_wps_method wps_method; - - struct p2p_peer_info info; - - /* - * If the peer was discovered based on an interface address (e.g., GO - * from Beacon/Probe Response), the interface address is stored here. - * p2p_device_addr must still be set in such a case to the unique - * identifier for the P2P Device. - */ - u8 interface_addr[ETH_ALEN]; - - /* - * P2P Device Address of the GO in whose group this P2P Device is a - * client. - */ - u8 member_in_go_dev[ETH_ALEN]; - - /* - * P2P Interface Address of the GO in whose group this P2P Device is a - * client. - */ - u8 member_in_go_iface[ETH_ALEN]; - - int go_neg_req_sent; - enum p2p_go_state go_state; - u8 dialog_token; - u8 intended_addr[ETH_ALEN]; - - char country[3]; - struct p2p_channels channels; - int oper_freq; - u8 oper_ssid[32]; - size_t oper_ssid_len; - - /** - * req_config_methods - Pending provisioning discovery methods - */ - u16 req_config_methods; - -#define P2P_DEV_PROBE_REQ_ONLY BIT(0) -#define P2P_DEV_REPORTED BIT(1) -#define P2P_DEV_NOT_YET_READY BIT(2) -#define P2P_DEV_SD_INFO BIT(3) -#define P2P_DEV_SD_SCHEDULE BIT(4) -#define P2P_DEV_PD_PEER_DISPLAY BIT(5) -#define P2P_DEV_PD_PEER_KEYPAD BIT(6) -#define P2P_DEV_USER_REJECTED BIT(7) -#define P2P_DEV_PEER_WAITING_RESPONSE BIT(8) -#define P2P_DEV_PREFER_PERSISTENT_GROUP BIT(9) -#define P2P_DEV_WAIT_GO_NEG_RESPONSE BIT(10) -#define P2P_DEV_WAIT_GO_NEG_CONFIRM BIT(11) -#define P2P_DEV_GROUP_CLIENT_ONLY BIT(12) -#define P2P_DEV_FORCE_FREQ BIT(13) -#define P2P_DEV_PD_FOR_JOIN BIT(14) -#define P2P_DEV_REPORTED_ONCE BIT(15) - unsigned int flags; - - int status; /* enum p2p_status_code */ - unsigned int wait_count; - unsigned int connect_reqs; - unsigned int invitation_reqs; - - u16 ext_listen_period; - u16 ext_listen_interval; - - u8 go_timeout; - u8 client_timeout; -}; - -struct p2p_sd_query { - struct p2p_sd_query *next; - u8 peer[ETH_ALEN]; - int for_all_peers; - struct wpabuf *tlvs; -}; - -struct p2p_pending_action_tx { - unsigned int freq; - u8 dst[ETH_ALEN]; - u8 src[ETH_ALEN]; - u8 bssid[ETH_ALEN]; - size_t len; - unsigned int wait_time; - /* Followed by len octets of the frame */ -}; - -/** - * struct p2p_data - P2P module data (internal to P2P module) - */ -struct p2p_data { - /** - * cfg - P2P module configuration - * - * This is included in the same memory allocation with the - * struct p2p_data and as such, must not be freed separately. - */ - struct p2p_config *cfg; - - /** - * state - The current P2P state - */ - enum p2p_state { - /** - * P2P_IDLE - Idle - */ - P2P_IDLE, - - /** - * P2P_SEARCH - Search (Device Discovery) - */ - P2P_SEARCH, - - /** - * P2P_CONNECT - Trying to start GO Negotiation - */ - P2P_CONNECT, - - /** - * P2P_CONNECT_LISTEN - Listen during GO Negotiation start - */ - P2P_CONNECT_LISTEN, - - /** - * P2P_GO_NEG - In GO Negotiation - */ - P2P_GO_NEG, - - /** - * P2P_LISTEN_ONLY - Listen only - */ - P2P_LISTEN_ONLY, - - /** - * P2P_WAIT_PEER_CONNECT - Waiting peer in List for GO Neg - */ - P2P_WAIT_PEER_CONNECT, - - /** - * P2P_WAIT_PEER_IDLE - Waiting peer idle for GO Neg - */ - P2P_WAIT_PEER_IDLE, - - /** - * P2P_SD_DURING_FIND - Service Discovery during find - */ - P2P_SD_DURING_FIND, - - /** - * P2P_PROVISIONING - Provisioning (during group formation) - */ - P2P_PROVISIONING, - - /** - * P2P_PD_DURING_FIND - Provision Discovery during find - */ - P2P_PD_DURING_FIND, - - /** - * P2P_INVITE - Trying to start Invite - */ - P2P_INVITE, - - /** - * P2P_INVITE_LISTEN - Listen during Invite - */ - P2P_INVITE_LISTEN, - } state; - - /** - * min_disc_int - minDiscoverableInterval - */ - int min_disc_int; - - /** - * max_disc_int - maxDiscoverableInterval - */ - int max_disc_int; - - /** - * devices - List of known P2P Device peers - */ - struct dl_list devices; - - /** - * go_neg_peer - Pointer to GO Negotiation peer - */ - struct p2p_device *go_neg_peer; - - /** - * invite_peer - Pointer to Invite peer - */ - struct p2p_device *invite_peer; - - const u8 *invite_go_dev_addr; - u8 invite_go_dev_addr_buf[ETH_ALEN]; - - /** - * sd_peer - Pointer to Service Discovery peer - */ - struct p2p_device *sd_peer; - - /** - * sd_query - Pointer to Service Discovery query - */ - struct p2p_sd_query *sd_query; - - /* GO Negotiation data */ - - /** - * intended_addr - Local Intended P2P Interface Address - * - * This address is used during group owner negotiation as the Intended - * P2P Interface Address and the group interface will be created with - * address as the local address in case of successfully completed - * negotiation. - */ - u8 intended_addr[ETH_ALEN]; - - /** - * go_intent - Local GO Intent to be used during GO Negotiation - */ - u8 go_intent; - - /** - * next_tie_breaker - Next tie-breaker value to use in GO Negotiation - */ - u8 next_tie_breaker; - - /** - * ssid - Selected SSID for GO Negotiation (if local end will be GO) - */ - u8 ssid[32]; - - /** - * ssid_len - ssid length in octets - */ - size_t ssid_len; - - /** - * Regulatory class for own operational channel - */ - u8 op_reg_class; - - /** - * op_channel - Own operational channel - */ - u8 op_channel; - - /** - * channels - Own supported regulatory classes and channels - * - * List of supposerted channels per regulatory class. The regulatory - * classes are defined in IEEE Std 802.11-2007 Annex J and the - * numbering of the clases depends on the configured country code. - */ - struct p2p_channels channels; - - enum p2p_pending_action_state { - P2P_NO_PENDING_ACTION, - P2P_PENDING_GO_NEG_REQUEST, - P2P_PENDING_GO_NEG_RESPONSE, - P2P_PENDING_GO_NEG_RESPONSE_FAILURE, - P2P_PENDING_GO_NEG_CONFIRM, - P2P_PENDING_SD, - P2P_PENDING_PD, - P2P_PENDING_INVITATION_REQUEST, - P2P_PENDING_INVITATION_RESPONSE, - P2P_PENDING_DEV_DISC_REQUEST, - P2P_PENDING_DEV_DISC_RESPONSE, - P2P_PENDING_GO_DISC_REQ - } pending_action_state; - - unsigned int pending_listen_freq; - unsigned int pending_listen_sec; - unsigned int pending_listen_usec; - - u8 dev_capab; - - int in_listen; - int drv_in_listen; - - /** - * sd_queries - Pending service discovery queries - */ - struct p2p_sd_query *sd_queries; - - /** - * srv_update_indic - Service Update Indicator for local services - */ - u16 srv_update_indic; - - struct wpabuf *sd_resp; /* Fragmented SD response */ - u8 sd_resp_addr[ETH_ALEN]; - u8 sd_resp_dialog_token; - size_t sd_resp_pos; /* Offset in sd_resp */ - u8 sd_frag_id; - - struct wpabuf *sd_rx_resp; /* Reassembled SD response */ - u16 sd_rx_update_indic; - - /* P2P Invitation data */ - enum p2p_invite_role inv_role; - u8 inv_bssid[ETH_ALEN]; - int inv_bssid_set; - u8 inv_ssid[32]; - size_t inv_ssid_len; - u8 inv_sa[ETH_ALEN]; - u8 inv_group_bssid[ETH_ALEN]; - u8 *inv_group_bssid_ptr; - u8 inv_go_dev_addr[ETH_ALEN]; - u8 inv_status; - int inv_op_freq; - int inv_persistent; - - enum p2p_discovery_type find_type; - u8 last_prog_scan_class; - u8 last_prog_scan_chan; - int p2p_scan_running; - enum p2p_after_scan { - P2P_AFTER_SCAN_NOTHING, - P2P_AFTER_SCAN_LISTEN, - P2P_AFTER_SCAN_CONNECT - } start_after_scan; - u8 after_scan_peer[ETH_ALEN]; - struct p2p_pending_action_tx *after_scan_tx; - - /* Requested device types for find/search */ - unsigned int num_req_dev_types; - u8 *req_dev_types; - - struct p2p_group **groups; - size_t num_groups; - - struct p2p_device *pending_client_disc_go; - u8 pending_client_disc_addr[ETH_ALEN]; - u8 pending_dev_disc_dialog_token; - u8 pending_dev_disc_addr[ETH_ALEN]; - int pending_dev_disc_freq; - unsigned int pending_client_disc_freq; - - int ext_listen_only; - unsigned int ext_listen_period; - unsigned int ext_listen_interval; - unsigned int ext_listen_interval_sec; - unsigned int ext_listen_interval_usec; - - u8 peer_filter[ETH_ALEN]; - - int cross_connect; - - int best_freq_24; - int best_freq_5; - int best_freq_overall; - - /** - * wps_vendor_ext - WPS Vendor Extensions to add - */ - struct wpabuf *wps_vendor_ext[P2P_MAX_WPS_VENDOR_EXT]; -}; - -/** - * struct p2p_message - Parsed P2P message (or P2P IE) - */ -struct p2p_message { - struct wpabuf *p2p_attributes; - struct wpabuf *wps_attributes; - - u8 dialog_token; - - const u8 *capability; - const u8 *go_intent; - const u8 *status; - const u8 *listen_channel; - const u8 *operating_channel; - const u8 *channel_list; - u8 channel_list_len; - const u8 *config_timeout; - const u8 *intended_addr; - const u8 *group_bssid; - const u8 *invitation_flags; - - const u8 *group_info; - size_t group_info_len; - - const u8 *group_id; - size_t group_id_len; - - const u8 *device_id; - - const u8 *manageability; - - const u8 *noa; - size_t noa_len; - - const u8 *ext_listen_timing; - - const u8 *minor_reason_code; - - /* P2P Device Info */ - const u8 *p2p_device_info; - size_t p2p_device_info_len; - const u8 *p2p_device_addr; - const u8 *pri_dev_type; - u8 num_sec_dev_types; - char device_name[33]; - u16 config_methods; - - /* WPS IE */ - u16 dev_password_id; - u16 wps_config_methods; - const u8 *wps_pri_dev_type; - const u8 *wps_sec_dev_type_list; - size_t wps_sec_dev_type_list_len; - const u8 *wps_vendor_ext[P2P_MAX_WPS_VENDOR_EXT]; - size_t wps_vendor_ext_len[P2P_MAX_WPS_VENDOR_EXT]; - const u8 *manufacturer; - size_t manufacturer_len; - const u8 *model_name; - size_t model_name_len; - const u8 *model_number; - size_t model_number_len; - const u8 *serial_number; - size_t serial_number_len; - - /* DS Parameter Set IE */ - const u8 *ds_params; - - /* SSID IE */ - const u8 *ssid; -}; - - -#define P2P_MAX_GROUP_ENTRIES 50 - -struct p2p_group_info { - unsigned int num_clients; - struct p2p_client_info { - const u8 *p2p_device_addr; - const u8 *p2p_interface_addr; - u8 dev_capab; - u16 config_methods; - const u8 *pri_dev_type; - u8 num_sec_dev_types; - const u8 *sec_dev_types; - const char *dev_name; - size_t dev_name_len; - } client[P2P_MAX_GROUP_ENTRIES]; -}; - - -/* p2p_utils.c */ -int p2p_random(char *buf, size_t len); -int p2p_channel_to_freq(const char *country, int reg_class, int channel); -int p2p_freq_to_channel(const char *country, unsigned int freq, u8 *reg_class, - u8 *channel); -void p2p_channels_intersect(const struct p2p_channels *a, - const struct p2p_channels *b, - struct p2p_channels *res); -int p2p_channels_includes(const struct p2p_channels *channels, u8 reg_class, - u8 channel); - -/* p2p_parse.c */ -int p2p_parse_p2p_ie(const struct wpabuf *buf, struct p2p_message *msg); -int p2p_parse_ies(const u8 *data, size_t len, struct p2p_message *msg); -int p2p_parse(const u8 *data, size_t len, struct p2p_message *msg); -void p2p_parse_free(struct p2p_message *msg); -int p2p_attr_text(struct wpabuf *data, char *buf, char *end); -int p2p_group_info_parse(const u8 *gi, size_t gi_len, - struct p2p_group_info *info); - -/* p2p_build.c */ - -struct p2p_noa_desc { - u8 count_type; - u32 duration; - u32 interval; - u32 start_time; -}; - -/* p2p_group.c */ -const u8 * p2p_group_get_interface_addr(struct p2p_group *group); -u8 p2p_group_presence_req(struct p2p_group *group, - const u8 *client_interface_addr, - const u8 *noa, size_t noa_len); - - -void p2p_buf_add_action_hdr(struct wpabuf *buf, u8 subtype, u8 dialog_token); -void p2p_buf_add_public_action_hdr(struct wpabuf *buf, u8 subtype, - u8 dialog_token); -u8 * p2p_buf_add_ie_hdr(struct wpabuf *buf); -void p2p_buf_add_status(struct wpabuf *buf, u8 status); -void p2p_buf_add_device_info(struct wpabuf *buf, struct p2p_data *p2p, - struct p2p_device *peer); -void p2p_buf_add_device_id(struct wpabuf *buf, const u8 *dev_addr); -void p2p_buf_update_ie_hdr(struct wpabuf *buf, u8 *len); -void p2p_buf_add_capability(struct wpabuf *buf, u8 dev_capab, u8 group_capab); -void p2p_buf_add_go_intent(struct wpabuf *buf, u8 go_intent); -void p2p_buf_add_listen_channel(struct wpabuf *buf, const char *country, - u8 reg_class, u8 channel); -void p2p_buf_add_operating_channel(struct wpabuf *buf, const char *country, - u8 reg_class, u8 channel); -void p2p_buf_add_channel_list(struct wpabuf *buf, const char *country, - struct p2p_channels *chan); -void p2p_buf_add_config_timeout(struct wpabuf *buf, u8 go_timeout, - u8 client_timeout); -void p2p_buf_add_intended_addr(struct wpabuf *buf, const u8 *interface_addr); -void p2p_buf_add_group_bssid(struct wpabuf *buf, const u8 *bssid); -void p2p_buf_add_group_id(struct wpabuf *buf, const u8 *dev_addr, - const u8 *ssid, size_t ssid_len); -void p2p_buf_add_invitation_flags(struct wpabuf *buf, u8 flags); -void p2p_buf_add_noa(struct wpabuf *buf, u8 noa_index, u8 opp_ps, u8 ctwindow, - struct p2p_noa_desc *desc1, struct p2p_noa_desc *desc2); -void p2p_buf_add_ext_listen_timing(struct wpabuf *buf, u16 period, - u16 interval); -void p2p_buf_add_p2p_interface(struct wpabuf *buf, struct p2p_data *p2p); -void p2p_build_wps_ie(struct p2p_data *p2p, struct wpabuf *buf, u16 pw_id, - int all_attr); - -/* p2p_sd.c */ -struct p2p_sd_query * p2p_pending_sd_req(struct p2p_data *p2p, - struct p2p_device *dev); -void p2p_free_sd_queries(struct p2p_data *p2p); -void p2p_rx_gas_initial_req(struct p2p_data *p2p, const u8 *sa, - const u8 *data, size_t len, int rx_freq); -void p2p_rx_gas_initial_resp(struct p2p_data *p2p, const u8 *sa, - const u8 *data, size_t len, int rx_freq); -void p2p_rx_gas_comeback_req(struct p2p_data *p2p, const u8 *sa, - const u8 *data, size_t len, int rx_freq); -void p2p_rx_gas_comeback_resp(struct p2p_data *p2p, const u8 *sa, - const u8 *data, size_t len, int rx_freq); -int p2p_start_sd(struct p2p_data *p2p, struct p2p_device *dev); - -/* p2p_go_neg.c */ -int p2p_peer_channels_check(struct p2p_data *p2p, struct p2p_channels *own, - struct p2p_device *dev, - const u8 *channel_list, size_t channel_list_len); -void p2p_process_go_neg_req(struct p2p_data *p2p, const u8 *sa, - const u8 *data, size_t len, int rx_freq); -void p2p_process_go_neg_resp(struct p2p_data *p2p, const u8 *sa, - const u8 *data, size_t len, int rx_freq); -void p2p_process_go_neg_conf(struct p2p_data *p2p, const u8 *sa, - const u8 *data, size_t len); -int p2p_connect_send(struct p2p_data *p2p, struct p2p_device *dev); - -/* p2p_pd.c */ -void p2p_process_prov_disc_req(struct p2p_data *p2p, const u8 *sa, - const u8 *data, size_t len, int rx_freq); -void p2p_process_prov_disc_resp(struct p2p_data *p2p, const u8 *sa, - const u8 *data, size_t len); -int p2p_send_prov_disc_req(struct p2p_data *p2p, struct p2p_device *dev, - int join); - -/* p2p_invitation.c */ -void p2p_process_invitation_req(struct p2p_data *p2p, const u8 *sa, - const u8 *data, size_t len, int rx_freq); -void p2p_process_invitation_resp(struct p2p_data *p2p, const u8 *sa, - const u8 *data, size_t len); -int p2p_invite_send(struct p2p_data *p2p, struct p2p_device *dev, - const u8 *go_dev_addr); -void p2p_invitation_req_cb(struct p2p_data *p2p, int success); -void p2p_invitation_resp_cb(struct p2p_data *p2p, int success); - -/* p2p_dev_disc.c */ -void p2p_process_dev_disc_req(struct p2p_data *p2p, const u8 *sa, - const u8 *data, size_t len, int rx_freq); -void p2p_dev_disc_req_cb(struct p2p_data *p2p, int success); -int p2p_send_dev_disc_req(struct p2p_data *p2p, struct p2p_device *dev); -void p2p_dev_disc_resp_cb(struct p2p_data *p2p, int success); -void p2p_process_dev_disc_resp(struct p2p_data *p2p, const u8 *sa, - const u8 *data, size_t len); -void p2p_go_disc_req_cb(struct p2p_data *p2p, int success); -void p2p_process_go_disc_req(struct p2p_data *p2p, const u8 *da, const u8 *sa, - const u8 *data, size_t len, int rx_freq); - -/* p2p.c */ -void p2p_set_state(struct p2p_data *p2p, int new_state); -void p2p_set_timeout(struct p2p_data *p2p, unsigned int sec, - unsigned int usec); -void p2p_clear_timeout(struct p2p_data *p2p); -void p2p_continue_find(struct p2p_data *p2p); -struct p2p_device * p2p_add_dev_from_go_neg_req(struct p2p_data *p2p, - const u8 *addr, - struct p2p_message *msg); -void p2p_add_dev_info(struct p2p_data *p2p, const u8 *addr, - struct p2p_device *dev, struct p2p_message *msg); -struct p2p_device * p2p_get_device(struct p2p_data *p2p, const u8 *addr); -struct p2p_device * p2p_get_device_interface(struct p2p_data *p2p, - const u8 *addr); -void p2p_go_neg_failed(struct p2p_data *p2p, struct p2p_device *peer, - int status); -void p2p_go_complete(struct p2p_data *p2p, struct p2p_device *peer); -int p2p_match_dev_type(struct p2p_data *p2p, struct wpabuf *wps); -int dev_type_list_match(const u8 *dev_type, const u8 *req_dev_type[], - size_t num_req_dev_type); -struct wpabuf * p2p_build_probe_resp_ies(struct p2p_data *p2p); -void p2p_build_ssid(struct p2p_data *p2p, u8 *ssid, size_t *ssid_len); -int p2p_send_action(struct p2p_data *p2p, unsigned int freq, const u8 *dst, - const u8 *src, const u8 *bssid, const u8 *buf, - size_t len, unsigned int wait_time); - -#endif /* P2P_I_H */ diff --git a/hostapd-0.8/src/p2p/p2p_invitation.c b/hostapd-0.8/src/p2p/p2p_invitation.c deleted file mode 100644 index bb2767d..0000000 --- a/hostapd-0.8/src/p2p/p2p_invitation.c +++ /dev/null @@ -1,489 +0,0 @@ -/* - * Wi-Fi Direct - P2P Invitation procedure - * Copyright (c) 2010, Atheros Communications - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#include "includes.h" - -#include "common.h" -#include "common/ieee802_11_defs.h" -#include "p2p_i.h" -#include "p2p.h" - - -static struct wpabuf * p2p_build_invitation_req(struct p2p_data *p2p, - struct p2p_device *peer, - const u8 *go_dev_addr) -{ - struct wpabuf *buf; - u8 *len; - const u8 *dev_addr; - - buf = wpabuf_alloc(1000); - if (buf == NULL) - return NULL; - - peer->dialog_token++; - if (peer->dialog_token == 0) - peer->dialog_token = 1; - p2p_buf_add_public_action_hdr(buf, P2P_INVITATION_REQ, - peer->dialog_token); - - len = p2p_buf_add_ie_hdr(buf); - if (p2p->inv_role == P2P_INVITE_ROLE_ACTIVE_GO || !p2p->inv_persistent) - p2p_buf_add_config_timeout(buf, 0, 0); - else - p2p_buf_add_config_timeout(buf, 100, 20); - p2p_buf_add_invitation_flags(buf, p2p->inv_persistent ? - P2P_INVITATION_FLAGS_TYPE : 0); - p2p_buf_add_operating_channel(buf, p2p->cfg->country, - p2p->op_reg_class, p2p->op_channel); - if (p2p->inv_bssid_set) - p2p_buf_add_group_bssid(buf, p2p->inv_bssid); - p2p_buf_add_channel_list(buf, p2p->cfg->country, &p2p->channels); - if (go_dev_addr) - dev_addr = go_dev_addr; - else if (p2p->inv_role == P2P_INVITE_ROLE_CLIENT) - dev_addr = peer->info.p2p_device_addr; - else - dev_addr = p2p->cfg->dev_addr; - p2p_buf_add_group_id(buf, dev_addr, p2p->inv_ssid, p2p->inv_ssid_len); - p2p_buf_add_device_info(buf, p2p, peer); - p2p_buf_update_ie_hdr(buf, len); - - return buf; -} - - -static struct wpabuf * p2p_build_invitation_resp(struct p2p_data *p2p, - struct p2p_device *peer, - u8 dialog_token, u8 status, - const u8 *group_bssid, - u8 reg_class, u8 channel, - struct p2p_channels *channels) -{ - struct wpabuf *buf; - u8 *len; - - buf = wpabuf_alloc(1000); - if (buf == NULL) - return NULL; - - p2p_buf_add_public_action_hdr(buf, P2P_INVITATION_RESP, - dialog_token); - - len = p2p_buf_add_ie_hdr(buf); - p2p_buf_add_status(buf, status); - p2p_buf_add_config_timeout(buf, 0, 0); /* FIX */ - if (reg_class && channel) - p2p_buf_add_operating_channel(buf, p2p->cfg->country, - reg_class, channel); - if (group_bssid) - p2p_buf_add_group_bssid(buf, group_bssid); - if (channels) - p2p_buf_add_channel_list(buf, p2p->cfg->country, channels); - p2p_buf_update_ie_hdr(buf, len); - - return buf; -} - - -void p2p_process_invitation_req(struct p2p_data *p2p, const u8 *sa, - const u8 *data, size_t len, int rx_freq) -{ - struct p2p_device *dev; - struct p2p_message msg; - struct wpabuf *resp = NULL; - u8 status = P2P_SC_FAIL_INFO_CURRENTLY_UNAVAILABLE; - int freq; - int go = 0; - u8 group_bssid[ETH_ALEN], *bssid; - int op_freq = 0; - u8 reg_class = 0, channel = 0; - struct p2p_channels intersection, *channels = NULL; - int persistent; - - os_memset(group_bssid, 0, sizeof(group_bssid)); - - wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, - "P2P: Received Invitation Request from " MACSTR " (freq=%d)", - MAC2STR(sa), rx_freq); - - if (p2p_parse(data, len, &msg)) - return; - - dev = p2p_get_device(p2p, sa); - if (dev == NULL || (dev->flags & P2P_DEV_PROBE_REQ_ONLY)) { - wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, - "P2P: Invitation Request from unknown peer " - MACSTR, MAC2STR(sa)); - - if (p2p_add_device(p2p, sa, rx_freq, 0, data + 1, len - 1)) { - wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, - "P2P: Invitation Request add device failed " - MACSTR, MAC2STR(sa)); - status = P2P_SC_FAIL_INFO_CURRENTLY_UNAVAILABLE; - goto fail; - } - - dev = p2p_get_device(p2p, sa); - if (dev == NULL) { - wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, - "P2P: Reject Invitation Request from unknown " - "peer " MACSTR, MAC2STR(sa)); - status = P2P_SC_FAIL_INFO_CURRENTLY_UNAVAILABLE; - goto fail; - } - } - - if (!msg.group_id || !msg.channel_list) { - wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, - "P2P: Mandatory attribute missing in Invitation " - "Request from " MACSTR, MAC2STR(sa)); - status = P2P_SC_FAIL_INVALID_PARAMS; - goto fail; - } - - if (msg.invitation_flags) - persistent = *msg.invitation_flags & P2P_INVITATION_FLAGS_TYPE; - else { - /* Invitation Flags is a mandatory attribute starting from P2P - * spec 1.06. As a backwards compatibility mechanism, assume - * the request was for a persistent group if the attribute is - * missing. - */ - wpa_printf(MSG_DEBUG, "P2P: Mandatory Invitation Flags " - "attribute missing from Invitation Request"); - persistent = 1; - } - - if (p2p_peer_channels_check(p2p, &p2p->cfg->channels, dev, - msg.channel_list, msg.channel_list_len) < - 0) { - wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, - "P2P: No common channels found"); - status = P2P_SC_FAIL_NO_COMMON_CHANNELS; - goto fail; - } - - if (p2p->cfg->invitation_process) { - status = p2p->cfg->invitation_process( - p2p->cfg->cb_ctx, sa, msg.group_bssid, msg.group_id, - msg.group_id + ETH_ALEN, msg.group_id_len - ETH_ALEN, - &go, group_bssid, &op_freq, persistent); - } - - if (op_freq) { - if (p2p_freq_to_channel(p2p->cfg->country, op_freq, - ®_class, &channel) < 0) { - wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, - "P2P: Unknown forced freq %d MHz from " - "invitation_process()", op_freq); - status = P2P_SC_FAIL_NO_COMMON_CHANNELS; - goto fail; - } - - p2p_channels_intersect(&p2p->cfg->channels, &dev->channels, - &intersection); - if (!p2p_channels_includes(&intersection, reg_class, channel)) - { - wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, - "P2P: forced freq %d MHz not in the supported " - "channels interaction", op_freq); - status = P2P_SC_FAIL_NO_COMMON_CHANNELS; - goto fail; - } - - if (status == P2P_SC_SUCCESS) - channels = &intersection; - } else { - op_freq = p2p_channel_to_freq(p2p->cfg->country, - p2p->cfg->op_reg_class, - p2p->cfg->op_channel); - if (op_freq < 0) { - wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, - "P2P: Unknown operational channel " - "(country=%c%c reg_class=%u channel=%u)", - p2p->cfg->country[0], p2p->cfg->country[1], - p2p->cfg->op_reg_class, p2p->cfg->op_channel); - status = P2P_SC_FAIL_NO_COMMON_CHANNELS; - goto fail; - } - - p2p_channels_intersect(&p2p->cfg->channels, &dev->channels, - &intersection); - if (status == P2P_SC_SUCCESS) { - reg_class = p2p->cfg->op_reg_class; - channel = p2p->cfg->op_channel; - channels = &intersection; - } - } - -fail: - if (go && status == P2P_SC_SUCCESS && !is_zero_ether_addr(group_bssid)) - bssid = group_bssid; - else - bssid = NULL; - resp = p2p_build_invitation_resp(p2p, dev, msg.dialog_token, status, - bssid, reg_class, channel, channels); - - if (resp == NULL) - goto out; - - if (rx_freq > 0) - freq = rx_freq; - else - freq = p2p_channel_to_freq(p2p->cfg->country, - p2p->cfg->reg_class, - p2p->cfg->channel); - if (freq < 0) { - wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, - "P2P: Unknown regulatory class/channel"); - goto out; - } - - /* - * Store copy of invitation data to be used when processing TX status - * callback for the Acton frame. - */ - os_memcpy(p2p->inv_sa, sa, ETH_ALEN); - if (msg.group_bssid) { - os_memcpy(p2p->inv_group_bssid, msg.group_bssid, ETH_ALEN); - p2p->inv_group_bssid_ptr = p2p->inv_group_bssid; - } else - p2p->inv_group_bssid_ptr = NULL; - if (msg.group_id_len - ETH_ALEN <= 32) { - os_memcpy(p2p->inv_ssid, msg.group_id + ETH_ALEN, - msg.group_id_len - ETH_ALEN); - p2p->inv_ssid_len = msg.group_id_len - ETH_ALEN; - } - os_memcpy(p2p->inv_go_dev_addr, msg.group_id, ETH_ALEN); - p2p->inv_status = status; - p2p->inv_op_freq = op_freq; - - p2p->pending_action_state = P2P_PENDING_INVITATION_RESPONSE; - if (p2p_send_action(p2p, freq, sa, p2p->cfg->dev_addr, - p2p->cfg->dev_addr, - wpabuf_head(resp), wpabuf_len(resp), 200) < 0) { - wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, - "P2P: Failed to send Action frame"); - } - -out: - wpabuf_free(resp); - p2p_parse_free(&msg); -} - - -void p2p_process_invitation_resp(struct p2p_data *p2p, const u8 *sa, - const u8 *data, size_t len) -{ - struct p2p_device *dev; - struct p2p_message msg; - - wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, - "P2P: Received Invitation Response from " MACSTR, - MAC2STR(sa)); - - dev = p2p_get_device(p2p, sa); - if (dev == NULL) { - wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, - "P2P: Ignore Invitation Response from unknown peer " - MACSTR, MAC2STR(sa)); - return; - } - - if (dev != p2p->invite_peer) { - wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, - "P2P: Ignore unexpected Invitation Response from peer " - MACSTR, MAC2STR(sa)); - return; - } - - if (p2p_parse(data, len, &msg)) - return; - - if (!msg.status) { - wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, - "P2P: Mandatory Status attribute missing in " - "Invitation Response from " MACSTR, MAC2STR(sa)); - p2p_parse_free(&msg); - return; - } - - if (p2p->cfg->invitation_result) - p2p->cfg->invitation_result(p2p->cfg->cb_ctx, *msg.status, - msg.group_bssid); - - p2p_parse_free(&msg); - - p2p_clear_timeout(p2p); - p2p_set_state(p2p, P2P_IDLE); - p2p->invite_peer = NULL; -} - - -int p2p_invite_send(struct p2p_data *p2p, struct p2p_device *dev, - const u8 *go_dev_addr) -{ - struct wpabuf *req; - int freq; - - freq = dev->listen_freq > 0 ? dev->listen_freq : dev->oper_freq; - if (freq <= 0) { - wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, - "P2P: No Listen/Operating frequency known for the " - "peer " MACSTR " to send Invitation Request", - MAC2STR(dev->info.p2p_device_addr)); - return -1; - } - - req = p2p_build_invitation_req(p2p, dev, go_dev_addr); - if (req == NULL) - return -1; - wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, - "P2P: Sending Invitation Request"); - p2p_set_state(p2p, P2P_INVITE); - p2p->pending_action_state = P2P_PENDING_INVITATION_REQUEST; - p2p->invite_peer = dev; - dev->invitation_reqs++; - if (p2p_send_action(p2p, freq, dev->info.p2p_device_addr, - p2p->cfg->dev_addr, dev->info.p2p_device_addr, - wpabuf_head(req), wpabuf_len(req), 200) < 0) { - wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, - "P2P: Failed to send Action frame"); - /* Use P2P find to recover and retry */ - p2p_set_timeout(p2p, 0, 0); - } - - wpabuf_free(req); - - return 0; -} - - -void p2p_invitation_req_cb(struct p2p_data *p2p, int success) -{ - wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, - "P2P: Invitation Request TX callback: success=%d", success); - - if (p2p->invite_peer == NULL) { - wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, - "P2P: No pending Invite"); - return; - } - - /* - * Use P2P find, if needed, to find the other device from its listen - * channel. - */ - p2p_set_state(p2p, P2P_INVITE); - p2p_set_timeout(p2p, 0, 100000); -} - - -void p2p_invitation_resp_cb(struct p2p_data *p2p, int success) -{ - wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, - "P2P: Invitation Response TX callback: success=%d", success); - p2p->cfg->send_action_done(p2p->cfg->cb_ctx); - - if (success && p2p->cfg->invitation_received) { - p2p->cfg->invitation_received(p2p->cfg->cb_ctx, - p2p->inv_sa, - p2p->inv_group_bssid_ptr, - p2p->inv_ssid, p2p->inv_ssid_len, - p2p->inv_go_dev_addr, - p2p->inv_status, - p2p->inv_op_freq); - } -} - - -int p2p_invite(struct p2p_data *p2p, const u8 *peer, enum p2p_invite_role role, - const u8 *bssid, const u8 *ssid, size_t ssid_len, - unsigned int force_freq, const u8 *go_dev_addr, - int persistent_group) -{ - struct p2p_device *dev; - - wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, - "P2P: Request to invite peer " MACSTR " role=%d persistent=%d " - "force_freq=%u", - MAC2STR(peer), role, persistent_group, force_freq); - if (bssid) - wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, - "P2P: Invitation for BSSID " MACSTR, MAC2STR(bssid)); - if (go_dev_addr) { - wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, - "P2P: Invitation for GO Device Address " MACSTR, - MAC2STR(go_dev_addr)); - os_memcpy(p2p->invite_go_dev_addr_buf, go_dev_addr, ETH_ALEN); - p2p->invite_go_dev_addr = p2p->invite_go_dev_addr_buf; - } else - p2p->invite_go_dev_addr = NULL; - wpa_hexdump_ascii(MSG_DEBUG, "P2P: Invitation for SSID", - ssid, ssid_len); - - dev = p2p_get_device(p2p, peer); - if (dev == NULL || (dev->listen_freq <= 0 && dev->oper_freq <= 0)) { - wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, - "P2P: Cannot invite unknown P2P Device " MACSTR, - MAC2STR(peer)); - return -1; - } - - if (dev->flags & P2P_DEV_GROUP_CLIENT_ONLY) { - if (!(dev->info.dev_capab & - P2P_DEV_CAPAB_CLIENT_DISCOVERABILITY)) { - wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, - "P2P: Cannot invite a P2P Device " MACSTR - " that is in a group and is not discoverable", - MAC2STR(peer)); - } - /* TODO: use device discoverability request through GO */ - } - - dev->invitation_reqs = 0; - - if (force_freq) { - if (p2p_freq_to_channel(p2p->cfg->country, force_freq, - &p2p->op_reg_class, &p2p->op_channel) < - 0) { - wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, - "P2P: Unsupported frequency %u MHz", - force_freq); - return -1; - } - p2p->channels.reg_classes = 1; - p2p->channels.reg_class[0].channels = 1; - p2p->channels.reg_class[0].reg_class = p2p->op_reg_class; - p2p->channels.reg_class[0].channel[0] = p2p->op_channel; - } else { - p2p->op_reg_class = p2p->cfg->op_reg_class; - p2p->op_channel = p2p->cfg->op_channel; - os_memcpy(&p2p->channels, &p2p->cfg->channels, - sizeof(struct p2p_channels)); - } - - if (p2p->state != P2P_IDLE) - p2p_stop_find(p2p); - - p2p->inv_role = role; - p2p->inv_bssid_set = bssid != NULL; - if (bssid) - os_memcpy(p2p->inv_bssid, bssid, ETH_ALEN); - os_memcpy(p2p->inv_ssid, ssid, ssid_len); - p2p->inv_ssid_len = ssid_len; - p2p->inv_persistent = persistent_group; - return p2p_invite_send(p2p, dev, go_dev_addr); -} diff --git a/hostapd-0.8/src/p2p/p2p_parse.c b/hostapd-0.8/src/p2p/p2p_parse.c deleted file mode 100644 index 5c5445a..0000000 --- a/hostapd-0.8/src/p2p/p2p_parse.c +++ /dev/null @@ -1,718 +0,0 @@ -/* - * P2P - IE parser - * Copyright (c) 2009-2010, Atheros Communications - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#include "includes.h" - -#include "common.h" -#include "common/ieee802_11_defs.h" -#include "common/ieee802_11_common.h" -#include "wps/wps_i.h" -#include "p2p_i.h" - - -static int p2p_parse_attribute(u8 id, const u8 *data, u16 len, - struct p2p_message *msg) -{ - const u8 *pos; - size_t i, nlen; - char devtype[WPS_DEV_TYPE_BUFSIZE]; - - switch (id) { - case P2P_ATTR_CAPABILITY: - if (len < 2) { - wpa_printf(MSG_DEBUG, "P2P: Too short Capability " - "attribute (length %d)", len); - return -1; - } - msg->capability = data; - wpa_printf(MSG_DEBUG, "P2P: * Device Capability %02x " - "Group Capability %02x", - data[0], data[1]); - break; - case P2P_ATTR_DEVICE_ID: - if (len < ETH_ALEN) { - wpa_printf(MSG_DEBUG, "P2P: Too short Device ID " - "attribute (length %d)", len); - return -1; - } - msg->device_id = data; - wpa_printf(MSG_DEBUG, "P2P: * Device ID " MACSTR, - MAC2STR(msg->device_id)); - break; - case P2P_ATTR_GROUP_OWNER_INTENT: - if (len < 1) { - wpa_printf(MSG_DEBUG, "P2P: Too short GO Intent " - "attribute (length %d)", len); - return -1; - } - msg->go_intent = data; - wpa_printf(MSG_DEBUG, "P2P: * GO Intent: Intent %u " - "Tie breaker %u", data[0] >> 1, data[0] & 0x01); - break; - case P2P_ATTR_STATUS: - if (len < 1) { - wpa_printf(MSG_DEBUG, "P2P: Too short Status " - "attribute (length %d)", len); - return -1; - } - msg->status = data; - wpa_printf(MSG_DEBUG, "P2P: * Status: %d", data[0]); - break; - case P2P_ATTR_LISTEN_CHANNEL: - if (len == 0) { - wpa_printf(MSG_DEBUG, "P2P: * Listen Channel: Ignore " - "null channel"); - break; - } - if (len < 5) { - wpa_printf(MSG_DEBUG, "P2P: Too short Listen Channel " - "attribute (length %d)", len); - return -1; - } - msg->listen_channel = data; - wpa_printf(MSG_DEBUG, "P2P: * Listen Channel: " - "Country %c%c(0x%02x) Regulatory " - "Class %d Channel Number %d", data[0], data[1], - data[2], data[3], data[4]); - break; - case P2P_ATTR_OPERATING_CHANNEL: - if (len == 0) { - wpa_printf(MSG_DEBUG, "P2P: * Operating Channel: " - "Ignore null channel"); - break; - } - if (len < 5) { - wpa_printf(MSG_DEBUG, "P2P: Too short Operating " - "Channel attribute (length %d)", len); - return -1; - } - msg->operating_channel = data; - wpa_printf(MSG_DEBUG, "P2P: * Operating Channel: " - "Country %c%c(0x%02x) Regulatory " - "Class %d Channel Number %d", data[0], data[1], - data[2], data[3], data[4]); - break; - case P2P_ATTR_CHANNEL_LIST: - if (len < 3) { - wpa_printf(MSG_DEBUG, "P2P: Too short Channel List " - "attribute (length %d)", len); - return -1; - } - msg->channel_list = data; - msg->channel_list_len = len; - wpa_printf(MSG_DEBUG, "P2P: * Channel List: Country String " - "'%c%c(0x%02x)'", data[0], data[1], data[2]); - wpa_hexdump(MSG_MSGDUMP, "P2P: Channel List", - msg->channel_list, msg->channel_list_len); - break; - case P2P_ATTR_GROUP_INFO: - msg->group_info = data; - msg->group_info_len = len; - wpa_printf(MSG_DEBUG, "P2P: * Group Info"); - break; - case P2P_ATTR_DEVICE_INFO: - if (len < ETH_ALEN + 2 + 8 + 1) { - wpa_printf(MSG_DEBUG, "P2P: Too short Device Info " - "attribute (length %d)", len); - return -1; - } - msg->p2p_device_info = data; - msg->p2p_device_info_len = len; - pos = data; - msg->p2p_device_addr = pos; - pos += ETH_ALEN; - msg->config_methods = WPA_GET_BE16(pos); - pos += 2; - msg->pri_dev_type = pos; - pos += 8; - msg->num_sec_dev_types = *pos++; - if (msg->num_sec_dev_types * 8 > data + len - pos) { - wpa_printf(MSG_DEBUG, "P2P: Device Info underflow"); - return -1; - } - pos += msg->num_sec_dev_types * 8; - if (data + len - pos < 4) { - wpa_printf(MSG_DEBUG, "P2P: Invalid Device Name " - "length %d", (int) (data + len - pos)); - return -1; - } - if (WPA_GET_BE16(pos) != ATTR_DEV_NAME) { - wpa_hexdump(MSG_DEBUG, "P2P: Unexpected Device Name " - "header", pos, 4); - return -1; - } - pos += 2; - nlen = WPA_GET_BE16(pos); - pos += 2; - if (data + len - pos < (int) nlen || nlen > 32) { - wpa_printf(MSG_DEBUG, "P2P: Invalid Device Name " - "length %d (buf len %d)", (int) nlen, - (int) (data + len - pos)); - return -1; - } - os_memcpy(msg->device_name, pos, nlen); - msg->device_name[nlen] = '\0'; - for (i = 0; i < nlen; i++) { - if (msg->device_name[i] == '\0') - break; - if (msg->device_name[i] > 0 && - msg->device_name[i] < 32) - msg->device_name[i] = '_'; - } - wpa_printf(MSG_DEBUG, "P2P: * Device Info: addr " MACSTR - " primary device type %s device name '%s' " - "config methods 0x%x", - MAC2STR(msg->p2p_device_addr), - wps_dev_type_bin2str(msg->pri_dev_type, devtype, - sizeof(devtype)), - msg->device_name, msg->config_methods); - break; - case P2P_ATTR_CONFIGURATION_TIMEOUT: - if (len < 2) { - wpa_printf(MSG_DEBUG, "P2P: Too short Configuration " - "Timeout attribute (length %d)", len); - return -1; - } - msg->config_timeout = data; - wpa_printf(MSG_DEBUG, "P2P: * Configuration Timeout"); - break; - case P2P_ATTR_INTENDED_INTERFACE_ADDR: - if (len < ETH_ALEN) { - wpa_printf(MSG_DEBUG, "P2P: Too short Intended P2P " - "Interface Address attribute (length %d)", - len); - return -1; - } - msg->intended_addr = data; - wpa_printf(MSG_DEBUG, "P2P: * Intended P2P Interface Address: " - MACSTR, MAC2STR(msg->intended_addr)); - break; - case P2P_ATTR_GROUP_BSSID: - if (len < ETH_ALEN) { - wpa_printf(MSG_DEBUG, "P2P: Too short P2P Group BSSID " - "attribute (length %d)", len); - return -1; - } - msg->group_bssid = data; - wpa_printf(MSG_DEBUG, "P2P: * P2P Group BSSID: " MACSTR, - MAC2STR(msg->group_bssid)); - break; - case P2P_ATTR_GROUP_ID: - if (len < ETH_ALEN || len > ETH_ALEN + 32) { - wpa_printf(MSG_DEBUG, "P2P: Invalid P2P Group ID " - "attribute length %d", len); - return -1; - } - msg->group_id = data; - msg->group_id_len = len; - wpa_printf(MSG_DEBUG, "P2P: * P2P Group ID: Device Address " - MACSTR, MAC2STR(msg->group_id)); - wpa_hexdump_ascii(MSG_DEBUG, "P2P: * P2P Group ID: SSID", - msg->group_id + ETH_ALEN, - msg->group_id_len - ETH_ALEN); - break; - case P2P_ATTR_INVITATION_FLAGS: - if (len < 1) { - wpa_printf(MSG_DEBUG, "P2P: Too short Invitation " - "Flag attribute (length %d)", len); - return -1; - } - msg->invitation_flags = data; - wpa_printf(MSG_DEBUG, "P2P: * Invitation Flags: bitmap 0x%x", - data[0]); - break; - case P2P_ATTR_MANAGEABILITY: - if (len < 1) { - wpa_printf(MSG_DEBUG, "P2P: Too short Manageability " - "attribute (length %d)", len); - return -1; - } - msg->manageability = data; - wpa_printf(MSG_DEBUG, "P2P: * Manageability: bitmap 0x%x", - data[0]); - break; - case P2P_ATTR_NOTICE_OF_ABSENCE: - if (len < 2) { - wpa_printf(MSG_DEBUG, "P2P: Too short Notice of " - "Absence attribute (length %d)", len); - return -1; - } - msg->noa = data; - msg->noa_len = len; - wpa_printf(MSG_DEBUG, "P2P: * Notice of Absence"); - break; - case P2P_ATTR_EXT_LISTEN_TIMING: - if (len < 4) { - wpa_printf(MSG_DEBUG, "P2P: Too short Extended Listen " - "Timing attribute (length %d)", len); - return -1; - } - msg->ext_listen_timing = data; - wpa_printf(MSG_DEBUG, "P2P: * Extended Listen Timing " - "(period %u msec interval %u msec)", - WPA_GET_LE16(msg->ext_listen_timing), - WPA_GET_LE16(msg->ext_listen_timing + 2)); - break; - case P2P_ATTR_MINOR_REASON_CODE: - if (len < 1) { - wpa_printf(MSG_DEBUG, "P2P: Too short Minor Reason " - "Code attribute (length %d)", len); - return -1; - } - msg->minor_reason_code = data; - wpa_printf(MSG_DEBUG, "P2P: * Minor Reason Code: %u", - *msg->minor_reason_code); - break; - default: - wpa_printf(MSG_DEBUG, "P2P: Skipped unknown attribute %d " - "(length %d)", id, len); - break; - } - - return 0; -} - - -/** - * p2p_parse_p2p_ie - Parse P2P IE - * @buf: Concatenated P2P IE(s) payload - * @msg: Buffer for returning parsed attributes - * Returns: 0 on success, -1 on failure - * - * Note: Caller is responsible for clearing the msg data structure before - * calling this function. - */ -int p2p_parse_p2p_ie(const struct wpabuf *buf, struct p2p_message *msg) -{ - const u8 *pos = wpabuf_head_u8(buf); - const u8 *end = pos + wpabuf_len(buf); - - wpa_printf(MSG_DEBUG, "P2P: Parsing P2P IE"); - - while (pos < end) { - u16 attr_len; - if (pos + 2 >= end) { - wpa_printf(MSG_DEBUG, "P2P: Invalid P2P attribute"); - return -1; - } - attr_len = WPA_GET_LE16(pos + 1); - wpa_printf(MSG_DEBUG, "P2P: Attribute %d length %u", - pos[0], attr_len); - if (pos + 3 + attr_len > end) { - wpa_printf(MSG_DEBUG, "P2P: Attribute underflow " - "(len=%u left=%d)", - attr_len, (int) (end - pos - 3)); - wpa_hexdump(MSG_MSGDUMP, "P2P: Data", pos, end - pos); - return -1; - } - if (p2p_parse_attribute(pos[0], pos + 3, attr_len, msg)) - return -1; - pos += 3 + attr_len; - } - - return 0; -} - - -static int p2p_parse_wps_ie(const struct wpabuf *buf, struct p2p_message *msg) -{ - struct wps_parse_attr attr; - int i; - - wpa_printf(MSG_DEBUG, "P2P: Parsing WPS IE"); - if (wps_parse_msg(buf, &attr)) - return -1; - if (attr.dev_name && attr.dev_name_len < sizeof(msg->device_name) && - !msg->device_name[0]) - os_memcpy(msg->device_name, attr.dev_name, attr.dev_name_len); - if (attr.config_methods) { - msg->wps_config_methods = - WPA_GET_BE16(attr.config_methods); - wpa_printf(MSG_DEBUG, "P2P: Config Methods (WPS): 0x%x", - msg->wps_config_methods); - } - if (attr.dev_password_id) { - msg->dev_password_id = WPA_GET_BE16(attr.dev_password_id); - wpa_printf(MSG_DEBUG, "P2P: Device Password ID: %d", - msg->dev_password_id); - } - if (attr.primary_dev_type) { - char devtype[WPS_DEV_TYPE_BUFSIZE]; - msg->wps_pri_dev_type = attr.primary_dev_type; - wpa_printf(MSG_DEBUG, "P2P: Primary Device Type (WPS): %s", - wps_dev_type_bin2str(msg->wps_pri_dev_type, devtype, - sizeof(devtype))); - } - if (attr.sec_dev_type_list) { - msg->wps_sec_dev_type_list = attr.sec_dev_type_list; - msg->wps_sec_dev_type_list_len = attr.sec_dev_type_list_len; - } - - for (i = 0; i < P2P_MAX_WPS_VENDOR_EXT; i++) { - msg->wps_vendor_ext[i] = attr.vendor_ext[i]; - msg->wps_vendor_ext_len[i] = attr.vendor_ext_len[i]; - } - - msg->manufacturer = attr.manufacturer; - msg->manufacturer_len = attr.manufacturer_len; - msg->model_name = attr.model_name; - msg->model_name_len = attr.model_name_len; - msg->model_number = attr.model_number; - msg->model_number_len = attr.model_number_len; - msg->serial_number = attr.serial_number; - msg->serial_number_len = attr.serial_number_len; - - return 0; -} - - -/** - * p2p_parse_ies - Parse P2P message IEs (both WPS and P2P IE) - * @data: IEs from the message - * @len: Length of data buffer in octets - * @msg: Buffer for returning parsed attributes - * Returns: 0 on success, -1 on failure - * - * Note: Caller is responsible for clearing the msg data structure before - * calling this function. - * - * Note: Caller must free temporary memory allocations by calling - * p2p_parse_free() when the parsed data is not needed anymore. - */ -int p2p_parse_ies(const u8 *data, size_t len, struct p2p_message *msg) -{ - struct ieee802_11_elems elems; - - ieee802_11_parse_elems(data, len, &elems, 0); - if (elems.ds_params && elems.ds_params_len >= 1) - msg->ds_params = elems.ds_params; - if (elems.ssid) - msg->ssid = elems.ssid - 2; - - msg->wps_attributes = ieee802_11_vendor_ie_concat(data, len, - WPS_DEV_OUI_WFA); - if (msg->wps_attributes && - p2p_parse_wps_ie(msg->wps_attributes, msg)) { - p2p_parse_free(msg); - return -1; - } - - msg->p2p_attributes = ieee802_11_vendor_ie_concat(data, len, - P2P_IE_VENDOR_TYPE); - if (msg->p2p_attributes && - p2p_parse_p2p_ie(msg->p2p_attributes, msg)) { - wpa_printf(MSG_DEBUG, "P2P: Failed to parse P2P IE data"); - if (msg->p2p_attributes) - wpa_hexdump_buf(MSG_MSGDUMP, "P2P: P2P IE data", - msg->p2p_attributes); - p2p_parse_free(msg); - return -1; - } - - return 0; -} - - -/** - * p2p_parse - Parse a P2P Action frame contents - * @data: Action frame payload after Category and Code fields - * @len: Length of data buffer in octets - * @msg: Buffer for returning parsed attributes - * Returns: 0 on success, -1 on failure - * - * Note: Caller must free temporary memory allocations by calling - * p2p_parse_free() when the parsed data is not needed anymore. - */ -int p2p_parse(const u8 *data, size_t len, struct p2p_message *msg) -{ - os_memset(msg, 0, sizeof(*msg)); - wpa_printf(MSG_DEBUG, "P2P: Parsing the received message"); - if (len < 1) { - wpa_printf(MSG_DEBUG, "P2P: No Dialog Token in the message"); - return -1; - } - msg->dialog_token = data[0]; - wpa_printf(MSG_DEBUG, "P2P: * Dialog Token: %d", msg->dialog_token); - - return p2p_parse_ies(data + 1, len - 1, msg); -} - - -/** - * p2p_parse_free - Free temporary data from P2P parsing - * @msg: Parsed attributes - */ -void p2p_parse_free(struct p2p_message *msg) -{ - wpabuf_free(msg->p2p_attributes); - msg->p2p_attributes = NULL; - wpabuf_free(msg->wps_attributes); - msg->wps_attributes = NULL; -} - - -int p2p_group_info_parse(const u8 *gi, size_t gi_len, - struct p2p_group_info *info) -{ - const u8 *g, *gend; - - os_memset(info, 0, sizeof(*info)); - if (gi == NULL) - return 0; - - g = gi; - gend = gi + gi_len; - while (g < gend) { - struct p2p_client_info *cli; - const u8 *t, *cend; - int count; - - cli = &info->client[info->num_clients]; - cend = g + 1 + g[0]; - if (cend > gend) - return -1; /* invalid data */ - /* g at start of P2P Client Info Descriptor */ - /* t at Device Capability Bitmap */ - t = g + 1 + 2 * ETH_ALEN; - if (t > cend) - return -1; /* invalid data */ - cli->p2p_device_addr = g + 1; - cli->p2p_interface_addr = g + 1 + ETH_ALEN; - cli->dev_capab = t[0]; - - if (t + 1 + 2 + 8 + 1 > cend) - return -1; /* invalid data */ - - cli->config_methods = WPA_GET_BE16(&t[1]); - cli->pri_dev_type = &t[3]; - - t += 1 + 2 + 8; - /* t at Number of Secondary Device Types */ - cli->num_sec_dev_types = *t++; - if (t + 8 * cli->num_sec_dev_types > cend) - return -1; /* invalid data */ - cli->sec_dev_types = t; - t += 8 * cli->num_sec_dev_types; - - /* t at Device Name in WPS TLV format */ - if (t + 2 + 2 > cend) - return -1; /* invalid data */ - if (WPA_GET_BE16(t) != ATTR_DEV_NAME) - return -1; /* invalid Device Name TLV */ - t += 2; - count = WPA_GET_BE16(t); - t += 2; - if (count > cend - t) - return -1; /* invalid Device Name TLV */ - if (count >= 32) - count = 32; - cli->dev_name = (const char *) t; - cli->dev_name_len = count; - - g = cend; - - info->num_clients++; - if (info->num_clients == P2P_MAX_GROUP_ENTRIES) - return -1; - } - - return 0; -} - - -static int p2p_group_info_text(const u8 *gi, size_t gi_len, char *buf, - char *end) -{ - char *pos = buf; - int ret; - struct p2p_group_info info; - unsigned int i; - - if (p2p_group_info_parse(gi, gi_len, &info) < 0) - return 0; - - for (i = 0; i < info.num_clients; i++) { - struct p2p_client_info *cli; - char name[33]; - char devtype[WPS_DEV_TYPE_BUFSIZE]; - u8 s; - int count; - - cli = &info.client[i]; - ret = os_snprintf(pos, end - pos, "p2p_group_client: " - "dev=" MACSTR " iface=" MACSTR, - MAC2STR(cli->p2p_device_addr), - MAC2STR(cli->p2p_interface_addr)); - if (ret < 0 || ret >= end - pos) - return pos - buf; - pos += ret; - - ret = os_snprintf(pos, end - pos, - " dev_capab=0x%x config_methods=0x%x " - "dev_type=%s", - cli->dev_capab, cli->config_methods, - wps_dev_type_bin2str(cli->pri_dev_type, - devtype, - sizeof(devtype))); - if (ret < 0 || ret >= end - pos) - return pos - buf; - pos += ret; - - for (s = 0; s < cli->num_sec_dev_types; s++) { - ret = os_snprintf(pos, end - pos, " dev_type=%s", - wps_dev_type_bin2str( - &cli->sec_dev_types[s * 8], - devtype, sizeof(devtype))); - if (ret < 0 || ret >= end - pos) - return pos - buf; - pos += ret; - } - - os_memcpy(name, cli->dev_name, cli->dev_name_len); - name[cli->dev_name_len] = '\0'; - count = (int) cli->dev_name_len - 1; - while (count >= 0) { - if (name[count] > 0 && name[count] < 32) - name[count] = '_'; - count--; - } - - ret = os_snprintf(pos, end - pos, " dev_name='%s'\n", name); - if (ret < 0 || ret >= end - pos) - return pos - buf; - pos += ret; - } - - return pos - buf; -} - - -/** - * p2p_attr_text - Build text format description of P2P IE attributes - * @data: P2P IE contents - * @buf: Buffer for returning text - * @end: Pointer to the end of the buf area - * Returns: Number of octets written to the buffer or -1 on faikure - * - * This function can be used to parse P2P IE contents into text format - * field=value lines. - */ -int p2p_attr_text(struct wpabuf *data, char *buf, char *end) -{ - struct p2p_message msg; - char *pos = buf; - int ret; - - os_memset(&msg, 0, sizeof(msg)); - if (p2p_parse_p2p_ie(data, &msg)) - return -1; - - if (msg.capability) { - ret = os_snprintf(pos, end - pos, - "p2p_dev_capab=0x%x\n" - "p2p_group_capab=0x%x\n", - msg.capability[0], msg.capability[1]); - if (ret < 0 || ret >= end - pos) - return pos - buf; - pos += ret; - } - - if (msg.pri_dev_type) { - char devtype[WPS_DEV_TYPE_BUFSIZE]; - ret = os_snprintf(pos, end - pos, - "p2p_primary_device_type=%s\n", - wps_dev_type_bin2str(msg.pri_dev_type, - devtype, - sizeof(devtype))); - if (ret < 0 || ret >= end - pos) - return pos - buf; - pos += ret; - } - - ret = os_snprintf(pos, end - pos, "p2p_device_name=%s\n", - msg.device_name); - if (ret < 0 || ret >= end - pos) - return pos - buf; - pos += ret; - - if (msg.p2p_device_addr) { - ret = os_snprintf(pos, end - pos, "p2p_device_addr=" MACSTR - "\n", - MAC2STR(msg.p2p_device_addr)); - if (ret < 0 || ret >= end - pos) - return pos - buf; - pos += ret; - } - - ret = os_snprintf(pos, end - pos, "p2p_config_methods=0x%x\n", - msg.config_methods); - if (ret < 0 || ret >= end - pos) - return pos - buf; - pos += ret; - - ret = p2p_group_info_text(msg.group_info, msg.group_info_len, - pos, end); - if (ret < 0) - return pos - buf; - pos += ret; - - return pos - buf; -} - - -int p2p_get_cross_connect_disallowed(const struct wpabuf *p2p_ie) -{ - struct p2p_message msg; - - os_memset(&msg, 0, sizeof(msg)); - if (p2p_parse_p2p_ie(p2p_ie, &msg)) - return 0; - - if (!msg.manageability) - return 0; - - return !(msg.manageability[0] & P2P_MAN_CROSS_CONNECTION_PERMITTED); -} - - -u8 p2p_get_group_capab(const struct wpabuf *p2p_ie) -{ - struct p2p_message msg; - - os_memset(&msg, 0, sizeof(msg)); - if (p2p_parse_p2p_ie(p2p_ie, &msg)) - return 0; - - if (!msg.capability) - return 0; - - return msg.capability[1]; -} - - -const u8 * p2p_get_go_dev_addr(const struct wpabuf *p2p_ie) -{ - struct p2p_message msg; - - os_memset(&msg, 0, sizeof(msg)); - if (p2p_parse_p2p_ie(p2p_ie, &msg)) - return NULL; - - if (msg.p2p_device_addr) - return msg.p2p_device_addr; - if (msg.device_id) - return msg.device_id; - - return NULL; -} diff --git a/hostapd-0.8/src/p2p/p2p_pd.c b/hostapd-0.8/src/p2p/p2p_pd.c deleted file mode 100644 index e064216..0000000 --- a/hostapd-0.8/src/p2p/p2p_pd.c +++ /dev/null @@ -1,347 +0,0 @@ -/* - * Wi-Fi Direct - P2P provision discovery - * Copyright (c) 2009-2010, Atheros Communications - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#include "includes.h" - -#include "common.h" -#include "common/ieee802_11_defs.h" -#include "wps/wps_defs.h" -#include "p2p_i.h" -#include "p2p.h" - - -static void p2p_build_wps_ie_config_methods(struct wpabuf *buf, - u16 config_methods) -{ - u8 *len; - wpabuf_put_u8(buf, WLAN_EID_VENDOR_SPECIFIC); - len = wpabuf_put(buf, 1); - wpabuf_put_be32(buf, WPS_DEV_OUI_WFA); - - /* Config Methods */ - wpabuf_put_be16(buf, ATTR_CONFIG_METHODS); - wpabuf_put_be16(buf, 2); - wpabuf_put_be16(buf, config_methods); - - p2p_buf_update_ie_hdr(buf, len); -} - - -static struct wpabuf * p2p_build_prov_disc_req(struct p2p_data *p2p, - u8 dialog_token, - u16 config_methods, - struct p2p_device *go) -{ - struct wpabuf *buf; - u8 *len; - - buf = wpabuf_alloc(1000); - if (buf == NULL) - return NULL; - - p2p_buf_add_public_action_hdr(buf, P2P_PROV_DISC_REQ, dialog_token); - - len = p2p_buf_add_ie_hdr(buf); - p2p_buf_add_capability(buf, p2p->dev_capab, 0); - p2p_buf_add_device_info(buf, p2p, NULL); - if (go) { - p2p_buf_add_group_id(buf, go->info.p2p_device_addr, - go->oper_ssid, go->oper_ssid_len); - } - p2p_buf_update_ie_hdr(buf, len); - - /* WPS IE with Config Methods attribute */ - p2p_build_wps_ie_config_methods(buf, config_methods); - - return buf; -} - - -static struct wpabuf * p2p_build_prov_disc_resp(struct p2p_data *p2p, - u8 dialog_token, - u16 config_methods) -{ - struct wpabuf *buf; - - buf = wpabuf_alloc(100); - if (buf == NULL) - return NULL; - - p2p_buf_add_public_action_hdr(buf, P2P_PROV_DISC_RESP, dialog_token); - - /* WPS IE with Config Methods attribute */ - p2p_build_wps_ie_config_methods(buf, config_methods); - - return buf; -} - - -void p2p_process_prov_disc_req(struct p2p_data *p2p, const u8 *sa, - const u8 *data, size_t len, int rx_freq) -{ - struct p2p_message msg; - struct p2p_device *dev; - int freq; - int reject = 1; - struct wpabuf *resp; - - if (p2p_parse(data, len, &msg)) - return; - - wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, - "P2P: Received Provision Discovery Request from " MACSTR - " with config methods 0x%x (freq=%d)", - MAC2STR(sa), msg.wps_config_methods, rx_freq); - - dev = p2p_get_device(p2p, sa); - if (dev == NULL || !(dev->flags & P2P_DEV_PROBE_REQ_ONLY)) { - wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, - "P2P: Provision Discovery Request from " - "unknown peer " MACSTR, MAC2STR(sa)); - if (p2p_add_device(p2p, sa, rx_freq, 0, data + 1, len - 1)) { - wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, - "P2P: Provision Discovery Request add device " - "failed " MACSTR, MAC2STR(sa)); - } - } - - if (!(msg.wps_config_methods & - (WPS_CONFIG_DISPLAY | WPS_CONFIG_KEYPAD | - WPS_CONFIG_PUSHBUTTON))) { - wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Unsupported " - "Config Methods in Provision Discovery Request"); - goto out; - } - - if (dev) - dev->flags &= ~(P2P_DEV_PD_PEER_DISPLAY | - P2P_DEV_PD_PEER_KEYPAD); - if (msg.wps_config_methods & WPS_CONFIG_DISPLAY) { - wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Peer " MACSTR - " requested us to show a PIN on display", MAC2STR(sa)); - if (dev) - dev->flags |= P2P_DEV_PD_PEER_KEYPAD; - } else if (msg.wps_config_methods & WPS_CONFIG_KEYPAD) { - wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Peer " MACSTR - " requested us to write its PIN using keypad", - MAC2STR(sa)); - if (dev) - dev->flags |= P2P_DEV_PD_PEER_DISPLAY; - } - - reject = 0; - -out: - resp = p2p_build_prov_disc_resp(p2p, msg.dialog_token, - reject ? 0 : msg.wps_config_methods); - if (resp == NULL) { - p2p_parse_free(&msg); - return; - } - wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, - "P2P: Sending Provision Discovery Response"); - if (rx_freq > 0) - freq = rx_freq; - else - freq = p2p_channel_to_freq(p2p->cfg->country, - p2p->cfg->reg_class, - p2p->cfg->channel); - if (freq < 0) { - wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, - "P2P: Unknown regulatory class/channel"); - wpabuf_free(resp); - p2p_parse_free(&msg); - return; - } - p2p->pending_action_state = P2P_NO_PENDING_ACTION; - if (p2p_send_action(p2p, freq, sa, p2p->cfg->dev_addr, - p2p->cfg->dev_addr, - wpabuf_head(resp), wpabuf_len(resp), 200) < 0) { - wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, - "P2P: Failed to send Action frame"); - } - - wpabuf_free(resp); - - if (!reject && p2p->cfg->prov_disc_req) { - const u8 *dev_addr = sa; - if (msg.p2p_device_addr) - dev_addr = msg.p2p_device_addr; - p2p->cfg->prov_disc_req(p2p->cfg->cb_ctx, sa, - msg.wps_config_methods, - dev_addr, msg.pri_dev_type, - msg.device_name, msg.config_methods, - msg.capability ? msg.capability[0] : 0, - msg.capability ? msg.capability[1] : - 0); - - } - p2p_parse_free(&msg); -} - - -void p2p_process_prov_disc_resp(struct p2p_data *p2p, const u8 *sa, - const u8 *data, size_t len) -{ - struct p2p_message msg; - struct p2p_device *dev; - u16 report_config_methods = 0; - - if (p2p_parse(data, len, &msg)) - return; - - wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, - "P2P: Received Provisioning Discovery Response from " MACSTR - " with config methods 0x%x", - MAC2STR(sa), msg.wps_config_methods); - - dev = p2p_get_device(p2p, sa); - if (dev == NULL || !dev->req_config_methods) { - wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, - "P2P: Ignore Provisioning Discovery Response from " - MACSTR " with no pending request", MAC2STR(sa)); - p2p_parse_free(&msg); - return; - } - - if (dev->dialog_token != msg.dialog_token) { - wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, - "P2P: Ignore Provisioning Discovery Response with " - "unexpected Dialog Token %u (expected %u)", - msg.dialog_token, dev->dialog_token); - p2p_parse_free(&msg); - return; - } - - if (msg.wps_config_methods != dev->req_config_methods) { - wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Peer rejected " - "our Provisioning Discovery Request"); - p2p_parse_free(&msg); - goto out; - } - - report_config_methods = dev->req_config_methods; - dev->flags &= ~(P2P_DEV_PD_PEER_DISPLAY | - P2P_DEV_PD_PEER_KEYPAD); - if (dev->req_config_methods & WPS_CONFIG_DISPLAY) { - wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Peer " MACSTR - " accepted to show a PIN on display", MAC2STR(sa)); - dev->flags |= P2P_DEV_PD_PEER_DISPLAY; - } else if (msg.wps_config_methods & WPS_CONFIG_KEYPAD) { - wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Peer " MACSTR - " accepted to write our PIN using keypad", - MAC2STR(sa)); - dev->flags |= P2P_DEV_PD_PEER_KEYPAD; - } - p2p_parse_free(&msg); - -out: - dev->req_config_methods = 0; - p2p->cfg->send_action_done(p2p->cfg->cb_ctx); - if (p2p->cfg->prov_disc_resp) - p2p->cfg->prov_disc_resp(p2p->cfg->cb_ctx, sa, - report_config_methods); -} - - -int p2p_send_prov_disc_req(struct p2p_data *p2p, struct p2p_device *dev, - int join) -{ - struct wpabuf *req; - int freq; - - freq = dev->listen_freq > 0 ? dev->listen_freq : dev->oper_freq; - if (freq <= 0) { - wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, - "P2P: No Listen/Operating frequency known for the " - "peer " MACSTR " to send Provision Discovery Request", - MAC2STR(dev->info.p2p_device_addr)); - return -1; - } - - if (dev->flags & P2P_DEV_GROUP_CLIENT_ONLY) { - if (!(dev->info.dev_capab & - P2P_DEV_CAPAB_CLIENT_DISCOVERABILITY)) { - wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, - "P2P: Cannot use PD with P2P Device " MACSTR - " that is in a group and is not discoverable", - MAC2STR(dev->info.p2p_device_addr)); - return -1; - } - /* TODO: use device discoverability request through GO */ - } - - dev->dialog_token++; - if (dev->dialog_token == 0) - dev->dialog_token = 1; - req = p2p_build_prov_disc_req(p2p, dev->dialog_token, - dev->req_config_methods, - join ? dev : NULL); - if (req == NULL) - return -1; - - p2p->pending_action_state = P2P_PENDING_PD; - if (p2p_send_action(p2p, freq, dev->info.p2p_device_addr, - p2p->cfg->dev_addr, dev->info.p2p_device_addr, - wpabuf_head(req), wpabuf_len(req), 200) < 0) { - wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, - "P2P: Failed to send Action frame"); - wpabuf_free(req); - return -1; - } - - wpabuf_free(req); - return 0; -} - - -int p2p_prov_disc_req(struct p2p_data *p2p, const u8 *peer_addr, - u16 config_methods, int join) -{ - struct p2p_device *dev; - - dev = p2p_get_device(p2p, peer_addr); - if (dev == NULL) - dev = p2p_get_device_interface(p2p, peer_addr); - if (dev == NULL || (dev->flags & P2P_DEV_PROBE_REQ_ONLY)) { - wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Provision " - "Discovery Request destination " MACSTR - " not yet known", MAC2STR(peer_addr)); - return -1; - } - - wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Provision Discovery " - "Request with " MACSTR " (config methods 0x%x)", - MAC2STR(peer_addr), config_methods); - if (config_methods == 0) - return -1; - - dev->req_config_methods = config_methods; - if (join) - dev->flags |= P2P_DEV_PD_FOR_JOIN; - else - dev->flags &= ~P2P_DEV_PD_FOR_JOIN; - - if (p2p->go_neg_peer || - (p2p->state != P2P_IDLE && p2p->state != P2P_SEARCH && - p2p->state != P2P_LISTEN_ONLY)) { - wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Busy with other " - "operations; postpone Provision Discovery Request " - "with " MACSTR " (config methods 0x%x)", - MAC2STR(peer_addr), config_methods); - return 0; - } - - return p2p_send_prov_disc_req(p2p, dev, join); -} diff --git a/hostapd-0.8/src/p2p/p2p_sd.c b/hostapd-0.8/src/p2p/p2p_sd.c deleted file mode 100644 index 926fc03..0000000 --- a/hostapd-0.8/src/p2p/p2p_sd.c +++ /dev/null @@ -1,951 +0,0 @@ -/* - * Wi-Fi Direct - P2P service discovery - * Copyright (c) 2009, Atheros Communications - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#include "includes.h" - -#include "common.h" -#include "common/ieee802_11_defs.h" -#include "p2p_i.h" -#include "p2p.h" - - -struct p2p_sd_query * p2p_pending_sd_req(struct p2p_data *p2p, - struct p2p_device *dev) -{ - struct p2p_sd_query *q; - - if (!(dev->info.dev_capab & P2P_DEV_CAPAB_SERVICE_DISCOVERY)) - return 0; /* peer does not support SD */ - - for (q = p2p->sd_queries; q; q = q->next) { - if (q->for_all_peers && !(dev->flags & P2P_DEV_SD_INFO)) - return q; - if (!q->for_all_peers && - os_memcmp(q->peer, dev->info.p2p_device_addr, ETH_ALEN) == - 0) - return q; - } - - return NULL; -} - - -static int p2p_unlink_sd_query(struct p2p_data *p2p, - struct p2p_sd_query *query) -{ - struct p2p_sd_query *q, *prev; - q = p2p->sd_queries; - prev = NULL; - while (q) { - if (q == query) { - if (prev) - prev->next = q->next; - else - p2p->sd_queries = q->next; - if (p2p->sd_query == query) - p2p->sd_query = NULL; - return 1; - } - prev = q; - q = q->next; - } - return 0; -} - - -static void p2p_free_sd_query(struct p2p_sd_query *q) -{ - if (q == NULL) - return; - wpabuf_free(q->tlvs); - os_free(q); -} - - -void p2p_free_sd_queries(struct p2p_data *p2p) -{ - struct p2p_sd_query *q, *prev; - q = p2p->sd_queries; - p2p->sd_queries = NULL; - while (q) { - prev = q; - q = q->next; - p2p_free_sd_query(prev); - } -} - - -static struct wpabuf * p2p_build_sd_query(u16 update_indic, - struct wpabuf *tlvs) -{ - struct wpabuf *buf; - u8 *len_pos, *len_pos2; - - buf = wpabuf_alloc(1000 + wpabuf_len(tlvs)); - if (buf == NULL) - return NULL; - - wpabuf_put_u8(buf, WLAN_ACTION_PUBLIC); - wpabuf_put_u8(buf, WLAN_PA_GAS_INITIAL_REQ); - wpabuf_put_u8(buf, 0); /* Dialog Token */ - - /* Advertisement Protocol IE */ - wpabuf_put_u8(buf, WLAN_EID_ADV_PROTO); - wpabuf_put_u8(buf, 2); /* Length */ - wpabuf_put_u8(buf, 0); /* QueryRespLenLimit | PAME-BI */ - wpabuf_put_u8(buf, NATIVE_QUERY_PROTOCOL); /* Advertisement Protocol */ - - /* Query Request */ - len_pos = wpabuf_put(buf, 2); /* Length (to be filled) */ - - /* NQP Query Request Frame */ - wpabuf_put_le16(buf, NQP_VENDOR_SPECIFIC); /* Info ID */ - len_pos2 = wpabuf_put(buf, 2); /* Length (to be filled) */ - wpabuf_put_be24(buf, OUI_WFA); - wpabuf_put_u8(buf, P2P_OUI_TYPE); - wpabuf_put_le16(buf, update_indic); /* Service Update Indicator */ - wpabuf_put_buf(buf, tlvs); - - WPA_PUT_LE16(len_pos2, (u8 *) wpabuf_put(buf, 0) - len_pos2 - 2); - WPA_PUT_LE16(len_pos, (u8 *) wpabuf_put(buf, 0) - len_pos - 2); - - return buf; -} - - -static struct wpabuf * p2p_build_gas_comeback_req(u8 dialog_token) -{ - struct wpabuf *buf; - - buf = wpabuf_alloc(3); - if (buf == NULL) - return NULL; - - wpabuf_put_u8(buf, WLAN_ACTION_PUBLIC); - wpabuf_put_u8(buf, WLAN_PA_GAS_COMEBACK_REQ); - wpabuf_put_u8(buf, dialog_token); - - return buf; -} - - -static void p2p_send_gas_comeback_req(struct p2p_data *p2p, const u8 *dst, - u8 dialog_token, int freq) -{ - struct wpabuf *req; - - req = p2p_build_gas_comeback_req(dialog_token); - if (req == NULL) - return; - - p2p->pending_action_state = P2P_NO_PENDING_ACTION; - if (p2p_send_action(p2p, freq, dst, p2p->cfg->dev_addr, dst, - wpabuf_head(req), wpabuf_len(req), 200) < 0) - wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, - "P2P: Failed to send Action frame"); - - wpabuf_free(req); -} - - -static struct wpabuf * p2p_build_sd_response(u8 dialog_token, u16 status_code, - u16 comeback_delay, - u16 update_indic, - const struct wpabuf *tlvs) -{ - struct wpabuf *buf; - u8 *len_pos, *len_pos2; - - buf = wpabuf_alloc(1000 + (tlvs ? wpabuf_len(tlvs) : 0)); - if (buf == NULL) - return NULL; - - wpabuf_put_u8(buf, WLAN_ACTION_PUBLIC); - wpabuf_put_u8(buf, WLAN_PA_GAS_INITIAL_RESP); - wpabuf_put_u8(buf, dialog_token); - wpabuf_put_le16(buf, status_code); - wpabuf_put_le16(buf, comeback_delay); - - /* Advertisement Protocol IE */ - wpabuf_put_u8(buf, WLAN_EID_ADV_PROTO); - wpabuf_put_u8(buf, 2); /* Length */ - wpabuf_put_u8(buf, 0x7f); /* QueryRespLenLimit | PAME-BI */ - wpabuf_put_u8(buf, NATIVE_QUERY_PROTOCOL); /* Advertisement Protocol */ - - /* Query Response */ - len_pos = wpabuf_put(buf, 2); /* Length (to be filled) */ - - if (tlvs) { - /* NQP Query Response Frame */ - wpabuf_put_le16(buf, NQP_VENDOR_SPECIFIC); /* Info ID */ - len_pos2 = wpabuf_put(buf, 2); /* Length (to be filled) */ - wpabuf_put_be24(buf, OUI_WFA); - wpabuf_put_u8(buf, P2P_OUI_TYPE); - /* Service Update Indicator */ - wpabuf_put_le16(buf, update_indic); - wpabuf_put_buf(buf, tlvs); - - WPA_PUT_LE16(len_pos2, - (u8 *) wpabuf_put(buf, 0) - len_pos2 - 2); - } - - WPA_PUT_LE16(len_pos, (u8 *) wpabuf_put(buf, 0) - len_pos - 2); - - return buf; -} - - -static struct wpabuf * p2p_build_gas_comeback_resp(u8 dialog_token, - u16 status_code, - u16 update_indic, - const u8 *data, size_t len, - u8 frag_id, u8 more, - u16 total_len) -{ - struct wpabuf *buf; - u8 *len_pos; - - buf = wpabuf_alloc(1000 + len); - if (buf == NULL) - return NULL; - - wpabuf_put_u8(buf, WLAN_ACTION_PUBLIC); - wpabuf_put_u8(buf, WLAN_PA_GAS_COMEBACK_RESP); - wpabuf_put_u8(buf, dialog_token); - wpabuf_put_le16(buf, status_code); - wpabuf_put_u8(buf, frag_id | (more ? 0x80 : 0)); - wpabuf_put_le16(buf, 0); /* Comeback Delay */ - - /* Advertisement Protocol IE */ - wpabuf_put_u8(buf, WLAN_EID_ADV_PROTO); - wpabuf_put_u8(buf, 2); /* Length */ - wpabuf_put_u8(buf, 0x7f); /* QueryRespLenLimit | PAME-BI */ - wpabuf_put_u8(buf, NATIVE_QUERY_PROTOCOL); /* Advertisement Protocol */ - - /* Query Response */ - len_pos = wpabuf_put(buf, 2); /* Length (to be filled) */ - - if (frag_id == 0) { - /* NQP Query Response Frame */ - wpabuf_put_le16(buf, NQP_VENDOR_SPECIFIC); /* Info ID */ - wpabuf_put_le16(buf, 3 + 1 + 2 + total_len); - wpabuf_put_be24(buf, OUI_WFA); - wpabuf_put_u8(buf, P2P_OUI_TYPE); - /* Service Update Indicator */ - wpabuf_put_le16(buf, update_indic); - } - - wpabuf_put_data(buf, data, len); - - WPA_PUT_LE16(len_pos, (u8 *) wpabuf_put(buf, 0) - len_pos - 2); - - return buf; -} - - -int p2p_start_sd(struct p2p_data *p2p, struct p2p_device *dev) -{ - struct wpabuf *req; - int ret = 0; - struct p2p_sd_query *query; - int freq; - - freq = dev->listen_freq > 0 ? dev->listen_freq : dev->oper_freq; - if (freq <= 0) { - wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, - "P2P: No Listen/Operating frequency known for the " - "peer " MACSTR " to send SD Request", - MAC2STR(dev->info.p2p_device_addr)); - return -1; - } - - query = p2p_pending_sd_req(p2p, dev); - if (query == NULL) - return -1; - - wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, - "P2P: Start Service Discovery with " MACSTR, - MAC2STR(dev->info.p2p_device_addr)); - - req = p2p_build_sd_query(p2p->srv_update_indic, query->tlvs); - if (req == NULL) - return -1; - - p2p->sd_peer = dev; - p2p->sd_query = query; - p2p->pending_action_state = P2P_PENDING_SD; - - if (p2p_send_action(p2p, freq, dev->info.p2p_device_addr, - p2p->cfg->dev_addr, dev->info.p2p_device_addr, - wpabuf_head(req), wpabuf_len(req), 5000) < 0) { - wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, - "P2P: Failed to send Action frame"); - ret = -1; - } - - wpabuf_free(req); - - return ret; -} - - -void p2p_rx_gas_initial_req(struct p2p_data *p2p, const u8 *sa, - const u8 *data, size_t len, int rx_freq) -{ - const u8 *pos = data; - const u8 *end = data + len; - const u8 *next; - u8 dialog_token; - u16 slen; - int freq; - u16 update_indic; - - - if (p2p->cfg->sd_request == NULL) - return; - - if (rx_freq > 0) - freq = rx_freq; - else - freq = p2p_channel_to_freq(p2p->cfg->country, - p2p->cfg->reg_class, - p2p->cfg->channel); - if (freq < 0) - return; - - if (len < 1 + 2) - return; - - dialog_token = *pos++; - wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, - "P2P: GAS Initial Request from " MACSTR " (dialog token %u, " - "freq %d)", - MAC2STR(sa), dialog_token, rx_freq); - - if (*pos != WLAN_EID_ADV_PROTO) { - wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, - "P2P: Unexpected IE in GAS Initial Request: %u", *pos); - return; - } - pos++; - - slen = *pos++; - next = pos + slen; - if (next > end || slen < 2) { - wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, - "P2P: Invalid IE in GAS Initial Request"); - return; - } - pos++; /* skip QueryRespLenLimit and PAME-BI */ - - if (*pos != NATIVE_QUERY_PROTOCOL) { - wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, - "P2P: Unsupported GAS advertisement protocol id %u", - *pos); - return; - } - - pos = next; - /* Query Request */ - if (pos + 2 > end) - return; - slen = WPA_GET_LE16(pos); - pos += 2; - if (pos + slen > end) - return; - end = pos + slen; - - /* NQP Query Request */ - if (pos + 4 > end) - return; - if (WPA_GET_LE16(pos) != NQP_VENDOR_SPECIFIC) { - wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, - "P2P: Unsupported NQP Info ID %u", WPA_GET_LE16(pos)); - return; - } - pos += 2; - - slen = WPA_GET_LE16(pos); - pos += 2; - if (pos + slen > end || slen < 3 + 1) { - wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, - "P2P: Invalid NQP Query Request length"); - return; - } - - if (WPA_GET_BE24(pos) != OUI_WFA) { - wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, - "P2P: Unsupported NQP OUI %06x", WPA_GET_BE24(pos)); - return; - } - pos += 3; - - if (*pos != P2P_OUI_TYPE) { - wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, - "P2P: Unsupported NQP vendor type %u", *pos); - return; - } - pos++; - - if (pos + 2 > end) - return; - update_indic = WPA_GET_LE16(pos); - wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, - "P2P: Service Update Indicator: %u", update_indic); - pos += 2; - - p2p->cfg->sd_request(p2p->cfg->cb_ctx, freq, sa, dialog_token, - update_indic, pos, end - pos); - /* the response will be indicated with a call to p2p_sd_response() */ -} - - -void p2p_sd_response(struct p2p_data *p2p, int freq, const u8 *dst, - u8 dialog_token, const struct wpabuf *resp_tlvs) -{ - struct wpabuf *resp; - - /* TODO: fix the length limit to match with the maximum frame length */ - if (wpabuf_len(resp_tlvs) > 1400) { - wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: SD response long " - "enough to require fragmentation"); - if (p2p->sd_resp) { - /* - * TODO: Could consider storing the fragmented response - * separately for each peer to avoid having to drop old - * one if there is more than one pending SD query. - * Though, that would eat more memory, so there are - * also benefits to just using a single buffer. - */ - wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Drop " - "previous SD response"); - wpabuf_free(p2p->sd_resp); - } - os_memcpy(p2p->sd_resp_addr, dst, ETH_ALEN); - p2p->sd_resp_dialog_token = dialog_token; - p2p->sd_resp = wpabuf_dup(resp_tlvs); - p2p->sd_resp_pos = 0; - p2p->sd_frag_id = 0; - resp = p2p_build_sd_response(dialog_token, WLAN_STATUS_SUCCESS, - 1, p2p->srv_update_indic, NULL); - } else { - wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: SD response fits " - "in initial response"); - resp = p2p_build_sd_response(dialog_token, - WLAN_STATUS_SUCCESS, 0, - p2p->srv_update_indic, resp_tlvs); - } - if (resp == NULL) - return; - - p2p->pending_action_state = P2P_NO_PENDING_ACTION; - if (p2p_send_action(p2p, freq, dst, p2p->cfg->dev_addr, - p2p->cfg->dev_addr, - wpabuf_head(resp), wpabuf_len(resp), 200) < 0) - wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, - "P2P: Failed to send Action frame"); - - wpabuf_free(resp); -} - - -void p2p_rx_gas_initial_resp(struct p2p_data *p2p, const u8 *sa, - const u8 *data, size_t len, int rx_freq) -{ - const u8 *pos = data; - const u8 *end = data + len; - const u8 *next; - u8 dialog_token; - u16 status_code; - u16 comeback_delay; - u16 slen; - u16 update_indic; - - if (p2p->state != P2P_SD_DURING_FIND || p2p->sd_peer == NULL || - os_memcmp(sa, p2p->sd_peer->info.p2p_device_addr, ETH_ALEN) != 0) { - wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, - "P2P: Ignore unexpected GAS Initial Response from " - MACSTR, MAC2STR(sa)); - return; - } - p2p->cfg->send_action_done(p2p->cfg->cb_ctx); - p2p_clear_timeout(p2p); - - wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, - "P2P: Received GAS Initial Response from " MACSTR " (len=%d)", - MAC2STR(sa), (int) len); - - if (len < 5 + 2) { - wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, - "P2P: Too short GAS Initial Response frame"); - return; - } - - dialog_token = *pos++; - /* TODO: check dialog_token match */ - status_code = WPA_GET_LE16(pos); - pos += 2; - comeback_delay = WPA_GET_LE16(pos); - pos += 2; - wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, - "P2P: dialog_token=%u status_code=%u comeback_delay=%u", - dialog_token, status_code, comeback_delay); - if (status_code) { - wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, - "P2P: Service Discovery failed: status code %u", - status_code); - return; - } - - if (*pos != WLAN_EID_ADV_PROTO) { - wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, - "P2P: Unexpected IE in GAS Initial Response: %u", - *pos); - return; - } - pos++; - - slen = *pos++; - next = pos + slen; - if (next > end || slen < 2) { - wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, - "P2P: Invalid IE in GAS Initial Response"); - return; - } - pos++; /* skip QueryRespLenLimit and PAME-BI */ - - if (*pos != NATIVE_QUERY_PROTOCOL) { - wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, - "P2P: Unsupported GAS advertisement protocol id %u", - *pos); - return; - } - - pos = next; - /* Query Response */ - if (pos + 2 > end) { - wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Too short Query " - "Response"); - return; - } - slen = WPA_GET_LE16(pos); - pos += 2; - wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Query Response Length: %d", - slen); - if (pos + slen > end) { - wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Not enough Query " - "Response data"); - return; - } - end = pos + slen; - - if (comeback_delay) { - wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Fragmented " - "response - request fragments"); - if (p2p->sd_rx_resp) { - wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Drop " - "old SD reassembly buffer"); - wpabuf_free(p2p->sd_rx_resp); - p2p->sd_rx_resp = NULL; - } - p2p_send_gas_comeback_req(p2p, sa, dialog_token, rx_freq); - return; - } - - /* NQP Query Response */ - if (pos + 4 > end) - return; - if (WPA_GET_LE16(pos) != NQP_VENDOR_SPECIFIC) { - wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, - "P2P: Unsupported NQP Info ID %u", WPA_GET_LE16(pos)); - return; - } - pos += 2; - - slen = WPA_GET_LE16(pos); - pos += 2; - if (pos + slen > end || slen < 3 + 1) { - wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, - "P2P: Invalid NQP Query Response length"); - return; - } - - if (WPA_GET_BE24(pos) != OUI_WFA) { - wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, - "P2P: Unsupported NQP OUI %06x", WPA_GET_BE24(pos)); - return; - } - pos += 3; - - if (*pos != P2P_OUI_TYPE) { - wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, - "P2P: Unsupported NQP vendor type %u", *pos); - return; - } - pos++; - - if (pos + 2 > end) - return; - update_indic = WPA_GET_LE16(pos); - wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, - "P2P: Service Update Indicator: %u", update_indic); - pos += 2; - - p2p->sd_peer->flags |= P2P_DEV_SD_INFO; - p2p->sd_peer->flags &= ~P2P_DEV_SD_SCHEDULE; - p2p->sd_peer = NULL; - - if (p2p->sd_query) { - if (!p2p->sd_query->for_all_peers) { - struct p2p_sd_query *q; - wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, - "P2P: Remove completed SD query %p", - p2p->sd_query); - q = p2p->sd_query; - p2p_unlink_sd_query(p2p, p2p->sd_query); - p2p_free_sd_query(q); - } - p2p->sd_query = NULL; - } - - if (p2p->cfg->sd_response) - p2p->cfg->sd_response(p2p->cfg->cb_ctx, sa, update_indic, - pos, end - pos); - p2p_continue_find(p2p); -} - - -void p2p_rx_gas_comeback_req(struct p2p_data *p2p, const u8 *sa, - const u8 *data, size_t len, int rx_freq) -{ - struct wpabuf *resp; - u8 dialog_token; - size_t frag_len; - int more = 0; - - wpa_hexdump(MSG_DEBUG, "P2P: RX GAS Comeback Request", data, len); - if (len < 1) - return; - dialog_token = *data; - wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Dialog Token: %u", - dialog_token); - if (dialog_token != p2p->sd_resp_dialog_token) { - wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: No pending SD " - "response fragment for dialog token %u", dialog_token); - return; - } - - if (p2p->sd_resp == NULL) { - wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: No pending SD " - "response fragment available"); - return; - } - if (os_memcmp(sa, p2p->sd_resp_addr, ETH_ALEN) != 0) { - wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: No pending SD " - "response fragment for " MACSTR, MAC2STR(sa)); - return; - } - - frag_len = wpabuf_len(p2p->sd_resp) - p2p->sd_resp_pos; - if (frag_len > 1400) { - frag_len = 1400; - more = 1; - } - resp = p2p_build_gas_comeback_resp(dialog_token, WLAN_STATUS_SUCCESS, - p2p->srv_update_indic, - wpabuf_head_u8(p2p->sd_resp) + - p2p->sd_resp_pos, frag_len, - p2p->sd_frag_id, more, - wpabuf_len(p2p->sd_resp)); - if (resp == NULL) - return; - wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Send GAS Comeback " - "Response (frag_id %d more=%d frag_len=%d)", - p2p->sd_frag_id, more, (int) frag_len); - p2p->sd_frag_id++; - p2p->sd_resp_pos += frag_len; - - if (more) { - wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: %d more bytes " - "remain to be sent", - (int) (wpabuf_len(p2p->sd_resp) - p2p->sd_resp_pos)); - } else { - wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: All fragments of " - "SD response sent"); - wpabuf_free(p2p->sd_resp); - p2p->sd_resp = NULL; - } - - p2p->pending_action_state = P2P_NO_PENDING_ACTION; - if (p2p_send_action(p2p, rx_freq, sa, p2p->cfg->dev_addr, - p2p->cfg->dev_addr, - wpabuf_head(resp), wpabuf_len(resp), 200) < 0) - wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, - "P2P: Failed to send Action frame"); - - wpabuf_free(resp); -} - - -void p2p_rx_gas_comeback_resp(struct p2p_data *p2p, const u8 *sa, - const u8 *data, size_t len, int rx_freq) -{ - const u8 *pos = data; - const u8 *end = data + len; - const u8 *next; - u8 dialog_token; - u16 status_code; - u8 frag_id; - u8 more_frags; - u16 comeback_delay; - u16 slen; - - wpa_hexdump(MSG_DEBUG, "P2P: RX GAS Comeback Response", data, len); - - if (p2p->state != P2P_SD_DURING_FIND || p2p->sd_peer == NULL || - os_memcmp(sa, p2p->sd_peer->info.p2p_device_addr, ETH_ALEN) != 0) { - wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, - "P2P: Ignore unexpected GAS Comeback Response from " - MACSTR, MAC2STR(sa)); - return; - } - p2p->cfg->send_action_done(p2p->cfg->cb_ctx); - p2p_clear_timeout(p2p); - - wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, - "P2P: Received GAS Comeback Response from " MACSTR " (len=%d)", - MAC2STR(sa), (int) len); - - if (len < 6 + 2) { - wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, - "P2P: Too short GAS Comeback Response frame"); - return; - } - - dialog_token = *pos++; - /* TODO: check dialog_token match */ - status_code = WPA_GET_LE16(pos); - pos += 2; - frag_id = *pos & 0x7f; - more_frags = (*pos & 0x80) >> 7; - pos++; - comeback_delay = WPA_GET_LE16(pos); - pos += 2; - wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, - "P2P: dialog_token=%u status_code=%u frag_id=%d more_frags=%d " - "comeback_delay=%u", - dialog_token, status_code, frag_id, more_frags, - comeback_delay); - /* TODO: check frag_id match */ - if (status_code) { - wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, - "P2P: Service Discovery failed: status code %u", - status_code); - return; - } - - if (*pos != WLAN_EID_ADV_PROTO) { - wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, - "P2P: Unexpected IE in GAS Comeback Response: %u", - *pos); - return; - } - pos++; - - slen = *pos++; - next = pos + slen; - if (next > end || slen < 2) { - wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, - "P2P: Invalid IE in GAS Comeback Response"); - return; - } - pos++; /* skip QueryRespLenLimit and PAME-BI */ - - if (*pos != NATIVE_QUERY_PROTOCOL) { - wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, - "P2P: Unsupported GAS advertisement protocol id %u", - *pos); - return; - } - - pos = next; - /* Query Response */ - if (pos + 2 > end) { - wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Too short Query " - "Response"); - return; - } - slen = WPA_GET_LE16(pos); - pos += 2; - wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Query Response Length: %d", - slen); - if (pos + slen > end) { - wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Not enough Query " - "Response data"); - return; - } - if (slen == 0) { - wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: No Query Response " - "data"); - return; - } - end = pos + slen; - - if (p2p->sd_rx_resp) { - /* - * NQP header is only included in the first fragment; rest of - * the fragments start with continue TLVs. - */ - goto skip_nqp_header; - } - - /* NQP Query Response */ - if (pos + 4 > end) - return; - if (WPA_GET_LE16(pos) != NQP_VENDOR_SPECIFIC) { - wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, - "P2P: Unsupported NQP Info ID %u", WPA_GET_LE16(pos)); - return; - } - pos += 2; - - slen = WPA_GET_LE16(pos); - pos += 2; - wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: NQP Query Response " - "length: %u", slen); - if (slen < 3 + 1) { - wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, - "P2P: Invalid NQP Query Response length"); - return; - } - if (pos + 4 > end) - return; - - if (WPA_GET_BE24(pos) != OUI_WFA) { - wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, - "P2P: Unsupported NQP OUI %06x", WPA_GET_BE24(pos)); - return; - } - pos += 3; - - if (*pos != P2P_OUI_TYPE) { - wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, - "P2P: Unsupported NQP vendor type %u", *pos); - return; - } - pos++; - - if (pos + 2 > end) - return; - p2p->sd_rx_update_indic = WPA_GET_LE16(pos); - wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, - "P2P: Service Update Indicator: %u", p2p->sd_rx_update_indic); - pos += 2; - -skip_nqp_header: - if (wpabuf_resize(&p2p->sd_rx_resp, end - pos) < 0) - return; - wpabuf_put_data(p2p->sd_rx_resp, pos, end - pos); - wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Current SD reassembly " - "buffer length: %u", - (unsigned int) wpabuf_len(p2p->sd_rx_resp)); - - if (more_frags) { - wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: More fragments " - "remains"); - /* TODO: what would be a good size limit? */ - if (wpabuf_len(p2p->sd_rx_resp) > 64000) { - wpabuf_free(p2p->sd_rx_resp); - p2p->sd_rx_resp = NULL; - wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Too long " - "SD response - drop it"); - return; - } - p2p_send_gas_comeback_req(p2p, sa, dialog_token, rx_freq); - return; - } - - p2p->sd_peer->flags |= P2P_DEV_SD_INFO; - p2p->sd_peer->flags &= ~P2P_DEV_SD_SCHEDULE; - p2p->sd_peer = NULL; - - if (p2p->sd_query) { - if (!p2p->sd_query->for_all_peers) { - struct p2p_sd_query *q; - wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, - "P2P: Remove completed SD query %p", - p2p->sd_query); - q = p2p->sd_query; - p2p_unlink_sd_query(p2p, p2p->sd_query); - p2p_free_sd_query(q); - } - p2p->sd_query = NULL; - } - - if (p2p->cfg->sd_response) - p2p->cfg->sd_response(p2p->cfg->cb_ctx, sa, - p2p->sd_rx_update_indic, - wpabuf_head(p2p->sd_rx_resp), - wpabuf_len(p2p->sd_rx_resp)); - wpabuf_free(p2p->sd_rx_resp); - p2p->sd_rx_resp = NULL; - - p2p_continue_find(p2p); -} - - -void * p2p_sd_request(struct p2p_data *p2p, const u8 *dst, - const struct wpabuf *tlvs) -{ - struct p2p_sd_query *q; - - q = os_zalloc(sizeof(*q)); - if (q == NULL) - return NULL; - - if (dst) - os_memcpy(q->peer, dst, ETH_ALEN); - else - q->for_all_peers = 1; - - q->tlvs = wpabuf_dup(tlvs); - if (q->tlvs == NULL) { - p2p_free_sd_query(q); - return NULL; - } - - q->next = p2p->sd_queries; - p2p->sd_queries = q; - wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Added SD Query %p", q); - - return q; -} - - -void p2p_sd_service_update(struct p2p_data *p2p) -{ - p2p->srv_update_indic++; -} - - -int p2p_sd_cancel_request(struct p2p_data *p2p, void *req) -{ - if (p2p_unlink_sd_query(p2p, req)) { - wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, - "P2P: Cancel pending SD query %p", req); - p2p_free_sd_query(req); - return 0; - } - return -1; -} diff --git a/hostapd-0.8/src/p2p/p2p_utils.c b/hostapd-0.8/src/p2p/p2p_utils.c deleted file mode 100644 index da4b6ed..0000000 --- a/hostapd-0.8/src/p2p/p2p_utils.c +++ /dev/null @@ -1,271 +0,0 @@ -/* - * P2P - generic helper functions - * Copyright (c) 2009, Atheros Communications - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#include "includes.h" - -#include "common.h" -#include "p2p_i.h" - - -/** - * p2p_random - Generate random string for SSID and passphrase - * @buf: Buffer for returning the result - * @len: Number of octets to write to the buffer - * Returns: 0 on success, -1 on failure - * - * This function generates a random string using the following character set: - * 'A'-'Z', 'a'-'z', '0'-'9'. - */ -int p2p_random(char *buf, size_t len) -{ - u8 val; - size_t i; - u8 letters = 'Z' - 'A' + 1; - u8 numbers = 10; - - if (os_get_random((unsigned char *) buf, len)) - return -1; - /* Character set: 'A'-'Z', 'a'-'z', '0'-'9' */ - for (i = 0; i < len; i++) { - val = buf[i]; - val %= 2 * letters + numbers; - if (val < letters) - buf[i] = 'A' + val; - else if (val < 2 * letters) - buf[i] = 'a' + (val - letters); - else - buf[i] = '0' + (val - 2 * letters); - } - - return 0; -} - - -static int p2p_channel_to_freq_j4(int reg_class, int channel) -{ - /* Table J-4 in P802.11REVmb/D4.0 - Global operating classes */ - /* TODO: more regulatory classes */ - switch (reg_class) { - case 81: - /* channels 1..13 */ - if (channel < 1 || channel > 13) - return -1; - return 2407 + 5 * channel; - case 82: - /* channel 14 */ - if (channel != 14) - return -1; - return 2414 + 5 * channel; - case 83: /* channels 1..9; 40 MHz */ - case 84: /* channels 5..13; 40 MHz */ - if (channel < 1 || channel > 13) - return -1; - return 2407 + 5 * channel; - case 115: /* channels 36,40,44,48; indoor only */ - case 118: /* channels 52,56,60,64; dfs */ - if (channel < 36 || channel > 64) - return -1; - return 5000 + 5 * channel; - case 124: /* channels 149,153,157,161 */ - case 125: /* channels 149,153,157,161,165,169 */ - if (channel < 149 || channel > 161) - return -1; - return 5000 + 5 * channel; - case 116: /* channels 36,44; 40 MHz; indoor only */ - case 117: /* channels 40,48; 40 MHz; indoor only */ - case 119: /* channels 52,60; 40 MHz; dfs */ - case 120: /* channels 56,64; 40 MHz; dfs */ - if (channel < 36 || channel > 64) - return -1; - return 5000 + 5 * channel; - case 126: /* channels 149,157; 40 MHz */ - case 127: /* channels 153,161; 40 MHz */ - if (channel < 149 || channel > 161) - return -1; - return 5000 + 5 * channel; - } - return -1; -} - - -/** - * p2p_channel_to_freq - Convert channel info to frequency - * @country: Country code - * @reg_class: Regulatory class - * @channel: Channel number - * Returns: Frequency in MHz or -1 if the specified channel is unknown - */ -int p2p_channel_to_freq(const char *country, int reg_class, int channel) -{ - if (country[2] == 0x04) - return p2p_channel_to_freq_j4(reg_class, channel); - - /* These are mainly for backwards compatibility; to be removed */ - switch (reg_class) { - case 1: /* US/1, EU/1, JP/1 = 5 GHz, channels 36,40,44,48 */ - if (channel < 36 || channel > 48) - return -1; - return 5000 + 5 * channel; - case 3: /* US/3 = 5 GHz, channels 149,153,157,161 */ - case 5: /* US/5 = 5 GHz, channels 149,153,157,161 */ - if (channel < 149 || channel > 161) - return -1; - return 5000 + 5 * channel; - case 4: /* EU/4 = 2.407 GHz, channels 1..13 */ - case 12: /* US/12 = 2.407 GHz, channels 1..11 */ - case 30: /* JP/30 = 2.407 GHz, channels 1..13 */ - if (channel < 1 || channel > 13) - return -1; - return 2407 + 5 * channel; - case 31: /* JP/31 = 2.414 GHz, channel 14 */ - if (channel != 14) - return -1; - return 2414 + 5 * channel; - } - - return -1; -} - - -/** - * p2p_freq_to_channel - Convert frequency into channel info - * @country: Country code - * @reg_class: Buffer for returning regulatory class - * @channel: Buffer for returning channel number - * Returns: 0 on success, -1 if the specified frequency is unknown - */ -int p2p_freq_to_channel(const char *country, unsigned int freq, u8 *reg_class, - u8 *channel) -{ - /* TODO: more operating classes */ - if (freq >= 2412 && freq <= 2472) { - *reg_class = 81; /* 2.407 GHz, channels 1..13 */ - *channel = (freq - 2407) / 5; - return 0; - } - - if (freq == 2484) { - *reg_class = 82; /* channel 14 */ - *channel = 14; - return 0; - } - - if (freq >= 5180 && freq <= 5240) { - *reg_class = 115; /* 5 GHz, channels 36..48 */ - *channel = (freq - 5000) / 5; - return 0; - } - - if (freq >= 5745 && freq <= 5805) { - *reg_class = 124; /* 5 GHz, channels 149..161 */ - *channel = (freq - 5000) / 5; - return 0; - } - - return -1; -} - - -static void p2p_reg_class_intersect(const struct p2p_reg_class *a, - const struct p2p_reg_class *b, - struct p2p_reg_class *res) -{ - size_t i, j; - - res->reg_class = a->reg_class; - - for (i = 0; i < a->channels; i++) { - for (j = 0; j < b->channels; j++) { - if (a->channel[i] != b->channel[j]) - continue; - res->channel[res->channels] = a->channel[i]; - res->channels++; - if (res->channels == P2P_MAX_REG_CLASS_CHANNELS) - return; - } - } -} - - -/** - * p2p_channels_intersect - Intersection of supported channel lists - * @a: First set of supported channels - * @b: Second set of supported channels - * @res: Data structure for returning the intersection of support channels - * - * This function can be used to find a common set of supported channels. Both - * input channels sets are assumed to use the same country code. If different - * country codes are used, the regulatory class numbers may not be matched - * correctly and results are undefined. - */ -void p2p_channels_intersect(const struct p2p_channels *a, - const struct p2p_channels *b, - struct p2p_channels *res) -{ - size_t i, j; - - os_memset(res, 0, sizeof(*res)); - - for (i = 0; i < a->reg_classes; i++) { - const struct p2p_reg_class *a_reg = &a->reg_class[i]; - for (j = 0; j < b->reg_classes; j++) { - const struct p2p_reg_class *b_reg = &b->reg_class[j]; - if (a_reg->reg_class != b_reg->reg_class) - continue; - p2p_reg_class_intersect( - a_reg, b_reg, - &res->reg_class[res->reg_classes]); - if (res->reg_class[res->reg_classes].channels) { - res->reg_classes++; - if (res->reg_classes == P2P_MAX_REG_CLASSES) - return; - } - } - } -} - - -/** - * p2p_channels_includes - Check whether a channel is included in the list - * @channels: List of supported channels - * @reg_class: Regulatory class of the channel to search - * @channel: Channel number of the channel to search - * Returns: 1 if channel was found or 0 if not - */ -int p2p_channels_includes(const struct p2p_channels *channels, u8 reg_class, - u8 channel) -{ - size_t i, j; - for (i = 0; i < channels->reg_classes; i++) { - const struct p2p_reg_class *reg = &channels->reg_class[i]; - if (reg->reg_class != reg_class) - continue; - for (j = 0; j < reg->channels; j++) { - if (reg->channel[j] == channel) - return 1; - } - } - return 0; -} - - -int p2p_supported_freq(struct p2p_data *p2p, unsigned int freq) -{ - u8 op_reg_class, op_channel; - if (p2p_freq_to_channel(p2p->cfg->country, freq, - &op_reg_class, &op_channel) < 0) - return 0; - return p2p_channels_includes(&p2p->cfg->channels, op_reg_class, - op_channel); -} diff --git a/hostapd-0.8/src/radius/.gitignore b/hostapd-0.8/src/radius/.gitignore deleted file mode 100644 index a89a1f9..0000000 --- a/hostapd-0.8/src/radius/.gitignore +++ /dev/null @@ -1 +0,0 @@ -libradius.a diff --git a/hostapd-0.8/src/radius/Makefile b/hostapd-0.8/src/radius/Makefile deleted file mode 100644 index b199be8..0000000 --- a/hostapd-0.8/src/radius/Makefile +++ /dev/null @@ -1,22 +0,0 @@ -all: libradius.a - -clean: - rm -f *~ *.o *.d libradius.a - -install: - @echo Nothing to be made. - - -include ../lib.rules - -CFLAGS += -DCONFIG_IPV6 - -LIB_OBJS= \ - radius.o \ - radius_client.o \ - radius_server.o - -libradius.a: $(LIB_OBJS) - $(AR) crT $@ $? - --include $(OBJS:%.o=%.d) diff --git a/hostapd-0.8/src/radius/radius.c b/hostapd-0.8/src/radius/radius.c deleted file mode 100644 index 70754ef..0000000 --- a/hostapd-0.8/src/radius/radius.c +++ /dev/null @@ -1,1317 +0,0 @@ -/* - * RADIUS message processing - * Copyright (c) 2002-2009, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#include "utils/includes.h" - -#include "utils/common.h" -#include "utils/wpabuf.h" -#include "crypto/md5.h" -#include "crypto/crypto.h" -#include "radius.h" - - -/** - * struct radius_msg - RADIUS message structure for new and parsed messages - */ -struct radius_msg { - /** - * buf - Allocated buffer for RADIUS message - */ - struct wpabuf *buf; - - /** - * hdr - Pointer to the RADIUS header in buf - */ - struct radius_hdr *hdr; - - /** - * attr_pos - Array of indexes to attributes - * - * The values are number of bytes from buf to the beginning of - * struct radius_attr_hdr. - */ - size_t *attr_pos; - - /** - * attr_size - Total size of the attribute pointer array - */ - size_t attr_size; - - /** - * attr_used - Total number of attributes in the array - */ - size_t attr_used; -}; - - -struct radius_hdr * radius_msg_get_hdr(struct radius_msg *msg) -{ - return msg->hdr; -} - - -struct wpabuf * radius_msg_get_buf(struct radius_msg *msg) -{ - return msg->buf; -} - - -static struct radius_attr_hdr * -radius_get_attr_hdr(struct radius_msg *msg, int idx) -{ - return (struct radius_attr_hdr *) - (wpabuf_mhead_u8(msg->buf) + msg->attr_pos[idx]); -} - - -static void radius_msg_set_hdr(struct radius_msg *msg, u8 code, u8 identifier) -{ - msg->hdr->code = code; - msg->hdr->identifier = identifier; -} - - -static int radius_msg_initialize(struct radius_msg *msg) -{ - msg->attr_pos = - os_zalloc(RADIUS_DEFAULT_ATTR_COUNT * sizeof(*msg->attr_pos)); - if (msg->attr_pos == NULL) - return -1; - - msg->attr_size = RADIUS_DEFAULT_ATTR_COUNT; - msg->attr_used = 0; - - return 0; -} - - -/** - * radius_msg_new - Create a new RADIUS message - * @code: Code for RADIUS header - * @identifier: Identifier for RADIUS header - * Returns: Context for RADIUS message or %NULL on failure - * - * The caller is responsible for freeing the returned data with - * radius_msg_free(). - */ -struct radius_msg * radius_msg_new(u8 code, u8 identifier) -{ - struct radius_msg *msg; - - msg = os_zalloc(sizeof(*msg)); - if (msg == NULL) - return NULL; - - msg->buf = wpabuf_alloc(RADIUS_DEFAULT_MSG_SIZE); - if (msg->buf == NULL || radius_msg_initialize(msg)) { - radius_msg_free(msg); - return NULL; - } - msg->hdr = wpabuf_put(msg->buf, sizeof(struct radius_hdr)); - - radius_msg_set_hdr(msg, code, identifier); - - return msg; -} - - -/** - * radius_msg_free - Free a RADIUS message - * @msg: RADIUS message from radius_msg_new() or radius_msg_parse() - */ -void radius_msg_free(struct radius_msg *msg) -{ - if (msg == NULL) - return; - - wpabuf_free(msg->buf); - os_free(msg->attr_pos); - os_free(msg); -} - - -static const char *radius_code_string(u8 code) -{ - switch (code) { - case RADIUS_CODE_ACCESS_REQUEST: return "Access-Request"; - case RADIUS_CODE_ACCESS_ACCEPT: return "Access-Accept"; - case RADIUS_CODE_ACCESS_REJECT: return "Access-Reject"; - case RADIUS_CODE_ACCOUNTING_REQUEST: return "Accounting-Request"; - case RADIUS_CODE_ACCOUNTING_RESPONSE: return "Accounting-Response"; - case RADIUS_CODE_ACCESS_CHALLENGE: return "Access-Challenge"; - case RADIUS_CODE_STATUS_SERVER: return "Status-Server"; - case RADIUS_CODE_STATUS_CLIENT: return "Status-Client"; - case RADIUS_CODE_RESERVED: return "Reserved"; - default: return "?Unknown?"; - } -} - - -struct radius_attr_type { - u8 type; - char *name; - enum { - RADIUS_ATTR_UNDIST, RADIUS_ATTR_TEXT, RADIUS_ATTR_IP, - RADIUS_ATTR_HEXDUMP, RADIUS_ATTR_INT32, RADIUS_ATTR_IPV6 - } data_type; -}; - -static struct radius_attr_type radius_attrs[] = -{ - { RADIUS_ATTR_USER_NAME, "User-Name", RADIUS_ATTR_TEXT }, - { RADIUS_ATTR_USER_PASSWORD, "User-Password", RADIUS_ATTR_UNDIST }, - { RADIUS_ATTR_NAS_IP_ADDRESS, "NAS-IP-Address", RADIUS_ATTR_IP }, - { RADIUS_ATTR_NAS_PORT, "NAS-Port", RADIUS_ATTR_INT32 }, - { RADIUS_ATTR_FRAMED_MTU, "Framed-MTU", RADIUS_ATTR_INT32 }, - { RADIUS_ATTR_REPLY_MESSAGE, "Reply-Message", RADIUS_ATTR_TEXT }, - { RADIUS_ATTR_STATE, "State", RADIUS_ATTR_UNDIST }, - { RADIUS_ATTR_CLASS, "Class", RADIUS_ATTR_UNDIST }, - { RADIUS_ATTR_VENDOR_SPECIFIC, "Vendor-Specific", RADIUS_ATTR_UNDIST }, - { RADIUS_ATTR_SESSION_TIMEOUT, "Session-Timeout", RADIUS_ATTR_INT32 }, - { RADIUS_ATTR_IDLE_TIMEOUT, "Idle-Timeout", RADIUS_ATTR_INT32 }, - { RADIUS_ATTR_TERMINATION_ACTION, "Termination-Action", - RADIUS_ATTR_INT32 }, - { RADIUS_ATTR_CALLED_STATION_ID, "Called-Station-Id", - RADIUS_ATTR_TEXT }, - { RADIUS_ATTR_CALLING_STATION_ID, "Calling-Station-Id", - RADIUS_ATTR_TEXT }, - { RADIUS_ATTR_NAS_IDENTIFIER, "NAS-Identifier", RADIUS_ATTR_TEXT }, - { RADIUS_ATTR_PROXY_STATE, "Proxy-State", RADIUS_ATTR_UNDIST }, - { RADIUS_ATTR_ACCT_STATUS_TYPE, "Acct-Status-Type", - RADIUS_ATTR_INT32 }, - { RADIUS_ATTR_ACCT_DELAY_TIME, "Acct-Delay-Time", RADIUS_ATTR_INT32 }, - { RADIUS_ATTR_ACCT_INPUT_OCTETS, "Acct-Input-Octets", - RADIUS_ATTR_INT32 }, - { RADIUS_ATTR_ACCT_OUTPUT_OCTETS, "Acct-Output-Octets", - RADIUS_ATTR_INT32 }, - { RADIUS_ATTR_ACCT_SESSION_ID, "Acct-Session-Id", RADIUS_ATTR_TEXT }, - { RADIUS_ATTR_ACCT_AUTHENTIC, "Acct-Authentic", RADIUS_ATTR_INT32 }, - { RADIUS_ATTR_ACCT_SESSION_TIME, "Acct-Session-Time", - RADIUS_ATTR_INT32 }, - { RADIUS_ATTR_ACCT_INPUT_PACKETS, "Acct-Input-Packets", - RADIUS_ATTR_INT32 }, - { RADIUS_ATTR_ACCT_OUTPUT_PACKETS, "Acct-Output-Packets", - RADIUS_ATTR_INT32 }, - { RADIUS_ATTR_ACCT_TERMINATE_CAUSE, "Acct-Terminate-Cause", - RADIUS_ATTR_INT32 }, - { RADIUS_ATTR_ACCT_MULTI_SESSION_ID, "Acct-Multi-Session-Id", - RADIUS_ATTR_TEXT }, - { RADIUS_ATTR_ACCT_LINK_COUNT, "Acct-Link-Count", RADIUS_ATTR_INT32 }, - { RADIUS_ATTR_ACCT_INPUT_GIGAWORDS, "Acct-Input-Gigawords", - RADIUS_ATTR_INT32 }, - { RADIUS_ATTR_ACCT_OUTPUT_GIGAWORDS, "Acct-Output-Gigawords", - RADIUS_ATTR_INT32 }, - { RADIUS_ATTR_EVENT_TIMESTAMP, "Event-Timestamp", - RADIUS_ATTR_INT32 }, - { RADIUS_ATTR_NAS_PORT_TYPE, "NAS-Port-Type", RADIUS_ATTR_INT32 }, - { RADIUS_ATTR_TUNNEL_TYPE, "Tunnel-Type", RADIUS_ATTR_HEXDUMP }, - { RADIUS_ATTR_TUNNEL_MEDIUM_TYPE, "Tunnel-Medium-Type", - RADIUS_ATTR_HEXDUMP }, - { RADIUS_ATTR_CONNECT_INFO, "Connect-Info", RADIUS_ATTR_TEXT }, - { RADIUS_ATTR_EAP_MESSAGE, "EAP-Message", RADIUS_ATTR_UNDIST }, - { RADIUS_ATTR_MESSAGE_AUTHENTICATOR, "Message-Authenticator", - RADIUS_ATTR_UNDIST }, - { RADIUS_ATTR_TUNNEL_PRIVATE_GROUP_ID, "Tunnel-Private-Group-Id", - RADIUS_ATTR_HEXDUMP }, - { RADIUS_ATTR_ACCT_INTERIM_INTERVAL, "Acct-Interim-Interval", - RADIUS_ATTR_INT32 }, - { RADIUS_ATTR_CHARGEABLE_USER_IDENTITY, "Chargable-User-Identity", - RADIUS_ATTR_TEXT }, - { RADIUS_ATTR_NAS_IPV6_ADDRESS, "NAS-IPv6-Address", RADIUS_ATTR_IPV6 }, -}; -#define RADIUS_ATTRS (sizeof(radius_attrs) / sizeof(radius_attrs[0])) - - -static struct radius_attr_type *radius_get_attr_type(u8 type) -{ - size_t i; - - for (i = 0; i < RADIUS_ATTRS; i++) { - if (type == radius_attrs[i].type) - return &radius_attrs[i]; - } - - return NULL; -} - - -static void print_char(char c) -{ - if (c >= 32 && c < 127) - printf("%c", c); - else - printf("<%02x>", c); -} - - -static void radius_msg_dump_attr(struct radius_attr_hdr *hdr) -{ - struct radius_attr_type *attr; - int i, len; - unsigned char *pos; - - attr = radius_get_attr_type(hdr->type); - - printf(" Attribute %d (%s) length=%d\n", - hdr->type, attr ? attr->name : "?Unknown?", hdr->length); - - if (attr == NULL) - return; - - len = hdr->length - sizeof(struct radius_attr_hdr); - pos = (unsigned char *) (hdr + 1); - - switch (attr->data_type) { - case RADIUS_ATTR_TEXT: - printf(" Value: '"); - for (i = 0; i < len; i++) - print_char(pos[i]); - printf("'\n"); - break; - - case RADIUS_ATTR_IP: - if (len == 4) { - struct in_addr addr; - os_memcpy(&addr, pos, 4); - printf(" Value: %s\n", inet_ntoa(addr)); - } else - printf(" Invalid IP address length %d\n", len); - break; - -#ifdef CONFIG_IPV6 - case RADIUS_ATTR_IPV6: - if (len == 16) { - char buf[128]; - const char *atxt; - struct in6_addr *addr = (struct in6_addr *) pos; - atxt = inet_ntop(AF_INET6, addr, buf, sizeof(buf)); - printf(" Value: %s\n", atxt ? atxt : "?"); - } else - printf(" Invalid IPv6 address length %d\n", len); - break; -#endif /* CONFIG_IPV6 */ - - case RADIUS_ATTR_HEXDUMP: - case RADIUS_ATTR_UNDIST: - printf(" Value:"); - for (i = 0; i < len; i++) - printf(" %02x", pos[i]); - printf("\n"); - break; - - case RADIUS_ATTR_INT32: - if (len == 4) - printf(" Value: %u\n", WPA_GET_BE32(pos)); - else - printf(" Invalid INT32 length %d\n", len); - break; - - default: - break; - } -} - - -void radius_msg_dump(struct radius_msg *msg) -{ - size_t i; - - printf("RADIUS message: code=%d (%s) identifier=%d length=%d\n", - msg->hdr->code, radius_code_string(msg->hdr->code), - msg->hdr->identifier, ntohs(msg->hdr->length)); - - for (i = 0; i < msg->attr_used; i++) { - struct radius_attr_hdr *attr = radius_get_attr_hdr(msg, i); - radius_msg_dump_attr(attr); - } -} - - -int radius_msg_finish(struct radius_msg *msg, const u8 *secret, - size_t secret_len) -{ - if (secret) { - u8 auth[MD5_MAC_LEN]; - struct radius_attr_hdr *attr; - - os_memset(auth, 0, MD5_MAC_LEN); - attr = radius_msg_add_attr(msg, - RADIUS_ATTR_MESSAGE_AUTHENTICATOR, - auth, MD5_MAC_LEN); - if (attr == NULL) { - wpa_printf(MSG_WARNING, "RADIUS: Could not add " - "Message-Authenticator"); - return -1; - } - msg->hdr->length = htons(wpabuf_len(msg->buf)); - hmac_md5(secret, secret_len, wpabuf_head(msg->buf), - wpabuf_len(msg->buf), (u8 *) (attr + 1)); - } else - msg->hdr->length = htons(wpabuf_len(msg->buf)); - - if (wpabuf_len(msg->buf) > 0xffff) { - wpa_printf(MSG_WARNING, "RADIUS: Too long message (%lu)", - (unsigned long) wpabuf_len(msg->buf)); - return -1; - } - return 0; -} - - -int radius_msg_finish_srv(struct radius_msg *msg, const u8 *secret, - size_t secret_len, const u8 *req_authenticator) -{ - u8 auth[MD5_MAC_LEN]; - struct radius_attr_hdr *attr; - const u8 *addr[4]; - size_t len[4]; - - os_memset(auth, 0, MD5_MAC_LEN); - attr = radius_msg_add_attr(msg, RADIUS_ATTR_MESSAGE_AUTHENTICATOR, - auth, MD5_MAC_LEN); - if (attr == NULL) { - printf("WARNING: Could not add Message-Authenticator\n"); - return -1; - } - msg->hdr->length = htons(wpabuf_len(msg->buf)); - os_memcpy(msg->hdr->authenticator, req_authenticator, - sizeof(msg->hdr->authenticator)); - hmac_md5(secret, secret_len, wpabuf_head(msg->buf), - wpabuf_len(msg->buf), (u8 *) (attr + 1)); - - /* ResponseAuth = MD5(Code+ID+Length+RequestAuth+Attributes+Secret) */ - addr[0] = (u8 *) msg->hdr; - len[0] = 1 + 1 + 2; - addr[1] = req_authenticator; - len[1] = MD5_MAC_LEN; - addr[2] = wpabuf_head_u8(msg->buf) + sizeof(struct radius_hdr); - len[2] = wpabuf_len(msg->buf) - sizeof(struct radius_hdr); - addr[3] = secret; - len[3] = secret_len; - md5_vector(4, addr, len, msg->hdr->authenticator); - - if (wpabuf_len(msg->buf) > 0xffff) { - wpa_printf(MSG_WARNING, "RADIUS: Too long message (%lu)", - (unsigned long) wpabuf_len(msg->buf)); - return -1; - } - return 0; -} - - -void radius_msg_finish_acct(struct radius_msg *msg, const u8 *secret, - size_t secret_len) -{ - const u8 *addr[2]; - size_t len[2]; - - msg->hdr->length = htons(wpabuf_len(msg->buf)); - os_memset(msg->hdr->authenticator, 0, MD5_MAC_LEN); - addr[0] = wpabuf_head(msg->buf); - len[0] = wpabuf_len(msg->buf); - addr[1] = secret; - len[1] = secret_len; - md5_vector(2, addr, len, msg->hdr->authenticator); - - if (wpabuf_len(msg->buf) > 0xffff) { - wpa_printf(MSG_WARNING, "RADIUS: Too long messages (%lu)", - (unsigned long) wpabuf_len(msg->buf)); - } -} - - -static int radius_msg_add_attr_to_array(struct radius_msg *msg, - struct radius_attr_hdr *attr) -{ - if (msg->attr_used >= msg->attr_size) { - size_t *nattr_pos; - int nlen = msg->attr_size * 2; - - nattr_pos = os_realloc(msg->attr_pos, - nlen * sizeof(*msg->attr_pos)); - if (nattr_pos == NULL) - return -1; - - msg->attr_pos = nattr_pos; - msg->attr_size = nlen; - } - - msg->attr_pos[msg->attr_used++] = - (unsigned char *) attr - wpabuf_head_u8(msg->buf); - - return 0; -} - - -struct radius_attr_hdr *radius_msg_add_attr(struct radius_msg *msg, u8 type, - const u8 *data, size_t data_len) -{ - size_t buf_needed; - struct radius_attr_hdr *attr; - - if (data_len > RADIUS_MAX_ATTR_LEN) { - printf("radius_msg_add_attr: too long attribute (%lu bytes)\n", - (unsigned long) data_len); - return NULL; - } - - buf_needed = sizeof(*attr) + data_len; - - if (wpabuf_tailroom(msg->buf) < buf_needed) { - /* allocate more space for message buffer */ - if (wpabuf_resize(&msg->buf, buf_needed) < 0) - return NULL; - msg->hdr = wpabuf_mhead(msg->buf); - } - - attr = wpabuf_put(msg->buf, sizeof(struct radius_attr_hdr)); - attr->type = type; - attr->length = sizeof(*attr) + data_len; - wpabuf_put_data(msg->buf, data, data_len); - - if (radius_msg_add_attr_to_array(msg, attr)) - return NULL; - - return attr; -} - - -/** - * radius_msg_parse - Parse a RADIUS message - * @data: RADIUS message to be parsed - * @len: Length of data buffer in octets - * Returns: Parsed RADIUS message or %NULL on failure - * - * This parses a RADIUS message and makes a copy of its data. The caller is - * responsible for freeing the returned data with radius_msg_free(). - */ -struct radius_msg * radius_msg_parse(const u8 *data, size_t len) -{ - struct radius_msg *msg; - struct radius_hdr *hdr; - struct radius_attr_hdr *attr; - size_t msg_len; - unsigned char *pos, *end; - - if (data == NULL || len < sizeof(*hdr)) - return NULL; - - hdr = (struct radius_hdr *) data; - - msg_len = ntohs(hdr->length); - if (msg_len < sizeof(*hdr) || msg_len > len) { - wpa_printf(MSG_INFO, "RADIUS: Invalid message length"); - return NULL; - } - - if (msg_len < len) { - wpa_printf(MSG_DEBUG, "RADIUS: Ignored %lu extra bytes after " - "RADIUS message", (unsigned long) len - msg_len); - } - - msg = os_zalloc(sizeof(*msg)); - if (msg == NULL) - return NULL; - - msg->buf = wpabuf_alloc_copy(data, msg_len); - if (msg->buf == NULL || radius_msg_initialize(msg)) { - radius_msg_free(msg); - return NULL; - } - msg->hdr = wpabuf_mhead(msg->buf); - - /* parse attributes */ - pos = wpabuf_mhead_u8(msg->buf) + sizeof(struct radius_hdr); - end = wpabuf_mhead_u8(msg->buf) + wpabuf_len(msg->buf); - while (pos < end) { - if ((size_t) (end - pos) < sizeof(*attr)) - goto fail; - - attr = (struct radius_attr_hdr *) pos; - - if (pos + attr->length > end || attr->length < sizeof(*attr)) - goto fail; - - /* TODO: check that attr->length is suitable for attr->type */ - - if (radius_msg_add_attr_to_array(msg, attr)) - goto fail; - - pos += attr->length; - } - - return msg; - - fail: - radius_msg_free(msg); - return NULL; -} - - -int radius_msg_add_eap(struct radius_msg *msg, const u8 *data, size_t data_len) -{ - const u8 *pos = data; - size_t left = data_len; - - while (left > 0) { - int len; - if (left > RADIUS_MAX_ATTR_LEN) - len = RADIUS_MAX_ATTR_LEN; - else - len = left; - - if (!radius_msg_add_attr(msg, RADIUS_ATTR_EAP_MESSAGE, - pos, len)) - return 0; - - pos += len; - left -= len; - } - - return 1; -} - - -u8 *radius_msg_get_eap(struct radius_msg *msg, size_t *eap_len) -{ - u8 *eap, *pos; - size_t len, i; - struct radius_attr_hdr *attr; - - if (msg == NULL) - return NULL; - - len = 0; - for (i = 0; i < msg->attr_used; i++) { - attr = radius_get_attr_hdr(msg, i); - if (attr->type == RADIUS_ATTR_EAP_MESSAGE) - len += attr->length - sizeof(struct radius_attr_hdr); - } - - if (len == 0) - return NULL; - - eap = os_malloc(len); - if (eap == NULL) - return NULL; - - pos = eap; - for (i = 0; i < msg->attr_used; i++) { - attr = radius_get_attr_hdr(msg, i); - if (attr->type == RADIUS_ATTR_EAP_MESSAGE) { - int flen = attr->length - sizeof(*attr); - os_memcpy(pos, attr + 1, flen); - pos += flen; - } - } - - if (eap_len) - *eap_len = len; - - return eap; -} - - -int radius_msg_verify_msg_auth(struct radius_msg *msg, const u8 *secret, - size_t secret_len, const u8 *req_auth) -{ - u8 auth[MD5_MAC_LEN], orig[MD5_MAC_LEN]; - u8 orig_authenticator[16]; - struct radius_attr_hdr *attr = NULL, *tmp; - size_t i; - - for (i = 0; i < msg->attr_used; i++) { - tmp = radius_get_attr_hdr(msg, i); - if (tmp->type == RADIUS_ATTR_MESSAGE_AUTHENTICATOR) { - if (attr != NULL) { - printf("Multiple Message-Authenticator " - "attributes in RADIUS message\n"); - return 1; - } - attr = tmp; - } - } - - if (attr == NULL) { - printf("No Message-Authenticator attribute found\n"); - return 1; - } - - os_memcpy(orig, attr + 1, MD5_MAC_LEN); - os_memset(attr + 1, 0, MD5_MAC_LEN); - if (req_auth) { - os_memcpy(orig_authenticator, msg->hdr->authenticator, - sizeof(orig_authenticator)); - os_memcpy(msg->hdr->authenticator, req_auth, - sizeof(msg->hdr->authenticator)); - } - hmac_md5(secret, secret_len, wpabuf_head(msg->buf), - wpabuf_len(msg->buf), auth); - os_memcpy(attr + 1, orig, MD5_MAC_LEN); - if (req_auth) { - os_memcpy(msg->hdr->authenticator, orig_authenticator, - sizeof(orig_authenticator)); - } - - if (os_memcmp(orig, auth, MD5_MAC_LEN) != 0) { - printf("Invalid Message-Authenticator!\n"); - return 1; - } - - return 0; -} - - -int radius_msg_verify(struct radius_msg *msg, const u8 *secret, - size_t secret_len, struct radius_msg *sent_msg, int auth) -{ - const u8 *addr[4]; - size_t len[4]; - u8 hash[MD5_MAC_LEN]; - - if (sent_msg == NULL) { - printf("No matching Access-Request message found\n"); - return 1; - } - - if (auth && - radius_msg_verify_msg_auth(msg, secret, secret_len, - sent_msg->hdr->authenticator)) { - return 1; - } - - /* ResponseAuth = MD5(Code+ID+Length+RequestAuth+Attributes+Secret) */ - addr[0] = (u8 *) msg->hdr; - len[0] = 1 + 1 + 2; - addr[1] = sent_msg->hdr->authenticator; - len[1] = MD5_MAC_LEN; - addr[2] = wpabuf_head_u8(msg->buf) + sizeof(struct radius_hdr); - len[2] = wpabuf_len(msg->buf) - sizeof(struct radius_hdr); - addr[3] = secret; - len[3] = secret_len; - md5_vector(4, addr, len, hash); - if (os_memcmp(hash, msg->hdr->authenticator, MD5_MAC_LEN) != 0) { - printf("Response Authenticator invalid!\n"); - return 1; - } - - return 0; -} - - -int radius_msg_copy_attr(struct radius_msg *dst, struct radius_msg *src, - u8 type) -{ - struct radius_attr_hdr *attr; - size_t i; - int count = 0; - - for (i = 0; i < src->attr_used; i++) { - attr = radius_get_attr_hdr(src, i); - if (attr->type == type) { - if (!radius_msg_add_attr(dst, type, (u8 *) (attr + 1), - attr->length - sizeof(*attr))) - return -1; - count++; - } - } - - return count; -} - - -/* Create Request Authenticator. The value should be unique over the lifetime - * of the shared secret between authenticator and authentication server. - * Use one-way MD5 hash calculated from current timestamp and some data given - * by the caller. */ -void radius_msg_make_authenticator(struct radius_msg *msg, - const u8 *data, size_t len) -{ - struct os_time tv; - long int l; - const u8 *addr[3]; - size_t elen[3]; - - os_get_time(&tv); - l = os_random(); - addr[0] = (u8 *) &tv; - elen[0] = sizeof(tv); - addr[1] = data; - elen[1] = len; - addr[2] = (u8 *) &l; - elen[2] = sizeof(l); - md5_vector(3, addr, elen, msg->hdr->authenticator); -} - - -/* Get Vendor-specific RADIUS Attribute from a parsed RADIUS message. - * Returns the Attribute payload and sets alen to indicate the length of the - * payload if a vendor attribute with subtype is found, otherwise returns NULL. - * The returned payload is allocated with os_malloc() and caller must free it - * by calling os_free(). - */ -static u8 *radius_msg_get_vendor_attr(struct radius_msg *msg, u32 vendor, - u8 subtype, size_t *alen) -{ - u8 *data, *pos; - size_t i, len; - - if (msg == NULL) - return NULL; - - for (i = 0; i < msg->attr_used; i++) { - struct radius_attr_hdr *attr = radius_get_attr_hdr(msg, i); - size_t left; - u32 vendor_id; - struct radius_attr_vendor *vhdr; - - if (attr->type != RADIUS_ATTR_VENDOR_SPECIFIC) - continue; - - left = attr->length - sizeof(*attr); - if (left < 4) - continue; - - pos = (u8 *) (attr + 1); - - os_memcpy(&vendor_id, pos, 4); - pos += 4; - left -= 4; - - if (ntohl(vendor_id) != vendor) - continue; - - while (left >= sizeof(*vhdr)) { - vhdr = (struct radius_attr_vendor *) pos; - if (vhdr->vendor_length > left || - vhdr->vendor_length < sizeof(*vhdr)) { - left = 0; - break; - } - if (vhdr->vendor_type != subtype) { - pos += vhdr->vendor_length; - left -= vhdr->vendor_length; - continue; - } - - len = vhdr->vendor_length - sizeof(*vhdr); - data = os_malloc(len); - if (data == NULL) - return NULL; - os_memcpy(data, pos + sizeof(*vhdr), len); - if (alen) - *alen = len; - return data; - } - } - - return NULL; -} - - -static u8 * decrypt_ms_key(const u8 *key, size_t len, - const u8 *req_authenticator, - const u8 *secret, size_t secret_len, size_t *reslen) -{ - u8 *plain, *ppos, *res; - const u8 *pos; - size_t left, plen; - u8 hash[MD5_MAC_LEN]; - int i, first = 1; - const u8 *addr[3]; - size_t elen[3]; - - /* key: 16-bit salt followed by encrypted key info */ - - if (len < 2 + 16) - return NULL; - - pos = key + 2; - left = len - 2; - if (left % 16) { - printf("Invalid ms key len %lu\n", (unsigned long) left); - return NULL; - } - - plen = left; - ppos = plain = os_malloc(plen); - if (plain == NULL) - return NULL; - plain[0] = 0; - - while (left > 0) { - /* b(1) = MD5(Secret + Request-Authenticator + Salt) - * b(i) = MD5(Secret + c(i - 1)) for i > 1 */ - - addr[0] = secret; - elen[0] = secret_len; - if (first) { - addr[1] = req_authenticator; - elen[1] = MD5_MAC_LEN; - addr[2] = key; - elen[2] = 2; /* Salt */ - } else { - addr[1] = pos - MD5_MAC_LEN; - elen[1] = MD5_MAC_LEN; - } - md5_vector(first ? 3 : 2, addr, elen, hash); - first = 0; - - for (i = 0; i < MD5_MAC_LEN; i++) - *ppos++ = *pos++ ^ hash[i]; - left -= MD5_MAC_LEN; - } - - if (plain[0] == 0 || plain[0] > plen - 1) { - printf("Failed to decrypt MPPE key\n"); - os_free(plain); - return NULL; - } - - res = os_malloc(plain[0]); - if (res == NULL) { - os_free(plain); - return NULL; - } - os_memcpy(res, plain + 1, plain[0]); - if (reslen) - *reslen = plain[0]; - os_free(plain); - return res; -} - - -static void encrypt_ms_key(const u8 *key, size_t key_len, u16 salt, - const u8 *req_authenticator, - const u8 *secret, size_t secret_len, - u8 *ebuf, size_t *elen) -{ - int i, len, first = 1; - u8 hash[MD5_MAC_LEN], saltbuf[2], *pos; - const u8 *addr[3]; - size_t _len[3]; - - WPA_PUT_BE16(saltbuf, salt); - - len = 1 + key_len; - if (len & 0x0f) { - len = (len & 0xf0) + 16; - } - os_memset(ebuf, 0, len); - ebuf[0] = key_len; - os_memcpy(ebuf + 1, key, key_len); - - *elen = len; - - pos = ebuf; - while (len > 0) { - /* b(1) = MD5(Secret + Request-Authenticator + Salt) - * b(i) = MD5(Secret + c(i - 1)) for i > 1 */ - addr[0] = secret; - _len[0] = secret_len; - if (first) { - addr[1] = req_authenticator; - _len[1] = MD5_MAC_LEN; - addr[2] = saltbuf; - _len[2] = sizeof(saltbuf); - } else { - addr[1] = pos - MD5_MAC_LEN; - _len[1] = MD5_MAC_LEN; - } - md5_vector(first ? 3 : 2, addr, _len, hash); - first = 0; - - for (i = 0; i < MD5_MAC_LEN; i++) - *pos++ ^= hash[i]; - - len -= MD5_MAC_LEN; - } -} - - -struct radius_ms_mppe_keys * -radius_msg_get_ms_keys(struct radius_msg *msg, struct radius_msg *sent_msg, - const u8 *secret, size_t secret_len) -{ - u8 *key; - size_t keylen; - struct radius_ms_mppe_keys *keys; - - if (msg == NULL || sent_msg == NULL) - return NULL; - - keys = os_zalloc(sizeof(*keys)); - if (keys == NULL) - return NULL; - - key = radius_msg_get_vendor_attr(msg, RADIUS_VENDOR_ID_MICROSOFT, - RADIUS_VENDOR_ATTR_MS_MPPE_SEND_KEY, - &keylen); - if (key) { - keys->send = decrypt_ms_key(key, keylen, - sent_msg->hdr->authenticator, - secret, secret_len, - &keys->send_len); - os_free(key); - } - - key = radius_msg_get_vendor_attr(msg, RADIUS_VENDOR_ID_MICROSOFT, - RADIUS_VENDOR_ATTR_MS_MPPE_RECV_KEY, - &keylen); - if (key) { - keys->recv = decrypt_ms_key(key, keylen, - sent_msg->hdr->authenticator, - secret, secret_len, - &keys->recv_len); - os_free(key); - } - - return keys; -} - - -struct radius_ms_mppe_keys * -radius_msg_get_cisco_keys(struct radius_msg *msg, struct radius_msg *sent_msg, - const u8 *secret, size_t secret_len) -{ - u8 *key; - size_t keylen; - struct radius_ms_mppe_keys *keys; - - if (msg == NULL || sent_msg == NULL) - return NULL; - - keys = os_zalloc(sizeof(*keys)); - if (keys == NULL) - return NULL; - - key = radius_msg_get_vendor_attr(msg, RADIUS_VENDOR_ID_CISCO, - RADIUS_CISCO_AV_PAIR, &keylen); - if (key && keylen == 51 && - os_memcmp(key, "leap:session-key=", 17) == 0) { - keys->recv = decrypt_ms_key(key + 17, keylen - 17, - sent_msg->hdr->authenticator, - secret, secret_len, - &keys->recv_len); - } - os_free(key); - - return keys; -} - - -int radius_msg_add_mppe_keys(struct radius_msg *msg, - const u8 *req_authenticator, - const u8 *secret, size_t secret_len, - const u8 *send_key, size_t send_key_len, - const u8 *recv_key, size_t recv_key_len) -{ - struct radius_attr_hdr *attr; - u32 vendor_id = htonl(RADIUS_VENDOR_ID_MICROSOFT); - u8 *buf; - struct radius_attr_vendor *vhdr; - u8 *pos; - size_t elen; - int hlen; - u16 salt; - - hlen = sizeof(vendor_id) + sizeof(*vhdr) + 2; - - /* MS-MPPE-Send-Key */ - buf = os_malloc(hlen + send_key_len + 16); - if (buf == NULL) { - return 0; - } - pos = buf; - os_memcpy(pos, &vendor_id, sizeof(vendor_id)); - pos += sizeof(vendor_id); - vhdr = (struct radius_attr_vendor *) pos; - vhdr->vendor_type = RADIUS_VENDOR_ATTR_MS_MPPE_SEND_KEY; - pos = (u8 *) (vhdr + 1); - salt = os_random() | 0x8000; - WPA_PUT_BE16(pos, salt); - pos += 2; - encrypt_ms_key(send_key, send_key_len, salt, req_authenticator, secret, - secret_len, pos, &elen); - vhdr->vendor_length = hlen + elen - sizeof(vendor_id); - - attr = radius_msg_add_attr(msg, RADIUS_ATTR_VENDOR_SPECIFIC, - buf, hlen + elen); - os_free(buf); - if (attr == NULL) { - return 0; - } - - /* MS-MPPE-Recv-Key */ - buf = os_malloc(hlen + send_key_len + 16); - if (buf == NULL) { - return 0; - } - pos = buf; - os_memcpy(pos, &vendor_id, sizeof(vendor_id)); - pos += sizeof(vendor_id); - vhdr = (struct radius_attr_vendor *) pos; - vhdr->vendor_type = RADIUS_VENDOR_ATTR_MS_MPPE_RECV_KEY; - pos = (u8 *) (vhdr + 1); - salt ^= 1; - WPA_PUT_BE16(pos, salt); - pos += 2; - encrypt_ms_key(recv_key, recv_key_len, salt, req_authenticator, secret, - secret_len, pos, &elen); - vhdr->vendor_length = hlen + elen - sizeof(vendor_id); - - attr = radius_msg_add_attr(msg, RADIUS_ATTR_VENDOR_SPECIFIC, - buf, hlen + elen); - os_free(buf); - if (attr == NULL) { - return 0; - } - - return 1; -} - - -/* Add User-Password attribute to a RADIUS message and encrypt it as specified - * in RFC 2865, Chap. 5.2 */ -struct radius_attr_hdr * -radius_msg_add_attr_user_password(struct radius_msg *msg, - const u8 *data, size_t data_len, - const u8 *secret, size_t secret_len) -{ - u8 buf[128]; - int padlen, i; - size_t buf_len, pos; - const u8 *addr[2]; - size_t len[2]; - u8 hash[16]; - - if (data_len > 128) - return NULL; - - os_memcpy(buf, data, data_len); - buf_len = data_len; - - padlen = data_len % 16; - if (padlen) { - padlen = 16 - padlen; - os_memset(buf + data_len, 0, padlen); - buf_len += padlen; - } - - addr[0] = secret; - len[0] = secret_len; - addr[1] = msg->hdr->authenticator; - len[1] = 16; - md5_vector(2, addr, len, hash); - - for (i = 0; i < 16; i++) - buf[i] ^= hash[i]; - pos = 16; - - while (pos < buf_len) { - addr[0] = secret; - len[0] = secret_len; - addr[1] = &buf[pos - 16]; - len[1] = 16; - md5_vector(2, addr, len, hash); - - for (i = 0; i < 16; i++) - buf[pos + i] ^= hash[i]; - - pos += 16; - } - - return radius_msg_add_attr(msg, RADIUS_ATTR_USER_PASSWORD, - buf, buf_len); -} - - -int radius_msg_get_attr(struct radius_msg *msg, u8 type, u8 *buf, size_t len) -{ - struct radius_attr_hdr *attr = NULL, *tmp; - size_t i, dlen; - - for (i = 0; i < msg->attr_used; i++) { - tmp = radius_get_attr_hdr(msg, i); - if (tmp->type == type) { - attr = tmp; - break; - } - } - - if (!attr) - return -1; - - dlen = attr->length - sizeof(*attr); - if (buf) - os_memcpy(buf, (attr + 1), dlen > len ? len : dlen); - return dlen; -} - - -int radius_msg_get_attr_ptr(struct radius_msg *msg, u8 type, u8 **buf, - size_t *len, const u8 *start) -{ - size_t i; - struct radius_attr_hdr *attr = NULL, *tmp; - - for (i = 0; i < msg->attr_used; i++) { - tmp = radius_get_attr_hdr(msg, i); - if (tmp->type == type && - (start == NULL || (u8 *) tmp > start)) { - attr = tmp; - break; - } - } - - if (!attr) - return -1; - - *buf = (u8 *) (attr + 1); - *len = attr->length - sizeof(*attr); - return 0; -} - - -int radius_msg_count_attr(struct radius_msg *msg, u8 type, int min_len) -{ - size_t i; - int count; - - for (count = 0, i = 0; i < msg->attr_used; i++) { - struct radius_attr_hdr *attr = radius_get_attr_hdr(msg, i); - if (attr->type == type && - attr->length >= sizeof(struct radius_attr_hdr) + min_len) - count++; - } - - return count; -} - - -struct radius_tunnel_attrs { - int tag_used; - int type; /* Tunnel-Type */ - int medium_type; /* Tunnel-Medium-Type */ - int vlanid; -}; - - -/** - * radius_msg_get_vlanid - Parse RADIUS attributes for VLAN tunnel information - * @msg: RADIUS message - * Returns: VLAN ID for the first tunnel configuration of -1 if none is found - */ -int radius_msg_get_vlanid(struct radius_msg *msg) -{ - struct radius_tunnel_attrs tunnel[RADIUS_TUNNEL_TAGS], *tun; - size_t i; - struct radius_attr_hdr *attr = NULL; - const u8 *data; - char buf[10]; - size_t dlen; - - os_memset(&tunnel, 0, sizeof(tunnel)); - - for (i = 0; i < msg->attr_used; i++) { - attr = radius_get_attr_hdr(msg, i); - data = (const u8 *) (attr + 1); - dlen = attr->length - sizeof(*attr); - if (attr->length < 3) - continue; - if (data[0] >= RADIUS_TUNNEL_TAGS) - tun = &tunnel[0]; - else - tun = &tunnel[data[0]]; - - switch (attr->type) { - case RADIUS_ATTR_TUNNEL_TYPE: - if (attr->length != 6) - break; - tun->tag_used++; - tun->type = WPA_GET_BE24(data + 1); - break; - case RADIUS_ATTR_TUNNEL_MEDIUM_TYPE: - if (attr->length != 6) - break; - tun->tag_used++; - tun->medium_type = WPA_GET_BE24(data + 1); - break; - case RADIUS_ATTR_TUNNEL_PRIVATE_GROUP_ID: - if (data[0] < RADIUS_TUNNEL_TAGS) { - data++; - dlen--; - } - if (dlen >= sizeof(buf)) - break; - os_memcpy(buf, data, dlen); - buf[dlen] = '\0'; - tun->tag_used++; - tun->vlanid = atoi(buf); - break; - } - } - - for (i = 0; i < RADIUS_TUNNEL_TAGS; i++) { - tun = &tunnel[i]; - if (tun->tag_used && - tun->type == RADIUS_TUNNEL_TYPE_VLAN && - tun->medium_type == RADIUS_TUNNEL_MEDIUM_TYPE_802 && - tun->vlanid > 0) - return tun->vlanid; - } - - return -1; -} - - -void radius_free_class(struct radius_class_data *c) -{ - size_t i; - if (c == NULL) - return; - for (i = 0; i < c->count; i++) - os_free(c->attr[i].data); - os_free(c->attr); - c->attr = NULL; - c->count = 0; -} - - -int radius_copy_class(struct radius_class_data *dst, - const struct radius_class_data *src) -{ - size_t i; - - if (src->attr == NULL) - return 0; - - dst->attr = os_zalloc(src->count * sizeof(struct radius_attr_data)); - if (dst->attr == NULL) - return -1; - - dst->count = 0; - - for (i = 0; i < src->count; i++) { - dst->attr[i].data = os_malloc(src->attr[i].len); - if (dst->attr[i].data == NULL) - break; - dst->count++; - os_memcpy(dst->attr[i].data, src->attr[i].data, - src->attr[i].len); - dst->attr[i].len = src->attr[i].len; - } - - return 0; -} diff --git a/hostapd-0.8/src/radius/radius.h b/hostapd-0.8/src/radius/radius.h deleted file mode 100644 index a3cdac0..0000000 --- a/hostapd-0.8/src/radius/radius.h +++ /dev/null @@ -1,273 +0,0 @@ -/* - * RADIUS message processing - * Copyright (c) 2002-2009, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#ifndef RADIUS_H -#define RADIUS_H - -/* RFC 2865 - RADIUS */ - -#ifdef _MSC_VER -#pragma pack(push, 1) -#endif /* _MSC_VER */ - -struct radius_hdr { - u8 code; - u8 identifier; - u16 length; /* including this header */ - u8 authenticator[16]; - /* followed by length-20 octets of attributes */ -} STRUCT_PACKED; - -enum { RADIUS_CODE_ACCESS_REQUEST = 1, - RADIUS_CODE_ACCESS_ACCEPT = 2, - RADIUS_CODE_ACCESS_REJECT = 3, - RADIUS_CODE_ACCOUNTING_REQUEST = 4, - RADIUS_CODE_ACCOUNTING_RESPONSE = 5, - RADIUS_CODE_ACCESS_CHALLENGE = 11, - RADIUS_CODE_STATUS_SERVER = 12, - RADIUS_CODE_STATUS_CLIENT = 13, - RADIUS_CODE_RESERVED = 255 -}; - -struct radius_attr_hdr { - u8 type; - u8 length; /* including this header */ - /* followed by length-2 octets of attribute value */ -} STRUCT_PACKED; - -#define RADIUS_MAX_ATTR_LEN (255 - sizeof(struct radius_attr_hdr)) - -enum { RADIUS_ATTR_USER_NAME = 1, - RADIUS_ATTR_USER_PASSWORD = 2, - RADIUS_ATTR_NAS_IP_ADDRESS = 4, - RADIUS_ATTR_NAS_PORT = 5, - RADIUS_ATTR_FRAMED_MTU = 12, - RADIUS_ATTR_REPLY_MESSAGE = 18, - RADIUS_ATTR_STATE = 24, - RADIUS_ATTR_CLASS = 25, - RADIUS_ATTR_VENDOR_SPECIFIC = 26, - RADIUS_ATTR_SESSION_TIMEOUT = 27, - RADIUS_ATTR_IDLE_TIMEOUT = 28, - RADIUS_ATTR_TERMINATION_ACTION = 29, - RADIUS_ATTR_CALLED_STATION_ID = 30, - RADIUS_ATTR_CALLING_STATION_ID = 31, - RADIUS_ATTR_NAS_IDENTIFIER = 32, - RADIUS_ATTR_PROXY_STATE = 33, - RADIUS_ATTR_ACCT_STATUS_TYPE = 40, - RADIUS_ATTR_ACCT_DELAY_TIME = 41, - RADIUS_ATTR_ACCT_INPUT_OCTETS = 42, - RADIUS_ATTR_ACCT_OUTPUT_OCTETS = 43, - RADIUS_ATTR_ACCT_SESSION_ID = 44, - RADIUS_ATTR_ACCT_AUTHENTIC = 45, - RADIUS_ATTR_ACCT_SESSION_TIME = 46, - RADIUS_ATTR_ACCT_INPUT_PACKETS = 47, - RADIUS_ATTR_ACCT_OUTPUT_PACKETS = 48, - RADIUS_ATTR_ACCT_TERMINATE_CAUSE = 49, - RADIUS_ATTR_ACCT_MULTI_SESSION_ID = 50, - RADIUS_ATTR_ACCT_LINK_COUNT = 51, - RADIUS_ATTR_ACCT_INPUT_GIGAWORDS = 52, - RADIUS_ATTR_ACCT_OUTPUT_GIGAWORDS = 53, - RADIUS_ATTR_EVENT_TIMESTAMP = 55, - RADIUS_ATTR_NAS_PORT_TYPE = 61, - RADIUS_ATTR_TUNNEL_TYPE = 64, - RADIUS_ATTR_TUNNEL_MEDIUM_TYPE = 65, - RADIUS_ATTR_CONNECT_INFO = 77, - RADIUS_ATTR_EAP_MESSAGE = 79, - RADIUS_ATTR_MESSAGE_AUTHENTICATOR = 80, - RADIUS_ATTR_TUNNEL_PRIVATE_GROUP_ID = 81, - RADIUS_ATTR_ACCT_INTERIM_INTERVAL = 85, - RADIUS_ATTR_CHARGEABLE_USER_IDENTITY = 89, - RADIUS_ATTR_NAS_IPV6_ADDRESS = 95 -}; - - -/* Termination-Action */ -#define RADIUS_TERMINATION_ACTION_DEFAULT 0 -#define RADIUS_TERMINATION_ACTION_RADIUS_REQUEST 1 - -/* NAS-Port-Type */ -#define RADIUS_NAS_PORT_TYPE_IEEE_802_11 19 - -/* Acct-Status-Type */ -#define RADIUS_ACCT_STATUS_TYPE_START 1 -#define RADIUS_ACCT_STATUS_TYPE_STOP 2 -#define RADIUS_ACCT_STATUS_TYPE_INTERIM_UPDATE 3 -#define RADIUS_ACCT_STATUS_TYPE_ACCOUNTING_ON 7 -#define RADIUS_ACCT_STATUS_TYPE_ACCOUNTING_OFF 8 - -/* Acct-Authentic */ -#define RADIUS_ACCT_AUTHENTIC_RADIUS 1 -#define RADIUS_ACCT_AUTHENTIC_LOCAL 2 -#define RADIUS_ACCT_AUTHENTIC_REMOTE 3 - -/* Acct-Terminate-Cause */ -#define RADIUS_ACCT_TERMINATE_CAUSE_USER_REQUEST 1 -#define RADIUS_ACCT_TERMINATE_CAUSE_LOST_CARRIER 2 -#define RADIUS_ACCT_TERMINATE_CAUSE_LOST_SERVICE 3 -#define RADIUS_ACCT_TERMINATE_CAUSE_IDLE_TIMEOUT 4 -#define RADIUS_ACCT_TERMINATE_CAUSE_SESSION_TIMEOUT 5 -#define RADIUS_ACCT_TERMINATE_CAUSE_ADMIN_RESET 6 -#define RADIUS_ACCT_TERMINATE_CAUSE_ADMIN_REBOOT 7 -#define RADIUS_ACCT_TERMINATE_CAUSE_PORT_ERROR 8 -#define RADIUS_ACCT_TERMINATE_CAUSE_NAS_ERROR 9 -#define RADIUS_ACCT_TERMINATE_CAUSE_NAS_REQUEST 10 -#define RADIUS_ACCT_TERMINATE_CAUSE_NAS_REBOOT 11 -#define RADIUS_ACCT_TERMINATE_CAUSE_PORT_UNNEEDED 12 -#define RADIUS_ACCT_TERMINATE_CAUSE_PORT_PREEMPTED 13 -#define RADIUS_ACCT_TERMINATE_CAUSE_PORT_SUSPENDED 14 -#define RADIUS_ACCT_TERMINATE_CAUSE_SERVICE_UNAVAILABLE 15 -#define RADIUS_ACCT_TERMINATE_CAUSE_CALLBACK 16 -#define RADIUS_ACCT_TERMINATE_CAUSE_USER_ERROR 17 -#define RADIUS_ACCT_TERMINATE_CAUSE_HOST_REQUEST 18 - -#define RADIUS_TUNNEL_TAGS 32 - -/* Tunnel-Type */ -#define RADIUS_TUNNEL_TYPE_PPTP 1 -#define RADIUS_TUNNEL_TYPE_L2TP 3 -#define RADIUS_TUNNEL_TYPE_IPIP 7 -#define RADIUS_TUNNEL_TYPE_GRE 10 -#define RADIUS_TUNNEL_TYPE_VLAN 13 - -/* Tunnel-Medium-Type */ -#define RADIUS_TUNNEL_MEDIUM_TYPE_IPV4 1 -#define RADIUS_TUNNEL_MEDIUM_TYPE_IPV6 2 -#define RADIUS_TUNNEL_MEDIUM_TYPE_802 6 - - -struct radius_attr_vendor { - u8 vendor_type; - u8 vendor_length; -} STRUCT_PACKED; - -#define RADIUS_VENDOR_ID_CISCO 9 -#define RADIUS_CISCO_AV_PAIR 1 - -/* RFC 2548 - Microsoft Vendor-specific RADIUS Attributes */ -#define RADIUS_VENDOR_ID_MICROSOFT 311 - -enum { RADIUS_VENDOR_ATTR_MS_MPPE_SEND_KEY = 16, - RADIUS_VENDOR_ATTR_MS_MPPE_RECV_KEY = 17 -}; - -#ifdef _MSC_VER -#pragma pack(pop) -#endif /* _MSC_VER */ - -struct radius_ms_mppe_keys { - u8 *send; - size_t send_len; - u8 *recv; - size_t recv_len; -}; - - -struct radius_msg; - -/* Default size to be allocated for new RADIUS messages */ -#define RADIUS_DEFAULT_MSG_SIZE 1024 - -/* Default size to be allocated for attribute array */ -#define RADIUS_DEFAULT_ATTR_COUNT 16 - - -/* MAC address ASCII format for IEEE 802.1X use - * (draft-congdon-radius-8021x-20.txt) */ -#define RADIUS_802_1X_ADDR_FORMAT "%02X-%02X-%02X-%02X-%02X-%02X" -/* MAC address ASCII format for non-802.1X use */ -#define RADIUS_ADDR_FORMAT "%02x%02x%02x%02x%02x%02x" - -struct radius_hdr * radius_msg_get_hdr(struct radius_msg *msg); -struct wpabuf * radius_msg_get_buf(struct radius_msg *msg); -struct radius_msg * radius_msg_new(u8 code, u8 identifier); -void radius_msg_free(struct radius_msg *msg); -void radius_msg_dump(struct radius_msg *msg); -int radius_msg_finish(struct radius_msg *msg, const u8 *secret, - size_t secret_len); -int radius_msg_finish_srv(struct radius_msg *msg, const u8 *secret, - size_t secret_len, const u8 *req_authenticator); -void radius_msg_finish_acct(struct radius_msg *msg, const u8 *secret, - size_t secret_len); -struct radius_attr_hdr * radius_msg_add_attr(struct radius_msg *msg, u8 type, - const u8 *data, size_t data_len); -struct radius_msg * radius_msg_parse(const u8 *data, size_t len); -int radius_msg_add_eap(struct radius_msg *msg, const u8 *data, - size_t data_len); -u8 *radius_msg_get_eap(struct radius_msg *msg, size_t *len); -int radius_msg_verify(struct radius_msg *msg, const u8 *secret, - size_t secret_len, struct radius_msg *sent_msg, - int auth); -int radius_msg_verify_msg_auth(struct radius_msg *msg, const u8 *secret, - size_t secret_len, const u8 *req_auth); -int radius_msg_copy_attr(struct radius_msg *dst, struct radius_msg *src, - u8 type); -void radius_msg_make_authenticator(struct radius_msg *msg, - const u8 *data, size_t len); -struct radius_ms_mppe_keys * -radius_msg_get_ms_keys(struct radius_msg *msg, struct radius_msg *sent_msg, - const u8 *secret, size_t secret_len); -struct radius_ms_mppe_keys * -radius_msg_get_cisco_keys(struct radius_msg *msg, struct radius_msg *sent_msg, - const u8 *secret, size_t secret_len); -int radius_msg_add_mppe_keys(struct radius_msg *msg, - const u8 *req_authenticator, - const u8 *secret, size_t secret_len, - const u8 *send_key, size_t send_key_len, - const u8 *recv_key, size_t recv_key_len); -struct radius_attr_hdr * -radius_msg_add_attr_user_password(struct radius_msg *msg, - const u8 *data, size_t data_len, - const u8 *secret, size_t secret_len); -int radius_msg_get_attr(struct radius_msg *msg, u8 type, u8 *buf, size_t len); -int radius_msg_get_vlanid(struct radius_msg *msg); - -static inline int radius_msg_add_attr_int32(struct radius_msg *msg, u8 type, - u32 value) -{ - u32 val = htonl(value); - return radius_msg_add_attr(msg, type, (u8 *) &val, 4) != NULL; -} - -static inline int radius_msg_get_attr_int32(struct radius_msg *msg, u8 type, - u32 *value) -{ - u32 val; - int res; - res = radius_msg_get_attr(msg, type, (u8 *) &val, 4); - if (res != 4) - return -1; - - *value = ntohl(val); - return 0; -} -int radius_msg_get_attr_ptr(struct radius_msg *msg, u8 type, u8 **buf, - size_t *len, const u8 *start); -int radius_msg_count_attr(struct radius_msg *msg, u8 type, int min_len); - - -struct radius_attr_data { - u8 *data; - size_t len; -}; - -struct radius_class_data { - struct radius_attr_data *attr; - size_t count; -}; - -void radius_free_class(struct radius_class_data *c); -int radius_copy_class(struct radius_class_data *dst, - const struct radius_class_data *src); - -#endif /* RADIUS_H */ diff --git a/hostapd-0.8/src/radius/radius_client.c b/hostapd-0.8/src/radius/radius_client.c deleted file mode 100644 index 691f77a..0000000 --- a/hostapd-0.8/src/radius/radius_client.c +++ /dev/null @@ -1,1499 +0,0 @@ -/* - * RADIUS client - * Copyright (c) 2002-2009, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#include "includes.h" - -#include "common.h" -#include "radius.h" -#include "radius_client.h" -#include "eloop.h" - -/* Defaults for RADIUS retransmit values (exponential backoff) */ - -/** - * RADIUS_CLIENT_FIRST_WAIT - RADIUS client timeout for first retry in seconds - */ -#define RADIUS_CLIENT_FIRST_WAIT 3 - -/** - * RADIUS_CLIENT_MAX_WAIT - RADIUS client maximum retry timeout in seconds - */ -#define RADIUS_CLIENT_MAX_WAIT 120 - -/** - * RADIUS_CLIENT_MAX_RETRIES - RADIUS client maximum retries - * - * Maximum number of retransmit attempts before the entry is removed from - * retransmit list. - */ -#define RADIUS_CLIENT_MAX_RETRIES 10 - -/** - * RADIUS_CLIENT_MAX_ENTRIES - RADIUS client maximum pending messages - * - * Maximum number of entries in retransmit list (oldest entries will be - * removed, if this limit is exceeded). - */ -#define RADIUS_CLIENT_MAX_ENTRIES 30 - -/** - * RADIUS_CLIENT_NUM_FAILOVER - RADIUS client failover point - * - * The number of failed retry attempts after which the RADIUS server will be - * changed (if one of more backup servers are configured). - */ -#define RADIUS_CLIENT_NUM_FAILOVER 4 - - -/** - * struct radius_rx_handler - RADIUS client RX handler - * - * This data structure is used internally inside the RADIUS client module to - * store registered RX handlers. These handlers are registered by calls to - * radius_client_register() and unregistered when the RADIUS client is - * deinitialized with a call to radius_client_deinit(). - */ -struct radius_rx_handler { - /** - * handler - Received RADIUS message handler - */ - RadiusRxResult (*handler)(struct radius_msg *msg, - struct radius_msg *req, - const u8 *shared_secret, - size_t shared_secret_len, - void *data); - - /** - * data - Context data for the handler - */ - void *data; -}; - - -/** - * struct radius_msg_list - RADIUS client message retransmit list - * - * This data structure is used internally inside the RADIUS client module to - * store pending RADIUS requests that may still need to be retransmitted. - */ -struct radius_msg_list { - /** - * addr - STA/client address - * - * This is used to find RADIUS messages for the same STA. - */ - u8 addr[ETH_ALEN]; - - /** - * msg - RADIUS message - */ - struct radius_msg *msg; - - /** - * msg_type - Message type - */ - RadiusType msg_type; - - /** - * first_try - Time of the first transmission attempt - */ - os_time_t first_try; - - /** - * next_try - Time for the next transmission attempt - */ - os_time_t next_try; - - /** - * attempts - Number of transmission attempts - */ - int attempts; - - /** - * next_wait - Next retransmission wait time in seconds - */ - int next_wait; - - /** - * last_attempt - Time of the last transmission attempt - */ - struct os_time last_attempt; - - /** - * shared_secret - Shared secret with the target RADIUS server - */ - const u8 *shared_secret; - - /** - * shared_secret_len - shared_secret length in octets - */ - size_t shared_secret_len; - - /* TODO: server config with failover to backup server(s) */ - - /** - * next - Next message in the list - */ - struct radius_msg_list *next; -}; - - -/** - * struct radius_client_data - Internal RADIUS client data - * - * This data structure is used internally inside the RADIUS client module. - * External users allocate this by calling radius_client_init() and free it by - * calling radius_client_deinit(). The pointer to this opaque data is used in - * calls to other functions as an identifier for the RADIUS client instance. - */ -struct radius_client_data { - /** - * ctx - Context pointer for hostapd_logger() callbacks - */ - void *ctx; - - /** - * conf - RADIUS client configuration (list of RADIUS servers to use) - */ - struct hostapd_radius_servers *conf; - - /** - * auth_serv_sock - IPv4 socket for RADIUS authentication messages - */ - int auth_serv_sock; - - /** - * acct_serv_sock - IPv4 socket for RADIUS accounting messages - */ - int acct_serv_sock; - - /** - * auth_serv_sock6 - IPv6 socket for RADIUS authentication messages - */ - int auth_serv_sock6; - - /** - * acct_serv_sock6 - IPv6 socket for RADIUS accounting messages - */ - int acct_serv_sock6; - - /** - * auth_sock - Currently used socket for RADIUS authentication server - */ - int auth_sock; - - /** - * acct_sock - Currently used socket for RADIUS accounting server - */ - int acct_sock; - - /** - * auth_handlers - Authentication message handlers - */ - struct radius_rx_handler *auth_handlers; - - /** - * num_auth_handlers - Number of handlers in auth_handlers - */ - size_t num_auth_handlers; - - /** - * acct_handlers - Accounting message handlers - */ - struct radius_rx_handler *acct_handlers; - - /** - * num_acct_handlers - Number of handlers in acct_handlers - */ - size_t num_acct_handlers; - - /** - * msgs - Pending outgoing RADIUS messages - */ - struct radius_msg_list *msgs; - - /** - * num_msgs - Number of pending messages in the msgs list - */ - size_t num_msgs; - - /** - * next_radius_identifier - Next RADIUS message identifier to use - */ - u8 next_radius_identifier; -}; - - -static int -radius_change_server(struct radius_client_data *radius, - struct hostapd_radius_server *nserv, - struct hostapd_radius_server *oserv, - int sock, int sock6, int auth); -static int radius_client_init_acct(struct radius_client_data *radius); -static int radius_client_init_auth(struct radius_client_data *radius); - - -static void radius_client_msg_free(struct radius_msg_list *req) -{ - radius_msg_free(req->msg); - os_free(req); -} - - -/** - * radius_client_register - Register a RADIUS client RX handler - * @radius: RADIUS client context from radius_client_init() - * @msg_type: RADIUS client type (RADIUS_AUTH or RADIUS_ACCT) - * @handler: Handler for received RADIUS messages - * @data: Context pointer for handler callbacks - * Returns: 0 on success, -1 on failure - * - * This function is used to register a handler for processing received RADIUS - * authentication and accounting messages. The handler() callback function will - * be called whenever a RADIUS message is received from the active server. - * - * There can be multiple registered RADIUS message handlers. The handlers will - * be called in order until one of them indicates that it has processed or - * queued the message. - */ -int radius_client_register(struct radius_client_data *radius, - RadiusType msg_type, - RadiusRxResult (*handler)(struct radius_msg *msg, - struct radius_msg *req, - const u8 *shared_secret, - size_t shared_secret_len, - void *data), - void *data) -{ - struct radius_rx_handler **handlers, *newh; - size_t *num; - - if (msg_type == RADIUS_ACCT) { - handlers = &radius->acct_handlers; - num = &radius->num_acct_handlers; - } else { - handlers = &radius->auth_handlers; - num = &radius->num_auth_handlers; - } - - newh = os_realloc(*handlers, - (*num + 1) * sizeof(struct radius_rx_handler)); - if (newh == NULL) - return -1; - - newh[*num].handler = handler; - newh[*num].data = data; - (*num)++; - *handlers = newh; - - return 0; -} - - -static void radius_client_handle_send_error(struct radius_client_data *radius, - int s, RadiusType msg_type) -{ -#ifndef CONFIG_NATIVE_WINDOWS - int _errno = errno; - perror("send[RADIUS]"); - if (_errno == ENOTCONN || _errno == EDESTADDRREQ || _errno == EINVAL || - _errno == EBADF) { - hostapd_logger(radius->ctx, NULL, HOSTAPD_MODULE_RADIUS, - HOSTAPD_LEVEL_INFO, - "Send failed - maybe interface status changed -" - " try to connect again"); - eloop_unregister_read_sock(s); - close(s); - if (msg_type == RADIUS_ACCT || msg_type == RADIUS_ACCT_INTERIM) - radius_client_init_acct(radius); - else - radius_client_init_auth(radius); - } -#endif /* CONFIG_NATIVE_WINDOWS */ -} - - -static int radius_client_retransmit(struct radius_client_data *radius, - struct radius_msg_list *entry, - os_time_t now) -{ - struct hostapd_radius_servers *conf = radius->conf; - int s; - struct wpabuf *buf; - - if (entry->msg_type == RADIUS_ACCT || - entry->msg_type == RADIUS_ACCT_INTERIM) { - s = radius->acct_sock; - if (entry->attempts == 0) - conf->acct_server->requests++; - else { - conf->acct_server->timeouts++; - conf->acct_server->retransmissions++; - } - } else { - s = radius->auth_sock; - if (entry->attempts == 0) - conf->auth_server->requests++; - else { - conf->auth_server->timeouts++; - conf->auth_server->retransmissions++; - } - } - - /* retransmit; remove entry if too many attempts */ - entry->attempts++; - hostapd_logger(radius->ctx, entry->addr, HOSTAPD_MODULE_RADIUS, - HOSTAPD_LEVEL_DEBUG, "Resending RADIUS message (id=%d)", - radius_msg_get_hdr(entry->msg)->identifier); - - os_get_time(&entry->last_attempt); - buf = radius_msg_get_buf(entry->msg); - if (send(s, wpabuf_head(buf), wpabuf_len(buf), 0) < 0) - radius_client_handle_send_error(radius, s, entry->msg_type); - - entry->next_try = now + entry->next_wait; - entry->next_wait *= 2; - if (entry->next_wait > RADIUS_CLIENT_MAX_WAIT) - entry->next_wait = RADIUS_CLIENT_MAX_WAIT; - if (entry->attempts >= RADIUS_CLIENT_MAX_RETRIES) { - printf("Removing un-ACKed RADIUS message due to too many " - "failed retransmit attempts\n"); - return 1; - } - - return 0; -} - - -static void radius_client_timer(void *eloop_ctx, void *timeout_ctx) -{ - struct radius_client_data *radius = eloop_ctx; - struct hostapd_radius_servers *conf = radius->conf; - struct os_time now; - os_time_t first; - struct radius_msg_list *entry, *prev, *tmp; - int auth_failover = 0, acct_failover = 0; - char abuf[50]; - - entry = radius->msgs; - if (!entry) - return; - - os_get_time(&now); - first = 0; - - prev = NULL; - while (entry) { - if (now.sec >= entry->next_try && - radius_client_retransmit(radius, entry, now.sec)) { - if (prev) - prev->next = entry->next; - else - radius->msgs = entry->next; - - tmp = entry; - entry = entry->next; - radius_client_msg_free(tmp); - radius->num_msgs--; - continue; - } - - if (entry->attempts > RADIUS_CLIENT_NUM_FAILOVER) { - if (entry->msg_type == RADIUS_ACCT || - entry->msg_type == RADIUS_ACCT_INTERIM) - acct_failover++; - else - auth_failover++; - } - - if (first == 0 || entry->next_try < first) - first = entry->next_try; - - prev = entry; - entry = entry->next; - } - - if (radius->msgs) { - if (first < now.sec) - first = now.sec; - eloop_register_timeout(first - now.sec, 0, - radius_client_timer, radius, NULL); - hostapd_logger(radius->ctx, NULL, HOSTAPD_MODULE_RADIUS, - HOSTAPD_LEVEL_DEBUG, "Next RADIUS client " - "retransmit in %ld seconds", - (long int) (first - now.sec)); - } - - if (auth_failover && conf->num_auth_servers > 1) { - struct hostapd_radius_server *next, *old; - old = conf->auth_server; - hostapd_logger(radius->ctx, NULL, HOSTAPD_MODULE_RADIUS, - HOSTAPD_LEVEL_NOTICE, - "No response from Authentication server " - "%s:%d - failover", - hostapd_ip_txt(&old->addr, abuf, sizeof(abuf)), - old->port); - - for (entry = radius->msgs; entry; entry = entry->next) { - if (entry->msg_type == RADIUS_AUTH) - old->timeouts++; - } - - next = old + 1; - if (next > &(conf->auth_servers[conf->num_auth_servers - 1])) - next = conf->auth_servers; - conf->auth_server = next; - radius_change_server(radius, next, old, - radius->auth_serv_sock, - radius->auth_serv_sock6, 1); - } - - if (acct_failover && conf->num_acct_servers > 1) { - struct hostapd_radius_server *next, *old; - old = conf->acct_server; - hostapd_logger(radius->ctx, NULL, HOSTAPD_MODULE_RADIUS, - HOSTAPD_LEVEL_NOTICE, - "No response from Accounting server " - "%s:%d - failover", - hostapd_ip_txt(&old->addr, abuf, sizeof(abuf)), - old->port); - - for (entry = radius->msgs; entry; entry = entry->next) { - if (entry->msg_type == RADIUS_ACCT || - entry->msg_type == RADIUS_ACCT_INTERIM) - old->timeouts++; - } - - next = old + 1; - if (next > &conf->acct_servers[conf->num_acct_servers - 1]) - next = conf->acct_servers; - conf->acct_server = next; - radius_change_server(radius, next, old, - radius->acct_serv_sock, - radius->acct_serv_sock6, 0); - } -} - - -static void radius_client_update_timeout(struct radius_client_data *radius) -{ - struct os_time now; - os_time_t first; - struct radius_msg_list *entry; - - eloop_cancel_timeout(radius_client_timer, radius, NULL); - - if (radius->msgs == NULL) { - return; - } - - first = 0; - for (entry = radius->msgs; entry; entry = entry->next) { - if (first == 0 || entry->next_try < first) - first = entry->next_try; - } - - os_get_time(&now); - if (first < now.sec) - first = now.sec; - eloop_register_timeout(first - now.sec, 0, radius_client_timer, radius, - NULL); - hostapd_logger(radius->ctx, NULL, HOSTAPD_MODULE_RADIUS, - HOSTAPD_LEVEL_DEBUG, "Next RADIUS client retransmit in" - " %ld seconds\n", (long int) (first - now.sec)); -} - - -static void radius_client_list_add(struct radius_client_data *radius, - struct radius_msg *msg, - RadiusType msg_type, - const u8 *shared_secret, - size_t shared_secret_len, const u8 *addr) -{ - struct radius_msg_list *entry, *prev; - - if (eloop_terminated()) { - /* No point in adding entries to retransmit queue since event - * loop has already been terminated. */ - radius_msg_free(msg); - return; - } - - entry = os_zalloc(sizeof(*entry)); - if (entry == NULL) { - printf("Failed to add RADIUS packet into retransmit list\n"); - radius_msg_free(msg); - return; - } - - if (addr) - os_memcpy(entry->addr, addr, ETH_ALEN); - entry->msg = msg; - entry->msg_type = msg_type; - entry->shared_secret = shared_secret; - entry->shared_secret_len = shared_secret_len; - os_get_time(&entry->last_attempt); - entry->first_try = entry->last_attempt.sec; - entry->next_try = entry->first_try + RADIUS_CLIENT_FIRST_WAIT; - entry->attempts = 1; - entry->next_wait = RADIUS_CLIENT_FIRST_WAIT * 2; - entry->next = radius->msgs; - radius->msgs = entry; - radius_client_update_timeout(radius); - - if (radius->num_msgs >= RADIUS_CLIENT_MAX_ENTRIES) { - printf("Removing the oldest un-ACKed RADIUS packet due to " - "retransmit list limits.\n"); - prev = NULL; - while (entry->next) { - prev = entry; - entry = entry->next; - } - if (prev) { - prev->next = NULL; - radius_client_msg_free(entry); - } - } else - radius->num_msgs++; -} - - -static void radius_client_list_del(struct radius_client_data *radius, - RadiusType msg_type, const u8 *addr) -{ - struct radius_msg_list *entry, *prev, *tmp; - - if (addr == NULL) - return; - - entry = radius->msgs; - prev = NULL; - while (entry) { - if (entry->msg_type == msg_type && - os_memcmp(entry->addr, addr, ETH_ALEN) == 0) { - if (prev) - prev->next = entry->next; - else - radius->msgs = entry->next; - tmp = entry; - entry = entry->next; - hostapd_logger(radius->ctx, addr, - HOSTAPD_MODULE_RADIUS, - HOSTAPD_LEVEL_DEBUG, - "Removing matching RADIUS message"); - radius_client_msg_free(tmp); - radius->num_msgs--; - continue; - } - prev = entry; - entry = entry->next; - } -} - - -/** - * radius_client_send - Send a RADIUS request - * @radius: RADIUS client context from radius_client_init() - * @msg: RADIUS message to be sent - * @msg_type: Message type (RADIUS_AUTH, RADIUS_ACCT, RADIUS_ACCT_INTERIM) - * @addr: MAC address of the device related to this message or %NULL - * Returns: 0 on success, -1 on failure - * - * This function is used to transmit a RADIUS authentication (RADIUS_AUTH) or - * accounting request (RADIUS_ACCT or RADIUS_ACCT_INTERIM). The only difference - * between accounting and interim accounting messages is that the interim - * message will override any pending interim accounting updates while a new - * accounting message does not remove any pending messages. - * - * The message is added on the retransmission queue and will be retransmitted - * automatically until a response is received or maximum number of retries - * (RADIUS_CLIENT_MAX_RETRIES) is reached. - * - * The related device MAC address can be used to identify pending messages that - * can be removed with radius_client_flush_auth() or with interim accounting - * updates. - */ -int radius_client_send(struct radius_client_data *radius, - struct radius_msg *msg, RadiusType msg_type, - const u8 *addr) -{ - struct hostapd_radius_servers *conf = radius->conf; - const u8 *shared_secret; - size_t shared_secret_len; - char *name; - int s, res; - struct wpabuf *buf; - - if (msg_type == RADIUS_ACCT_INTERIM) { - /* Remove any pending interim acct update for the same STA. */ - radius_client_list_del(radius, msg_type, addr); - } - - if (msg_type == RADIUS_ACCT || msg_type == RADIUS_ACCT_INTERIM) { - if (conf->acct_server == NULL) { - hostapd_logger(radius->ctx, NULL, - HOSTAPD_MODULE_RADIUS, - HOSTAPD_LEVEL_INFO, - "No accounting server configured"); - return -1; - } - shared_secret = conf->acct_server->shared_secret; - shared_secret_len = conf->acct_server->shared_secret_len; - radius_msg_finish_acct(msg, shared_secret, shared_secret_len); - name = "accounting"; - s = radius->acct_sock; - conf->acct_server->requests++; - } else { - if (conf->auth_server == NULL) { - hostapd_logger(radius->ctx, NULL, - HOSTAPD_MODULE_RADIUS, - HOSTAPD_LEVEL_INFO, - "No authentication server configured"); - return -1; - } - shared_secret = conf->auth_server->shared_secret; - shared_secret_len = conf->auth_server->shared_secret_len; - radius_msg_finish(msg, shared_secret, shared_secret_len); - name = "authentication"; - s = radius->auth_sock; - conf->auth_server->requests++; - } - - hostapd_logger(radius->ctx, NULL, HOSTAPD_MODULE_RADIUS, - HOSTAPD_LEVEL_DEBUG, "Sending RADIUS message to %s " - "server", name); - if (conf->msg_dumps) - radius_msg_dump(msg); - - buf = radius_msg_get_buf(msg); - res = send(s, wpabuf_head(buf), wpabuf_len(buf), 0); - if (res < 0) - radius_client_handle_send_error(radius, s, msg_type); - - radius_client_list_add(radius, msg, msg_type, shared_secret, - shared_secret_len, addr); - - return res; -} - - -static void radius_client_receive(int sock, void *eloop_ctx, void *sock_ctx) -{ - struct radius_client_data *radius = eloop_ctx; - struct hostapd_radius_servers *conf = radius->conf; - RadiusType msg_type = (RadiusType) sock_ctx; - int len, roundtrip; - unsigned char buf[3000]; - struct radius_msg *msg; - struct radius_hdr *hdr; - struct radius_rx_handler *handlers; - size_t num_handlers, i; - struct radius_msg_list *req, *prev_req; - struct os_time now; - struct hostapd_radius_server *rconf; - int invalid_authenticator = 0; - - if (msg_type == RADIUS_ACCT) { - handlers = radius->acct_handlers; - num_handlers = radius->num_acct_handlers; - rconf = conf->acct_server; - } else { - handlers = radius->auth_handlers; - num_handlers = radius->num_auth_handlers; - rconf = conf->auth_server; - } - - len = recv(sock, buf, sizeof(buf), MSG_DONTWAIT); - if (len < 0) { - perror("recv[RADIUS]"); - return; - } - hostapd_logger(radius->ctx, NULL, HOSTAPD_MODULE_RADIUS, - HOSTAPD_LEVEL_DEBUG, "Received %d bytes from RADIUS " - "server", len); - if (len == sizeof(buf)) { - printf("Possibly too long UDP frame for our buffer - " - "dropping it\n"); - return; - } - - msg = radius_msg_parse(buf, len); - if (msg == NULL) { - printf("Parsing incoming RADIUS frame failed\n"); - rconf->malformed_responses++; - return; - } - hdr = radius_msg_get_hdr(msg); - - hostapd_logger(radius->ctx, NULL, HOSTAPD_MODULE_RADIUS, - HOSTAPD_LEVEL_DEBUG, "Received RADIUS message"); - if (conf->msg_dumps) - radius_msg_dump(msg); - - switch (hdr->code) { - case RADIUS_CODE_ACCESS_ACCEPT: - rconf->access_accepts++; - break; - case RADIUS_CODE_ACCESS_REJECT: - rconf->access_rejects++; - break; - case RADIUS_CODE_ACCESS_CHALLENGE: - rconf->access_challenges++; - break; - case RADIUS_CODE_ACCOUNTING_RESPONSE: - rconf->responses++; - break; - } - - prev_req = NULL; - req = radius->msgs; - while (req) { - /* TODO: also match by src addr:port of the packet when using - * alternative RADIUS servers (?) */ - if ((req->msg_type == msg_type || - (req->msg_type == RADIUS_ACCT_INTERIM && - msg_type == RADIUS_ACCT)) && - radius_msg_get_hdr(req->msg)->identifier == - hdr->identifier) - break; - - prev_req = req; - req = req->next; - } - - if (req == NULL) { - hostapd_logger(radius->ctx, NULL, HOSTAPD_MODULE_RADIUS, - HOSTAPD_LEVEL_DEBUG, - "No matching RADIUS request found (type=%d " - "id=%d) - dropping packet", - msg_type, hdr->identifier); - goto fail; - } - - os_get_time(&now); - roundtrip = (now.sec - req->last_attempt.sec) * 100 + - (now.usec - req->last_attempt.usec) / 10000; - hostapd_logger(radius->ctx, req->addr, HOSTAPD_MODULE_RADIUS, - HOSTAPD_LEVEL_DEBUG, - "Received RADIUS packet matched with a pending " - "request, round trip time %d.%02d sec", - roundtrip / 100, roundtrip % 100); - rconf->round_trip_time = roundtrip; - - /* Remove ACKed RADIUS packet from retransmit list */ - if (prev_req) - prev_req->next = req->next; - else - radius->msgs = req->next; - radius->num_msgs--; - - for (i = 0; i < num_handlers; i++) { - RadiusRxResult res; - res = handlers[i].handler(msg, req->msg, req->shared_secret, - req->shared_secret_len, - handlers[i].data); - switch (res) { - case RADIUS_RX_PROCESSED: - radius_msg_free(msg); - /* continue */ - case RADIUS_RX_QUEUED: - radius_client_msg_free(req); - return; - case RADIUS_RX_INVALID_AUTHENTICATOR: - invalid_authenticator++; - /* continue */ - case RADIUS_RX_UNKNOWN: - /* continue with next handler */ - break; - } - } - - if (invalid_authenticator) - rconf->bad_authenticators++; - else - rconf->unknown_types++; - hostapd_logger(radius->ctx, req->addr, HOSTAPD_MODULE_RADIUS, - HOSTAPD_LEVEL_DEBUG, "No RADIUS RX handler found " - "(type=%d code=%d id=%d)%s - dropping packet", - msg_type, hdr->code, hdr->identifier, - invalid_authenticator ? " [INVALID AUTHENTICATOR]" : - ""); - radius_client_msg_free(req); - - fail: - radius_msg_free(msg); -} - - -/** - * radius_client_get_id - Get an identifier for a new RADIUS message - * @radius: RADIUS client context from radius_client_init() - * Returns: Allocated identifier - * - * This function is used to fetch a unique (among pending requests) identifier - * for a new RADIUS message. - */ -u8 radius_client_get_id(struct radius_client_data *radius) -{ - struct radius_msg_list *entry, *prev, *_remove; - u8 id = radius->next_radius_identifier++; - - /* remove entries with matching id from retransmit list to avoid - * using new reply from the RADIUS server with an old request */ - entry = radius->msgs; - prev = NULL; - while (entry) { - if (radius_msg_get_hdr(entry->msg)->identifier == id) { - hostapd_logger(radius->ctx, entry->addr, - HOSTAPD_MODULE_RADIUS, - HOSTAPD_LEVEL_DEBUG, - "Removing pending RADIUS message, " - "since its id (%d) is reused", id); - if (prev) - prev->next = entry->next; - else - radius->msgs = entry->next; - _remove = entry; - } else { - _remove = NULL; - prev = entry; - } - entry = entry->next; - - if (_remove) - radius_client_msg_free(_remove); - } - - return id; -} - - -/** - * radius_client_flush - Flush all pending RADIUS client messages - * @radius: RADIUS client context from radius_client_init() - * @only_auth: Whether only authentication messages are removed - */ -void radius_client_flush(struct radius_client_data *radius, int only_auth) -{ - struct radius_msg_list *entry, *prev, *tmp; - - if (!radius) - return; - - prev = NULL; - entry = radius->msgs; - - while (entry) { - if (!only_auth || entry->msg_type == RADIUS_AUTH) { - if (prev) - prev->next = entry->next; - else - radius->msgs = entry->next; - - tmp = entry; - entry = entry->next; - radius_client_msg_free(tmp); - radius->num_msgs--; - } else { - prev = entry; - entry = entry->next; - } - } - - if (radius->msgs == NULL) - eloop_cancel_timeout(radius_client_timer, radius, NULL); -} - - -static void radius_client_update_acct_msgs(struct radius_client_data *radius, - const u8 *shared_secret, - size_t shared_secret_len) -{ - struct radius_msg_list *entry; - - if (!radius) - return; - - for (entry = radius->msgs; entry; entry = entry->next) { - if (entry->msg_type == RADIUS_ACCT) { - entry->shared_secret = shared_secret; - entry->shared_secret_len = shared_secret_len; - radius_msg_finish_acct(entry->msg, shared_secret, - shared_secret_len); - } - } -} - - -static int -radius_change_server(struct radius_client_data *radius, - struct hostapd_radius_server *nserv, - struct hostapd_radius_server *oserv, - int sock, int sock6, int auth) -{ - struct sockaddr_in serv, claddr; -#ifdef CONFIG_IPV6 - struct sockaddr_in6 serv6, claddr6; -#endif /* CONFIG_IPV6 */ - struct sockaddr *addr, *cl_addr; - socklen_t addrlen, claddrlen; - char abuf[50]; - int sel_sock; - struct radius_msg_list *entry; - struct hostapd_radius_servers *conf = radius->conf; - - hostapd_logger(radius->ctx, NULL, HOSTAPD_MODULE_RADIUS, - HOSTAPD_LEVEL_INFO, - "%s server %s:%d", - auth ? "Authentication" : "Accounting", - hostapd_ip_txt(&nserv->addr, abuf, sizeof(abuf)), - nserv->port); - - if (!oserv || nserv->shared_secret_len != oserv->shared_secret_len || - os_memcmp(nserv->shared_secret, oserv->shared_secret, - nserv->shared_secret_len) != 0) { - /* Pending RADIUS packets used different shared secret, so - * they need to be modified. Update accounting message - * authenticators here. Authentication messages are removed - * since they would require more changes and the new RADIUS - * server may not be prepared to receive them anyway due to - * missing state information. Client will likely retry - * authentication, so this should not be an issue. */ - if (auth) - radius_client_flush(radius, 1); - else { - radius_client_update_acct_msgs( - radius, nserv->shared_secret, - nserv->shared_secret_len); - } - } - - /* Reset retry counters for the new server */ - for (entry = radius->msgs; entry; entry = entry->next) { - if ((auth && entry->msg_type != RADIUS_AUTH) || - (!auth && entry->msg_type != RADIUS_ACCT)) - continue; - entry->next_try = entry->first_try + RADIUS_CLIENT_FIRST_WAIT; - entry->attempts = 0; - entry->next_wait = RADIUS_CLIENT_FIRST_WAIT * 2; - } - - if (radius->msgs) { - eloop_cancel_timeout(radius_client_timer, radius, NULL); - eloop_register_timeout(RADIUS_CLIENT_FIRST_WAIT, 0, - radius_client_timer, radius, NULL); - } - - switch (nserv->addr.af) { - case AF_INET: - os_memset(&serv, 0, sizeof(serv)); - serv.sin_family = AF_INET; - serv.sin_addr.s_addr = nserv->addr.u.v4.s_addr; - serv.sin_port = htons(nserv->port); - addr = (struct sockaddr *) &serv; - addrlen = sizeof(serv); - sel_sock = sock; - break; -#ifdef CONFIG_IPV6 - case AF_INET6: - os_memset(&serv6, 0, sizeof(serv6)); - serv6.sin6_family = AF_INET6; - os_memcpy(&serv6.sin6_addr, &nserv->addr.u.v6, - sizeof(struct in6_addr)); - serv6.sin6_port = htons(nserv->port); - addr = (struct sockaddr *) &serv6; - addrlen = sizeof(serv6); - sel_sock = sock6; - break; -#endif /* CONFIG_IPV6 */ - default: - return -1; - } - - if (conf->force_client_addr) { - switch (conf->client_addr.af) { - case AF_INET: - os_memset(&claddr, 0, sizeof(claddr)); - claddr.sin_family = AF_INET; - claddr.sin_addr.s_addr = conf->client_addr.u.v4.s_addr; - claddr.sin_port = htons(0); - cl_addr = (struct sockaddr *) &claddr; - claddrlen = sizeof(claddr); - break; -#ifdef CONFIG_IPV6 - case AF_INET6: - os_memset(&claddr6, 0, sizeof(claddr6)); - claddr6.sin6_family = AF_INET6; - os_memcpy(&claddr6.sin6_addr, &conf->client_addr.u.v6, - sizeof(struct in6_addr)); - claddr6.sin6_port = htons(0); - cl_addr = (struct sockaddr *) &claddr6; - claddrlen = sizeof(claddr6); - break; -#endif /* CONFIG_IPV6 */ - default: - return -1; - } - - if (bind(sel_sock, cl_addr, claddrlen) < 0) { - perror("bind[radius]"); - return -1; - } - } - - if (connect(sel_sock, addr, addrlen) < 0) { - perror("connect[radius]"); - return -1; - } - -#ifndef CONFIG_NATIVE_WINDOWS - switch (nserv->addr.af) { - case AF_INET: - claddrlen = sizeof(claddr); - getsockname(sel_sock, (struct sockaddr *) &claddr, &claddrlen); - wpa_printf(MSG_DEBUG, "RADIUS local address: %s:%u", - inet_ntoa(claddr.sin_addr), ntohs(claddr.sin_port)); - break; -#ifdef CONFIG_IPV6 - case AF_INET6: { - claddrlen = sizeof(claddr6); - getsockname(sel_sock, (struct sockaddr *) &claddr6, - &claddrlen); - wpa_printf(MSG_DEBUG, "RADIUS local address: %s:%u", - inet_ntop(AF_INET6, &claddr6.sin6_addr, - abuf, sizeof(abuf)), - ntohs(claddr6.sin6_port)); - break; - } -#endif /* CONFIG_IPV6 */ - } -#endif /* CONFIG_NATIVE_WINDOWS */ - - if (auth) - radius->auth_sock = sel_sock; - else - radius->acct_sock = sel_sock; - - return 0; -} - - -static void radius_retry_primary_timer(void *eloop_ctx, void *timeout_ctx) -{ - struct radius_client_data *radius = eloop_ctx; - struct hostapd_radius_servers *conf = radius->conf; - struct hostapd_radius_server *oserv; - - if (radius->auth_sock >= 0 && conf->auth_servers && - conf->auth_server != conf->auth_servers) { - oserv = conf->auth_server; - conf->auth_server = conf->auth_servers; - radius_change_server(radius, conf->auth_server, oserv, - radius->auth_serv_sock, - radius->auth_serv_sock6, 1); - } - - if (radius->acct_sock >= 0 && conf->acct_servers && - conf->acct_server != conf->acct_servers) { - oserv = conf->acct_server; - conf->acct_server = conf->acct_servers; - radius_change_server(radius, conf->acct_server, oserv, - radius->acct_serv_sock, - radius->acct_serv_sock6, 0); - } - - if (conf->retry_primary_interval) - eloop_register_timeout(conf->retry_primary_interval, 0, - radius_retry_primary_timer, radius, - NULL); -} - - -static int radius_client_disable_pmtu_discovery(int s) -{ - int r = -1; -#if defined(IP_MTU_DISCOVER) && defined(IP_PMTUDISC_DONT) - /* Turn off Path MTU discovery on IPv4/UDP sockets. */ - int action = IP_PMTUDISC_DONT; - r = setsockopt(s, IPPROTO_IP, IP_MTU_DISCOVER, &action, - sizeof(action)); - if (r == -1) - wpa_printf(MSG_ERROR, "Failed to set IP_MTU_DISCOVER: " - "%s", strerror(errno)); -#endif - return r; -} - - -static int radius_client_init_auth(struct radius_client_data *radius) -{ - struct hostapd_radius_servers *conf = radius->conf; - int ok = 0; - - radius->auth_serv_sock = socket(PF_INET, SOCK_DGRAM, 0); - if (radius->auth_serv_sock < 0) - perror("socket[PF_INET,SOCK_DGRAM]"); - else { - radius_client_disable_pmtu_discovery(radius->auth_serv_sock); - ok++; - } - -#ifdef CONFIG_IPV6 - radius->auth_serv_sock6 = socket(PF_INET6, SOCK_DGRAM, 0); - if (radius->auth_serv_sock6 < 0) - perror("socket[PF_INET6,SOCK_DGRAM]"); - else - ok++; -#endif /* CONFIG_IPV6 */ - - if (ok == 0) - return -1; - - radius_change_server(radius, conf->auth_server, NULL, - radius->auth_serv_sock, radius->auth_serv_sock6, - 1); - - if (radius->auth_serv_sock >= 0 && - eloop_register_read_sock(radius->auth_serv_sock, - radius_client_receive, radius, - (void *) RADIUS_AUTH)) { - printf("Could not register read socket for authentication " - "server\n"); - return -1; - } - -#ifdef CONFIG_IPV6 - if (radius->auth_serv_sock6 >= 0 && - eloop_register_read_sock(radius->auth_serv_sock6, - radius_client_receive, radius, - (void *) RADIUS_AUTH)) { - printf("Could not register read socket for authentication " - "server\n"); - return -1; - } -#endif /* CONFIG_IPV6 */ - - return 0; -} - - -static int radius_client_init_acct(struct radius_client_data *radius) -{ - struct hostapd_radius_servers *conf = radius->conf; - int ok = 0; - - radius->acct_serv_sock = socket(PF_INET, SOCK_DGRAM, 0); - if (radius->acct_serv_sock < 0) - perror("socket[PF_INET,SOCK_DGRAM]"); - else { - radius_client_disable_pmtu_discovery(radius->acct_serv_sock); - ok++; - } - -#ifdef CONFIG_IPV6 - radius->acct_serv_sock6 = socket(PF_INET6, SOCK_DGRAM, 0); - if (radius->acct_serv_sock6 < 0) - perror("socket[PF_INET6,SOCK_DGRAM]"); - else - ok++; -#endif /* CONFIG_IPV6 */ - - if (ok == 0) - return -1; - - radius_change_server(radius, conf->acct_server, NULL, - radius->acct_serv_sock, radius->acct_serv_sock6, - 0); - - if (radius->acct_serv_sock >= 0 && - eloop_register_read_sock(radius->acct_serv_sock, - radius_client_receive, radius, - (void *) RADIUS_ACCT)) { - printf("Could not register read socket for accounting " - "server\n"); - return -1; - } - -#ifdef CONFIG_IPV6 - if (radius->acct_serv_sock6 >= 0 && - eloop_register_read_sock(radius->acct_serv_sock6, - radius_client_receive, radius, - (void *) RADIUS_ACCT)) { - printf("Could not register read socket for accounting " - "server\n"); - return -1; - } -#endif /* CONFIG_IPV6 */ - - return 0; -} - - -/** - * radius_client_init - Initialize RADIUS client - * @ctx: Callback context to be used in hostapd_logger() calls - * @conf: RADIUS client configuration (RADIUS servers) - * Returns: Pointer to private RADIUS client context or %NULL on failure - * - * The caller is responsible for keeping the configuration data available for - * the lifetime of the RADIUS client, i.e., until radius_client_deinit() is - * called for the returned context pointer. - */ -struct radius_client_data * -radius_client_init(void *ctx, struct hostapd_radius_servers *conf) -{ - struct radius_client_data *radius; - - radius = os_zalloc(sizeof(struct radius_client_data)); - if (radius == NULL) - return NULL; - - radius->ctx = ctx; - radius->conf = conf; - radius->auth_serv_sock = radius->acct_serv_sock = - radius->auth_serv_sock6 = radius->acct_serv_sock6 = - radius->auth_sock = radius->acct_sock = -1; - - if (conf->auth_server && radius_client_init_auth(radius)) { - radius_client_deinit(radius); - return NULL; - } - - if (conf->acct_server && radius_client_init_acct(radius)) { - radius_client_deinit(radius); - return NULL; - } - - if (conf->retry_primary_interval) - eloop_register_timeout(conf->retry_primary_interval, 0, - radius_retry_primary_timer, radius, - NULL); - - return radius; -} - - -/** - * radius_client_deinit - Deinitialize RADIUS client - * @radius: RADIUS client context from radius_client_init() - */ -void radius_client_deinit(struct radius_client_data *radius) -{ - if (!radius) - return; - - if (radius->auth_serv_sock >= 0) - eloop_unregister_read_sock(radius->auth_serv_sock); - if (radius->acct_serv_sock >= 0) - eloop_unregister_read_sock(radius->acct_serv_sock); -#ifdef CONFIG_IPV6 - if (radius->auth_serv_sock6 >= 0) - eloop_unregister_read_sock(radius->auth_serv_sock6); - if (radius->acct_serv_sock6 >= 0) - eloop_unregister_read_sock(radius->acct_serv_sock6); -#endif /* CONFIG_IPV6 */ - - eloop_cancel_timeout(radius_retry_primary_timer, radius, NULL); - - radius_client_flush(radius, 0); - os_free(radius->auth_handlers); - os_free(radius->acct_handlers); - os_free(radius); -} - - -/** - * radius_client_flush_auth - Flush pending RADIUS messages for an address - * @radius: RADIUS client context from radius_client_init() - * @addr: MAC address of the related device - * - * This function can be used to remove pending RADIUS authentication messages - * that are related to a specific device. The addr parameter is matched with - * the one used in radius_client_send() call that was used to transmit the - * authentication request. - */ -void radius_client_flush_auth(struct radius_client_data *radius, - const u8 *addr) -{ - struct radius_msg_list *entry, *prev, *tmp; - - prev = NULL; - entry = radius->msgs; - while (entry) { - if (entry->msg_type == RADIUS_AUTH && - os_memcmp(entry->addr, addr, ETH_ALEN) == 0) { - hostapd_logger(radius->ctx, addr, - HOSTAPD_MODULE_RADIUS, - HOSTAPD_LEVEL_DEBUG, - "Removing pending RADIUS authentication" - " message for removed client"); - - if (prev) - prev->next = entry->next; - else - radius->msgs = entry->next; - - tmp = entry; - entry = entry->next; - radius_client_msg_free(tmp); - radius->num_msgs--; - continue; - } - - prev = entry; - entry = entry->next; - } -} - - -static int radius_client_dump_auth_server(char *buf, size_t buflen, - struct hostapd_radius_server *serv, - struct radius_client_data *cli) -{ - int pending = 0; - struct radius_msg_list *msg; - char abuf[50]; - - if (cli) { - for (msg = cli->msgs; msg; msg = msg->next) { - if (msg->msg_type == RADIUS_AUTH) - pending++; - } - } - - return os_snprintf(buf, buflen, - "radiusAuthServerIndex=%d\n" - "radiusAuthServerAddress=%s\n" - "radiusAuthClientServerPortNumber=%d\n" - "radiusAuthClientRoundTripTime=%d\n" - "radiusAuthClientAccessRequests=%u\n" - "radiusAuthClientAccessRetransmissions=%u\n" - "radiusAuthClientAccessAccepts=%u\n" - "radiusAuthClientAccessRejects=%u\n" - "radiusAuthClientAccessChallenges=%u\n" - "radiusAuthClientMalformedAccessResponses=%u\n" - "radiusAuthClientBadAuthenticators=%u\n" - "radiusAuthClientPendingRequests=%u\n" - "radiusAuthClientTimeouts=%u\n" - "radiusAuthClientUnknownTypes=%u\n" - "radiusAuthClientPacketsDropped=%u\n", - serv->index, - hostapd_ip_txt(&serv->addr, abuf, sizeof(abuf)), - serv->port, - serv->round_trip_time, - serv->requests, - serv->retransmissions, - serv->access_accepts, - serv->access_rejects, - serv->access_challenges, - serv->malformed_responses, - serv->bad_authenticators, - pending, - serv->timeouts, - serv->unknown_types, - serv->packets_dropped); -} - - -static int radius_client_dump_acct_server(char *buf, size_t buflen, - struct hostapd_radius_server *serv, - struct radius_client_data *cli) -{ - int pending = 0; - struct radius_msg_list *msg; - char abuf[50]; - - if (cli) { - for (msg = cli->msgs; msg; msg = msg->next) { - if (msg->msg_type == RADIUS_ACCT || - msg->msg_type == RADIUS_ACCT_INTERIM) - pending++; - } - } - - return os_snprintf(buf, buflen, - "radiusAccServerIndex=%d\n" - "radiusAccServerAddress=%s\n" - "radiusAccClientServerPortNumber=%d\n" - "radiusAccClientRoundTripTime=%d\n" - "radiusAccClientRequests=%u\n" - "radiusAccClientRetransmissions=%u\n" - "radiusAccClientResponses=%u\n" - "radiusAccClientMalformedResponses=%u\n" - "radiusAccClientBadAuthenticators=%u\n" - "radiusAccClientPendingRequests=%u\n" - "radiusAccClientTimeouts=%u\n" - "radiusAccClientUnknownTypes=%u\n" - "radiusAccClientPacketsDropped=%u\n", - serv->index, - hostapd_ip_txt(&serv->addr, abuf, sizeof(abuf)), - serv->port, - serv->round_trip_time, - serv->requests, - serv->retransmissions, - serv->responses, - serv->malformed_responses, - serv->bad_authenticators, - pending, - serv->timeouts, - serv->unknown_types, - serv->packets_dropped); -} - - -/** - * radius_client_get_mib - Get RADIUS client MIB information - * @radius: RADIUS client context from radius_client_init() - * @buf: Buffer for returning MIB data in text format - * @buflen: Maximum buf length in octets - * Returns: Number of octets written into the buffer - */ -int radius_client_get_mib(struct radius_client_data *radius, char *buf, - size_t buflen) -{ - struct hostapd_radius_servers *conf = radius->conf; - int i; - struct hostapd_radius_server *serv; - int count = 0; - - if (conf->auth_servers) { - for (i = 0; i < conf->num_auth_servers; i++) { - serv = &conf->auth_servers[i]; - count += radius_client_dump_auth_server( - buf + count, buflen - count, serv, - serv == conf->auth_server ? - radius : NULL); - } - } - - if (conf->acct_servers) { - for (i = 0; i < conf->num_acct_servers; i++) { - serv = &conf->acct_servers[i]; - count += radius_client_dump_acct_server( - buf + count, buflen - count, serv, - serv == conf->acct_server ? - radius : NULL); - } - } - - return count; -} - - -void radius_client_reconfig(struct radius_client_data *radius, - struct hostapd_radius_servers *conf) -{ - if (radius) - radius->conf = conf; -} diff --git a/hostapd-0.8/src/radius/radius_client.h b/hostapd-0.8/src/radius/radius_client.h deleted file mode 100644 index 18e7290..0000000 --- a/hostapd-0.8/src/radius/radius_client.h +++ /dev/null @@ -1,265 +0,0 @@ -/* - * RADIUS client - * Copyright (c) 2002-2009, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#ifndef RADIUS_CLIENT_H -#define RADIUS_CLIENT_H - -#include "ip_addr.h" - -struct radius_msg; - -/** - * struct hostapd_radius_server - RADIUS server information for RADIUS client - * - * This structure contains information about a RADIUS server. The values are - * mainly for MIB information. The MIB variable prefix (radiusAuth or - * radiusAcc) depends on whether this is an authentication or accounting - * server. - * - * radiusAuthClientPendingRequests (or radiusAccClientPendingRequests) is the - * number struct radius_client_data::msgs for matching msg_type. - */ -struct hostapd_radius_server { - /** - * addr - radiusAuthServerAddress or radiusAccServerAddress - */ - struct hostapd_ip_addr addr; - - /** - * port - radiusAuthClientServerPortNumber or radiusAccClientServerPortNumber - */ - int port; - - /** - * shared_secret - Shared secret for authenticating RADIUS messages - */ - u8 *shared_secret; - - /** - * shared_secret_len - Length of shared_secret in octets - */ - size_t shared_secret_len; - - /* Dynamic (not from configuration file) MIB data */ - - /** - * index - radiusAuthServerIndex or radiusAccServerIndex - */ - int index; - - /** - * round_trip_time - radiusAuthClientRoundTripTime or radiusAccClientRoundTripTime - * Round-trip time in hundredths of a second. - */ - int round_trip_time; - - /** - * requests - radiusAuthClientAccessRequests or radiusAccClientRequests - */ - u32 requests; - - /** - * retransmissions - radiusAuthClientAccessRetransmissions or radiusAccClientRetransmissions - */ - u32 retransmissions; - - /** - * access_accepts - radiusAuthClientAccessAccepts - */ - u32 access_accepts; - - /** - * access_rejects - radiusAuthClientAccessRejects - */ - u32 access_rejects; - - /** - * access_challenges - radiusAuthClientAccessChallenges - */ - u32 access_challenges; - - /** - * responses - radiusAccClientResponses - */ - u32 responses; - - /** - * malformed_responses - radiusAuthClientMalformedAccessResponses or radiusAccClientMalformedResponses - */ - u32 malformed_responses; - - /** - * bad_authenticators - radiusAuthClientBadAuthenticators or radiusAccClientBadAuthenticators - */ - u32 bad_authenticators; - - /** - * timeouts - radiusAuthClientTimeouts or radiusAccClientTimeouts - */ - u32 timeouts; - - /** - * unknown_types - radiusAuthClientUnknownTypes or radiusAccClientUnknownTypes - */ - u32 unknown_types; - - /** - * packets_dropped - radiusAuthClientPacketsDropped or radiusAccClientPacketsDropped - */ - u32 packets_dropped; -}; - -/** - * struct hostapd_radius_servers - RADIUS servers for RADIUS client - */ -struct hostapd_radius_servers { - /** - * auth_servers - RADIUS Authentication servers in priority order - */ - struct hostapd_radius_server *auth_servers; - - /** - * num_auth_servers - Number of auth_servers entries - */ - int num_auth_servers; - - /** - * auth_server - The current Authentication server - */ - struct hostapd_radius_server *auth_server; - - /** - * acct_servers - RADIUS Accounting servers in priority order - */ - struct hostapd_radius_server *acct_servers; - - /** - * num_acct_servers - Number of acct_servers entries - */ - int num_acct_servers; - - /** - * acct_server - The current Accounting server - */ - struct hostapd_radius_server *acct_server; - - /** - * retry_primary_interval - Retry interval for trying primary server - * - * This specifies a retry interval in sexconds for trying to return to - * the primary RADIUS server. RADIUS client code will automatically try - * to use the next server when the current server is not replying to - * requests. If this interval is set (non-zero), the primary server - * will be retried after the specified number of seconds has passed - * even if the current used secondary server is still working. - */ - int retry_primary_interval; - - /** - * msg_dumps - Whether RADIUS message details are shown in stdout - */ - int msg_dumps; - - /** - * client_addr - Client (local) address to use if force_client_addr - */ - struct hostapd_ip_addr client_addr; - - /** - * force_client_addr - Whether to force client (local) address - */ - int force_client_addr; -}; - - -/** - * RadiusType - RADIUS server type for RADIUS client - */ -typedef enum { - /** - * RADIUS authentication - */ - RADIUS_AUTH, - - /** - * RADIUS_ACCT - RADIUS accounting - */ - RADIUS_ACCT, - - /** - * RADIUS_ACCT_INTERIM - RADIUS interim accounting message - * - * Used only with radius_client_send(). This behaves just like - * RADIUS_ACCT, but removes any pending interim RADIUS Accounting - * messages for the same STA before sending the new interim update. - */ - RADIUS_ACCT_INTERIM -} RadiusType; - -/** - * RadiusRxResult - RADIUS client RX handler result - */ -typedef enum { - /** - * RADIUS_RX_PROCESSED - Message processed - * - * This stops handler calls and frees the message. - */ - RADIUS_RX_PROCESSED, - - /** - * RADIUS_RX_QUEUED - Message has been queued - * - * This stops handler calls, but does not free the message; the handler - * that returned this is responsible for eventually freeing the - * message. - */ - RADIUS_RX_QUEUED, - - /** - * RADIUS_RX_UNKNOWN - Message is not for this handler - */ - RADIUS_RX_UNKNOWN, - - /** - * RADIUS_RX_INVALID_AUTHENTICATOR - Message has invalid Authenticator - */ - RADIUS_RX_INVALID_AUTHENTICATOR -} RadiusRxResult; - -struct radius_client_data; - -int radius_client_register(struct radius_client_data *radius, - RadiusType msg_type, - RadiusRxResult (*handler) - (struct radius_msg *msg, struct radius_msg *req, - const u8 *shared_secret, size_t shared_secret_len, - void *data), - void *data); -int radius_client_send(struct radius_client_data *radius, - struct radius_msg *msg, - RadiusType msg_type, const u8 *addr); -u8 radius_client_get_id(struct radius_client_data *radius); -void radius_client_flush(struct radius_client_data *radius, int only_auth); -struct radius_client_data * -radius_client_init(void *ctx, struct hostapd_radius_servers *conf); -void radius_client_deinit(struct radius_client_data *radius); -void radius_client_flush_auth(struct radius_client_data *radius, - const u8 *addr); -int radius_client_get_mib(struct radius_client_data *radius, char *buf, - size_t buflen); -void radius_client_reconfig(struct radius_client_data *radius, - struct hostapd_radius_servers *conf); - -#endif /* RADIUS_CLIENT_H */ diff --git a/hostapd-0.8/src/radius/radius_server.c b/hostapd-0.8/src/radius/radius_server.c deleted file mode 100644 index 6f1c3a5..0000000 --- a/hostapd-0.8/src/radius/radius_server.c +++ /dev/null @@ -1,1527 +0,0 @@ -/* - * RADIUS authentication server - * Copyright (c) 2005-2009, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#include "includes.h" -#include - -#include "common.h" -#include "radius.h" -#include "eloop.h" -#include "eap_server/eap.h" -#include "radius_server.h" - -/** - * RADIUS_SESSION_TIMEOUT - Session timeout in seconds - */ -#define RADIUS_SESSION_TIMEOUT 60 - -/** - * RADIUS_MAX_SESSION - Maximum number of active sessions - */ -#define RADIUS_MAX_SESSION 100 - -/** - * RADIUS_MAX_MSG_LEN - Maximum message length for incoming RADIUS messages - */ -#define RADIUS_MAX_MSG_LEN 3000 - -static struct eapol_callbacks radius_server_eapol_cb; - -struct radius_client; -struct radius_server_data; - -/** - * struct radius_server_counters - RADIUS server statistics counters - */ -struct radius_server_counters { - u32 access_requests; - u32 invalid_requests; - u32 dup_access_requests; - u32 access_accepts; - u32 access_rejects; - u32 access_challenges; - u32 malformed_access_requests; - u32 bad_authenticators; - u32 packets_dropped; - u32 unknown_types; -}; - -/** - * struct radius_session - Internal RADIUS server data for a session - */ -struct radius_session { - struct radius_session *next; - struct radius_client *client; - struct radius_server_data *server; - unsigned int sess_id; - struct eap_sm *eap; - struct eap_eapol_interface *eap_if; - - struct radius_msg *last_msg; - char *last_from_addr; - int last_from_port; - struct sockaddr_storage last_from; - socklen_t last_fromlen; - u8 last_identifier; - struct radius_msg *last_reply; - u8 last_authenticator[16]; -}; - -/** - * struct radius_client - Internal RADIUS server data for a client - */ -struct radius_client { - struct radius_client *next; - struct in_addr addr; - struct in_addr mask; -#ifdef CONFIG_IPV6 - struct in6_addr addr6; - struct in6_addr mask6; -#endif /* CONFIG_IPV6 */ - char *shared_secret; - int shared_secret_len; - struct radius_session *sessions; - struct radius_server_counters counters; -}; - -/** - * struct radius_server_data - Internal RADIUS server data - */ -struct radius_server_data { - /** - * auth_sock - Socket for RADIUS authentication messages - */ - int auth_sock; - - /** - * clients - List of authorized RADIUS clients - */ - struct radius_client *clients; - - /** - * next_sess_id - Next session identifier - */ - unsigned int next_sess_id; - - /** - * conf_ctx - Context pointer for callbacks - * - * This is used as the ctx argument in get_eap_user() calls. - */ - void *conf_ctx; - - /** - * num_sess - Number of active sessions - */ - int num_sess; - - /** - * eap_sim_db_priv - EAP-SIM/AKA database context - * - * This is passed to the EAP-SIM/AKA server implementation as a - * callback context. - */ - void *eap_sim_db_priv; - - /** - * ssl_ctx - TLS context - * - * This is passed to the EAP server implementation as a callback - * context for TLS operations. - */ - void *ssl_ctx; - - /** - * pac_opaque_encr_key - PAC-Opaque encryption key for EAP-FAST - * - * This parameter is used to set a key for EAP-FAST to encrypt the - * PAC-Opaque data. It can be set to %NULL if EAP-FAST is not used. If - * set, must point to a 16-octet key. - */ - u8 *pac_opaque_encr_key; - - /** - * eap_fast_a_id - EAP-FAST authority identity (A-ID) - * - * If EAP-FAST is not used, this can be set to %NULL. In theory, this - * is a variable length field, but due to some existing implementations - * requiring A-ID to be 16 octets in length, it is recommended to use - * that length for the field to provide interoperability with deployed - * peer implementations. - */ - u8 *eap_fast_a_id; - - /** - * eap_fast_a_id_len - Length of eap_fast_a_id buffer in octets - */ - size_t eap_fast_a_id_len; - - /** - * eap_fast_a_id_info - EAP-FAST authority identifier information - * - * This A-ID-Info contains a user-friendly name for the A-ID. For - * example, this could be the enterprise and server names in - * human-readable format. This field is encoded as UTF-8. If EAP-FAST - * is not used, this can be set to %NULL. - */ - char *eap_fast_a_id_info; - - /** - * eap_fast_prov - EAP-FAST provisioning modes - * - * 0 = provisioning disabled, 1 = only anonymous provisioning allowed, - * 2 = only authenticated provisioning allowed, 3 = both provisioning - * modes allowed. - */ - int eap_fast_prov; - - /** - * pac_key_lifetime - EAP-FAST PAC-Key lifetime in seconds - * - * This is the hard limit on how long a provisioned PAC-Key can be - * used. - */ - int pac_key_lifetime; - - /** - * pac_key_refresh_time - EAP-FAST PAC-Key refresh time in seconds - * - * This is a soft limit on the PAC-Key. The server will automatically - * generate a new PAC-Key when this number of seconds (or fewer) of the - * lifetime remains. - */ - int pac_key_refresh_time; - - /** - * eap_sim_aka_result_ind - EAP-SIM/AKA protected success indication - * - * This controls whether the protected success/failure indication - * (AT_RESULT_IND) is used with EAP-SIM and EAP-AKA. - */ - int eap_sim_aka_result_ind; - - /** - * tnc - Trusted Network Connect (TNC) - * - * This controls whether TNC is enabled and will be required before the - * peer is allowed to connect. Note: This is only used with EAP-TTLS - * and EAP-FAST. If any other EAP method is enabled, the peer will be - * allowed to connect without TNC. - */ - int tnc; - - /** - * pwd_group - The D-H group assigned for EAP-pwd - * - * If EAP-pwd is not used it can be set to zero. - */ - u16 pwd_group; - - /** - * wps - Wi-Fi Protected Setup context - * - * If WPS is used with an external RADIUS server (which is quite - * unlikely configuration), this is used to provide a pointer to WPS - * context data. Normally, this can be set to %NULL. - */ - struct wps_context *wps; - - /** - * ipv6 - Whether to enable IPv6 support in the RADIUS server - */ - int ipv6; - - /** - * start_time - Timestamp of server start - */ - struct os_time start_time; - - /** - * counters - Statistics counters for server operations - * - * These counters are the sum over all clients. - */ - struct radius_server_counters counters; - - /** - * get_eap_user - Callback for fetching EAP user information - * @ctx: Context data from conf_ctx - * @identity: User identity - * @identity_len: identity buffer length in octets - * @phase2: Whether this is for Phase 2 identity - * @user: Data structure for filling in the user information - * Returns: 0 on success, -1 on failure - * - * This is used to fetch information from user database. The callback - * will fill in information about allowed EAP methods and the user - * password. The password field will be an allocated copy of the - * password data and RADIUS server will free it after use. - */ - int (*get_eap_user)(void *ctx, const u8 *identity, size_t identity_len, - int phase2, struct eap_user *user); - - /** - * eap_req_id_text - Optional data for EAP-Request/Identity - * - * This can be used to configure an optional, displayable message that - * will be sent in EAP-Request/Identity. This string can contain an - * ASCII-0 character (nul) to separate network infromation per RFC - * 4284. The actual string length is explicit provided in - * eap_req_id_text_len since nul character will not be used as a string - * terminator. - */ - char *eap_req_id_text; - - /** - * eap_req_id_text_len - Length of eap_req_id_text buffer in octets - */ - size_t eap_req_id_text_len; - - /* - * msg_ctx - Context data for wpa_msg() calls - */ - void *msg_ctx; -}; - - -extern int wpa_debug_level; - -#define RADIUS_DEBUG(args...) \ -wpa_printf(MSG_DEBUG, "RADIUS SRV: " args) -#define RADIUS_ERROR(args...) \ -wpa_printf(MSG_ERROR, "RADIUS SRV: " args) -#define RADIUS_DUMP(args...) \ -wpa_hexdump(MSG_MSGDUMP, "RADIUS SRV: " args) -#define RADIUS_DUMP_ASCII(args...) \ -wpa_hexdump_ascii(MSG_MSGDUMP, "RADIUS SRV: " args) - - -static void radius_server_session_timeout(void *eloop_ctx, void *timeout_ctx); -static void radius_server_session_remove_timeout(void *eloop_ctx, - void *timeout_ctx); - - -static struct radius_client * -radius_server_get_client(struct radius_server_data *data, struct in_addr *addr, - int ipv6) -{ - struct radius_client *client = data->clients; - - while (client) { -#ifdef CONFIG_IPV6 - if (ipv6) { - struct in6_addr *addr6; - int i; - - addr6 = (struct in6_addr *) addr; - for (i = 0; i < 16; i++) { - if ((addr6->s6_addr[i] & - client->mask6.s6_addr[i]) != - (client->addr6.s6_addr[i] & - client->mask6.s6_addr[i])) { - i = 17; - break; - } - } - if (i == 16) { - break; - } - } -#endif /* CONFIG_IPV6 */ - if (!ipv6 && (client->addr.s_addr & client->mask.s_addr) == - (addr->s_addr & client->mask.s_addr)) { - break; - } - - client = client->next; - } - - return client; -} - - -static struct radius_session * -radius_server_get_session(struct radius_client *client, unsigned int sess_id) -{ - struct radius_session *sess = client->sessions; - - while (sess) { - if (sess->sess_id == sess_id) { - break; - } - sess = sess->next; - } - - return sess; -} - - -static void radius_server_session_free(struct radius_server_data *data, - struct radius_session *sess) -{ - eloop_cancel_timeout(radius_server_session_timeout, data, sess); - eloop_cancel_timeout(radius_server_session_remove_timeout, data, sess); - eap_server_sm_deinit(sess->eap); - radius_msg_free(sess->last_msg); - os_free(sess->last_from_addr); - radius_msg_free(sess->last_reply); - os_free(sess); - data->num_sess--; -} - - -static void radius_server_session_remove(struct radius_server_data *data, - struct radius_session *sess) -{ - struct radius_client *client = sess->client; - struct radius_session *session, *prev; - - eloop_cancel_timeout(radius_server_session_remove_timeout, data, sess); - - prev = NULL; - session = client->sessions; - while (session) { - if (session == sess) { - if (prev == NULL) { - client->sessions = sess->next; - } else { - prev->next = sess->next; - } - radius_server_session_free(data, sess); - break; - } - prev = session; - session = session->next; - } -} - - -static void radius_server_session_remove_timeout(void *eloop_ctx, - void *timeout_ctx) -{ - struct radius_server_data *data = eloop_ctx; - struct radius_session *sess = timeout_ctx; - RADIUS_DEBUG("Removing completed session 0x%x", sess->sess_id); - radius_server_session_remove(data, sess); -} - - -static void radius_server_session_timeout(void *eloop_ctx, void *timeout_ctx) -{ - struct radius_server_data *data = eloop_ctx; - struct radius_session *sess = timeout_ctx; - - RADIUS_DEBUG("Timing out authentication session 0x%x", sess->sess_id); - radius_server_session_remove(data, sess); -} - - -static struct radius_session * -radius_server_new_session(struct radius_server_data *data, - struct radius_client *client) -{ - struct radius_session *sess; - - if (data->num_sess >= RADIUS_MAX_SESSION) { - RADIUS_DEBUG("Maximum number of existing session - no room " - "for a new session"); - return NULL; - } - - sess = os_zalloc(sizeof(*sess)); - if (sess == NULL) - return NULL; - - sess->server = data; - sess->client = client; - sess->sess_id = data->next_sess_id++; - sess->next = client->sessions; - client->sessions = sess; - eloop_register_timeout(RADIUS_SESSION_TIMEOUT, 0, - radius_server_session_timeout, data, sess); - data->num_sess++; - return sess; -} - - -static struct radius_session * -radius_server_get_new_session(struct radius_server_data *data, - struct radius_client *client, - struct radius_msg *msg) -{ - u8 *user; - size_t user_len; - int res; - struct radius_session *sess; - struct eap_config eap_conf; - - RADIUS_DEBUG("Creating a new session"); - - user = os_malloc(256); - if (user == NULL) { - return NULL; - } - res = radius_msg_get_attr(msg, RADIUS_ATTR_USER_NAME, user, 256); - if (res < 0 || res > 256) { - RADIUS_DEBUG("Could not get User-Name"); - os_free(user); - return NULL; - } - user_len = res; - RADIUS_DUMP_ASCII("User-Name", user, user_len); - - res = data->get_eap_user(data->conf_ctx, user, user_len, 0, NULL); - os_free(user); - - if (res == 0) { - RADIUS_DEBUG("Matching user entry found"); - sess = radius_server_new_session(data, client); - if (sess == NULL) { - RADIUS_DEBUG("Failed to create a new session"); - return NULL; - } - } else { - RADIUS_DEBUG("User-Name not found from user database"); - return NULL; - } - - os_memset(&eap_conf, 0, sizeof(eap_conf)); - eap_conf.ssl_ctx = data->ssl_ctx; - eap_conf.msg_ctx = data->msg_ctx; - eap_conf.eap_sim_db_priv = data->eap_sim_db_priv; - eap_conf.backend_auth = TRUE; - eap_conf.eap_server = 1; - eap_conf.pac_opaque_encr_key = data->pac_opaque_encr_key; - eap_conf.eap_fast_a_id = data->eap_fast_a_id; - eap_conf.eap_fast_a_id_len = data->eap_fast_a_id_len; - eap_conf.eap_fast_a_id_info = data->eap_fast_a_id_info; - eap_conf.eap_fast_prov = data->eap_fast_prov; - eap_conf.pac_key_lifetime = data->pac_key_lifetime; - eap_conf.pac_key_refresh_time = data->pac_key_refresh_time; - eap_conf.eap_sim_aka_result_ind = data->eap_sim_aka_result_ind; - eap_conf.tnc = data->tnc; - eap_conf.wps = data->wps; - eap_conf.pwd_group = data->pwd_group; - sess->eap = eap_server_sm_init(sess, &radius_server_eapol_cb, - &eap_conf); - if (sess->eap == NULL) { - RADIUS_DEBUG("Failed to initialize EAP state machine for the " - "new session"); - radius_server_session_free(data, sess); - return NULL; - } - sess->eap_if = eap_get_interface(sess->eap); - sess->eap_if->eapRestart = TRUE; - sess->eap_if->portEnabled = TRUE; - - RADIUS_DEBUG("New session 0x%x initialized", sess->sess_id); - - return sess; -} - - -static struct radius_msg * -radius_server_encapsulate_eap(struct radius_server_data *data, - struct radius_client *client, - struct radius_session *sess, - struct radius_msg *request) -{ - struct radius_msg *msg; - int code; - unsigned int sess_id; - struct radius_hdr *hdr = radius_msg_get_hdr(request); - - if (sess->eap_if->eapFail) { - sess->eap_if->eapFail = FALSE; - code = RADIUS_CODE_ACCESS_REJECT; - } else if (sess->eap_if->eapSuccess) { - sess->eap_if->eapSuccess = FALSE; - code = RADIUS_CODE_ACCESS_ACCEPT; - } else { - sess->eap_if->eapReq = FALSE; - code = RADIUS_CODE_ACCESS_CHALLENGE; - } - - msg = radius_msg_new(code, hdr->identifier); - if (msg == NULL) { - RADIUS_DEBUG("Failed to allocate reply message"); - return NULL; - } - - sess_id = htonl(sess->sess_id); - if (code == RADIUS_CODE_ACCESS_CHALLENGE && - !radius_msg_add_attr(msg, RADIUS_ATTR_STATE, - (u8 *) &sess_id, sizeof(sess_id))) { - RADIUS_DEBUG("Failed to add State attribute"); - } - - if (sess->eap_if->eapReqData && - !radius_msg_add_eap(msg, wpabuf_head(sess->eap_if->eapReqData), - wpabuf_len(sess->eap_if->eapReqData))) { - RADIUS_DEBUG("Failed to add EAP-Message attribute"); - } - - if (code == RADIUS_CODE_ACCESS_ACCEPT && sess->eap_if->eapKeyData) { - int len; - if (sess->eap_if->eapKeyDataLen > 64) { - len = 32; - } else { - len = sess->eap_if->eapKeyDataLen / 2; - } - if (!radius_msg_add_mppe_keys(msg, hdr->authenticator, - (u8 *) client->shared_secret, - client->shared_secret_len, - sess->eap_if->eapKeyData + len, - len, sess->eap_if->eapKeyData, - len)) { - RADIUS_DEBUG("Failed to add MPPE key attributes"); - } - } - - if (radius_msg_copy_attr(msg, request, RADIUS_ATTR_PROXY_STATE) < 0) { - RADIUS_DEBUG("Failed to copy Proxy-State attribute(s)"); - radius_msg_free(msg); - return NULL; - } - - if (radius_msg_finish_srv(msg, (u8 *) client->shared_secret, - client->shared_secret_len, - hdr->authenticator) < 0) { - RADIUS_DEBUG("Failed to add Message-Authenticator attribute"); - } - - return msg; -} - - -static int radius_server_reject(struct radius_server_data *data, - struct radius_client *client, - struct radius_msg *request, - struct sockaddr *from, socklen_t fromlen, - const char *from_addr, int from_port) -{ - struct radius_msg *msg; - int ret = 0; - struct eap_hdr eapfail; - struct wpabuf *buf; - struct radius_hdr *hdr = radius_msg_get_hdr(request); - - RADIUS_DEBUG("Reject invalid request from %s:%d", - from_addr, from_port); - - msg = radius_msg_new(RADIUS_CODE_ACCESS_REJECT, hdr->identifier); - if (msg == NULL) { - return -1; - } - - os_memset(&eapfail, 0, sizeof(eapfail)); - eapfail.code = EAP_CODE_FAILURE; - eapfail.identifier = 0; - eapfail.length = host_to_be16(sizeof(eapfail)); - - if (!radius_msg_add_eap(msg, (u8 *) &eapfail, sizeof(eapfail))) { - RADIUS_DEBUG("Failed to add EAP-Message attribute"); - } - - if (radius_msg_copy_attr(msg, request, RADIUS_ATTR_PROXY_STATE) < 0) { - RADIUS_DEBUG("Failed to copy Proxy-State attribute(s)"); - radius_msg_free(msg); - return -1; - } - - if (radius_msg_finish_srv(msg, (u8 *) client->shared_secret, - client->shared_secret_len, - hdr->authenticator) < - 0) { - RADIUS_DEBUG("Failed to add Message-Authenticator attribute"); - } - - if (wpa_debug_level <= MSG_MSGDUMP) { - radius_msg_dump(msg); - } - - data->counters.access_rejects++; - client->counters.access_rejects++; - buf = radius_msg_get_buf(msg); - if (sendto(data->auth_sock, wpabuf_head(buf), wpabuf_len(buf), 0, - (struct sockaddr *) from, sizeof(*from)) < 0) { - perror("sendto[RADIUS SRV]"); - ret = -1; - } - - radius_msg_free(msg); - - return ret; -} - - -static int radius_server_request(struct radius_server_data *data, - struct radius_msg *msg, - struct sockaddr *from, socklen_t fromlen, - struct radius_client *client, - const char *from_addr, int from_port, - struct radius_session *force_sess) -{ - u8 *eap = NULL; - size_t eap_len; - int res, state_included = 0; - u8 statebuf[4]; - unsigned int state; - struct radius_session *sess; - struct radius_msg *reply; - int is_complete = 0; - - if (force_sess) - sess = force_sess; - else { - res = radius_msg_get_attr(msg, RADIUS_ATTR_STATE, statebuf, - sizeof(statebuf)); - state_included = res >= 0; - if (res == sizeof(statebuf)) { - state = WPA_GET_BE32(statebuf); - sess = radius_server_get_session(client, state); - } else { - sess = NULL; - } - } - - if (sess) { - RADIUS_DEBUG("Request for session 0x%x", sess->sess_id); - } else if (state_included) { - RADIUS_DEBUG("State attribute included but no session found"); - radius_server_reject(data, client, msg, from, fromlen, - from_addr, from_port); - return -1; - } else { - sess = radius_server_get_new_session(data, client, msg); - if (sess == NULL) { - RADIUS_DEBUG("Could not create a new session"); - radius_server_reject(data, client, msg, from, fromlen, - from_addr, from_port); - return -1; - } - } - - if (sess->last_from_port == from_port && - sess->last_identifier == radius_msg_get_hdr(msg)->identifier && - os_memcmp(sess->last_authenticator, - radius_msg_get_hdr(msg)->authenticator, 16) == 0) { - RADIUS_DEBUG("Duplicate message from %s", from_addr); - data->counters.dup_access_requests++; - client->counters.dup_access_requests++; - - if (sess->last_reply) { - struct wpabuf *buf; - buf = radius_msg_get_buf(sess->last_reply); - res = sendto(data->auth_sock, wpabuf_head(buf), - wpabuf_len(buf), 0, - (struct sockaddr *) from, fromlen); - if (res < 0) { - perror("sendto[RADIUS SRV]"); - } - return 0; - } - - RADIUS_DEBUG("No previous reply available for duplicate " - "message"); - return -1; - } - - eap = radius_msg_get_eap(msg, &eap_len); - if (eap == NULL) { - RADIUS_DEBUG("No EAP-Message in RADIUS packet from %s", - from_addr); - data->counters.packets_dropped++; - client->counters.packets_dropped++; - return -1; - } - - RADIUS_DUMP("Received EAP data", eap, eap_len); - - /* FIX: if Code is Request, Success, or Failure, send Access-Reject; - * RFC3579 Sect. 2.6.2. - * Include EAP-Response/Nak with no preferred method if - * code == request. - * If code is not 1-4, discard the packet silently. - * Or is this already done by the EAP state machine? */ - - wpabuf_free(sess->eap_if->eapRespData); - sess->eap_if->eapRespData = wpabuf_alloc_ext_data(eap, eap_len); - if (sess->eap_if->eapRespData == NULL) - os_free(eap); - eap = NULL; - sess->eap_if->eapResp = TRUE; - eap_server_sm_step(sess->eap); - - if ((sess->eap_if->eapReq || sess->eap_if->eapSuccess || - sess->eap_if->eapFail) && sess->eap_if->eapReqData) { - RADIUS_DUMP("EAP data from the state machine", - wpabuf_head(sess->eap_if->eapReqData), - wpabuf_len(sess->eap_if->eapReqData)); - } else if (sess->eap_if->eapFail) { - RADIUS_DEBUG("No EAP data from the state machine, but eapFail " - "set"); - } else if (eap_sm_method_pending(sess->eap)) { - radius_msg_free(sess->last_msg); - sess->last_msg = msg; - sess->last_from_port = from_port; - os_free(sess->last_from_addr); - sess->last_from_addr = os_strdup(from_addr); - sess->last_fromlen = fromlen; - os_memcpy(&sess->last_from, from, fromlen); - return -2; - } else { - RADIUS_DEBUG("No EAP data from the state machine - ignore this" - " Access-Request silently (assuming it was a " - "duplicate)"); - data->counters.packets_dropped++; - client->counters.packets_dropped++; - return -1; - } - - if (sess->eap_if->eapSuccess || sess->eap_if->eapFail) - is_complete = 1; - - reply = radius_server_encapsulate_eap(data, client, sess, msg); - - if (reply) { - struct wpabuf *buf; - struct radius_hdr *hdr; - - RADIUS_DEBUG("Reply to %s:%d", from_addr, from_port); - if (wpa_debug_level <= MSG_MSGDUMP) { - radius_msg_dump(reply); - } - - switch (radius_msg_get_hdr(reply)->code) { - case RADIUS_CODE_ACCESS_ACCEPT: - data->counters.access_accepts++; - client->counters.access_accepts++; - break; - case RADIUS_CODE_ACCESS_REJECT: - data->counters.access_rejects++; - client->counters.access_rejects++; - break; - case RADIUS_CODE_ACCESS_CHALLENGE: - data->counters.access_challenges++; - client->counters.access_challenges++; - break; - } - buf = radius_msg_get_buf(reply); - res = sendto(data->auth_sock, wpabuf_head(buf), - wpabuf_len(buf), 0, - (struct sockaddr *) from, fromlen); - if (res < 0) { - perror("sendto[RADIUS SRV]"); - } - radius_msg_free(sess->last_reply); - sess->last_reply = reply; - sess->last_from_port = from_port; - hdr = radius_msg_get_hdr(msg); - sess->last_identifier = hdr->identifier; - os_memcpy(sess->last_authenticator, hdr->authenticator, 16); - } else { - data->counters.packets_dropped++; - client->counters.packets_dropped++; - } - - if (is_complete) { - RADIUS_DEBUG("Removing completed session 0x%x after timeout", - sess->sess_id); - eloop_cancel_timeout(radius_server_session_remove_timeout, - data, sess); - eloop_register_timeout(10, 0, - radius_server_session_remove_timeout, - data, sess); - } - - return 0; -} - - -static void radius_server_receive_auth(int sock, void *eloop_ctx, - void *sock_ctx) -{ - struct radius_server_data *data = eloop_ctx; - u8 *buf = NULL; - union { - struct sockaddr_storage ss; - struct sockaddr_in sin; -#ifdef CONFIG_IPV6 - struct sockaddr_in6 sin6; -#endif /* CONFIG_IPV6 */ - } from; - socklen_t fromlen; - int len; - struct radius_client *client = NULL; - struct radius_msg *msg = NULL; - char abuf[50]; - int from_port = 0; - - buf = os_malloc(RADIUS_MAX_MSG_LEN); - if (buf == NULL) { - goto fail; - } - - fromlen = sizeof(from); - len = recvfrom(sock, buf, RADIUS_MAX_MSG_LEN, 0, - (struct sockaddr *) &from.ss, &fromlen); - if (len < 0) { - perror("recvfrom[radius_server]"); - goto fail; - } - -#ifdef CONFIG_IPV6 - if (data->ipv6) { - if (inet_ntop(AF_INET6, &from.sin6.sin6_addr, abuf, - sizeof(abuf)) == NULL) - abuf[0] = '\0'; - from_port = ntohs(from.sin6.sin6_port); - RADIUS_DEBUG("Received %d bytes from %s:%d", - len, abuf, from_port); - - client = radius_server_get_client(data, - (struct in_addr *) - &from.sin6.sin6_addr, 1); - } -#endif /* CONFIG_IPV6 */ - - if (!data->ipv6) { - os_strlcpy(abuf, inet_ntoa(from.sin.sin_addr), sizeof(abuf)); - from_port = ntohs(from.sin.sin_port); - RADIUS_DEBUG("Received %d bytes from %s:%d", - len, abuf, from_port); - - client = radius_server_get_client(data, &from.sin.sin_addr, 0); - } - - RADIUS_DUMP("Received data", buf, len); - - if (client == NULL) { - RADIUS_DEBUG("Unknown client %s - packet ignored", abuf); - data->counters.invalid_requests++; - goto fail; - } - - msg = radius_msg_parse(buf, len); - if (msg == NULL) { - RADIUS_DEBUG("Parsing incoming RADIUS frame failed"); - data->counters.malformed_access_requests++; - client->counters.malformed_access_requests++; - goto fail; - } - - os_free(buf); - buf = NULL; - - if (wpa_debug_level <= MSG_MSGDUMP) { - radius_msg_dump(msg); - } - - if (radius_msg_get_hdr(msg)->code != RADIUS_CODE_ACCESS_REQUEST) { - RADIUS_DEBUG("Unexpected RADIUS code %d", - radius_msg_get_hdr(msg)->code); - data->counters.unknown_types++; - client->counters.unknown_types++; - goto fail; - } - - data->counters.access_requests++; - client->counters.access_requests++; - - if (radius_msg_verify_msg_auth(msg, (u8 *) client->shared_secret, - client->shared_secret_len, NULL)) { - RADIUS_DEBUG("Invalid Message-Authenticator from %s", abuf); - data->counters.bad_authenticators++; - client->counters.bad_authenticators++; - goto fail; - } - - if (radius_server_request(data, msg, (struct sockaddr *) &from, - fromlen, client, abuf, from_port, NULL) == - -2) - return; /* msg was stored with the session */ - -fail: - radius_msg_free(msg); - os_free(buf); -} - - -static int radius_server_disable_pmtu_discovery(int s) -{ - int r = -1; -#if defined(IP_MTU_DISCOVER) && defined(IP_PMTUDISC_DONT) - /* Turn off Path MTU discovery on IPv4/UDP sockets. */ - int action = IP_PMTUDISC_DONT; - r = setsockopt(s, IPPROTO_IP, IP_MTU_DISCOVER, &action, - sizeof(action)); - if (r == -1) - wpa_printf(MSG_ERROR, "Failed to set IP_MTU_DISCOVER: " - "%s", strerror(errno)); -#endif - return r; -} - - -static int radius_server_open_socket(int port) -{ - int s; - struct sockaddr_in addr; - - s = socket(PF_INET, SOCK_DGRAM, 0); - if (s < 0) { - perror("socket"); - return -1; - } - - radius_server_disable_pmtu_discovery(s); - - os_memset(&addr, 0, sizeof(addr)); - addr.sin_family = AF_INET; - addr.sin_port = htons(port); - if (bind(s, (struct sockaddr *) &addr, sizeof(addr)) < 0) { - perror("bind"); - close(s); - return -1; - } - - return s; -} - - -#ifdef CONFIG_IPV6 -static int radius_server_open_socket6(int port) -{ - int s; - struct sockaddr_in6 addr; - - s = socket(PF_INET6, SOCK_DGRAM, 0); - if (s < 0) { - perror("socket[IPv6]"); - return -1; - } - - os_memset(&addr, 0, sizeof(addr)); - addr.sin6_family = AF_INET6; - os_memcpy(&addr.sin6_addr, &in6addr_any, sizeof(in6addr_any)); - addr.sin6_port = htons(port); - if (bind(s, (struct sockaddr *) &addr, sizeof(addr)) < 0) { - perror("bind"); - close(s); - return -1; - } - - return s; -} -#endif /* CONFIG_IPV6 */ - - -static void radius_server_free_sessions(struct radius_server_data *data, - struct radius_session *sessions) -{ - struct radius_session *session, *prev; - - session = sessions; - while (session) { - prev = session; - session = session->next; - radius_server_session_free(data, prev); - } -} - - -static void radius_server_free_clients(struct radius_server_data *data, - struct radius_client *clients) -{ - struct radius_client *client, *prev; - - client = clients; - while (client) { - prev = client; - client = client->next; - - radius_server_free_sessions(data, prev->sessions); - os_free(prev->shared_secret); - os_free(prev); - } -} - - -static struct radius_client * -radius_server_read_clients(const char *client_file, int ipv6) -{ - FILE *f; - const int buf_size = 1024; - char *buf, *pos; - struct radius_client *clients, *tail, *entry; - int line = 0, mask, failed = 0, i; - struct in_addr addr; -#ifdef CONFIG_IPV6 - struct in6_addr addr6; -#endif /* CONFIG_IPV6 */ - unsigned int val; - - f = fopen(client_file, "r"); - if (f == NULL) { - RADIUS_ERROR("Could not open client file '%s'", client_file); - return NULL; - } - - buf = os_malloc(buf_size); - if (buf == NULL) { - fclose(f); - return NULL; - } - - clients = tail = NULL; - while (fgets(buf, buf_size, f)) { - /* Configuration file format: - * 192.168.1.0/24 secret - * 192.168.1.2 secret - * fe80::211:22ff:fe33:4455/64 secretipv6 - */ - line++; - buf[buf_size - 1] = '\0'; - pos = buf; - while (*pos != '\0' && *pos != '\n') - pos++; - if (*pos == '\n') - *pos = '\0'; - if (*buf == '\0' || *buf == '#') - continue; - - pos = buf; - while ((*pos >= '0' && *pos <= '9') || *pos == '.' || - (*pos >= 'a' && *pos <= 'f') || *pos == ':' || - (*pos >= 'A' && *pos <= 'F')) { - pos++; - } - - if (*pos == '\0') { - failed = 1; - break; - } - - if (*pos == '/') { - char *end; - *pos++ = '\0'; - mask = strtol(pos, &end, 10); - if ((pos == end) || - (mask < 0 || mask > (ipv6 ? 128 : 32))) { - failed = 1; - break; - } - pos = end; - } else { - mask = ipv6 ? 128 : 32; - *pos++ = '\0'; - } - - if (!ipv6 && inet_aton(buf, &addr) == 0) { - failed = 1; - break; - } -#ifdef CONFIG_IPV6 - if (ipv6 && inet_pton(AF_INET6, buf, &addr6) <= 0) { - if (inet_pton(AF_INET, buf, &addr) <= 0) { - failed = 1; - break; - } - /* Convert IPv4 address to IPv6 */ - if (mask <= 32) - mask += (128 - 32); - os_memset(addr6.s6_addr, 0, 10); - addr6.s6_addr[10] = 0xff; - addr6.s6_addr[11] = 0xff; - os_memcpy(addr6.s6_addr + 12, (char *) &addr.s_addr, - 4); - } -#endif /* CONFIG_IPV6 */ - - while (*pos == ' ' || *pos == '\t') { - pos++; - } - - if (*pos == '\0') { - failed = 1; - break; - } - - entry = os_zalloc(sizeof(*entry)); - if (entry == NULL) { - failed = 1; - break; - } - entry->shared_secret = os_strdup(pos); - if (entry->shared_secret == NULL) { - failed = 1; - os_free(entry); - break; - } - entry->shared_secret_len = os_strlen(entry->shared_secret); - entry->addr.s_addr = addr.s_addr; - if (!ipv6) { - val = 0; - for (i = 0; i < mask; i++) - val |= 1 << (31 - i); - entry->mask.s_addr = htonl(val); - } -#ifdef CONFIG_IPV6 - if (ipv6) { - int offset = mask / 8; - - os_memcpy(entry->addr6.s6_addr, addr6.s6_addr, 16); - os_memset(entry->mask6.s6_addr, 0xff, offset); - val = 0; - for (i = 0; i < (mask % 8); i++) - val |= 1 << (7 - i); - if (offset < 16) - entry->mask6.s6_addr[offset] = val; - } -#endif /* CONFIG_IPV6 */ - - if (tail == NULL) { - clients = tail = entry; - } else { - tail->next = entry; - tail = entry; - } - } - - if (failed) { - RADIUS_ERROR("Invalid line %d in '%s'", line, client_file); - radius_server_free_clients(NULL, clients); - clients = NULL; - } - - os_free(buf); - fclose(f); - - return clients; -} - - -/** - * radius_server_init - Initialize RADIUS server - * @conf: Configuration for the RADIUS server - * Returns: Pointer to private RADIUS server context or %NULL on failure - * - * This initializes a RADIUS server instance and returns a context pointer that - * will be used in other calls to the RADIUS server module. The server can be - * deinitialize by calling radius_server_deinit(). - */ -struct radius_server_data * -radius_server_init(struct radius_server_conf *conf) -{ - struct radius_server_data *data; - -#ifndef CONFIG_IPV6 - if (conf->ipv6) { - fprintf(stderr, "RADIUS server compiled without IPv6 " - "support.\n"); - return NULL; - } -#endif /* CONFIG_IPV6 */ - - data = os_zalloc(sizeof(*data)); - if (data == NULL) - return NULL; - - os_get_time(&data->start_time); - data->conf_ctx = conf->conf_ctx; - data->eap_sim_db_priv = conf->eap_sim_db_priv; - data->ssl_ctx = conf->ssl_ctx; - data->msg_ctx = conf->msg_ctx; - data->ipv6 = conf->ipv6; - if (conf->pac_opaque_encr_key) { - data->pac_opaque_encr_key = os_malloc(16); - os_memcpy(data->pac_opaque_encr_key, conf->pac_opaque_encr_key, - 16); - } - if (conf->eap_fast_a_id) { - data->eap_fast_a_id = os_malloc(conf->eap_fast_a_id_len); - if (data->eap_fast_a_id) { - os_memcpy(data->eap_fast_a_id, conf->eap_fast_a_id, - conf->eap_fast_a_id_len); - data->eap_fast_a_id_len = conf->eap_fast_a_id_len; - } - } - if (conf->eap_fast_a_id_info) - data->eap_fast_a_id_info = os_strdup(conf->eap_fast_a_id_info); - data->eap_fast_prov = conf->eap_fast_prov; - data->pac_key_lifetime = conf->pac_key_lifetime; - data->pac_key_refresh_time = conf->pac_key_refresh_time; - data->get_eap_user = conf->get_eap_user; - data->eap_sim_aka_result_ind = conf->eap_sim_aka_result_ind; - data->tnc = conf->tnc; - data->wps = conf->wps; - data->pwd_group = conf->pwd_group; - if (conf->eap_req_id_text) { - data->eap_req_id_text = os_malloc(conf->eap_req_id_text_len); - if (data->eap_req_id_text) { - os_memcpy(data->eap_req_id_text, conf->eap_req_id_text, - conf->eap_req_id_text_len); - data->eap_req_id_text_len = conf->eap_req_id_text_len; - } - } - - data->clients = radius_server_read_clients(conf->client_file, - conf->ipv6); - if (data->clients == NULL) { - printf("No RADIUS clients configured.\n"); - radius_server_deinit(data); - return NULL; - } - -#ifdef CONFIG_IPV6 - if (conf->ipv6) - data->auth_sock = radius_server_open_socket6(conf->auth_port); - else -#endif /* CONFIG_IPV6 */ - data->auth_sock = radius_server_open_socket(conf->auth_port); - if (data->auth_sock < 0) { - printf("Failed to open UDP socket for RADIUS authentication " - "server\n"); - radius_server_deinit(data); - return NULL; - } - if (eloop_register_read_sock(data->auth_sock, - radius_server_receive_auth, - data, NULL)) { - radius_server_deinit(data); - return NULL; - } - - return data; -} - - -/** - * radius_server_deinit - Deinitialize RADIUS server - * @data: RADIUS server context from radius_server_init() - */ -void radius_server_deinit(struct radius_server_data *data) -{ - if (data == NULL) - return; - - if (data->auth_sock >= 0) { - eloop_unregister_read_sock(data->auth_sock); - close(data->auth_sock); - } - - radius_server_free_clients(data, data->clients); - - os_free(data->pac_opaque_encr_key); - os_free(data->eap_fast_a_id); - os_free(data->eap_fast_a_id_info); - os_free(data->eap_req_id_text); - os_free(data); -} - - -/** - * radius_server_get_mib - Get RADIUS server MIB information - * @data: RADIUS server context from radius_server_init() - * @buf: Buffer for returning the MIB data in text format - * @buflen: buf length in octets - * Returns: Number of octets written into buf - */ -int radius_server_get_mib(struct radius_server_data *data, char *buf, - size_t buflen) -{ - int ret, uptime; - unsigned int idx; - char *end, *pos; - struct os_time now; - struct radius_client *cli; - - /* RFC 2619 - RADIUS Authentication Server MIB */ - - if (data == NULL || buflen == 0) - return 0; - - pos = buf; - end = buf + buflen; - - os_get_time(&now); - uptime = (now.sec - data->start_time.sec) * 100 + - ((now.usec - data->start_time.usec) / 10000) % 100; - ret = os_snprintf(pos, end - pos, - "RADIUS-AUTH-SERVER-MIB\n" - "radiusAuthServIdent=hostapd\n" - "radiusAuthServUpTime=%d\n" - "radiusAuthServResetTime=0\n" - "radiusAuthServConfigReset=4\n", - uptime); - if (ret < 0 || ret >= end - pos) { - *pos = '\0'; - return pos - buf; - } - pos += ret; - - ret = os_snprintf(pos, end - pos, - "radiusAuthServTotalAccessRequests=%u\n" - "radiusAuthServTotalInvalidRequests=%u\n" - "radiusAuthServTotalDupAccessRequests=%u\n" - "radiusAuthServTotalAccessAccepts=%u\n" - "radiusAuthServTotalAccessRejects=%u\n" - "radiusAuthServTotalAccessChallenges=%u\n" - "radiusAuthServTotalMalformedAccessRequests=%u\n" - "radiusAuthServTotalBadAuthenticators=%u\n" - "radiusAuthServTotalPacketsDropped=%u\n" - "radiusAuthServTotalUnknownTypes=%u\n", - data->counters.access_requests, - data->counters.invalid_requests, - data->counters.dup_access_requests, - data->counters.access_accepts, - data->counters.access_rejects, - data->counters.access_challenges, - data->counters.malformed_access_requests, - data->counters.bad_authenticators, - data->counters.packets_dropped, - data->counters.unknown_types); - if (ret < 0 || ret >= end - pos) { - *pos = '\0'; - return pos - buf; - } - pos += ret; - - for (cli = data->clients, idx = 0; cli; cli = cli->next, idx++) { - char abuf[50], mbuf[50]; -#ifdef CONFIG_IPV6 - if (data->ipv6) { - if (inet_ntop(AF_INET6, &cli->addr6, abuf, - sizeof(abuf)) == NULL) - abuf[0] = '\0'; - if (inet_ntop(AF_INET6, &cli->mask6, abuf, - sizeof(mbuf)) == NULL) - mbuf[0] = '\0'; - } -#endif /* CONFIG_IPV6 */ - if (!data->ipv6) { - os_strlcpy(abuf, inet_ntoa(cli->addr), sizeof(abuf)); - os_strlcpy(mbuf, inet_ntoa(cli->mask), sizeof(mbuf)); - } - - ret = os_snprintf(pos, end - pos, - "radiusAuthClientIndex=%u\n" - "radiusAuthClientAddress=%s/%s\n" - "radiusAuthServAccessRequests=%u\n" - "radiusAuthServDupAccessRequests=%u\n" - "radiusAuthServAccessAccepts=%u\n" - "radiusAuthServAccessRejects=%u\n" - "radiusAuthServAccessChallenges=%u\n" - "radiusAuthServMalformedAccessRequests=%u\n" - "radiusAuthServBadAuthenticators=%u\n" - "radiusAuthServPacketsDropped=%u\n" - "radiusAuthServUnknownTypes=%u\n", - idx, - abuf, mbuf, - cli->counters.access_requests, - cli->counters.dup_access_requests, - cli->counters.access_accepts, - cli->counters.access_rejects, - cli->counters.access_challenges, - cli->counters.malformed_access_requests, - cli->counters.bad_authenticators, - cli->counters.packets_dropped, - cli->counters.unknown_types); - if (ret < 0 || ret >= end - pos) { - *pos = '\0'; - return pos - buf; - } - pos += ret; - } - - return pos - buf; -} - - -static int radius_server_get_eap_user(void *ctx, const u8 *identity, - size_t identity_len, int phase2, - struct eap_user *user) -{ - struct radius_session *sess = ctx; - struct radius_server_data *data = sess->server; - - return data->get_eap_user(data->conf_ctx, identity, identity_len, - phase2, user); -} - - -static const char * radius_server_get_eap_req_id_text(void *ctx, size_t *len) -{ - struct radius_session *sess = ctx; - struct radius_server_data *data = sess->server; - *len = data->eap_req_id_text_len; - return data->eap_req_id_text; -} - - -static struct eapol_callbacks radius_server_eapol_cb = -{ - .get_eap_user = radius_server_get_eap_user, - .get_eap_req_id_text = radius_server_get_eap_req_id_text, -}; - - -/** - * radius_server_eap_pending_cb - Pending EAP data notification - * @data: RADIUS server context from radius_server_init() - * @ctx: Pending EAP context pointer - * - * This function is used to notify EAP server module that a pending operation - * has been completed and processing of the EAP session can proceed. - */ -void radius_server_eap_pending_cb(struct radius_server_data *data, void *ctx) -{ - struct radius_client *cli; - struct radius_session *s, *sess = NULL; - struct radius_msg *msg; - - if (data == NULL) - return; - - for (cli = data->clients; cli; cli = cli->next) { - for (s = cli->sessions; s; s = s->next) { - if (s->eap == ctx && s->last_msg) { - sess = s; - break; - } - if (sess) - break; - } - if (sess) - break; - } - - if (sess == NULL) { - RADIUS_DEBUG("No session matched callback ctx"); - return; - } - - msg = sess->last_msg; - sess->last_msg = NULL; - eap_sm_pending_cb(sess->eap); - if (radius_server_request(data, msg, - (struct sockaddr *) &sess->last_from, - sess->last_fromlen, cli, - sess->last_from_addr, - sess->last_from_port, sess) == -2) - return; /* msg was stored with the session */ - - radius_msg_free(msg); -} diff --git a/hostapd-0.8/src/radius/radius_server.h b/hostapd-0.8/src/radius/radius_server.h deleted file mode 100644 index 126e314..0000000 --- a/hostapd-0.8/src/radius/radius_server.h +++ /dev/null @@ -1,217 +0,0 @@ -/* - * RADIUS authentication server - * Copyright (c) 2005-2009, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#ifndef RADIUS_SERVER_H -#define RADIUS_SERVER_H - -struct radius_server_data; -struct eap_user; - -/** - * struct radius_server_conf - RADIUS server configuration - */ -struct radius_server_conf { - /** - * auth_port - UDP port to listen to as an authentication server - */ - int auth_port; - - /** - * client_file - RADIUS client configuration file - * - * This file contains the RADIUS clients and the shared secret to be - * used with them in a format where each client is on its own line. The - * first item on the line is the IPv4 or IPv6 address of the client - * with an optional address mask to allow full network to be specified - * (e.g., 192.168.1.2 or 192.168.1.0/24). This is followed by white - * space (space or tabulator) and the shared secret. Lines starting - * with '#' are skipped and can be used as comments. - */ - char *client_file; - - /** - * conf_ctx - Context pointer for callbacks - * - * This is used as the ctx argument in get_eap_user() calls. - */ - void *conf_ctx; - - /** - * eap_sim_db_priv - EAP-SIM/AKA database context - * - * This is passed to the EAP-SIM/AKA server implementation as a - * callback context. - */ - void *eap_sim_db_priv; - - /** - * ssl_ctx - TLS context - * - * This is passed to the EAP server implementation as a callback - * context for TLS operations. - */ - void *ssl_ctx; - - /** - * pac_opaque_encr_key - PAC-Opaque encryption key for EAP-FAST - * - * This parameter is used to set a key for EAP-FAST to encrypt the - * PAC-Opaque data. It can be set to %NULL if EAP-FAST is not used. If - * set, must point to a 16-octet key. - */ - u8 *pac_opaque_encr_key; - - /** - * eap_fast_a_id - EAP-FAST authority identity (A-ID) - * - * If EAP-FAST is not used, this can be set to %NULL. In theory, this - * is a variable length field, but due to some existing implementations - * requiring A-ID to be 16 octets in length, it is recommended to use - * that length for the field to provide interoperability with deployed - * peer implementations. - */ - u8 *eap_fast_a_id; - - /** - * eap_fast_a_id_len - Length of eap_fast_a_id buffer in octets - */ - size_t eap_fast_a_id_len; - - /** - * eap_fast_a_id_info - EAP-FAST authority identifier information - * - * This A-ID-Info contains a user-friendly name for the A-ID. For - * example, this could be the enterprise and server names in - * human-readable format. This field is encoded as UTF-8. If EAP-FAST - * is not used, this can be set to %NULL. - */ - char *eap_fast_a_id_info; - - /** - * eap_fast_prov - EAP-FAST provisioning modes - * - * 0 = provisioning disabled, 1 = only anonymous provisioning allowed, - * 2 = only authenticated provisioning allowed, 3 = both provisioning - * modes allowed. - */ - int eap_fast_prov; - - /** - * pac_key_lifetime - EAP-FAST PAC-Key lifetime in seconds - * - * This is the hard limit on how long a provisioned PAC-Key can be - * used. - */ - int pac_key_lifetime; - - /** - * pac_key_refresh_time - EAP-FAST PAC-Key refresh time in seconds - * - * This is a soft limit on the PAC-Key. The server will automatically - * generate a new PAC-Key when this number of seconds (or fewer) of the - * lifetime remains. - */ - int pac_key_refresh_time; - - /** - * eap_sim_aka_result_ind - EAP-SIM/AKA protected success indication - * - * This controls whether the protected success/failure indication - * (AT_RESULT_IND) is used with EAP-SIM and EAP-AKA. - */ - int eap_sim_aka_result_ind; - - /** - * tnc - Trusted Network Connect (TNC) - * - * This controls whether TNC is enabled and will be required before the - * peer is allowed to connect. Note: This is only used with EAP-TTLS - * and EAP-FAST. If any other EAP method is enabled, the peer will be - * allowed to connect without TNC. - */ - int tnc; - - /** - * pwd_group - EAP-pwd D-H group - * - * This is used to select which D-H group to use with EAP-pwd. - */ - u16 pwd_group; - - /** - * wps - Wi-Fi Protected Setup context - * - * If WPS is used with an external RADIUS server (which is quite - * unlikely configuration), this is used to provide a pointer to WPS - * context data. Normally, this can be set to %NULL. - */ - struct wps_context *wps; - - /** - * ipv6 - Whether to enable IPv6 support in the RADIUS server - */ - int ipv6; - - /** - * get_eap_user - Callback for fetching EAP user information - * @ctx: Context data from conf_ctx - * @identity: User identity - * @identity_len: identity buffer length in octets - * @phase2: Whether this is for Phase 2 identity - * @user: Data structure for filling in the user information - * Returns: 0 on success, -1 on failure - * - * This is used to fetch information from user database. The callback - * will fill in information about allowed EAP methods and the user - * password. The password field will be an allocated copy of the - * password data and RADIUS server will free it after use. - */ - int (*get_eap_user)(void *ctx, const u8 *identity, size_t identity_len, - int phase2, struct eap_user *user); - - /** - * eap_req_id_text - Optional data for EAP-Request/Identity - * - * This can be used to configure an optional, displayable message that - * will be sent in EAP-Request/Identity. This string can contain an - * ASCII-0 character (nul) to separate network infromation per RFC - * 4284. The actual string length is explicit provided in - * eap_req_id_text_len since nul character will not be used as a string - * terminator. - */ - const char *eap_req_id_text; - - /** - * eap_req_id_text_len - Length of eap_req_id_text buffer in octets - */ - size_t eap_req_id_text_len; - - /* - * msg_ctx - Context data for wpa_msg() calls - */ - void *msg_ctx; -}; - - -struct radius_server_data * -radius_server_init(struct radius_server_conf *conf); - -void radius_server_deinit(struct radius_server_data *data); - -int radius_server_get_mib(struct radius_server_data *data, char *buf, - size_t buflen); - -void radius_server_eap_pending_cb(struct radius_server_data *data, void *ctx); - -#endif /* RADIUS_SERVER_H */ diff --git a/hostapd-0.8/src/rsn_supp/Makefile b/hostapd-0.8/src/rsn_supp/Makefile deleted file mode 100644 index 9c41962..0000000 --- a/hostapd-0.8/src/rsn_supp/Makefile +++ /dev/null @@ -1,8 +0,0 @@ -all: - @echo Nothing to be made. - -clean: - rm -f *~ *.o *.d - -install: - @echo Nothing to be made. diff --git a/hostapd-0.8/src/rsn_supp/peerkey.c b/hostapd-0.8/src/rsn_supp/peerkey.c deleted file mode 100644 index 2b3332e..0000000 --- a/hostapd-0.8/src/rsn_supp/peerkey.c +++ /dev/null @@ -1,1186 +0,0 @@ -/* - * WPA Supplicant - PeerKey for Direct Link Setup (DLS) - * Copyright (c) 2006-2008, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#include "includes.h" - -#ifdef CONFIG_PEERKEY - -#include "common.h" -#include "eloop.h" -#include "crypto/sha1.h" -#include "crypto/sha256.h" -#include "crypto/random.h" -#include "common/ieee802_11_defs.h" -#include "wpa.h" -#include "wpa_i.h" -#include "wpa_ie.h" -#include "peerkey.h" - - -static u8 * wpa_add_ie(u8 *pos, const u8 *ie, size_t ie_len) -{ - os_memcpy(pos, ie, ie_len); - return pos + ie_len; -} - - -static u8 * wpa_add_kde(u8 *pos, u32 kde, const u8 *data, size_t data_len) -{ - *pos++ = WLAN_EID_VENDOR_SPECIFIC; - *pos++ = RSN_SELECTOR_LEN + data_len; - RSN_SELECTOR_PUT(pos, kde); - pos += RSN_SELECTOR_LEN; - os_memcpy(pos, data, data_len); - pos += data_len; - return pos; -} - - -static void wpa_supplicant_smk_timeout(void *eloop_ctx, void *timeout_ctx) -{ -#if 0 - struct wpa_sm *sm = eloop_ctx; - struct wpa_peerkey *peerkey = timeout_ctx; -#endif - /* TODO: time out SMK and any STK that was generated using this SMK */ -} - - -static void wpa_supplicant_peerkey_free(struct wpa_sm *sm, - struct wpa_peerkey *peerkey) -{ - eloop_cancel_timeout(wpa_supplicant_smk_timeout, sm, peerkey); - os_free(peerkey); -} - - -static int wpa_supplicant_send_smk_error(struct wpa_sm *sm, const u8 *dst, - const u8 *peer, - u16 mui, u16 error_type, int ver) -{ - size_t rlen; - struct wpa_eapol_key *err; - struct rsn_error_kde error; - u8 *rbuf, *pos; - size_t kde_len; - u16 key_info; - - kde_len = 2 + RSN_SELECTOR_LEN + sizeof(error); - if (peer) - kde_len += 2 + RSN_SELECTOR_LEN + ETH_ALEN; - - rbuf = wpa_sm_alloc_eapol(sm, IEEE802_1X_TYPE_EAPOL_KEY, - NULL, sizeof(*err) + kde_len, &rlen, - (void *) &err); - if (rbuf == NULL) - return -1; - - err->type = EAPOL_KEY_TYPE_RSN; - key_info = ver | WPA_KEY_INFO_SMK_MESSAGE | WPA_KEY_INFO_MIC | - WPA_KEY_INFO_SECURE | WPA_KEY_INFO_ERROR | - WPA_KEY_INFO_REQUEST; - WPA_PUT_BE16(err->key_info, key_info); - WPA_PUT_BE16(err->key_length, 0); - os_memcpy(err->replay_counter, sm->request_counter, - WPA_REPLAY_COUNTER_LEN); - inc_byte_array(sm->request_counter, WPA_REPLAY_COUNTER_LEN); - - WPA_PUT_BE16(err->key_data_length, (u16) kde_len); - pos = (u8 *) (err + 1); - - if (peer) { - /* Peer MAC Address KDE */ - pos = wpa_add_kde(pos, RSN_KEY_DATA_MAC_ADDR, peer, ETH_ALEN); - } - - /* Error KDE */ - error.mui = host_to_be16(mui); - error.error_type = host_to_be16(error_type); - wpa_add_kde(pos, RSN_KEY_DATA_ERROR, (u8 *) &error, sizeof(error)); - - if (peer) { - wpa_printf(MSG_DEBUG, "RSN: Sending EAPOL-Key SMK Error (peer " - MACSTR " mui %d error_type %d)", - MAC2STR(peer), mui, error_type); - } else { - wpa_printf(MSG_DEBUG, "RSN: Sending EAPOL-Key SMK Error " - "(mui %d error_type %d)", mui, error_type); - } - - wpa_eapol_key_send(sm, sm->ptk.kck, ver, dst, ETH_P_EAPOL, - rbuf, rlen, err->key_mic); - - return 0; -} - - -static int wpa_supplicant_send_smk_m3(struct wpa_sm *sm, - const unsigned char *src_addr, - const struct wpa_eapol_key *key, - int ver, struct wpa_peerkey *peerkey) -{ - size_t rlen; - struct wpa_eapol_key *reply; - u8 *rbuf, *pos; - size_t kde_len; - u16 key_info; - - /* KDEs: Peer RSN IE, Initiator MAC Address, Initiator Nonce */ - kde_len = peerkey->rsnie_p_len + - 2 + RSN_SELECTOR_LEN + ETH_ALEN + - 2 + RSN_SELECTOR_LEN + WPA_NONCE_LEN; - - rbuf = wpa_sm_alloc_eapol(sm, IEEE802_1X_TYPE_EAPOL_KEY, - NULL, sizeof(*reply) + kde_len, &rlen, - (void *) &reply); - if (rbuf == NULL) - return -1; - - reply->type = EAPOL_KEY_TYPE_RSN; - key_info = ver | WPA_KEY_INFO_SMK_MESSAGE | WPA_KEY_INFO_MIC | - WPA_KEY_INFO_SECURE; - WPA_PUT_BE16(reply->key_info, key_info); - WPA_PUT_BE16(reply->key_length, 0); - os_memcpy(reply->replay_counter, key->replay_counter, - WPA_REPLAY_COUNTER_LEN); - - os_memcpy(reply->key_nonce, peerkey->pnonce, WPA_NONCE_LEN); - - WPA_PUT_BE16(reply->key_data_length, (u16) kde_len); - pos = (u8 *) (reply + 1); - - /* Peer RSN IE */ - pos = wpa_add_ie(pos, peerkey->rsnie_p, peerkey->rsnie_p_len); - - /* Initiator MAC Address KDE */ - pos = wpa_add_kde(pos, RSN_KEY_DATA_MAC_ADDR, peerkey->addr, ETH_ALEN); - - /* Initiator Nonce */ - wpa_add_kde(pos, RSN_KEY_DATA_NONCE, peerkey->inonce, WPA_NONCE_LEN); - - wpa_printf(MSG_DEBUG, "RSN: Sending EAPOL-Key SMK M3"); - wpa_eapol_key_send(sm, sm->ptk.kck, ver, src_addr, ETH_P_EAPOL, - rbuf, rlen, reply->key_mic); - - return 0; -} - - -static int wpa_supplicant_process_smk_m2( - struct wpa_sm *sm, const unsigned char *src_addr, - const struct wpa_eapol_key *key, size_t extra_len, int ver) -{ - struct wpa_peerkey *peerkey; - struct wpa_eapol_ie_parse kde; - struct wpa_ie_data ie; - int cipher; - struct rsn_ie_hdr *hdr; - u8 *pos; - - wpa_printf(MSG_DEBUG, "RSN: Received SMK M2"); - - if (!sm->peerkey_enabled || sm->proto != WPA_PROTO_RSN) { - wpa_printf(MSG_INFO, "RSN: SMK handshake not allowed for " - "the current network"); - return -1; - } - - if (wpa_supplicant_parse_ies((const u8 *) (key + 1), extra_len, &kde) < - 0) { - wpa_printf(MSG_INFO, "RSN: Failed to parse KDEs in SMK M2"); - return -1; - } - - if (kde.rsn_ie == NULL || kde.mac_addr == NULL || - kde.mac_addr_len < ETH_ALEN) { - wpa_printf(MSG_INFO, "RSN: No RSN IE or MAC address KDE in " - "SMK M2"); - return -1; - } - - wpa_printf(MSG_DEBUG, "RSN: SMK M2 - SMK initiator " MACSTR, - MAC2STR(kde.mac_addr)); - - if (kde.rsn_ie_len > PEERKEY_MAX_IE_LEN) { - wpa_printf(MSG_INFO, "RSN: Too long Initiator RSN IE in SMK " - "M2"); - return -1; - } - - if (wpa_parse_wpa_ie_rsn(kde.rsn_ie, kde.rsn_ie_len, &ie) < 0) { - wpa_printf(MSG_INFO, "RSN: Failed to parse RSN IE in SMK M2"); - return -1; - } - - cipher = ie.pairwise_cipher & sm->allowed_pairwise_cipher; - if (cipher & WPA_CIPHER_CCMP) { - wpa_printf(MSG_DEBUG, "RSN: Using CCMP for PeerKey"); - cipher = WPA_CIPHER_CCMP; - } else if (cipher & WPA_CIPHER_TKIP) { - wpa_printf(MSG_DEBUG, "RSN: Using TKIP for PeerKey"); - cipher = WPA_CIPHER_TKIP; - } else { - wpa_printf(MSG_INFO, "RSN: No acceptable cipher in SMK M2"); - wpa_supplicant_send_smk_error(sm, src_addr, kde.mac_addr, - STK_MUI_SMK, STK_ERR_CPHR_NS, - ver); - return -1; - } - - /* TODO: find existing entry and if found, use that instead of adding - * a new one; how to handle the case where both ends initiate at the - * same time? */ - peerkey = os_zalloc(sizeof(*peerkey)); - if (peerkey == NULL) - return -1; - os_memcpy(peerkey->addr, kde.mac_addr, ETH_ALEN); - os_memcpy(peerkey->inonce, key->key_nonce, WPA_NONCE_LEN); - os_memcpy(peerkey->rsnie_i, kde.rsn_ie, kde.rsn_ie_len); - peerkey->rsnie_i_len = kde.rsn_ie_len; - peerkey->cipher = cipher; -#ifdef CONFIG_IEEE80211W - if (ie.key_mgmt & (WPA_KEY_MGMT_IEEE8021X_SHA256 | - WPA_KEY_MGMT_PSK_SHA256)) - peerkey->use_sha256 = 1; -#endif /* CONFIG_IEEE80211W */ - - if (random_get_bytes(peerkey->pnonce, WPA_NONCE_LEN)) { - wpa_msg(sm->ctx->msg_ctx, MSG_WARNING, - "WPA: Failed to get random data for PNonce"); - wpa_supplicant_peerkey_free(sm, peerkey); - return -1; - } - - hdr = (struct rsn_ie_hdr *) peerkey->rsnie_p; - hdr->elem_id = WLAN_EID_RSN; - WPA_PUT_LE16(hdr->version, RSN_VERSION); - pos = (u8 *) (hdr + 1); - /* Group Suite can be anything for SMK RSN IE; receiver will just - * ignore it. */ - RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_CCMP); - pos += RSN_SELECTOR_LEN; - /* Include only the selected cipher in pairwise cipher suite */ - WPA_PUT_LE16(pos, 1); - pos += 2; - if (cipher == WPA_CIPHER_CCMP) - RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_CCMP); - else if (cipher == WPA_CIPHER_TKIP) - RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_TKIP); - pos += RSN_SELECTOR_LEN; - - hdr->len = (pos - peerkey->rsnie_p) - 2; - peerkey->rsnie_p_len = pos - peerkey->rsnie_p; - wpa_hexdump(MSG_DEBUG, "WPA: RSN IE for SMK handshake", - peerkey->rsnie_p, peerkey->rsnie_p_len); - - wpa_supplicant_send_smk_m3(sm, src_addr, key, ver, peerkey); - - peerkey->next = sm->peerkey; - sm->peerkey = peerkey; - - return 0; -} - - -/** - * rsn_smkid - Derive SMK identifier - * @smk: Station master key (32 bytes) - * @pnonce: Peer Nonce - * @mac_p: Peer MAC address - * @inonce: Initiator Nonce - * @mac_i: Initiator MAC address - * @use_sha256: Whether to use SHA256-based KDF - * - * 8.5.1.4 Station to station (STK) key hierarchy - * SMKID = HMAC-SHA1-128(SMK, "SMK Name" || PNonce || MAC_P || INonce || MAC_I) - */ -static void rsn_smkid(const u8 *smk, const u8 *pnonce, const u8 *mac_p, - const u8 *inonce, const u8 *mac_i, u8 *smkid, - int use_sha256) -{ - char *title = "SMK Name"; - const u8 *addr[5]; - const size_t len[5] = { 8, WPA_NONCE_LEN, ETH_ALEN, WPA_NONCE_LEN, - ETH_ALEN }; - unsigned char hash[SHA256_MAC_LEN]; - - addr[0] = (u8 *) title; - addr[1] = pnonce; - addr[2] = mac_p; - addr[3] = inonce; - addr[4] = mac_i; - -#ifdef CONFIG_IEEE80211W - if (use_sha256) - hmac_sha256_vector(smk, PMK_LEN, 5, addr, len, hash); - else -#endif /* CONFIG_IEEE80211W */ - hmac_sha1_vector(smk, PMK_LEN, 5, addr, len, hash); - os_memcpy(smkid, hash, PMKID_LEN); -} - - -static void wpa_supplicant_send_stk_1_of_4(struct wpa_sm *sm, - struct wpa_peerkey *peerkey) -{ - size_t mlen; - struct wpa_eapol_key *msg; - u8 *mbuf; - size_t kde_len; - u16 key_info, ver; - - kde_len = 2 + RSN_SELECTOR_LEN + PMKID_LEN; - - mbuf = wpa_sm_alloc_eapol(sm, IEEE802_1X_TYPE_EAPOL_KEY, NULL, - sizeof(*msg) + kde_len, &mlen, - (void *) &msg); - if (mbuf == NULL) - return; - - msg->type = EAPOL_KEY_TYPE_RSN; - - if (peerkey->cipher == WPA_CIPHER_CCMP) - ver = WPA_KEY_INFO_TYPE_HMAC_SHA1_AES; - else - ver = WPA_KEY_INFO_TYPE_HMAC_MD5_RC4; - - key_info = ver | WPA_KEY_INFO_KEY_TYPE | WPA_KEY_INFO_ACK; - WPA_PUT_BE16(msg->key_info, key_info); - - if (peerkey->cipher == WPA_CIPHER_CCMP) - WPA_PUT_BE16(msg->key_length, 16); - else - WPA_PUT_BE16(msg->key_length, 32); - - os_memcpy(msg->replay_counter, peerkey->replay_counter, - WPA_REPLAY_COUNTER_LEN); - inc_byte_array(peerkey->replay_counter, WPA_REPLAY_COUNTER_LEN); - - WPA_PUT_BE16(msg->key_data_length, kde_len); - wpa_add_kde((u8 *) (msg + 1), RSN_KEY_DATA_PMKID, - peerkey->smkid, PMKID_LEN); - - if (random_get_bytes(peerkey->inonce, WPA_NONCE_LEN)) { - wpa_msg(sm->ctx->msg_ctx, MSG_WARNING, - "RSN: Failed to get random data for INonce (STK)"); - os_free(mbuf); - return; - } - wpa_hexdump(MSG_DEBUG, "RSN: INonce for STK 4-Way Handshake", - peerkey->inonce, WPA_NONCE_LEN); - os_memcpy(msg->key_nonce, peerkey->inonce, WPA_NONCE_LEN); - - wpa_printf(MSG_DEBUG, "RSN: Sending EAPOL-Key STK 1/4 to " MACSTR, - MAC2STR(peerkey->addr)); - wpa_eapol_key_send(sm, NULL, ver, peerkey->addr, ETH_P_EAPOL, - mbuf, mlen, NULL); -} - - -static void wpa_supplicant_send_stk_3_of_4(struct wpa_sm *sm, - struct wpa_peerkey *peerkey) -{ - size_t mlen; - struct wpa_eapol_key *msg; - u8 *mbuf, *pos; - size_t kde_len; - u16 key_info, ver; - be32 lifetime; - - kde_len = peerkey->rsnie_i_len + - 2 + RSN_SELECTOR_LEN + sizeof(lifetime); - - mbuf = wpa_sm_alloc_eapol(sm, IEEE802_1X_TYPE_EAPOL_KEY, NULL, - sizeof(*msg) + kde_len, &mlen, - (void *) &msg); - if (mbuf == NULL) - return; - - msg->type = EAPOL_KEY_TYPE_RSN; - - if (peerkey->cipher == WPA_CIPHER_CCMP) - ver = WPA_KEY_INFO_TYPE_HMAC_SHA1_AES; - else - ver = WPA_KEY_INFO_TYPE_HMAC_MD5_RC4; - - key_info = ver | WPA_KEY_INFO_KEY_TYPE | WPA_KEY_INFO_ACK | - WPA_KEY_INFO_MIC | WPA_KEY_INFO_SECURE; - WPA_PUT_BE16(msg->key_info, key_info); - - if (peerkey->cipher == WPA_CIPHER_CCMP) - WPA_PUT_BE16(msg->key_length, 16); - else - WPA_PUT_BE16(msg->key_length, 32); - - os_memcpy(msg->replay_counter, peerkey->replay_counter, - WPA_REPLAY_COUNTER_LEN); - inc_byte_array(peerkey->replay_counter, WPA_REPLAY_COUNTER_LEN); - - WPA_PUT_BE16(msg->key_data_length, kde_len); - pos = (u8 *) (msg + 1); - pos = wpa_add_ie(pos, peerkey->rsnie_i, peerkey->rsnie_i_len); - lifetime = host_to_be32(peerkey->lifetime); - wpa_add_kde(pos, RSN_KEY_DATA_LIFETIME, - (u8 *) &lifetime, sizeof(lifetime)); - - os_memcpy(msg->key_nonce, peerkey->inonce, WPA_NONCE_LEN); - - wpa_printf(MSG_DEBUG, "RSN: Sending EAPOL-Key STK 3/4 to " MACSTR, - MAC2STR(peerkey->addr)); - wpa_eapol_key_send(sm, peerkey->stk.kck, ver, peerkey->addr, - ETH_P_EAPOL, mbuf, mlen, msg->key_mic); -} - - -static int wpa_supplicant_process_smk_m4(struct wpa_peerkey *peerkey, - struct wpa_eapol_ie_parse *kde) -{ - wpa_printf(MSG_DEBUG, "RSN: Received SMK M4 (Initiator " MACSTR ")", - MAC2STR(kde->mac_addr)); - - if (os_memcmp(kde->smk + PMK_LEN, peerkey->pnonce, WPA_NONCE_LEN) != 0) - { - wpa_printf(MSG_INFO, "RSN: PNonce in SMK KDE does not " - "match with the one used in SMK M3"); - return -1; - } - - if (os_memcmp(kde->nonce, peerkey->inonce, WPA_NONCE_LEN) != 0) { - wpa_printf(MSG_INFO, "RSN: INonce in SMK M4 did not " - "match with the one received in SMK M2"); - return -1; - } - - return 0; -} - - -static int wpa_supplicant_process_smk_m5(struct wpa_sm *sm, - const unsigned char *src_addr, - const struct wpa_eapol_key *key, - int ver, - struct wpa_peerkey *peerkey, - struct wpa_eapol_ie_parse *kde) -{ - int cipher; - struct wpa_ie_data ie; - - wpa_printf(MSG_DEBUG, "RSN: Received SMK M5 (Peer " MACSTR ")", - MAC2STR(kde->mac_addr)); - if (kde->rsn_ie == NULL || kde->rsn_ie_len > PEERKEY_MAX_IE_LEN || - wpa_parse_wpa_ie_rsn(kde->rsn_ie, kde->rsn_ie_len, &ie) < 0) { - wpa_printf(MSG_INFO, "RSN: No RSN IE in SMK M5"); - /* TODO: abort negotiation */ - return -1; - } - - if (os_memcmp(key->key_nonce, peerkey->inonce, WPA_NONCE_LEN) != 0) { - wpa_printf(MSG_INFO, "RSN: Key Nonce in SMK M5 does " - "not match with INonce used in SMK M1"); - return -1; - } - - if (os_memcmp(kde->smk + PMK_LEN, peerkey->inonce, WPA_NONCE_LEN) != 0) - { - wpa_printf(MSG_INFO, "RSN: INonce in SMK KDE does not " - "match with the one used in SMK M1"); - return -1; - } - - os_memcpy(peerkey->rsnie_p, kde->rsn_ie, kde->rsn_ie_len); - peerkey->rsnie_p_len = kde->rsn_ie_len; - os_memcpy(peerkey->pnonce, kde->nonce, WPA_NONCE_LEN); - - cipher = ie.pairwise_cipher & sm->allowed_pairwise_cipher; - if (cipher & WPA_CIPHER_CCMP) { - wpa_printf(MSG_DEBUG, "RSN: Using CCMP for PeerKey"); - peerkey->cipher = WPA_CIPHER_CCMP; - } else if (cipher & WPA_CIPHER_TKIP) { - wpa_printf(MSG_DEBUG, "RSN: Using TKIP for PeerKey"); - peerkey->cipher = WPA_CIPHER_TKIP; - } else { - wpa_printf(MSG_INFO, "RSN: SMK Peer STA " MACSTR " selected " - "unacceptable cipher", MAC2STR(kde->mac_addr)); - wpa_supplicant_send_smk_error(sm, src_addr, kde->mac_addr, - STK_MUI_SMK, STK_ERR_CPHR_NS, - ver); - /* TODO: abort negotiation */ - return -1; - } - - return 0; -} - - -static int wpa_supplicant_process_smk_m45( - struct wpa_sm *sm, const unsigned char *src_addr, - const struct wpa_eapol_key *key, size_t extra_len, int ver) -{ - struct wpa_peerkey *peerkey; - struct wpa_eapol_ie_parse kde; - u32 lifetime; - struct os_time now; - - if (!sm->peerkey_enabled || sm->proto != WPA_PROTO_RSN) { - wpa_printf(MSG_DEBUG, "RSN: SMK handshake not allowed for " - "the current network"); - return -1; - } - - if (wpa_supplicant_parse_ies((const u8 *) (key + 1), extra_len, &kde) < - 0) { - wpa_printf(MSG_INFO, "RSN: Failed to parse KDEs in SMK M4/M5"); - return -1; - } - - if (kde.mac_addr == NULL || kde.mac_addr_len < ETH_ALEN || - kde.nonce == NULL || kde.nonce_len < WPA_NONCE_LEN || - kde.smk == NULL || kde.smk_len < PMK_LEN + WPA_NONCE_LEN || - kde.lifetime == NULL || kde.lifetime_len < 4) { - wpa_printf(MSG_INFO, "RSN: No MAC Address, Nonce, SMK, or " - "Lifetime KDE in SMK M4/M5"); - return -1; - } - - for (peerkey = sm->peerkey; peerkey; peerkey = peerkey->next) { - if (os_memcmp(peerkey->addr, kde.mac_addr, ETH_ALEN) == 0 && - os_memcmp(peerkey->initiator ? peerkey->inonce : - peerkey->pnonce, - key->key_nonce, WPA_NONCE_LEN) == 0) - break; - } - if (peerkey == NULL) { - wpa_printf(MSG_INFO, "RSN: No matching SMK handshake found " - "for SMK M4/M5: peer " MACSTR, - MAC2STR(kde.mac_addr)); - return -1; - } - - if (peerkey->initiator) { - if (wpa_supplicant_process_smk_m5(sm, src_addr, key, ver, - peerkey, &kde) < 0) - return -1; - } else { - if (wpa_supplicant_process_smk_m4(peerkey, &kde) < 0) - return -1; - } - - os_memcpy(peerkey->smk, kde.smk, PMK_LEN); - peerkey->smk_complete = 1; - wpa_hexdump_key(MSG_DEBUG, "RSN: SMK", peerkey->smk, PMK_LEN); - lifetime = WPA_GET_BE32(kde.lifetime); - wpa_printf(MSG_DEBUG, "RSN: SMK lifetime %u seconds", lifetime); - if (lifetime > 1000000000) - lifetime = 1000000000; /* avoid overflowing expiration time */ - peerkey->lifetime = lifetime; - os_get_time(&now); - peerkey->expiration = now.sec + lifetime; - eloop_register_timeout(lifetime, 0, wpa_supplicant_smk_timeout, - sm, peerkey); - - if (peerkey->initiator) { - rsn_smkid(peerkey->smk, peerkey->pnonce, peerkey->addr, - peerkey->inonce, sm->own_addr, peerkey->smkid, - peerkey->use_sha256); - wpa_supplicant_send_stk_1_of_4(sm, peerkey); - } else { - rsn_smkid(peerkey->smk, peerkey->pnonce, sm->own_addr, - peerkey->inonce, peerkey->addr, peerkey->smkid, - peerkey->use_sha256); - } - wpa_hexdump(MSG_DEBUG, "RSN: SMKID", peerkey->smkid, PMKID_LEN); - - return 0; -} - - -static int wpa_supplicant_process_smk_error( - struct wpa_sm *sm, const unsigned char *src_addr, - const struct wpa_eapol_key *key, size_t extra_len) -{ - struct wpa_eapol_ie_parse kde; - struct rsn_error_kde error; - u8 peer[ETH_ALEN]; - u16 error_type; - - wpa_printf(MSG_DEBUG, "RSN: Received SMK Error"); - - if (!sm->peerkey_enabled || sm->proto != WPA_PROTO_RSN) { - wpa_printf(MSG_DEBUG, "RSN: SMK handshake not allowed for " - "the current network"); - return -1; - } - - if (wpa_supplicant_parse_ies((const u8 *) (key + 1), extra_len, &kde) < - 0) { - wpa_printf(MSG_INFO, "RSN: Failed to parse KDEs in SMK Error"); - return -1; - } - - if (kde.error == NULL || kde.error_len < sizeof(error)) { - wpa_printf(MSG_INFO, "RSN: No Error KDE in SMK Error"); - return -1; - } - - if (kde.mac_addr && kde.mac_addr_len >= ETH_ALEN) - os_memcpy(peer, kde.mac_addr, ETH_ALEN); - else - os_memset(peer, 0, ETH_ALEN); - os_memcpy(&error, kde.error, sizeof(error)); - error_type = be_to_host16(error.error_type); - wpa_msg(sm->ctx->msg_ctx, MSG_INFO, - "RSN: SMK Error KDE received: MUI %d error_type %d peer " - MACSTR, - be_to_host16(error.mui), error_type, - MAC2STR(peer)); - - if (kde.mac_addr && - (error_type == STK_ERR_STA_NR || error_type == STK_ERR_STA_NRSN || - error_type == STK_ERR_CPHR_NS)) { - struct wpa_peerkey *peerkey; - - for (peerkey = sm->peerkey; peerkey; peerkey = peerkey->next) { - if (os_memcmp(peerkey->addr, kde.mac_addr, ETH_ALEN) == - 0) - break; - } - if (peerkey == NULL) { - wpa_printf(MSG_DEBUG, "RSN: No matching SMK handshake " - "found for SMK Error"); - return -1; - } - /* TODO: abort SMK/STK handshake and remove all related keys */ - } - - return 0; -} - - -static void wpa_supplicant_process_stk_1_of_4(struct wpa_sm *sm, - struct wpa_peerkey *peerkey, - const struct wpa_eapol_key *key, - u16 ver) -{ - struct wpa_eapol_ie_parse ie; - const u8 *kde; - size_t len, kde_buf_len; - struct wpa_ptk *stk; - u8 buf[8], *kde_buf, *pos; - be32 lifetime; - - wpa_printf(MSG_DEBUG, "RSN: RX message 1 of STK 4-Way Handshake from " - MACSTR " (ver=%d)", MAC2STR(peerkey->addr), ver); - - os_memset(&ie, 0, sizeof(ie)); - - /* RSN: msg 1/4 should contain SMKID for the selected SMK */ - kde = (const u8 *) (key + 1); - len = WPA_GET_BE16(key->key_data_length); - wpa_hexdump(MSG_DEBUG, "RSN: msg 1/4 key data", kde, len); - if (wpa_supplicant_parse_ies(kde, len, &ie) < 0 || ie.pmkid == NULL) { - wpa_printf(MSG_DEBUG, "RSN: No SMKID in STK 1/4"); - return; - } - if (os_memcmp(ie.pmkid, peerkey->smkid, PMKID_LEN) != 0) { - wpa_hexdump(MSG_DEBUG, "RSN: Unknown SMKID in STK 1/4", - ie.pmkid, PMKID_LEN); - return; - } - - if (random_get_bytes(peerkey->pnonce, WPA_NONCE_LEN)) { - wpa_msg(sm->ctx->msg_ctx, MSG_WARNING, - "RSN: Failed to get random data for PNonce"); - return; - } - wpa_hexdump(MSG_DEBUG, "WPA: Renewed PNonce", - peerkey->pnonce, WPA_NONCE_LEN); - - /* Calculate STK which will be stored as a temporary STK until it has - * been verified when processing message 3/4. */ - stk = &peerkey->tstk; - wpa_pmk_to_ptk(peerkey->smk, PMK_LEN, "Peer key expansion", - sm->own_addr, peerkey->addr, - peerkey->pnonce, key->key_nonce, - (u8 *) stk, sizeof(*stk), - peerkey->use_sha256); - /* Supplicant: swap tx/rx Mic keys */ - os_memcpy(buf, stk->u.auth.tx_mic_key, 8); - os_memcpy(stk->u.auth.tx_mic_key, stk->u.auth.rx_mic_key, 8); - os_memcpy(stk->u.auth.rx_mic_key, buf, 8); - peerkey->tstk_set = 1; - - kde_buf_len = peerkey->rsnie_p_len + - 2 + RSN_SELECTOR_LEN + sizeof(lifetime) + - 2 + RSN_SELECTOR_LEN + PMKID_LEN; - kde_buf = os_malloc(kde_buf_len); - if (kde_buf == NULL) - return; - pos = kde_buf; - pos = wpa_add_ie(pos, peerkey->rsnie_p, peerkey->rsnie_p_len); - lifetime = host_to_be32(peerkey->lifetime); - pos = wpa_add_kde(pos, RSN_KEY_DATA_LIFETIME, - (u8 *) &lifetime, sizeof(lifetime)); - wpa_add_kde(pos, RSN_KEY_DATA_PMKID, peerkey->smkid, PMKID_LEN); - - if (wpa_supplicant_send_2_of_4(sm, peerkey->addr, key, ver, - peerkey->pnonce, kde_buf, kde_buf_len, - stk)) { - os_free(kde_buf); - return; - } - os_free(kde_buf); - - os_memcpy(peerkey->inonce, key->key_nonce, WPA_NONCE_LEN); -} - - -static void wpa_supplicant_update_smk_lifetime(struct wpa_sm *sm, - struct wpa_peerkey *peerkey, - struct wpa_eapol_ie_parse *kde) -{ - u32 lifetime; - struct os_time now; - - if (kde->lifetime == NULL || kde->lifetime_len < sizeof(lifetime)) - return; - - lifetime = WPA_GET_BE32(kde->lifetime); - - if (lifetime >= peerkey->lifetime) { - wpa_printf(MSG_DEBUG, "RSN: Peer used SMK lifetime %u seconds " - "which is larger than or equal to own value %u " - "seconds - ignored", lifetime, peerkey->lifetime); - return; - } - - wpa_printf(MSG_DEBUG, "RSN: Peer used shorter SMK lifetime %u seconds " - "(own was %u seconds) - updated", - lifetime, peerkey->lifetime); - peerkey->lifetime = lifetime; - - os_get_time(&now); - peerkey->expiration = now.sec + lifetime; - eloop_cancel_timeout(wpa_supplicant_smk_timeout, sm, peerkey); - eloop_register_timeout(lifetime, 0, wpa_supplicant_smk_timeout, - sm, peerkey); -} - - -static void wpa_supplicant_process_stk_2_of_4(struct wpa_sm *sm, - struct wpa_peerkey *peerkey, - const struct wpa_eapol_key *key, - u16 ver) -{ - struct wpa_eapol_ie_parse kde; - const u8 *keydata; - size_t len; - - wpa_printf(MSG_DEBUG, "RSN: RX message 2 of STK 4-Way Handshake from " - MACSTR " (ver=%d)", MAC2STR(peerkey->addr), ver); - - os_memset(&kde, 0, sizeof(kde)); - - /* RSN: msg 2/4 should contain SMKID for the selected SMK and RSN IE - * from the peer. It may also include Lifetime KDE. */ - keydata = (const u8 *) (key + 1); - len = WPA_GET_BE16(key->key_data_length); - wpa_hexdump(MSG_DEBUG, "RSN: msg 2/4 key data", keydata, len); - if (wpa_supplicant_parse_ies(keydata, len, &kde) < 0 || - kde.pmkid == NULL || kde.rsn_ie == NULL) { - wpa_printf(MSG_DEBUG, "RSN: No SMKID or RSN IE in STK 2/4"); - return; - } - - if (os_memcmp(kde.pmkid, peerkey->smkid, PMKID_LEN) != 0) { - wpa_hexdump(MSG_DEBUG, "RSN: Unknown SMKID in STK 2/4", - kde.pmkid, PMKID_LEN); - return; - } - - if (kde.rsn_ie_len != peerkey->rsnie_p_len || - os_memcmp(kde.rsn_ie, peerkey->rsnie_p, kde.rsn_ie_len) != 0) { - wpa_printf(MSG_INFO, "RSN: Peer RSN IE in SMK and STK " - "handshakes did not match"); - wpa_hexdump(MSG_DEBUG, "RSN: Peer RSN IE in SMK handshake", - peerkey->rsnie_p, peerkey->rsnie_p_len); - wpa_hexdump(MSG_DEBUG, "RSN: Peer RSN IE in STK handshake", - kde.rsn_ie, kde.rsn_ie_len); - return; - } - - wpa_supplicant_update_smk_lifetime(sm, peerkey, &kde); - - wpa_supplicant_send_stk_3_of_4(sm, peerkey); - os_memcpy(peerkey->pnonce, key->key_nonce, WPA_NONCE_LEN); -} - - -static void wpa_supplicant_process_stk_3_of_4(struct wpa_sm *sm, - struct wpa_peerkey *peerkey, - const struct wpa_eapol_key *key, - u16 ver) -{ - struct wpa_eapol_ie_parse kde; - const u8 *keydata; - size_t len, key_len; - const u8 *_key; - u8 key_buf[32], rsc[6]; - - wpa_printf(MSG_DEBUG, "RSN: RX message 3 of STK 4-Way Handshake from " - MACSTR " (ver=%d)", MAC2STR(peerkey->addr), ver); - - os_memset(&kde, 0, sizeof(kde)); - - /* RSN: msg 3/4 should contain Initiator RSN IE. It may also include - * Lifetime KDE. */ - keydata = (const u8 *) (key + 1); - len = WPA_GET_BE16(key->key_data_length); - wpa_hexdump(MSG_DEBUG, "RSN: msg 3/4 key data", keydata, len); - if (wpa_supplicant_parse_ies(keydata, len, &kde) < 0) { - wpa_printf(MSG_DEBUG, "RSN: Failed to parse key data in " - "STK 3/4"); - return; - } - - if (kde.rsn_ie_len != peerkey->rsnie_i_len || - os_memcmp(kde.rsn_ie, peerkey->rsnie_i, kde.rsn_ie_len) != 0) { - wpa_printf(MSG_INFO, "RSN: Initiator RSN IE in SMK and STK " - "handshakes did not match"); - wpa_hexdump(MSG_DEBUG, "RSN: Initiator RSN IE in SMK " - "handshake", - peerkey->rsnie_i, peerkey->rsnie_i_len); - wpa_hexdump(MSG_DEBUG, "RSN: Initiator RSN IE in STK " - "handshake", - kde.rsn_ie, kde.rsn_ie_len); - return; - } - - if (os_memcmp(peerkey->inonce, key->key_nonce, WPA_NONCE_LEN) != 0) { - wpa_printf(MSG_WARNING, "RSN: INonce from message 1 of STK " - "4-Way Handshake differs from 3 of STK 4-Way " - "Handshake - drop packet (src=" MACSTR ")", - MAC2STR(peerkey->addr)); - return; - } - - wpa_supplicant_update_smk_lifetime(sm, peerkey, &kde); - - if (wpa_supplicant_send_4_of_4(sm, peerkey->addr, key, ver, - WPA_GET_BE16(key->key_info), - NULL, 0, &peerkey->stk)) - return; - - _key = (u8 *) peerkey->stk.tk1; - if (peerkey->cipher == WPA_CIPHER_TKIP) { - /* Swap Tx/Rx keys for Michael MIC */ - os_memcpy(key_buf, _key, 16); - os_memcpy(key_buf + 16, peerkey->stk.u.auth.rx_mic_key, 8); - os_memcpy(key_buf + 24, peerkey->stk.u.auth.tx_mic_key, 8); - _key = key_buf; - key_len = 32; - } else - key_len = 16; - - os_memset(rsc, 0, 6); - if (wpa_sm_set_key(sm, peerkey->cipher, peerkey->addr, 0, 1, - rsc, sizeof(rsc), _key, key_len) < 0) { - wpa_printf(MSG_WARNING, "RSN: Failed to set STK to the " - "driver."); - return; - } -} - - -static void wpa_supplicant_process_stk_4_of_4(struct wpa_sm *sm, - struct wpa_peerkey *peerkey, - const struct wpa_eapol_key *key, - u16 ver) -{ - u8 rsc[6]; - - wpa_printf(MSG_DEBUG, "RSN: RX message 4 of STK 4-Way Handshake from " - MACSTR " (ver=%d)", MAC2STR(peerkey->addr), ver); - - os_memset(rsc, 0, 6); - if (wpa_sm_set_key(sm, peerkey->cipher, peerkey->addr, 0, 1, - rsc, sizeof(rsc), (u8 *) peerkey->stk.tk1, - peerkey->cipher == WPA_CIPHER_TKIP ? 32 : 16) < 0) { - wpa_printf(MSG_WARNING, "RSN: Failed to set STK to the " - "driver."); - return; - } -} - - -/** - * peerkey_verify_eapol_key_mic - Verify PeerKey MIC - * @sm: Pointer to WPA state machine data from wpa_sm_init() - * @peerkey: Pointer to the PeerKey data for the peer - * @key: Pointer to the EAPOL-Key frame header - * @ver: Version bits from EAPOL-Key Key Info - * @buf: Pointer to the beginning of EAPOL-Key frame - * @len: Length of the EAPOL-Key frame - * Returns: 0 on success, -1 on failure - */ -int peerkey_verify_eapol_key_mic(struct wpa_sm *sm, - struct wpa_peerkey *peerkey, - struct wpa_eapol_key *key, u16 ver, - const u8 *buf, size_t len) -{ - u8 mic[16]; - int ok = 0; - - if (peerkey->initiator && !peerkey->stk_set) { - wpa_pmk_to_ptk(peerkey->smk, PMK_LEN, "Peer key expansion", - sm->own_addr, peerkey->addr, - peerkey->inonce, key->key_nonce, - (u8 *) &peerkey->stk, sizeof(peerkey->stk), - peerkey->use_sha256); - peerkey->stk_set = 1; - } - - os_memcpy(mic, key->key_mic, 16); - if (peerkey->tstk_set) { - os_memset(key->key_mic, 0, 16); - wpa_eapol_key_mic(peerkey->tstk.kck, ver, buf, len, - key->key_mic); - if (os_memcmp(mic, key->key_mic, 16) != 0) { - wpa_printf(MSG_WARNING, "RSN: Invalid EAPOL-Key MIC " - "when using TSTK - ignoring TSTK"); - } else { - ok = 1; - peerkey->tstk_set = 0; - peerkey->stk_set = 1; - os_memcpy(&peerkey->stk, &peerkey->tstk, - sizeof(peerkey->stk)); - } - } - - if (!ok && peerkey->stk_set) { - os_memset(key->key_mic, 0, 16); - wpa_eapol_key_mic(peerkey->stk.kck, ver, buf, len, - key->key_mic); - if (os_memcmp(mic, key->key_mic, 16) != 0) { - wpa_printf(MSG_WARNING, "RSN: Invalid EAPOL-Key MIC " - "- dropping packet"); - return -1; - } - ok = 1; - } - - if (!ok) { - wpa_printf(MSG_WARNING, "RSN: Could not verify EAPOL-Key MIC " - "- dropping packet"); - return -1; - } - - os_memcpy(peerkey->replay_counter, key->replay_counter, - WPA_REPLAY_COUNTER_LEN); - peerkey->replay_counter_set = 1; - return 0; -} - - -/** - * wpa_sm_stkstart - Send EAPOL-Key Request for STK handshake (STK M1) - * @sm: Pointer to WPA state machine data from wpa_sm_init() - * @peer: MAC address of the peer STA - * Returns: 0 on success, or -1 on failure - * - * Send an EAPOL-Key Request to the current authenticator to start STK - * handshake with the peer. - */ -int wpa_sm_stkstart(struct wpa_sm *sm, const u8 *peer) -{ - size_t rlen, kde_len; - struct wpa_eapol_key *req; - int key_info, ver; - u8 bssid[ETH_ALEN], *rbuf, *pos, *count_pos; - u16 count; - struct rsn_ie_hdr *hdr; - struct wpa_peerkey *peerkey; - struct wpa_ie_data ie; - - if (sm->proto != WPA_PROTO_RSN || !sm->ptk_set || !sm->peerkey_enabled) - return -1; - - if (sm->ap_rsn_ie && - wpa_parse_wpa_ie_rsn(sm->ap_rsn_ie, sm->ap_rsn_ie_len, &ie) == 0 && - !(ie.capabilities & WPA_CAPABILITY_PEERKEY_ENABLED)) { - wpa_printf(MSG_DEBUG, "RSN: Current AP does not support STK"); - return -1; - } - - if (sm->pairwise_cipher == WPA_CIPHER_CCMP) - ver = WPA_KEY_INFO_TYPE_HMAC_SHA1_AES; - else - ver = WPA_KEY_INFO_TYPE_HMAC_MD5_RC4; - - if (wpa_sm_get_bssid(sm, bssid) < 0) { - wpa_printf(MSG_WARNING, "Failed to read BSSID for EAPOL-Key " - "SMK M1"); - return -1; - } - - /* TODO: find existing entry and if found, use that instead of adding - * a new one */ - peerkey = os_zalloc(sizeof(*peerkey)); - if (peerkey == NULL) - return -1; - peerkey->initiator = 1; - os_memcpy(peerkey->addr, peer, ETH_ALEN); -#ifdef CONFIG_IEEE80211W - if (wpa_key_mgmt_sha256(sm->key_mgmt)) - peerkey->use_sha256 = 1; -#endif /* CONFIG_IEEE80211W */ - - /* SMK M1: - * EAPOL-Key(S=1, M=1, A=0, I=0, K=0, SM=1, KeyRSC=0, Nonce=INonce, - * MIC=MIC, DataKDs=(RSNIE_I, MAC_P KDE)) - */ - - hdr = (struct rsn_ie_hdr *) peerkey->rsnie_i; - hdr->elem_id = WLAN_EID_RSN; - WPA_PUT_LE16(hdr->version, RSN_VERSION); - pos = (u8 *) (hdr + 1); - /* Group Suite can be anything for SMK RSN IE; receiver will just - * ignore it. */ - RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_CCMP); - pos += RSN_SELECTOR_LEN; - count_pos = pos; - pos += 2; - - count = 0; - if (sm->allowed_pairwise_cipher & WPA_CIPHER_CCMP) { - RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_CCMP); - pos += RSN_SELECTOR_LEN; - count++; - } - if (sm->allowed_pairwise_cipher & WPA_CIPHER_TKIP) { - RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_TKIP); - pos += RSN_SELECTOR_LEN; - count++; - } - WPA_PUT_LE16(count_pos, count); - - hdr->len = (pos - peerkey->rsnie_i) - 2; - peerkey->rsnie_i_len = pos - peerkey->rsnie_i; - wpa_hexdump(MSG_DEBUG, "WPA: RSN IE for SMK handshake", - peerkey->rsnie_i, peerkey->rsnie_i_len); - - kde_len = peerkey->rsnie_i_len + 2 + RSN_SELECTOR_LEN + ETH_ALEN; - - rbuf = wpa_sm_alloc_eapol(sm, IEEE802_1X_TYPE_EAPOL_KEY, NULL, - sizeof(*req) + kde_len, &rlen, - (void *) &req); - if (rbuf == NULL) { - wpa_supplicant_peerkey_free(sm, peerkey); - return -1; - } - - req->type = EAPOL_KEY_TYPE_RSN; - key_info = WPA_KEY_INFO_SMK_MESSAGE | WPA_KEY_INFO_MIC | - WPA_KEY_INFO_SECURE | WPA_KEY_INFO_REQUEST | ver; - WPA_PUT_BE16(req->key_info, key_info); - WPA_PUT_BE16(req->key_length, 0); - os_memcpy(req->replay_counter, sm->request_counter, - WPA_REPLAY_COUNTER_LEN); - inc_byte_array(sm->request_counter, WPA_REPLAY_COUNTER_LEN); - - if (random_get_bytes(peerkey->inonce, WPA_NONCE_LEN)) { - wpa_msg(sm->ctx->msg_ctx, MSG_WARNING, - "WPA: Failed to get random data for INonce"); - os_free(rbuf); - wpa_supplicant_peerkey_free(sm, peerkey); - return -1; - } - os_memcpy(req->key_nonce, peerkey->inonce, WPA_NONCE_LEN); - wpa_hexdump(MSG_DEBUG, "WPA: INonce for SMK handshake", - req->key_nonce, WPA_NONCE_LEN); - - WPA_PUT_BE16(req->key_data_length, (u16) kde_len); - pos = (u8 *) (req + 1); - - /* Initiator RSN IE */ - pos = wpa_add_ie(pos, peerkey->rsnie_i, peerkey->rsnie_i_len); - /* Peer MAC address KDE */ - wpa_add_kde(pos, RSN_KEY_DATA_MAC_ADDR, peer, ETH_ALEN); - - wpa_printf(MSG_INFO, "RSN: Sending EAPOL-Key SMK M1 Request (peer " - MACSTR ")", MAC2STR(peer)); - wpa_eapol_key_send(sm, sm->ptk.kck, ver, bssid, ETH_P_EAPOL, - rbuf, rlen, req->key_mic); - - peerkey->next = sm->peerkey; - sm->peerkey = peerkey; - - return 0; -} - - -/** - * peerkey_deinit - Free PeerKey values - * @sm: Pointer to WPA state machine data from wpa_sm_init() - */ -void peerkey_deinit(struct wpa_sm *sm) -{ - struct wpa_peerkey *prev, *peerkey = sm->peerkey; - while (peerkey) { - prev = peerkey; - peerkey = peerkey->next; - os_free(prev); - } - sm->peerkey = NULL; -} - - -void peerkey_rx_eapol_4way(struct wpa_sm *sm, struct wpa_peerkey *peerkey, - struct wpa_eapol_key *key, u16 key_info, u16 ver) -{ - if ((key_info & (WPA_KEY_INFO_MIC | WPA_KEY_INFO_ACK)) == - (WPA_KEY_INFO_MIC | WPA_KEY_INFO_ACK)) { - /* 3/4 STK 4-Way Handshake */ - wpa_supplicant_process_stk_3_of_4(sm, peerkey, key, ver); - } else if (key_info & WPA_KEY_INFO_ACK) { - /* 1/4 STK 4-Way Handshake */ - wpa_supplicant_process_stk_1_of_4(sm, peerkey, key, ver); - } else if (key_info & WPA_KEY_INFO_SECURE) { - /* 4/4 STK 4-Way Handshake */ - wpa_supplicant_process_stk_4_of_4(sm, peerkey, key, ver); - } else { - /* 2/4 STK 4-Way Handshake */ - wpa_supplicant_process_stk_2_of_4(sm, peerkey, key, ver); - } -} - - -void peerkey_rx_eapol_smk(struct wpa_sm *sm, const u8 *src_addr, - struct wpa_eapol_key *key, size_t extra_len, - u16 key_info, u16 ver) -{ - if (key_info & WPA_KEY_INFO_ERROR) { - /* SMK Error */ - wpa_supplicant_process_smk_error(sm, src_addr, key, extra_len); - } else if (key_info & WPA_KEY_INFO_ACK) { - /* SMK M2 */ - wpa_supplicant_process_smk_m2(sm, src_addr, key, extra_len, - ver); - } else { - /* SMK M4 or M5 */ - wpa_supplicant_process_smk_m45(sm, src_addr, key, extra_len, - ver); - } -} - -#endif /* CONFIG_PEERKEY */ diff --git a/hostapd-0.8/src/rsn_supp/peerkey.h b/hostapd-0.8/src/rsn_supp/peerkey.h deleted file mode 100644 index 2613127..0000000 --- a/hostapd-0.8/src/rsn_supp/peerkey.h +++ /dev/null @@ -1,87 +0,0 @@ -/* - * WPA Supplicant - PeerKey for Direct Link Setup (DLS) - * Copyright (c) 2006-2008, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#ifndef PEERKEY_H -#define PEERKEY_H - -#define PEERKEY_MAX_IE_LEN 80 -struct wpa_peerkey { - struct wpa_peerkey *next; - int initiator; /* whether this end was initator for SMK handshake */ - u8 addr[ETH_ALEN]; /* other end MAC address */ - u8 inonce[WPA_NONCE_LEN]; /* Initiator Nonce */ - u8 pnonce[WPA_NONCE_LEN]; /* Peer Nonce */ - u8 rsnie_i[PEERKEY_MAX_IE_LEN]; /* Initiator RSN IE */ - size_t rsnie_i_len; - u8 rsnie_p[PEERKEY_MAX_IE_LEN]; /* Peer RSN IE */ - size_t rsnie_p_len; - u8 smk[PMK_LEN]; - int smk_complete; - u8 smkid[PMKID_LEN]; - u32 lifetime; - os_time_t expiration; - int cipher; /* Selected cipher (WPA_CIPHER_*) */ - u8 replay_counter[WPA_REPLAY_COUNTER_LEN]; - int replay_counter_set; - int use_sha256; /* whether AKMP indicate SHA256-based derivations */ - - struct wpa_ptk stk, tstk; - int stk_set, tstk_set; -}; - - -#ifdef CONFIG_PEERKEY - -int peerkey_verify_eapol_key_mic(struct wpa_sm *sm, - struct wpa_peerkey *peerkey, - struct wpa_eapol_key *key, u16 ver, - const u8 *buf, size_t len); -void peerkey_rx_eapol_4way(struct wpa_sm *sm, struct wpa_peerkey *peerkey, - struct wpa_eapol_key *key, u16 key_info, u16 ver); -void peerkey_rx_eapol_smk(struct wpa_sm *sm, const u8 *src_addr, - struct wpa_eapol_key *key, size_t extra_len, - u16 key_info, u16 ver); -void peerkey_deinit(struct wpa_sm *sm); - -#else /* CONFIG_PEERKEY */ - -static inline int -peerkey_verify_eapol_key_mic(struct wpa_sm *sm, - struct wpa_peerkey *peerkey, - struct wpa_eapol_key *key, u16 ver, - const u8 *buf, size_t len) -{ - return -1; -} - -static inline void -peerkey_rx_eapol_4way(struct wpa_sm *sm, struct wpa_peerkey *peerkey, - struct wpa_eapol_key *key, u16 key_info, u16 ver) -{ -} - -static inline void -peerkey_rx_eapol_smk(struct wpa_sm *sm, const u8 *src_addr, - struct wpa_eapol_key *key, size_t extra_len, - u16 key_info, u16 ver) -{ -} - -static inline void peerkey_deinit(struct wpa_sm *sm) -{ -} - -#endif /* CONFIG_PEERKEY */ - -#endif /* PEERKEY_H */ diff --git a/hostapd-0.8/src/rsn_supp/pmksa_cache.c b/hostapd-0.8/src/rsn_supp/pmksa_cache.c deleted file mode 100644 index cac8c83..0000000 --- a/hostapd-0.8/src/rsn_supp/pmksa_cache.c +++ /dev/null @@ -1,476 +0,0 @@ -/* - * WPA Supplicant - RSN PMKSA cache - * Copyright (c) 2004-2008, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#include "includes.h" - -#include "common.h" -#include "eloop.h" -#include "eapol_supp/eapol_supp_sm.h" -#include "wpa.h" -#include "wpa_i.h" -#include "pmksa_cache.h" - -#if defined(IEEE8021X_EAPOL) && !defined(CONFIG_NO_WPA2) - -static const int pmksa_cache_max_entries = 32; - -struct rsn_pmksa_cache { - struct rsn_pmksa_cache_entry *pmksa; /* PMKSA cache */ - int pmksa_count; /* number of entries in PMKSA cache */ - struct wpa_sm *sm; /* TODO: get rid of this reference(?) */ - - void (*free_cb)(struct rsn_pmksa_cache_entry *entry, void *ctx, - int replace); - void *ctx; -}; - - -static void pmksa_cache_set_expiration(struct rsn_pmksa_cache *pmksa); - - -static void _pmksa_cache_free_entry(struct rsn_pmksa_cache_entry *entry) -{ - os_free(entry); -} - - -static void pmksa_cache_free_entry(struct rsn_pmksa_cache *pmksa, - struct rsn_pmksa_cache_entry *entry, - int replace) -{ - pmksa->pmksa_count--; - pmksa->free_cb(entry, pmksa->ctx, replace); - _pmksa_cache_free_entry(entry); -} - - -static void pmksa_cache_expire(void *eloop_ctx, void *timeout_ctx) -{ - struct rsn_pmksa_cache *pmksa = eloop_ctx; - struct os_time now; - - os_get_time(&now); - while (pmksa->pmksa && pmksa->pmksa->expiration <= now.sec) { - struct rsn_pmksa_cache_entry *entry = pmksa->pmksa; - pmksa->pmksa = entry->next; - wpa_printf(MSG_DEBUG, "RSN: expired PMKSA cache entry for " - MACSTR, MAC2STR(entry->aa)); - pmksa_cache_free_entry(pmksa, entry, 0); - } - - pmksa_cache_set_expiration(pmksa); -} - - -static void pmksa_cache_reauth(void *eloop_ctx, void *timeout_ctx) -{ - struct rsn_pmksa_cache *pmksa = eloop_ctx; - pmksa->sm->cur_pmksa = NULL; - eapol_sm_request_reauth(pmksa->sm->eapol); -} - - -static void pmksa_cache_set_expiration(struct rsn_pmksa_cache *pmksa) -{ - int sec; - struct rsn_pmksa_cache_entry *entry; - struct os_time now; - - eloop_cancel_timeout(pmksa_cache_expire, pmksa, NULL); - eloop_cancel_timeout(pmksa_cache_reauth, pmksa, NULL); - if (pmksa->pmksa == NULL) - return; - os_get_time(&now); - sec = pmksa->pmksa->expiration - now.sec; - if (sec < 0) - sec = 0; - eloop_register_timeout(sec + 1, 0, pmksa_cache_expire, pmksa, NULL); - - entry = pmksa->sm->cur_pmksa ? pmksa->sm->cur_pmksa : - pmksa_cache_get(pmksa, pmksa->sm->bssid, NULL); - if (entry) { - sec = pmksa->pmksa->reauth_time - now.sec; - if (sec < 0) - sec = 0; - eloop_register_timeout(sec, 0, pmksa_cache_reauth, pmksa, - NULL); - } -} - - -/** - * pmksa_cache_add - Add a PMKSA cache entry - * @pmksa: Pointer to PMKSA cache data from pmksa_cache_init() - * @pmk: The new pairwise master key - * @pmk_len: PMK length in bytes, usually PMK_LEN (32) - * @aa: Authenticator address - * @spa: Supplicant address - * @network_ctx: Network configuration context for this PMK - * @akmp: WPA_KEY_MGMT_* used in key derivation - * Returns: Pointer to the added PMKSA cache entry or %NULL on error - * - * This function create a PMKSA entry for a new PMK and adds it to the PMKSA - * cache. If an old entry is already in the cache for the same Authenticator, - * this entry will be replaced with the new entry. PMKID will be calculated - * based on the PMK and the driver interface is notified of the new PMKID. - */ -struct rsn_pmksa_cache_entry * -pmksa_cache_add(struct rsn_pmksa_cache *pmksa, const u8 *pmk, size_t pmk_len, - const u8 *aa, const u8 *spa, void *network_ctx, int akmp) -{ - struct rsn_pmksa_cache_entry *entry, *pos, *prev; - struct os_time now; - - if (pmk_len > PMK_LEN) - return NULL; - - entry = os_zalloc(sizeof(*entry)); - if (entry == NULL) - return NULL; - os_memcpy(entry->pmk, pmk, pmk_len); - entry->pmk_len = pmk_len; - rsn_pmkid(pmk, pmk_len, aa, spa, entry->pmkid, - wpa_key_mgmt_sha256(akmp)); - os_get_time(&now); - entry->expiration = now.sec + pmksa->sm->dot11RSNAConfigPMKLifetime; - entry->reauth_time = now.sec + pmksa->sm->dot11RSNAConfigPMKLifetime * - pmksa->sm->dot11RSNAConfigPMKReauthThreshold / 100; - entry->akmp = akmp; - os_memcpy(entry->aa, aa, ETH_ALEN); - entry->network_ctx = network_ctx; - - /* Replace an old entry for the same Authenticator (if found) with the - * new entry */ - pos = pmksa->pmksa; - prev = NULL; - while (pos) { - if (os_memcmp(aa, pos->aa, ETH_ALEN) == 0) { - if (pos->pmk_len == pmk_len && - os_memcmp(pos->pmk, pmk, pmk_len) == 0 && - os_memcmp(pos->pmkid, entry->pmkid, PMKID_LEN) == - 0) { - wpa_printf(MSG_DEBUG, "WPA: reusing previous " - "PMKSA entry"); - os_free(entry); - return pos; - } - if (prev == NULL) - pmksa->pmksa = pos->next; - else - prev->next = pos->next; - if (pos == pmksa->sm->cur_pmksa) { - /* We are about to replace the current PMKSA - * cache entry. This happens when the PMKSA - * caching attempt fails, so we don't want to - * force pmksa_cache_free_entry() to disconnect - * at this point. Let's just make sure the old - * PMKSA cache entry will not be used in the - * future. - */ - wpa_printf(MSG_DEBUG, "RSN: replacing current " - "PMKSA entry"); - pmksa->sm->cur_pmksa = NULL; - } - wpa_printf(MSG_DEBUG, "RSN: Replace PMKSA entry for " - "the current AP"); - pmksa_cache_free_entry(pmksa, pos, 1); - break; - } - prev = pos; - pos = pos->next; - } - - if (pmksa->pmksa_count >= pmksa_cache_max_entries && pmksa->pmksa) { - /* Remove the oldest entry to make room for the new entry */ - pos = pmksa->pmksa; - pmksa->pmksa = pos->next; - wpa_printf(MSG_DEBUG, "RSN: removed the oldest PMKSA cache " - "entry (for " MACSTR ") to make room for new one", - MAC2STR(pos->aa)); - wpa_sm_remove_pmkid(pmksa->sm, pos->aa, pos->pmkid); - pmksa_cache_free_entry(pmksa, pos, 0); - } - - /* Add the new entry; order by expiration time */ - pos = pmksa->pmksa; - prev = NULL; - while (pos) { - if (pos->expiration > entry->expiration) - break; - prev = pos; - pos = pos->next; - } - if (prev == NULL) { - entry->next = pmksa->pmksa; - pmksa->pmksa = entry; - pmksa_cache_set_expiration(pmksa); - } else { - entry->next = prev->next; - prev->next = entry; - } - pmksa->pmksa_count++; - wpa_printf(MSG_DEBUG, "RSN: added PMKSA cache entry for " MACSTR, - MAC2STR(entry->aa)); - wpa_sm_add_pmkid(pmksa->sm, entry->aa, entry->pmkid); - - return entry; -} - - -/** - * pmksa_cache_deinit - Free all entries in PMKSA cache - * @pmksa: Pointer to PMKSA cache data from pmksa_cache_init() - */ -void pmksa_cache_deinit(struct rsn_pmksa_cache *pmksa) -{ - struct rsn_pmksa_cache_entry *entry, *prev; - - if (pmksa == NULL) - return; - - entry = pmksa->pmksa; - pmksa->pmksa = NULL; - while (entry) { - prev = entry; - entry = entry->next; - os_free(prev); - } - pmksa_cache_set_expiration(pmksa); - os_free(pmksa); -} - - -/** - * pmksa_cache_get - Fetch a PMKSA cache entry - * @pmksa: Pointer to PMKSA cache data from pmksa_cache_init() - * @aa: Authenticator address or %NULL to match any - * @pmkid: PMKID or %NULL to match any - * Returns: Pointer to PMKSA cache entry or %NULL if no match was found - */ -struct rsn_pmksa_cache_entry * pmksa_cache_get(struct rsn_pmksa_cache *pmksa, - const u8 *aa, const u8 *pmkid) -{ - struct rsn_pmksa_cache_entry *entry = pmksa->pmksa; - while (entry) { - if ((aa == NULL || os_memcmp(entry->aa, aa, ETH_ALEN) == 0) && - (pmkid == NULL || - os_memcmp(entry->pmkid, pmkid, PMKID_LEN) == 0)) - return entry; - entry = entry->next; - } - return NULL; -} - - -/** - * pmksa_cache_notify_reconfig - Reconfiguration notification for PMKSA cache - * @pmksa: Pointer to PMKSA cache data from pmksa_cache_init() - * - * Clear references to old data structures when wpa_supplicant is reconfigured. - */ -void pmksa_cache_notify_reconfig(struct rsn_pmksa_cache *pmksa) -{ - struct rsn_pmksa_cache_entry *entry = pmksa->pmksa; - while (entry) { - entry->network_ctx = NULL; - entry = entry->next; - } -} - - -static struct rsn_pmksa_cache_entry * -pmksa_cache_clone_entry(struct rsn_pmksa_cache *pmksa, - const struct rsn_pmksa_cache_entry *old_entry, - const u8 *aa) -{ - struct rsn_pmksa_cache_entry *new_entry; - - new_entry = pmksa_cache_add(pmksa, old_entry->pmk, old_entry->pmk_len, - aa, pmksa->sm->own_addr, - old_entry->network_ctx, old_entry->akmp); - if (new_entry == NULL) - return NULL; - - /* TODO: reorder entries based on expiration time? */ - new_entry->expiration = old_entry->expiration; - new_entry->opportunistic = 1; - - return new_entry; -} - - -/** - * pmksa_cache_get_opportunistic - Try to get an opportunistic PMKSA entry - * @pmksa: Pointer to PMKSA cache data from pmksa_cache_init() - * @network_ctx: Network configuration context - * @aa: Authenticator address for the new AP - * Returns: Pointer to a new PMKSA cache entry or %NULL if not available - * - * Try to create a new PMKSA cache entry opportunistically by guessing that the - * new AP is sharing the same PMK as another AP that has the same SSID and has - * already an entry in PMKSA cache. - */ -struct rsn_pmksa_cache_entry * -pmksa_cache_get_opportunistic(struct rsn_pmksa_cache *pmksa, void *network_ctx, - const u8 *aa) -{ - struct rsn_pmksa_cache_entry *entry = pmksa->pmksa; - - if (network_ctx == NULL) - return NULL; - while (entry) { - if (entry->network_ctx == network_ctx) { - entry = pmksa_cache_clone_entry(pmksa, entry, aa); - if (entry) { - wpa_printf(MSG_DEBUG, "RSN: added " - "opportunistic PMKSA cache entry " - "for " MACSTR, MAC2STR(aa)); - } - return entry; - } - entry = entry->next; - } - return NULL; -} - - -/** - * pmksa_cache_get_current - Get the current used PMKSA entry - * @sm: Pointer to WPA state machine data from wpa_sm_init() - * Returns: Pointer to the current PMKSA cache entry or %NULL if not available - */ -struct rsn_pmksa_cache_entry * pmksa_cache_get_current(struct wpa_sm *sm) -{ - if (sm == NULL) - return NULL; - return sm->cur_pmksa; -} - - -/** - * pmksa_cache_clear_current - Clear the current PMKSA entry selection - * @sm: Pointer to WPA state machine data from wpa_sm_init() - */ -void pmksa_cache_clear_current(struct wpa_sm *sm) -{ - if (sm == NULL) - return; - sm->cur_pmksa = NULL; -} - - -/** - * pmksa_cache_set_current - Set the current PMKSA entry selection - * @sm: Pointer to WPA state machine data from wpa_sm_init() - * @pmkid: PMKID for selecting PMKSA or %NULL if not used - * @bssid: BSSID for PMKSA or %NULL if not used - * @network_ctx: Network configuration context - * @try_opportunistic: Whether to allow opportunistic PMKSA caching - * Returns: 0 if PMKSA was found or -1 if no matching entry was found - */ -int pmksa_cache_set_current(struct wpa_sm *sm, const u8 *pmkid, - const u8 *bssid, void *network_ctx, - int try_opportunistic) -{ - struct rsn_pmksa_cache *pmksa = sm->pmksa; - sm->cur_pmksa = NULL; - if (pmkid) - sm->cur_pmksa = pmksa_cache_get(pmksa, NULL, pmkid); - if (sm->cur_pmksa == NULL && bssid) - sm->cur_pmksa = pmksa_cache_get(pmksa, bssid, NULL); - if (sm->cur_pmksa == NULL && try_opportunistic && bssid) - sm->cur_pmksa = pmksa_cache_get_opportunistic(pmksa, - network_ctx, - bssid); - if (sm->cur_pmksa) { - wpa_hexdump(MSG_DEBUG, "RSN: PMKID", - sm->cur_pmksa->pmkid, PMKID_LEN); - return 0; - } - return -1; -} - - -/** - * pmksa_cache_list - Dump text list of entries in PMKSA cache - * @pmksa: Pointer to PMKSA cache data from pmksa_cache_init() - * @buf: Buffer for the list - * @len: Length of the buffer - * Returns: number of bytes written to buffer - * - * This function is used to generate a text format representation of the - * current PMKSA cache contents for the ctrl_iface PMKSA command. - */ -int pmksa_cache_list(struct rsn_pmksa_cache *pmksa, char *buf, size_t len) -{ - int i, ret; - char *pos = buf; - struct rsn_pmksa_cache_entry *entry; - struct os_time now; - - os_get_time(&now); - ret = os_snprintf(pos, buf + len - pos, - "Index / AA / PMKID / expiration (in seconds) / " - "opportunistic\n"); - if (ret < 0 || ret >= buf + len - pos) - return pos - buf; - pos += ret; - i = 0; - entry = pmksa->pmksa; - while (entry) { - i++; - ret = os_snprintf(pos, buf + len - pos, "%d " MACSTR " ", - i, MAC2STR(entry->aa)); - if (ret < 0 || ret >= buf + len - pos) - return pos - buf; - pos += ret; - pos += wpa_snprintf_hex(pos, buf + len - pos, entry->pmkid, - PMKID_LEN); - ret = os_snprintf(pos, buf + len - pos, " %d %d\n", - (int) (entry->expiration - now.sec), - entry->opportunistic); - if (ret < 0 || ret >= buf + len - pos) - return pos - buf; - pos += ret; - entry = entry->next; - } - return pos - buf; -} - - -/** - * pmksa_cache_init - Initialize PMKSA cache - * @free_cb: Callback function to be called when a PMKSA cache entry is freed - * @ctx: Context pointer for free_cb function - * @sm: Pointer to WPA state machine data from wpa_sm_init() - * Returns: Pointer to PMKSA cache data or %NULL on failure - */ -struct rsn_pmksa_cache * -pmksa_cache_init(void (*free_cb)(struct rsn_pmksa_cache_entry *entry, - void *ctx, int replace), - void *ctx, struct wpa_sm *sm) -{ - struct rsn_pmksa_cache *pmksa; - - pmksa = os_zalloc(sizeof(*pmksa)); - if (pmksa) { - pmksa->free_cb = free_cb; - pmksa->ctx = ctx; - pmksa->sm = sm; - } - - return pmksa; -} - -#endif /* IEEE8021X_EAPOL and !CONFIG_NO_WPA2 */ diff --git a/hostapd-0.8/src/rsn_supp/pmksa_cache.h b/hostapd-0.8/src/rsn_supp/pmksa_cache.h deleted file mode 100644 index a1447e5..0000000 --- a/hostapd-0.8/src/rsn_supp/pmksa_cache.h +++ /dev/null @@ -1,127 +0,0 @@ -/* - * wpa_supplicant - WPA2/RSN PMKSA cache functions - * Copyright (c) 2003-2008, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#ifndef PMKSA_CACHE_H -#define PMKSA_CACHE_H - -/** - * struct rsn_pmksa_cache_entry - PMKSA cache entry - */ -struct rsn_pmksa_cache_entry { - struct rsn_pmksa_cache_entry *next; - u8 pmkid[PMKID_LEN]; - u8 pmk[PMK_LEN]; - size_t pmk_len; - os_time_t expiration; - int akmp; /* WPA_KEY_MGMT_* */ - u8 aa[ETH_ALEN]; - - os_time_t reauth_time; - - /** - * network_ctx - Network configuration context - * - * This field is only used to match PMKSA cache entries to a specific - * network configuration (e.g., a specific SSID and security policy). - * This can be a pointer to the configuration entry, but PMKSA caching - * code does not dereference the value and this could be any kind of - * identifier. - */ - void *network_ctx; - int opportunistic; -}; - -struct rsn_pmksa_cache; - -#if defined(IEEE8021X_EAPOL) && !defined(CONFIG_NO_WPA2) - -struct rsn_pmksa_cache * -pmksa_cache_init(void (*free_cb)(struct rsn_pmksa_cache_entry *entry, - void *ctx, int replace), - void *ctx, struct wpa_sm *sm); -void pmksa_cache_deinit(struct rsn_pmksa_cache *pmksa); -struct rsn_pmksa_cache_entry * pmksa_cache_get(struct rsn_pmksa_cache *pmksa, - const u8 *aa, const u8 *pmkid); -int pmksa_cache_list(struct rsn_pmksa_cache *pmksa, char *buf, size_t len); -struct rsn_pmksa_cache_entry * -pmksa_cache_add(struct rsn_pmksa_cache *pmksa, const u8 *pmk, size_t pmk_len, - const u8 *aa, const u8 *spa, void *network_ctx, int akmp); -void pmksa_cache_notify_reconfig(struct rsn_pmksa_cache *pmksa); -struct rsn_pmksa_cache_entry * pmksa_cache_get_current(struct wpa_sm *sm); -void pmksa_cache_clear_current(struct wpa_sm *sm); -int pmksa_cache_set_current(struct wpa_sm *sm, const u8 *pmkid, - const u8 *bssid, void *network_ctx, - int try_opportunistic); -struct rsn_pmksa_cache_entry * -pmksa_cache_get_opportunistic(struct rsn_pmksa_cache *pmksa, - void *network_ctx, const u8 *aa); - -#else /* IEEE8021X_EAPOL and !CONFIG_NO_WPA2 */ - -static inline struct rsn_pmksa_cache * -pmksa_cache_init(void (*free_cb)(struct rsn_pmksa_cache_entry *entry, - void *ctx, int replace), - void *ctx, struct wpa_sm *sm) -{ - return (void *) -1; -} - -static inline void pmksa_cache_deinit(struct rsn_pmksa_cache *pmksa) -{ -} - -static inline struct rsn_pmksa_cache_entry * -pmksa_cache_get(struct rsn_pmksa_cache *pmksa, const u8 *aa, const u8 *pmkid) -{ - return NULL; -} - -static inline struct rsn_pmksa_cache_entry * -pmksa_cache_get_current(struct wpa_sm *sm) -{ - return NULL; -} - -static inline int pmksa_cache_list(struct rsn_pmksa_cache *pmksa, char *buf, - size_t len) -{ - return -1; -} - -static inline struct rsn_pmksa_cache_entry * -pmksa_cache_add(struct rsn_pmksa_cache *pmksa, const u8 *pmk, size_t pmk_len, - const u8 *aa, const u8 *spa, void *network_ctx, int akmp) -{ - return NULL; -} - -static inline void pmksa_cache_notify_reconfig(struct rsn_pmksa_cache *pmksa) -{ -} - -static inline void pmksa_cache_clear_current(struct wpa_sm *sm) -{ -} - -static inline int pmksa_cache_set_current(struct wpa_sm *sm, const u8 *pmkid, - const u8 *bssid, - void *network_ctx, - int try_opportunistic) -{ - return -1; -} - -#endif /* IEEE8021X_EAPOL and !CONFIG_NO_WPA2 */ - -#endif /* PMKSA_CACHE_H */ diff --git a/hostapd-0.8/src/rsn_supp/preauth.c b/hostapd-0.8/src/rsn_supp/preauth.c deleted file mode 100644 index 6109f5e..0000000 --- a/hostapd-0.8/src/rsn_supp/preauth.c +++ /dev/null @@ -1,518 +0,0 @@ -/* - * RSN pre-authentication (supplicant) - * Copyright (c) 2003-2010, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#include "includes.h" - -#include "common.h" -#include "wpa.h" -#include "eloop.h" -#include "l2_packet/l2_packet.h" -#include "eapol_supp/eapol_supp_sm.h" -#include "preauth.h" -#include "pmksa_cache.h" -#include "wpa_i.h" -#include "common/ieee802_11_defs.h" - - -#if defined(IEEE8021X_EAPOL) && !defined(CONFIG_NO_WPA2) - -#define PMKID_CANDIDATE_PRIO_SCAN 1000 - - -struct rsn_pmksa_candidate { - struct dl_list list; - u8 bssid[ETH_ALEN]; - int priority; -}; - - -/** - * pmksa_candidate_free - Free all entries in PMKSA candidate list - * @sm: Pointer to WPA state machine data from wpa_sm_init() - */ -void pmksa_candidate_free(struct wpa_sm *sm) -{ - struct rsn_pmksa_candidate *entry, *n; - - if (sm == NULL) - return; - - dl_list_for_each_safe(entry, n, &sm->pmksa_candidates, - struct rsn_pmksa_candidate, list) { - dl_list_del(&entry->list); - os_free(entry); - } -} - - -static void rsn_preauth_receive(void *ctx, const u8 *src_addr, - const u8 *buf, size_t len) -{ - struct wpa_sm *sm = ctx; - - wpa_printf(MSG_DEBUG, "RX pre-auth from " MACSTR, MAC2STR(src_addr)); - wpa_hexdump(MSG_MSGDUMP, "RX pre-auth", buf, len); - - if (sm->preauth_eapol == NULL || - is_zero_ether_addr(sm->preauth_bssid) || - os_memcmp(sm->preauth_bssid, src_addr, ETH_ALEN) != 0) { - wpa_printf(MSG_WARNING, "RSN pre-auth frame received from " - "unexpected source " MACSTR " - dropped", - MAC2STR(src_addr)); - return; - } - - eapol_sm_rx_eapol(sm->preauth_eapol, src_addr, buf, len); -} - - -static void rsn_preauth_eapol_cb(struct eapol_sm *eapol, int success, - void *ctx) -{ - struct wpa_sm *sm = ctx; - u8 pmk[PMK_LEN]; - - if (success) { - int res, pmk_len; - pmk_len = PMK_LEN; - res = eapol_sm_get_key(eapol, pmk, PMK_LEN); - if (res) { - /* - * EAP-LEAP is an exception from other EAP methods: it - * uses only 16-byte PMK. - */ - res = eapol_sm_get_key(eapol, pmk, 16); - pmk_len = 16; - } - if (res == 0) { - wpa_hexdump_key(MSG_DEBUG, "RSN: PMK from pre-auth", - pmk, pmk_len); - sm->pmk_len = pmk_len; - pmksa_cache_add(sm->pmksa, pmk, pmk_len, - sm->preauth_bssid, sm->own_addr, - sm->network_ctx, - WPA_KEY_MGMT_IEEE8021X); - } else { - wpa_msg(sm->ctx->msg_ctx, MSG_INFO, - "RSN: failed to get master session key from " - "pre-auth EAPOL state machines"); - success = 0; - } - } - - wpa_msg(sm->ctx->msg_ctx, MSG_INFO, "RSN: pre-authentication with " - MACSTR " %s", MAC2STR(sm->preauth_bssid), - success ? "completed successfully" : "failed"); - - rsn_preauth_deinit(sm); - rsn_preauth_candidate_process(sm); -} - - -static void rsn_preauth_timeout(void *eloop_ctx, void *timeout_ctx) -{ - struct wpa_sm *sm = eloop_ctx; - - wpa_msg(sm->ctx->msg_ctx, MSG_INFO, "RSN: pre-authentication with " - MACSTR " timed out", MAC2STR(sm->preauth_bssid)); - rsn_preauth_deinit(sm); - rsn_preauth_candidate_process(sm); -} - - -static int rsn_preauth_eapol_send(void *ctx, int type, const u8 *buf, - size_t len) -{ - struct wpa_sm *sm = ctx; - u8 *msg; - size_t msglen; - int res; - - /* TODO: could add l2_packet_sendmsg that allows fragments to avoid - * extra copy here */ - - if (sm->l2_preauth == NULL) - return -1; - - msg = wpa_sm_alloc_eapol(sm, type, buf, len, &msglen, NULL); - if (msg == NULL) - return -1; - - wpa_hexdump(MSG_MSGDUMP, "TX EAPOL (preauth)", msg, msglen); - res = l2_packet_send(sm->l2_preauth, sm->preauth_bssid, - ETH_P_RSN_PREAUTH, msg, msglen); - os_free(msg); - return res; -} - - -/** - * rsn_preauth_init - Start new RSN pre-authentication - * @sm: Pointer to WPA state machine data from wpa_sm_init() - * @dst: Authenticator address (BSSID) with which to preauthenticate - * @eap_conf: Current EAP configuration - * Returns: 0 on success, -1 on another pre-authentication is in progress, - * -2 on layer 2 packet initialization failure, -3 on EAPOL state machine - * initialization failure, -4 on memory allocation failure - * - * This function request an RSN pre-authentication with a given destination - * address. This is usually called for PMKSA candidates found from scan results - * or from driver reports. In addition, ctrl_iface PREAUTH command can trigger - * pre-authentication. - */ -int rsn_preauth_init(struct wpa_sm *sm, const u8 *dst, - struct eap_peer_config *eap_conf) -{ - struct eapol_config eapol_conf; - struct eapol_ctx *ctx; - - if (sm->preauth_eapol) - return -1; - - wpa_msg(sm->ctx->msg_ctx, MSG_DEBUG, - "RSN: starting pre-authentication with " MACSTR, MAC2STR(dst)); - - sm->l2_preauth = l2_packet_init(sm->ifname, sm->own_addr, - ETH_P_RSN_PREAUTH, - rsn_preauth_receive, sm, 0); - if (sm->l2_preauth == NULL) { - wpa_printf(MSG_WARNING, "RSN: Failed to initialize L2 packet " - "processing for pre-authentication"); - return -2; - } - - if (sm->bridge_ifname) { - sm->l2_preauth_br = l2_packet_init(sm->bridge_ifname, - sm->own_addr, - ETH_P_RSN_PREAUTH, - rsn_preauth_receive, sm, 0); - if (sm->l2_preauth_br == NULL) { - wpa_printf(MSG_WARNING, "RSN: Failed to initialize L2 " - "packet processing (bridge) for " - "pre-authentication"); - return -2; - } - } - - ctx = os_zalloc(sizeof(*ctx)); - if (ctx == NULL) { - wpa_printf(MSG_WARNING, "Failed to allocate EAPOL context."); - return -4; - } - ctx->ctx = sm->ctx->ctx; - ctx->msg_ctx = sm->ctx->ctx; - ctx->preauth = 1; - ctx->cb = rsn_preauth_eapol_cb; - ctx->cb_ctx = sm; - ctx->scard_ctx = sm->scard_ctx; - ctx->eapol_send = rsn_preauth_eapol_send; - ctx->eapol_send_ctx = sm; - ctx->set_config_blob = sm->ctx->set_config_blob; - ctx->get_config_blob = sm->ctx->get_config_blob; - - sm->preauth_eapol = eapol_sm_init(ctx); - if (sm->preauth_eapol == NULL) { - os_free(ctx); - wpa_printf(MSG_WARNING, "RSN: Failed to initialize EAPOL " - "state machines for pre-authentication"); - return -3; - } - os_memset(&eapol_conf, 0, sizeof(eapol_conf)); - eapol_conf.accept_802_1x_keys = 0; - eapol_conf.required_keys = 0; - eapol_conf.fast_reauth = sm->fast_reauth; - eapol_conf.workaround = sm->eap_workaround; - eapol_sm_notify_config(sm->preauth_eapol, eap_conf, &eapol_conf); - /* - * Use a shorter startPeriod with preauthentication since the first - * preauth EAPOL-Start frame may end up being dropped due to race - * condition in the AP between the data receive and key configuration - * after the 4-Way Handshake. - */ - eapol_sm_configure(sm->preauth_eapol, -1, -1, 5, 6); - os_memcpy(sm->preauth_bssid, dst, ETH_ALEN); - - eapol_sm_notify_portValid(sm->preauth_eapol, TRUE); - /* 802.1X::portControl = Auto */ - eapol_sm_notify_portEnabled(sm->preauth_eapol, TRUE); - - eloop_register_timeout(sm->dot11RSNAConfigSATimeout, 0, - rsn_preauth_timeout, sm, NULL); - - return 0; -} - - -/** - * rsn_preauth_deinit - Abort RSN pre-authentication - * @sm: Pointer to WPA state machine data from wpa_sm_init() - * - * This function aborts the current RSN pre-authentication (if one is started) - * and frees resources allocated for it. - */ -void rsn_preauth_deinit(struct wpa_sm *sm) -{ - if (sm == NULL || !sm->preauth_eapol) - return; - - eloop_cancel_timeout(rsn_preauth_timeout, sm, NULL); - eapol_sm_deinit(sm->preauth_eapol); - sm->preauth_eapol = NULL; - os_memset(sm->preauth_bssid, 0, ETH_ALEN); - - l2_packet_deinit(sm->l2_preauth); - sm->l2_preauth = NULL; - if (sm->l2_preauth_br) { - l2_packet_deinit(sm->l2_preauth_br); - sm->l2_preauth_br = NULL; - } -} - - -/** - * rsn_preauth_candidate_process - Process PMKSA candidates - * @sm: Pointer to WPA state machine data from wpa_sm_init() - * - * Go through the PMKSA candidates and start pre-authentication if a candidate - * without an existing PMKSA cache entry is found. Processed candidates will be - * removed from the list. - */ -void rsn_preauth_candidate_process(struct wpa_sm *sm) -{ - struct rsn_pmksa_candidate *candidate, *n; - - if (dl_list_empty(&sm->pmksa_candidates)) - return; - - /* TODO: drop priority for old candidate entries */ - - wpa_msg(sm->ctx->msg_ctx, MSG_DEBUG, "RSN: processing PMKSA candidate " - "list"); - if (sm->preauth_eapol || - sm->proto != WPA_PROTO_RSN || - wpa_sm_get_state(sm) != WPA_COMPLETED || - (sm->key_mgmt != WPA_KEY_MGMT_IEEE8021X && - sm->key_mgmt != WPA_KEY_MGMT_IEEE8021X_SHA256)) { - wpa_msg(sm->ctx->msg_ctx, MSG_DEBUG, "RSN: not in suitable " - "state for new pre-authentication"); - return; /* invalid state for new pre-auth */ - } - - dl_list_for_each_safe(candidate, n, &sm->pmksa_candidates, - struct rsn_pmksa_candidate, list) { - struct rsn_pmksa_cache_entry *p = NULL; - p = pmksa_cache_get(sm->pmksa, candidate->bssid, NULL); - if (os_memcmp(sm->bssid, candidate->bssid, ETH_ALEN) != 0 && - (p == NULL || p->opportunistic)) { - wpa_msg(sm->ctx->msg_ctx, MSG_DEBUG, "RSN: PMKSA " - "candidate " MACSTR - " selected for pre-authentication", - MAC2STR(candidate->bssid)); - dl_list_del(&candidate->list); - rsn_preauth_init(sm, candidate->bssid, - sm->eap_conf_ctx); - os_free(candidate); - return; - } - wpa_msg(sm->ctx->msg_ctx, MSG_DEBUG, "RSN: PMKSA candidate " - MACSTR " does not need pre-authentication anymore", - MAC2STR(candidate->bssid)); - /* Some drivers (e.g., NDIS) expect to get notified about the - * PMKIDs again, so report the existing data now. */ - if (p) { - wpa_sm_add_pmkid(sm, candidate->bssid, p->pmkid); - } - - dl_list_del(&candidate->list); - os_free(candidate); - } - wpa_msg(sm->ctx->msg_ctx, MSG_DEBUG, "RSN: no more pending PMKSA " - "candidates"); -} - - -/** - * pmksa_candidate_add - Add a new PMKSA candidate - * @sm: Pointer to WPA state machine data from wpa_sm_init() - * @bssid: BSSID (authenticator address) of the candidate - * @prio: Priority (the smaller number, the higher priority) - * @preauth: Whether the candidate AP advertises support for pre-authentication - * - * This function is used to add PMKSA candidates for RSN pre-authentication. It - * is called from scan result processing and from driver events for PMKSA - * candidates, i.e., EVENT_PMKID_CANDIDATE events to wpa_supplicant_event(). - */ -void pmksa_candidate_add(struct wpa_sm *sm, const u8 *bssid, - int prio, int preauth) -{ - struct rsn_pmksa_candidate *cand, *pos; - - if (sm->network_ctx && sm->proactive_key_caching) - pmksa_cache_get_opportunistic(sm->pmksa, sm->network_ctx, - bssid); - - if (!preauth) { - wpa_printf(MSG_DEBUG, "RSN: Ignored PMKID candidate without " - "preauth flag"); - return; - } - - /* If BSSID already on candidate list, update the priority of the old - * entry. Do not override priority based on normal scan results. */ - cand = NULL; - dl_list_for_each(pos, &sm->pmksa_candidates, - struct rsn_pmksa_candidate, list) { - if (os_memcmp(pos->bssid, bssid, ETH_ALEN) == 0) { - cand = pos; - break; - } - } - - if (cand) { - dl_list_del(&cand->list); - if (prio < PMKID_CANDIDATE_PRIO_SCAN) - cand->priority = prio; - } else { - cand = os_zalloc(sizeof(*cand)); - if (cand == NULL) - return; - os_memcpy(cand->bssid, bssid, ETH_ALEN); - cand->priority = prio; - } - - /* Add candidate to the list; order by increasing priority value. i.e., - * highest priority (smallest value) first. */ - dl_list_for_each(pos, &sm->pmksa_candidates, - struct rsn_pmksa_candidate, list) { - if (cand->priority <= pos->priority) { - dl_list_add(pos->list.prev, &cand->list); - cand = NULL; - break; - } - } - if (cand) - dl_list_add_tail(&sm->pmksa_candidates, &cand->list); - - wpa_msg(sm->ctx->msg_ctx, MSG_DEBUG, "RSN: added PMKSA cache " - "candidate " MACSTR " prio %d", MAC2STR(bssid), prio); - rsn_preauth_candidate_process(sm); -} - - -/* TODO: schedule periodic scans if current AP supports preauth */ - -/** - * rsn_preauth_scan_results - Start processing scan results for canditates - * @sm: Pointer to WPA state machine data from wpa_sm_init() - * Returns: 0 if ready to process results or -1 to skip processing - * - * This functions is used to notify RSN code about start of new scan results - * processing. The actual scan results will be provided by calling - * rsn_preauth_scan_result() for each BSS if this function returned 0. - */ -int rsn_preauth_scan_results(struct wpa_sm *sm) -{ - if (sm->ssid_len == 0) - return -1; - - /* - * TODO: is it ok to free all candidates? What about the entries - * received from EVENT_PMKID_CANDIDATE? - */ - pmksa_candidate_free(sm); - - return 0; -} - - -/** - * rsn_preauth_scan_result - Processing scan result for PMKSA canditates - * @sm: Pointer to WPA state machine data from wpa_sm_init() - * - * Add all suitable APs (Authenticators) from scan results into PMKSA - * candidate list. - */ -void rsn_preauth_scan_result(struct wpa_sm *sm, const u8 *bssid, - const u8 *ssid, const u8 *rsn) -{ - struct wpa_ie_data ie; - struct rsn_pmksa_cache_entry *pmksa; - - if (ssid[1] != sm->ssid_len || - os_memcmp(ssid + 2, sm->ssid, sm->ssid_len) != 0) - return; /* Not for the current SSID */ - - if (os_memcmp(bssid, sm->bssid, ETH_ALEN) == 0) - return; /* Ignore current AP */ - - if (wpa_parse_wpa_ie(rsn, 2 + rsn[1], &ie)) - return; - - pmksa = pmksa_cache_get(sm->pmksa, bssid, NULL); - if (pmksa && (!pmksa->opportunistic || - !(ie.capabilities & WPA_CAPABILITY_PREAUTH))) - return; - - /* Give less priority to candidates found from normal scan results. */ - pmksa_candidate_add(sm, bssid, PMKID_CANDIDATE_PRIO_SCAN, - ie.capabilities & WPA_CAPABILITY_PREAUTH); -} - - -#ifdef CONFIG_CTRL_IFACE -/** - * rsn_preauth_get_status - Get pre-authentication status - * @sm: Pointer to WPA state machine data from wpa_sm_init() - * @buf: Buffer for status information - * @buflen: Maximum buffer length - * @verbose: Whether to include verbose status information - * Returns: Number of bytes written to buf. - * - * Query WPA2 pre-authentication for status information. This function fills in - * a text area with current status information. If the buffer (buf) is not - * large enough, status information will be truncated to fit the buffer. - */ -int rsn_preauth_get_status(struct wpa_sm *sm, char *buf, size_t buflen, - int verbose) -{ - char *pos = buf, *end = buf + buflen; - int res, ret; - - if (sm->preauth_eapol) { - ret = os_snprintf(pos, end - pos, "Pre-authentication " - "EAPOL state machines:\n"); - if (ret < 0 || ret >= end - pos) - return pos - buf; - pos += ret; - res = eapol_sm_get_status(sm->preauth_eapol, - pos, end - pos, verbose); - if (res >= 0) - pos += res; - } - - return pos - buf; -} -#endif /* CONFIG_CTRL_IFACE */ - - -/** - * rsn_preauth_in_progress - Verify whether pre-authentication is in progress - * @sm: Pointer to WPA state machine data from wpa_sm_init() - */ -int rsn_preauth_in_progress(struct wpa_sm *sm) -{ - return sm->preauth_eapol != NULL; -} - -#endif /* IEEE8021X_EAPOL and !CONFIG_NO_WPA2 */ diff --git a/hostapd-0.8/src/rsn_supp/preauth.h b/hostapd-0.8/src/rsn_supp/preauth.h deleted file mode 100644 index f8240ab..0000000 --- a/hostapd-0.8/src/rsn_supp/preauth.h +++ /dev/null @@ -1,85 +0,0 @@ -/* - * wpa_supplicant - WPA2/RSN pre-authentication functions - * Copyright (c) 2003-2009, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#ifndef PREAUTH_H -#define PREAUTH_H - -struct wpa_scan_results; - -#if defined(IEEE8021X_EAPOL) && !defined(CONFIG_NO_WPA2) - -void pmksa_candidate_free(struct wpa_sm *sm); -int rsn_preauth_init(struct wpa_sm *sm, const u8 *dst, - struct eap_peer_config *eap_conf); -void rsn_preauth_deinit(struct wpa_sm *sm); -int rsn_preauth_scan_results(struct wpa_sm *sm); -void rsn_preauth_scan_result(struct wpa_sm *sm, const u8 *bssid, - const u8 *ssid, const u8 *rsn); -void pmksa_candidate_add(struct wpa_sm *sm, const u8 *bssid, - int prio, int preauth); -void rsn_preauth_candidate_process(struct wpa_sm *sm); -int rsn_preauth_get_status(struct wpa_sm *sm, char *buf, size_t buflen, - int verbose); -int rsn_preauth_in_progress(struct wpa_sm *sm); - -#else /* IEEE8021X_EAPOL and !CONFIG_NO_WPA2 */ - -static inline void pmksa_candidate_free(struct wpa_sm *sm) -{ -} - -static inline void rsn_preauth_candidate_process(struct wpa_sm *sm) -{ -} - -static inline int rsn_preauth_init(struct wpa_sm *sm, const u8 *dst, - struct eap_peer_config *eap_conf) -{ - return -1; -} - -static inline void rsn_preauth_deinit(struct wpa_sm *sm) -{ -} - -static inline int rsn_preauth_scan_results(struct wpa_sm *sm) -{ - return -1; -} - -static inline void rsn_preauth_scan_result(struct wpa_sm *sm, const u8 *bssid, - const u8 *ssid, const u8 *rsn) -{ -} - -static inline void pmksa_candidate_add(struct wpa_sm *sm, - const u8 *bssid, - int prio, int preauth) -{ -} - -static inline int rsn_preauth_get_status(struct wpa_sm *sm, char *buf, - size_t buflen, int verbose) -{ - return 0; -} - -static inline int rsn_preauth_in_progress(struct wpa_sm *sm) -{ - return 0; -} - -#endif /* IEEE8021X_EAPOL and !CONFIG_NO_WPA2 */ - -#endif /* PREAUTH_H */ diff --git a/hostapd-0.8/src/rsn_supp/tdls.c b/hostapd-0.8/src/rsn_supp/tdls.c deleted file mode 100644 index e751867..0000000 --- a/hostapd-0.8/src/rsn_supp/tdls.c +++ /dev/null @@ -1,2069 +0,0 @@ -/* - * wpa_supplicant - TDLS - * Copyright (c) 2010-2011, Atheros Communications - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#include "utils/includes.h" - -#include "utils/common.h" -#include "utils/eloop.h" -#include "utils/os.h" -#include "common/ieee802_11_defs.h" -#include "crypto/sha256.h" -#include "crypto/crypto.h" -#include "crypto/aes_wrap.h" -#include "rsn_supp/wpa.h" -#include "rsn_supp/wpa_ie.h" -#include "rsn_supp/wpa_i.h" -#include "drivers/driver.h" -#include "l2_packet/l2_packet.h" - -#ifdef CONFIG_TDLS_TESTING -#define TDLS_TESTING_LONG_FRAME BIT(0) -#define TDLS_TESTING_ALT_RSN_IE BIT(1) -#define TDLS_TESTING_DIFF_BSSID BIT(2) -#define TDLS_TESTING_SHORT_LIFETIME BIT(3) -#define TDLS_TESTING_WRONG_LIFETIME_RESP BIT(4) -#define TDLS_TESTING_WRONG_LIFETIME_CONF BIT(5) -#define TDLS_TESTING_LONG_LIFETIME BIT(6) -#define TDLS_TESTING_CONCURRENT_INIT BIT(7) -#define TDLS_TESTING_NO_TPK_EXPIRATION BIT(8) -#define TDLS_TESTING_DECLINE_RESP BIT(9) -#define TDLS_TESTING_IGNORE_AP_PROHIBIT BIT(10) -unsigned int tdls_testing = 0; -#endif /* CONFIG_TDLS_TESTING */ - -#define TPK_LIFETIME 43200 /* 12 hours */ -#define TPK_RETRY_COUNT 3 -#define TPK_TIMEOUT 5000 /* in milliseconds */ - -#define TDLS_MIC_LEN 16 - -#define TDLS_TIMEOUT_LEN 4 - -struct wpa_tdls_ftie { - u8 ie_type; /* FTIE */ - u8 ie_len; - u8 mic_ctrl[2]; - u8 mic[TDLS_MIC_LEN]; - u8 Anonce[WPA_NONCE_LEN]; /* Responder Nonce in TDLS */ - u8 Snonce[WPA_NONCE_LEN]; /* Initiator Nonce in TDLS */ - /* followed by optional elements */ -} STRUCT_PACKED; - -struct wpa_tdls_timeoutie { - u8 ie_type; /* Timeout IE */ - u8 ie_len; - u8 interval_type; - u8 value[TDLS_TIMEOUT_LEN]; -} STRUCT_PACKED; - -struct wpa_tdls_lnkid { - u8 ie_type; /* Link Identifier IE */ - u8 ie_len; - u8 bssid[ETH_ALEN]; - u8 init_sta[ETH_ALEN]; - u8 resp_sta[ETH_ALEN]; -} STRUCT_PACKED; - -/* TDLS frame headers as per IEEE Std 802.11z-2010 */ -struct wpa_tdls_frame { - u8 payloadtype; /* IEEE80211_TDLS_RFTYPE */ - u8 category; /* Category */ - u8 action; /* Action (enum tdls_frame_type) */ -} STRUCT_PACKED; - -static u8 * wpa_add_tdls_timeoutie(u8 *pos, u8 *ie, size_t ie_len, u32 tsecs); -static void wpa_tdls_tpk_retry_timeout(void *eloop_ctx, void *timeout_ctx); -static void wpa_tdls_peer_free(struct wpa_sm *sm, struct wpa_tdls_peer *peer); - - -#define TDLS_MAX_IE_LEN 80 -struct wpa_tdls_peer { - struct wpa_tdls_peer *next; - int initiator; /* whether this end was initiator for TDLS setup */ - u8 addr[ETH_ALEN]; /* other end MAC address */ - u8 inonce[WPA_NONCE_LEN]; /* Initiator Nonce */ - u8 rnonce[WPA_NONCE_LEN]; /* Responder Nonce */ - u8 rsnie_i[TDLS_MAX_IE_LEN]; /* Initiator RSN IE */ - size_t rsnie_i_len; - u8 rsnie_p[TDLS_MAX_IE_LEN]; /* Peer RSN IE */ - size_t rsnie_p_len; - u32 lifetime; - int cipher; /* Selected cipher (WPA_CIPHER_*) */ - u8 dtoken; - - struct tpk { - u8 kck[16]; /* TPK-KCK */ - u8 tk[16]; /* TPK-TK; assuming only CCMP will be used */ - } tpk; - int tpk_set; - int tpk_success; - - struct tpk_timer { - u8 dest[ETH_ALEN]; - int count; /* Retry Count */ - int timer; /* Timeout in milliseconds */ - u8 action_code; /* TDLS frame type */ - u8 dialog_token; - u16 status_code; - int buf_len; /* length of TPK message for retransmission */ - u8 *buf; /* buffer for TPK message */ - } sm_tmr; -}; - - -static int wpa_tdls_get_privacy(struct wpa_sm *sm) -{ - /* - * Get info needed from supplicant to check if the current BSS supports - * security. Other than OPEN mode, rest are considered secured - * WEP/WPA/WPA2 hence TDLS frames are processed for TPK handshake. - */ - return sm->pairwise_cipher != WPA_CIPHER_NONE; -} - - -static u8 * wpa_add_ie(u8 *pos, const u8 *ie, size_t ie_len) -{ - os_memcpy(pos, ie, ie_len); - return pos + ie_len; -} - - -static int wpa_tdls_del_key(struct wpa_sm *sm, struct wpa_tdls_peer *peer) -{ - if (wpa_sm_set_key(sm, WPA_ALG_NONE, peer->addr, - 0, 0, NULL, 0, NULL, 0) < 0) { - wpa_printf(MSG_WARNING, "TDLS: Failed to delete TPK-TK from " - "the driver"); - return -1; - } - - return 0; -} - - -static int wpa_tdls_set_key(struct wpa_sm *sm, struct wpa_tdls_peer *peer) -{ - u8 key_len; - u8 rsc[6]; - enum wpa_alg alg; - - os_memset(rsc, 0, 6); - - switch (peer->cipher) { - case WPA_CIPHER_CCMP: - alg = WPA_ALG_CCMP; - key_len = 16; - break; - case WPA_CIPHER_NONE: - wpa_printf(MSG_DEBUG, "TDLS: Pairwise Cipher Suite: " - "NONE - do not use pairwise keys"); - return -1; - default: - wpa_printf(MSG_WARNING, "TDLS: Unsupported pairwise cipher %d", - sm->pairwise_cipher); - return -1; - } - - if (wpa_sm_set_key(sm, alg, peer->addr, -1, 1, - rsc, sizeof(rsc), peer->tpk.tk, key_len) < 0) { - wpa_printf(MSG_WARNING, "TDLS: Failed to set TPK to the " - "driver"); - return -1; - } - return 0; -} - - -static int wpa_tdls_send_tpk_msg(struct wpa_sm *sm, const u8 *dst, - u8 action_code, u8 dialog_token, - u16 status_code, const u8 *buf, size_t len) -{ - return wpa_sm_send_tdls_mgmt(sm, dst, action_code, dialog_token, - status_code, buf, len); -} - - -static int wpa_tdls_tpk_send(struct wpa_sm *sm, const u8 *dest, u8 action_code, - u8 dialog_token, u16 status_code, - const u8 *msg, size_t msg_len) -{ - struct wpa_tdls_peer *peer; - - wpa_printf(MSG_DEBUG, "TDLS: TPK send dest=" MACSTR " action_code=%u " - "dialog_token=%u status_code=%u msg_len=%u", - MAC2STR(dest), action_code, dialog_token, status_code, - (unsigned int) msg_len); - - if (wpa_tdls_send_tpk_msg(sm, dest, action_code, dialog_token, - status_code, msg, msg_len)) { - wpa_printf(MSG_INFO, "TDLS: Failed to send message " - "(action_code=%u)", action_code); - return -1; - } - - if (action_code == WLAN_TDLS_SETUP_CONFIRM || - action_code == WLAN_TDLS_TEARDOWN) - return 0; /* No retries */ - - for (peer = sm->tdls; peer; peer = peer->next) { - if (os_memcmp(peer->addr, dest, ETH_ALEN) == 0) - break; - } - - if (peer == NULL) { - wpa_printf(MSG_INFO, "TDLS: No matching entry found for " - "retry " MACSTR, MAC2STR(dest)); - return 0; - } - - eloop_cancel_timeout(wpa_tdls_tpk_retry_timeout, sm, peer); - - peer->sm_tmr.count = TPK_RETRY_COUNT; - peer->sm_tmr.timer = TPK_TIMEOUT; - - /* Copy message to resend on timeout */ - os_memcpy(peer->sm_tmr.dest, dest, ETH_ALEN); - peer->sm_tmr.action_code = action_code; - peer->sm_tmr.dialog_token = dialog_token; - peer->sm_tmr.status_code = status_code; - peer->sm_tmr.buf_len = msg_len; - os_free(peer->sm_tmr.buf); - peer->sm_tmr.buf = os_malloc(msg_len); - if (peer->sm_tmr.buf == NULL) - return -1; - os_memcpy(peer->sm_tmr.buf, msg, msg_len); - - wpa_printf(MSG_DEBUG, "TDLS: Retry timeout registered " - "(action_code=%u)", action_code); - eloop_register_timeout(peer->sm_tmr.timer / 1000, 0, - wpa_tdls_tpk_retry_timeout, sm, peer); - return 0; -} - - -static void wpa_tdls_tpk_retry_timeout(void *eloop_ctx, void *timeout_ctx) -{ - - struct wpa_sm *sm = eloop_ctx; - struct wpa_tdls_peer *peer = timeout_ctx; - - if (peer->sm_tmr.count) { - peer->sm_tmr.count--; - peer->sm_tmr.timer = TPK_TIMEOUT; - - wpa_printf(MSG_INFO, "TDLS: Retrying sending of message " - "(action_code=%u)", - peer->sm_tmr.action_code); - - if (peer->sm_tmr.buf == NULL) { - wpa_printf(MSG_INFO, "TDLS: No retry buffer available " - "for action_code=%u", - peer->sm_tmr.action_code); - eloop_cancel_timeout(wpa_tdls_tpk_retry_timeout, sm, - peer); - return; - } - - /* resend TPK Handshake Message to Peer */ - if (wpa_tdls_send_tpk_msg(sm, peer->sm_tmr.dest, - peer->sm_tmr.action_code, - peer->sm_tmr.dialog_token, - peer->sm_tmr.status_code, - peer->sm_tmr.buf, - peer->sm_tmr.buf_len)) { - wpa_printf(MSG_INFO, "TDLS: Failed to retry " - "transmission"); - } - - eloop_cancel_timeout(wpa_tdls_tpk_retry_timeout, sm, peer); - eloop_register_timeout(peer->sm_tmr.timer / 1000, 0, - wpa_tdls_tpk_retry_timeout, sm, peer); - } else { - wpa_printf(MSG_INFO, "Sending Tear_Down Request"); - wpa_sm_tdls_oper(sm, TDLS_TEARDOWN, peer->addr); - - wpa_printf(MSG_INFO, "Clearing SM: Peerkey(" MACSTR ")", - MAC2STR(peer->addr)); - eloop_cancel_timeout(wpa_tdls_tpk_retry_timeout, sm, peer); - - /* clear the Peerkey statemachine */ - wpa_tdls_peer_free(sm, peer); - } -} - - -static void wpa_tdls_tpk_retry_timeout_cancel(struct wpa_sm *sm, - struct wpa_tdls_peer *peer, - u8 action_code) -{ - if (action_code == peer->sm_tmr.action_code) { - wpa_printf(MSG_DEBUG, "TDLS: Retry timeout cancelled for " - "action_code=%u", action_code); - - /* Cancel Timeout registered */ - eloop_cancel_timeout(wpa_tdls_tpk_retry_timeout, sm, peer); - - /* free all resources meant for retry */ - os_free(peer->sm_tmr.buf); - peer->sm_tmr.buf = NULL; - - peer->sm_tmr.count = 0; - peer->sm_tmr.timer = 0; - peer->sm_tmr.buf_len = 0; - peer->sm_tmr.action_code = 0xff; - } else { - wpa_printf(MSG_INFO, "TDLS: Error in cancelling retry timeout " - "(Unknown action_code=%u)", action_code); - } -} - - -static void wpa_tdls_generate_tpk(struct wpa_tdls_peer *peer, - const u8 *own_addr, const u8 *bssid) -{ - u8 key_input[SHA256_MAC_LEN]; - const u8 *nonce[2]; - size_t len[2]; - u8 data[3 * ETH_ALEN]; - - /* IEEE Std 802.11z-2010 8.5.9.1: - * TPK-Key-Input = SHA-256(min(SNonce, ANonce) || max(SNonce, ANonce)) - */ - len[0] = WPA_NONCE_LEN; - len[1] = WPA_NONCE_LEN; - if (os_memcmp(peer->inonce, peer->rnonce, WPA_NONCE_LEN) < 0) { - nonce[0] = peer->inonce; - nonce[1] = peer->rnonce; - } else { - nonce[0] = peer->rnonce; - nonce[1] = peer->inonce; - } - wpa_hexdump(MSG_DEBUG, "TDLS: min(Nonce)", nonce[0], WPA_NONCE_LEN); - wpa_hexdump(MSG_DEBUG, "TDLS: max(Nonce)", nonce[1], WPA_NONCE_LEN); - sha256_vector(2, nonce, len, key_input); - wpa_hexdump_key(MSG_DEBUG, "TDLS: TPK-Key-Input", - key_input, SHA256_MAC_LEN); - - /* - * TPK-Key-Data = KDF-N_KEY(TPK-Key-Input, "TDLS PMK", - * min(MAC_I, MAC_R) || max(MAC_I, MAC_R) || BSSID || N_KEY) - * TODO: is N_KEY really included in KDF Context and if so, in which - * presentation format (little endian 16-bit?) is it used? It gets - * added by the KDF anyway.. - */ - - if (os_memcmp(own_addr, peer->addr, ETH_ALEN) < 0) { - os_memcpy(data, own_addr, ETH_ALEN); - os_memcpy(data + ETH_ALEN, peer->addr, ETH_ALEN); - } else { - os_memcpy(data, peer->addr, ETH_ALEN); - os_memcpy(data + ETH_ALEN, own_addr, ETH_ALEN); - } - os_memcpy(data + 2 * ETH_ALEN, bssid, ETH_ALEN); - wpa_hexdump(MSG_DEBUG, "TDLS: KDF Context", data, sizeof(data)); - - sha256_prf(key_input, SHA256_MAC_LEN, "TDLS PMK", data, sizeof(data), - (u8 *) &peer->tpk, sizeof(peer->tpk)); - wpa_hexdump_key(MSG_DEBUG, "TDLS: TPK-KCK", - peer->tpk.kck, sizeof(peer->tpk.kck)); - wpa_hexdump_key(MSG_DEBUG, "TDLS: TPK-TK", - peer->tpk.tk, sizeof(peer->tpk.tk)); - peer->tpk_set = 1; -} - - -/** - * wpa_tdls_ftie_mic - Calculate TDLS FTIE MIC - * @kck: TPK-KCK - * @lnkid: Pointer to the beginning of Link Identifier IE - * @rsnie: Pointer to the beginning of RSN IE used for handshake - * @timeoutie: Pointer to the beginning of Timeout IE used for handshake - * @ftie: Pointer to the beginning of FT IE - * @mic: Pointer for writing MIC - * - * Calculate MIC for TDLS frame. - */ -static int wpa_tdls_ftie_mic(const u8 *kck, u8 trans_seq, const u8 *lnkid, - const u8 *rsnie, const u8 *timeoutie, - const u8 *ftie, u8 *mic) -{ - u8 *buf, *pos; - struct wpa_tdls_ftie *_ftie; - const struct wpa_tdls_lnkid *_lnkid; - int ret; - int len = 2 * ETH_ALEN + 1 + 2 + lnkid[1] + 2 + rsnie[1] + - 2 + timeoutie[1] + 2 + ftie[1]; - buf = os_zalloc(len); - if (!buf) { - wpa_printf(MSG_WARNING, "TDLS: No memory for MIC calculation"); - return -1; - } - - pos = buf; - _lnkid = (const struct wpa_tdls_lnkid *) lnkid; - /* 1) TDLS initiator STA MAC address */ - os_memcpy(pos, _lnkid->init_sta, ETH_ALEN); - pos += ETH_ALEN; - /* 2) TDLS responder STA MAC address */ - os_memcpy(pos, _lnkid->resp_sta, ETH_ALEN); - pos += ETH_ALEN; - /* 3) Transaction Sequence number */ - *pos++ = trans_seq; - /* 4) Link Identifier IE */ - os_memcpy(pos, lnkid, 2 + lnkid[1]); - pos += 2 + lnkid[1]; - /* 5) RSN IE */ - os_memcpy(pos, rsnie, 2 + rsnie[1]); - pos += 2 + rsnie[1]; - /* 6) Timeout Interval IE */ - os_memcpy(pos, timeoutie, 2 + timeoutie[1]); - pos += 2 + timeoutie[1]; - /* 7) FTIE, with the MIC field of the FTIE set to 0 */ - os_memcpy(pos, ftie, 2 + ftie[1]); - _ftie = (struct wpa_tdls_ftie *) pos; - os_memset(_ftie->mic, 0, TDLS_MIC_LEN); - pos += 2 + ftie[1]; - - wpa_hexdump(MSG_DEBUG, "TDLS: Data for FTIE MIC", buf, pos - buf); - wpa_hexdump_key(MSG_DEBUG, "TDLS: KCK", kck, 16); - ret = omac1_aes_128(kck, buf, pos - buf, mic); - os_free(buf); - wpa_hexdump(MSG_DEBUG, "TDLS: FTIE MIC", mic, 16); - return ret; -} - - -/** - * wpa_tdls_key_mic_teardown - Calculate TDLS FTIE MIC for Teardown frame - * @kck: TPK-KCK - * @trans_seq: Transaction Sequence Number (4 - Teardown) - * @rcode: Reason code for Teardown - * @dtoken: Dialog Token used for that particular link - * @lnkid: Pointer to the beginning of Link Identifier IE - * @ftie: Pointer to the beginning of FT IE - * @mic: Pointer for writing MIC - * - * Calculate MIC for TDLS frame. - */ -static int wpa_tdls_key_mic_teardown(const u8 *kck, u8 trans_seq, u16 rcode, - u8 dtoken, const u8 *lnkid, - const u8 *ftie, u8 *mic) -{ - u8 *buf, *pos; - struct wpa_tdls_ftie *_ftie; - int ret; - int len; - - if (lnkid == NULL) - return -1; - - len = 2 + lnkid[1] + sizeof(rcode) + sizeof(dtoken) + - sizeof(trans_seq) + 2 + ftie[1]; - - buf = os_zalloc(len); - if (!buf) { - wpa_printf(MSG_WARNING, "TDLS: No memory for MIC calculation"); - return -1; - } - - pos = buf; - /* 1) Link Identifier IE */ - os_memcpy(pos, lnkid, 2 + lnkid[1]); - pos += 2 + lnkid[1]; - /* 2) Reason Code */ - WPA_PUT_LE16(pos, rcode); - pos += sizeof(rcode); - /* 3) Dialog token */ - *pos++ = dtoken; - /* 4) Transaction Sequence number */ - *pos++ = trans_seq; - /* 7) FTIE, with the MIC field of the FTIE set to 0 */ - os_memcpy(pos, ftie, 2 + ftie[1]); - _ftie = (struct wpa_tdls_ftie *) pos; - os_memset(_ftie->mic, 0, TDLS_MIC_LEN); - pos += 2 + ftie[1]; - - wpa_hexdump(MSG_DEBUG, "TDLS: Data for FTIE MIC", buf, pos - buf); - wpa_hexdump_key(MSG_DEBUG, "TDLS: KCK", kck, 16); - ret = omac1_aes_128(kck, buf, pos - buf, mic); - os_free(buf); - wpa_hexdump(MSG_DEBUG, "TDLS: FTIE MIC", mic, 16); - return ret; -} - - -static int wpa_supplicant_verify_tdls_mic(u8 trans_seq, - struct wpa_tdls_peer *peer, - const u8 *lnkid, const u8 *timeoutie, - const struct wpa_tdls_ftie *ftie) -{ - u8 mic[16]; - - if (peer->tpk_set) { - wpa_tdls_ftie_mic(peer->tpk.kck, trans_seq, lnkid, - peer->rsnie_p, timeoutie, (u8 *) ftie, - mic); - if (os_memcmp(mic, ftie->mic, 16) != 0) { - wpa_printf(MSG_INFO, "TDLS: Invalid MIC in FTIE - " - "dropping packet"); - wpa_hexdump(MSG_DEBUG, "TDLS: Received MIC", - ftie->mic, 16); - wpa_hexdump(MSG_DEBUG, "TDLS: Calculated MIC", - mic, 16); - return -1; - } - } else { - wpa_printf(MSG_WARNING, "TDLS: Could not verify TDLS MIC, " - "TPK not set - dropping packet"); - return -1; - } - return 0; -} - - -static int wpa_supplicant_verify_tdls_mic_teardown( - u8 trans_seq, u16 rcode, u8 dtoken, struct wpa_tdls_peer *peer, - const u8 *lnkid, const struct wpa_tdls_ftie *ftie) -{ - u8 mic[16]; - - if (peer->tpk_set) { - wpa_tdls_key_mic_teardown(peer->tpk.kck, trans_seq, rcode, - dtoken, lnkid, (u8 *) ftie, mic); - if (os_memcmp(mic, ftie->mic, 16) != 0) { - wpa_printf(MSG_INFO, "TDLS: Invalid MIC in Teardown - " - "dropping packet"); - return -1; - } - } else { - wpa_printf(MSG_INFO, "TDLS: Could not verify TDLS Teardown " - "MIC, TPK not set - dropping packet"); - return -1; - } - return 0; -} - - -static void wpa_tdls_tpk_timeout(void *eloop_ctx, void *timeout_ctx) -{ - struct wpa_sm *sm = eloop_ctx; - struct wpa_tdls_peer *peer = timeout_ctx; - - /* - * On TPK lifetime expiration, we have an option of either tearing down - * the direct link or trying to re-initiate it. The selection of what - * to do is not strictly speaking controlled by our role in the expired - * link, but for now, use that to select whether to renew or tear down - * the link. - */ - - if (peer->initiator) { - wpa_printf(MSG_DEBUG, "TDLS: TPK lifetime expired for " MACSTR - " - try to renew", MAC2STR(peer->addr)); - wpa_tdls_start(sm, peer->addr); - } else { - wpa_printf(MSG_DEBUG, "TDLS: TPK lifetime expired for " MACSTR - " - tear down", MAC2STR(peer->addr)); - wpa_sm_tdls_oper(sm, TDLS_TEARDOWN, peer->addr); - } -} - - -static void wpa_tdls_peer_free(struct wpa_sm *sm, struct wpa_tdls_peer *peer) -{ - wpa_printf(MSG_DEBUG, "TDLS: Clear state for peer " MACSTR, - MAC2STR(peer->addr)); - eloop_cancel_timeout(wpa_tdls_tpk_timeout, sm, peer); - eloop_cancel_timeout(wpa_tdls_tpk_retry_timeout, sm, peer); - peer->initiator = 0; - os_free(peer->sm_tmr.buf); - peer->sm_tmr.buf = NULL; - peer->rsnie_i_len = peer->rsnie_p_len = 0; - peer->cipher = 0; - peer->tpk_set = peer->tpk_success = 0; - os_memset(&peer->tpk, 0, sizeof(peer->tpk)); - os_memset(peer->inonce, 0, WPA_NONCE_LEN); - os_memset(peer->rnonce, 0, WPA_NONCE_LEN); -} - - -static void wpa_tdls_linkid(struct wpa_sm *sm, struct wpa_tdls_peer *peer, - struct wpa_tdls_lnkid *lnkid) -{ - lnkid->ie_type = WLAN_EID_LINK_ID; - lnkid->ie_len = 3 * ETH_ALEN; - os_memcpy(lnkid->bssid, sm->bssid, ETH_ALEN); - if (peer->initiator) { - os_memcpy(lnkid->init_sta, sm->own_addr, ETH_ALEN); - os_memcpy(lnkid->resp_sta, peer->addr, ETH_ALEN); - } else { - os_memcpy(lnkid->init_sta, peer->addr, ETH_ALEN); - os_memcpy(lnkid->resp_sta, sm->own_addr, ETH_ALEN); - } -} - - -int wpa_tdls_recv_teardown_notify(struct wpa_sm *sm, const u8 *addr, - u16 reason_code) -{ - struct wpa_tdls_peer *peer; - struct wpa_tdls_ftie *ftie; - struct wpa_tdls_lnkid lnkid; - u8 dialog_token; - u8 *rbuf, *pos; - int ielen; - - if (sm->tdls_disabled) - return -1; - - /* Find the node and free from the list */ - for (peer = sm->tdls; peer; peer = peer->next) { - if (os_memcmp(peer->addr, addr, ETH_ALEN) == 0) - break; - } - - if (peer == NULL) { - wpa_printf(MSG_INFO, "TDLS: No matching entry found for " - "Teardown " MACSTR, MAC2STR(addr)); - return 0; - } - - dialog_token = peer->dtoken; - - wpa_printf(MSG_DEBUG, "TDLS: TDLS Teardown for " MACSTR, - MAC2STR(addr)); - - ielen = 0; - if (wpa_tdls_get_privacy(sm) && peer->tpk_set && peer->tpk_success) { - /* To add FTIE for Teardown request and compute MIC */ - ielen += sizeof(*ftie); -#ifdef CONFIG_TDLS_TESTING - if (tdls_testing & TDLS_TESTING_LONG_FRAME) - ielen += 170; -#endif /* CONFIG_TDLS_TESTING */ - } - - rbuf = os_zalloc(ielen + 1); - if (rbuf == NULL) - return -1; - pos = rbuf; - - if (!wpa_tdls_get_privacy(sm) || !peer->tpk_set || !peer->tpk_success) - goto skip_ies; - - ftie = (struct wpa_tdls_ftie *) pos; - ftie->ie_type = WLAN_EID_FAST_BSS_TRANSITION; - /* Using the recent nonce which should be for CONFIRM frame */ - os_memcpy(ftie->Anonce, peer->rnonce, WPA_NONCE_LEN); - os_memcpy(ftie->Snonce, peer->inonce, WPA_NONCE_LEN); - ftie->ie_len = sizeof(struct wpa_tdls_ftie) - 2; - pos = (u8 *) (ftie + 1); -#ifdef CONFIG_TDLS_TESTING - if (tdls_testing & TDLS_TESTING_LONG_FRAME) { - wpa_printf(MSG_DEBUG, "TDLS: Testing - add extra subelem to " - "FTIE"); - ftie->ie_len += 170; - *pos++ = 255; /* FTIE subelem */ - *pos++ = 168; /* FTIE subelem length */ - } -#endif /* CONFIG_TDLS_TESTING */ - wpa_hexdump(MSG_DEBUG, "TDLS: FTIE for TDLS Teardown handshake", - (u8 *) ftie, sizeof(*ftie)); - - /* compute MIC before sending */ - wpa_tdls_linkid(sm, peer, &lnkid); - wpa_tdls_key_mic_teardown(peer->tpk.kck, 4, reason_code, - dialog_token, (u8 *) &lnkid, (u8 *) ftie, - ftie->mic); - -skip_ies: - /* TODO: register for a Timeout handler, if Teardown is not received at - * the other end, then try again another time */ - - /* request driver to send Teardown using this FTIE */ - wpa_tdls_tpk_send(sm, addr, WLAN_TDLS_TEARDOWN, 0, - WLAN_REASON_TDLS_TEARDOWN_UNSPECIFIED, rbuf, - pos - rbuf); - os_free(rbuf); - - /* clear the Peerkey statemachine */ - wpa_tdls_peer_free(sm, peer); - - return 0; -} - - -static int wpa_tdls_recv_teardown(struct wpa_sm *sm, const u8 *src_addr, - const u8 *buf, size_t len) -{ - struct wpa_tdls_peer *peer = NULL; - struct wpa_tdls_ftie *ftie; - struct wpa_tdls_lnkid *lnkid; - struct wpa_eapol_ie_parse kde; - u16 reason_code; - const u8 *pos; - int ielen; - - /* Find the node and free from the list */ - for (peer = sm->tdls; peer; peer = peer->next) { - if (os_memcmp(peer->addr, src_addr, ETH_ALEN) == 0) - break; - } - - if (peer == NULL) { - wpa_printf(MSG_INFO, "TDLS: No matching entry found for " - "Teardown " MACSTR, MAC2STR(src_addr)); - return 0; - } - - pos = buf; - pos += 1 /* pkt_type */ + 1 /* Category */ + 1 /* Action */; - - reason_code = WPA_GET_LE16(pos); - pos += 2; - - wpa_printf(MSG_DEBUG, "TDLS: TDLS Teardown Request from " MACSTR - " (reason code %u)", MAC2STR(src_addr), reason_code); - - ielen = len - (pos - buf); /* start of IE in buf */ - if (wpa_supplicant_parse_ies((const u8 *) pos, ielen, &kde) < 0) { - wpa_printf(MSG_INFO, "TDLS: Failed to parse IEs in Teardown"); - return -1; - } - - if (kde.lnkid == NULL || kde.lnkid_len < 3 * ETH_ALEN) { - wpa_printf(MSG_INFO, "TDLS: No Link Identifier IE in TDLS " - "Teardown"); - return -1; - } - lnkid = (struct wpa_tdls_lnkid *) kde.lnkid; - - if (!wpa_tdls_get_privacy(sm) || !peer->tpk_set || !peer->tpk_success) - goto skip_ftie; - - if (kde.ftie == NULL || kde.ftie_len < sizeof(*ftie)) { - wpa_printf(MSG_INFO, "TDLS: No FTIE in TDLS Teardown"); - return -1; - } - - ftie = (struct wpa_tdls_ftie *) kde.ftie; - - /* Process MIC check to see if TDLS Teardown is right */ - if (wpa_supplicant_verify_tdls_mic_teardown(4, reason_code, - peer->dtoken, peer, - (u8 *) lnkid, ftie) < 0) { - wpa_printf(MSG_DEBUG, "TDLS: MIC failure for TDLS " - "Teardown Request from " MACSTR, MAC2STR(src_addr)); - return -1; - } - -skip_ftie: - /* - * Request the driver to disable the direct link and clear associated - * keys. - */ - wpa_sm_tdls_oper(sm, TDLS_DISABLE_LINK, src_addr); - - /* clear the Peerkey statemachine */ - wpa_tdls_peer_free(sm, peer); - - return 0; -} - - -/** - * wpa_tdls_send_error - To send suitable TDLS status response with - * appropriate status code mentioning reason for error/failure. - * @dst - MAC addr of Peer station - * @tdls_action - TDLS frame type for which error code is sent - * @status - status code mentioning reason - */ - -static int wpa_tdls_send_error(struct wpa_sm *sm, const u8 *dst, - u8 tdls_action, u8 dialog_token, u16 status) -{ - wpa_printf(MSG_DEBUG, "TDLS: Sending error to " MACSTR - " (action=%u status=%u)", - MAC2STR(dst), tdls_action, status); - return wpa_tdls_tpk_send(sm, dst, tdls_action, dialog_token, status, - NULL, 0); -} - - -static int wpa_tdls_send_tpk_m1(struct wpa_sm *sm, - struct wpa_tdls_peer *peer) -{ - size_t buf_len; - struct wpa_tdls_timeoutie timeoutie; - u16 rsn_capab; - struct wpa_tdls_ftie *ftie; - u8 *rbuf, *pos, *count_pos; - u16 count; - struct rsn_ie_hdr *hdr; - - if (!wpa_tdls_get_privacy(sm)) { - wpa_printf(MSG_DEBUG, "TDLS: No security used on the link"); - peer->rsnie_i_len = 0; - goto skip_rsnie; - } - - /* - * TPK Handshake Message 1: - * FTIE: ANonce=0, SNonce=initiator nonce MIC=0, DataKDs=(RSNIE_I, - * Timeout Interval IE)) - */ - - /* Filling RSN IE */ - hdr = (struct rsn_ie_hdr *) peer->rsnie_i; - hdr->elem_id = WLAN_EID_RSN; - WPA_PUT_LE16(hdr->version, RSN_VERSION); - - pos = (u8 *) (hdr + 1); - RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_NO_GROUP_ADDRESSED); - pos += RSN_SELECTOR_LEN; - count_pos = pos; - pos += 2; - - count = 0; - - /* - * AES-CCMP is the default Encryption preferred for TDLS, so - * RSN IE is filled only with CCMP CIPHER - * Note: TKIP is not used to encrypt TDLS link. - * - * Regardless of the cipher used on the AP connection, select CCMP - * here. - */ - RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_CCMP); - pos += RSN_SELECTOR_LEN; - count++; - - WPA_PUT_LE16(count_pos, count); - - WPA_PUT_LE16(pos, 1); - pos += 2; - RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_TPK_HANDSHAKE); - pos += RSN_SELECTOR_LEN; - - rsn_capab = WPA_CAPABILITY_PEERKEY_ENABLED; - rsn_capab |= RSN_NUM_REPLAY_COUNTERS_16 << 2; -#ifdef CONFIG_TDLS_TESTING - if (tdls_testing & TDLS_TESTING_ALT_RSN_IE) { - wpa_printf(MSG_DEBUG, "TDLS: Use alternative RSN IE for " - "testing"); - rsn_capab = WPA_CAPABILITY_PEERKEY_ENABLED; - } -#endif /* CONFIG_TDLS_TESTING */ - WPA_PUT_LE16(pos, rsn_capab); - pos += 2; -#ifdef CONFIG_TDLS_TESTING - if (tdls_testing & TDLS_TESTING_ALT_RSN_IE) { - /* Number of PMKIDs */ - *pos++ = 0x00; - *pos++ = 0x00; - } -#endif /* CONFIG_TDLS_TESTING */ - - hdr->len = (pos - peer->rsnie_i) - 2; - peer->rsnie_i_len = pos - peer->rsnie_i; - wpa_hexdump(MSG_DEBUG, "TDLS: RSN IE for TPK handshake", - peer->rsnie_i, peer->rsnie_i_len); - -skip_rsnie: - buf_len = 0; - if (wpa_tdls_get_privacy(sm)) - buf_len += peer->rsnie_i_len + sizeof(struct wpa_tdls_ftie) + - sizeof(struct wpa_tdls_timeoutie); -#ifdef CONFIG_TDLS_TESTING - if (wpa_tdls_get_privacy(sm) && - (tdls_testing & TDLS_TESTING_LONG_FRAME)) - buf_len += 170; - if (tdls_testing & TDLS_TESTING_DIFF_BSSID) - buf_len += sizeof(struct wpa_tdls_lnkid); -#endif /* CONFIG_TDLS_TESTING */ - rbuf = os_zalloc(buf_len + 1); - if (rbuf == NULL) { - wpa_tdls_peer_free(sm, peer); - return -1; - } - pos = rbuf; - - if (!wpa_tdls_get_privacy(sm)) - goto skip_ies; - - /* Initiator RSN IE */ - pos = wpa_add_ie(pos, peer->rsnie_i, peer->rsnie_i_len); - - ftie = (struct wpa_tdls_ftie *) pos; - ftie->ie_type = WLAN_EID_FAST_BSS_TRANSITION; - ftie->ie_len = sizeof(struct wpa_tdls_ftie) - 2; - - if (os_get_random(peer->inonce, WPA_NONCE_LEN)) { - wpa_msg(sm->ctx->msg_ctx, MSG_WARNING, - "TDLS: Failed to get random data for initiator Nonce"); - os_free(rbuf); - wpa_tdls_peer_free(sm, peer); - return -1; - } - wpa_hexdump(MSG_DEBUG, "TDLS: Initiator Nonce for TPK handshake", - peer->inonce, WPA_NONCE_LEN); - os_memcpy(ftie->Snonce, peer->inonce, WPA_NONCE_LEN); - - wpa_hexdump(MSG_DEBUG, "TDLS: FTIE for TPK Handshake M1", - (u8 *) ftie, sizeof(struct wpa_tdls_ftie)); - - pos = (u8 *) (ftie + 1); - -#ifdef CONFIG_TDLS_TESTING - if (tdls_testing & TDLS_TESTING_LONG_FRAME) { - wpa_printf(MSG_DEBUG, "TDLS: Testing - add extra subelem to " - "FTIE"); - ftie->ie_len += 170; - *pos++ = 255; /* FTIE subelem */ - *pos++ = 168; /* FTIE subelem length */ - pos += 168; - } -#endif /* CONFIG_TDLS_TESTING */ - - /* Lifetime */ - peer->lifetime = TPK_LIFETIME; -#ifdef CONFIG_TDLS_TESTING - if (tdls_testing & TDLS_TESTING_SHORT_LIFETIME) { - wpa_printf(MSG_DEBUG, "TDLS: Testing - use short TPK " - "lifetime"); - peer->lifetime = 301; - } - if (tdls_testing & TDLS_TESTING_LONG_LIFETIME) { - wpa_printf(MSG_DEBUG, "TDLS: Testing - use long TPK " - "lifetime"); - peer->lifetime = 0xffffffff; - } -#endif /* CONFIG_TDLS_TESTING */ - pos = wpa_add_tdls_timeoutie(pos, (u8 *) &timeoutie, - sizeof(timeoutie), peer->lifetime); - wpa_printf(MSG_DEBUG, "TDLS: TPK lifetime %u seconds", peer->lifetime); - -skip_ies: - -#ifdef CONFIG_TDLS_TESTING - if (tdls_testing & TDLS_TESTING_DIFF_BSSID) { - wpa_printf(MSG_DEBUG, "TDLS: Testing - use incorrect BSSID in " - "Link Identifier"); - struct wpa_tdls_lnkid *l = (struct wpa_tdls_lnkid *) pos; - wpa_tdls_linkid(sm, peer, l); - l->bssid[5] ^= 0x01; - pos += sizeof(*l); - } -#endif /* CONFIG_TDLS_TESTING */ - - wpa_printf(MSG_DEBUG, "TDLS: Sending TDLS Setup Request / TPK " - "Handshake Message 1 (peer " MACSTR ")", - MAC2STR(peer->addr)); - - wpa_tdls_tpk_send(sm, peer->addr, WLAN_TDLS_SETUP_REQUEST, 0, 0, - rbuf, pos - rbuf); - os_free(rbuf); - - return 0; -} - - -static int wpa_tdls_send_tpk_m2(struct wpa_sm *sm, - const unsigned char *src_addr, u8 dtoken, - struct wpa_tdls_lnkid *lnkid, - const struct wpa_tdls_peer *peer) -{ - u8 *rbuf, *pos; - size_t buf_len; - u32 lifetime; - struct wpa_tdls_timeoutie timeoutie; - struct wpa_tdls_ftie *ftie; - - buf_len = 0; - if (wpa_tdls_get_privacy(sm)) { - /* Peer RSN IE, FTIE(Initiator Nonce, Responder Nonce), - * Lifetime */ - buf_len += peer->rsnie_i_len + sizeof(struct wpa_tdls_ftie) + - sizeof(struct wpa_tdls_timeoutie); -#ifdef CONFIG_TDLS_TESTING - if (tdls_testing & TDLS_TESTING_LONG_FRAME) - buf_len += 170; -#endif /* CONFIG_TDLS_TESTING */ - } - - rbuf = os_zalloc(buf_len + 1); - if (rbuf == NULL) - return -1; - pos = rbuf; - - if (!wpa_tdls_get_privacy(sm)) - goto skip_ies; - - /* Peer RSN IE */ - pos = wpa_add_ie(pos, peer->rsnie_p, peer->rsnie_p_len); - - ftie = (struct wpa_tdls_ftie *) pos; - ftie->ie_type = WLAN_EID_FAST_BSS_TRANSITION; - /* TODO: ftie->mic_control to set 2-RESPONSE */ - os_memcpy(ftie->Anonce, peer->rnonce, WPA_NONCE_LEN); - os_memcpy(ftie->Snonce, peer->inonce, WPA_NONCE_LEN); - ftie->ie_len = sizeof(struct wpa_tdls_ftie) - 2; - wpa_hexdump(MSG_DEBUG, "TDLS: FTIE for TPK M2", - (u8 *) ftie, sizeof(*ftie)); - - pos = (u8 *) (ftie + 1); - -#ifdef CONFIG_TDLS_TESTING - if (tdls_testing & TDLS_TESTING_LONG_FRAME) { - wpa_printf(MSG_DEBUG, "TDLS: Testing - add extra subelem to " - "FTIE"); - ftie->ie_len += 170; - *pos++ = 255; /* FTIE subelem */ - *pos++ = 168; /* FTIE subelem length */ - pos += 168; - } -#endif /* CONFIG_TDLS_TESTING */ - - /* Lifetime */ - lifetime = peer->lifetime; -#ifdef CONFIG_TDLS_TESTING - if (tdls_testing & TDLS_TESTING_WRONG_LIFETIME_RESP) { - wpa_printf(MSG_DEBUG, "TDLS: Testing - use wrong TPK " - "lifetime in response"); - lifetime++; - } -#endif /* CONFIG_TDLS_TESTING */ - pos = wpa_add_tdls_timeoutie(pos, (u8 *) &timeoutie, - sizeof(timeoutie), lifetime); - wpa_printf(MSG_DEBUG, "TDLS: TPK lifetime %u seconds from initiator", - lifetime); - - /* compute MIC before sending */ - wpa_tdls_ftie_mic(peer->tpk.kck, 2, (u8 *) lnkid, peer->rsnie_p, - (u8 *) &timeoutie, (u8 *) ftie, ftie->mic); - -skip_ies: - wpa_tdls_tpk_send(sm, src_addr, WLAN_TDLS_SETUP_RESPONSE, dtoken, 0, - rbuf, pos - rbuf); - os_free(rbuf); - - return 0; -} - - -static int wpa_tdls_send_tpk_m3(struct wpa_sm *sm, - const unsigned char *src_addr, u8 dtoken, - struct wpa_tdls_lnkid *lnkid, - const struct wpa_tdls_peer *peer) -{ - u8 *rbuf, *pos; - size_t buf_len; - struct wpa_tdls_ftie *ftie; - struct wpa_tdls_timeoutie timeoutie; - u32 lifetime; - - buf_len = 0; - if (wpa_tdls_get_privacy(sm)) { - /* Peer RSN IE, FTIE(Initiator Nonce, Responder Nonce), - * Lifetime */ - buf_len += peer->rsnie_i_len + sizeof(struct wpa_tdls_ftie) + - sizeof(struct wpa_tdls_timeoutie); -#ifdef CONFIG_TDLS_TESTING - if (tdls_testing & TDLS_TESTING_LONG_FRAME) - buf_len += 170; -#endif /* CONFIG_TDLS_TESTING */ - } - - rbuf = os_zalloc(buf_len + 1); - if (rbuf == NULL) - return -1; - pos = rbuf; - - if (!wpa_tdls_get_privacy(sm)) - goto skip_ies; - - /* Peer RSN IE */ - pos = wpa_add_ie(pos, peer->rsnie_p, peer->rsnie_p_len); - - ftie = (struct wpa_tdls_ftie *) pos; - ftie->ie_type = WLAN_EID_FAST_BSS_TRANSITION; - /*TODO: ftie->mic_control to set 3-CONFIRM */ - os_memcpy(ftie->Anonce, peer->rnonce, WPA_NONCE_LEN); - os_memcpy(ftie->Snonce, peer->inonce, WPA_NONCE_LEN); - ftie->ie_len = sizeof(struct wpa_tdls_ftie) - 2; - - pos = (u8 *) (ftie + 1); - -#ifdef CONFIG_TDLS_TESTING - if (tdls_testing & TDLS_TESTING_LONG_FRAME) { - wpa_printf(MSG_DEBUG, "TDLS: Testing - add extra subelem to " - "FTIE"); - ftie->ie_len += 170; - *pos++ = 255; /* FTIE subelem */ - *pos++ = 168; /* FTIE subelem length */ - pos += 168; - } -#endif /* CONFIG_TDLS_TESTING */ - - /* Lifetime */ - lifetime = peer->lifetime; -#ifdef CONFIG_TDLS_TESTING - if (tdls_testing & TDLS_TESTING_WRONG_LIFETIME_CONF) { - wpa_printf(MSG_DEBUG, "TDLS: Testing - use wrong TPK " - "lifetime in confirm"); - lifetime++; - } -#endif /* CONFIG_TDLS_TESTING */ - pos = wpa_add_tdls_timeoutie(pos, (u8 *) &timeoutie, - sizeof(timeoutie), lifetime); - wpa_printf(MSG_DEBUG, "TDLS: TPK lifetime %u seconds", - lifetime); - - /* compute MIC before sending */ - wpa_tdls_ftie_mic(peer->tpk.kck, 3, (u8 *) lnkid, peer->rsnie_p, - (u8 *) &timeoutie, (u8 *) ftie, ftie->mic); - -skip_ies: - wpa_tdls_tpk_send(sm, src_addr, WLAN_TDLS_SETUP_CONFIRM, dtoken, 0, - rbuf, pos - rbuf); - os_free(rbuf); - - return 0; -} - - -static int wpa_tdls_process_tpk_m1(struct wpa_sm *sm, const u8 *src_addr, - const u8 *buf, size_t len) -{ - struct wpa_tdls_peer *peer; - struct wpa_eapol_ie_parse kde; - struct wpa_ie_data ie; - int cipher; - const u8 *cpos; - struct wpa_tdls_ftie *ftie = NULL; - struct wpa_tdls_timeoutie *timeoutie; - struct wpa_tdls_lnkid *lnkid; - u32 lifetime = 0; -#if 0 - struct rsn_ie_hdr *hdr; - u8 *pos; - u16 rsn_capab; - u16 rsn_ver; -#endif - u8 dtoken; - u16 ielen; - u16 status = WLAN_STATUS_UNSPECIFIED_FAILURE; - int tdls_prohibited = sm->tdls_prohibited; - - if (len < 3 + 3) - return -1; - - cpos = buf; - cpos += 1 /* pkt_type */ + 1 /* Category */ + 1 /* Action */; - - /* driver had already verified the frame format */ - dtoken = *cpos++; /* dialog token */ - - wpa_printf(MSG_INFO, "TDLS: Dialog Token in TPK M1 %d", dtoken); - - cpos += 2; /* capability information */ - - ielen = len - (cpos - buf); /* start of IE in buf */ - if (wpa_supplicant_parse_ies(cpos, ielen, &kde) < 0) { - wpa_printf(MSG_INFO, "TDLS: Failed to parse IEs in TPK M1"); - goto error; - } - - if (kde.lnkid == NULL || kde.lnkid_len < 3 * ETH_ALEN) { - wpa_printf(MSG_INFO, "TDLS: No valid Link Identifier IE in " - "TPK M1"); - goto error; - } - wpa_hexdump(MSG_DEBUG, "TDLS: Link ID Received from TPK M1", - kde.lnkid, kde.lnkid_len); - lnkid = (struct wpa_tdls_lnkid *) kde.lnkid; - if (os_memcmp(sm->bssid, lnkid->bssid, ETH_ALEN) != 0) { - wpa_printf(MSG_INFO, "TDLS: TPK M1 from diff BSS"); - status = WLAN_STATUS_NOT_IN_SAME_BSS; - goto error; - } - - wpa_printf(MSG_DEBUG, "TDLS: TPK M1 - TPK initiator " MACSTR, - MAC2STR(src_addr)); - -#ifdef CONFIG_TDLS_TESTING - if (tdls_testing & TDLS_TESTING_CONCURRENT_INIT) { - for (peer = sm->tdls; peer; peer = peer->next) { - if (os_memcmp(peer->addr, src_addr, ETH_ALEN) == 0) - break; - } - if (peer == NULL) { - peer = os_zalloc(sizeof(*peer)); - if (peer == NULL) - goto error; - os_memcpy(peer->addr, src_addr, ETH_ALEN); - peer->next = sm->tdls; - sm->tdls = peer; - } - wpa_printf(MSG_DEBUG, "TDLS: Testing concurrent initiation of " - "TDLS setup - send own request"); - peer->initiator = 1; - wpa_tdls_send_tpk_m1(sm, peer); - } - - if ((tdls_testing & TDLS_TESTING_IGNORE_AP_PROHIBIT) && - tdls_prohibited) { - wpa_printf(MSG_DEBUG, "TDLS: Testing - ignore AP prohibition " - "on TDLS"); - tdls_prohibited = 0; - } -#endif /* CONFIG_TDLS_TESTING */ - - if (tdls_prohibited) { - wpa_printf(MSG_INFO, "TDLS: TDLS prohibited in this BSS"); - status = WLAN_STATUS_REQUEST_DECLINED; - goto error; - } - - if (!wpa_tdls_get_privacy(sm)) { - if (kde.rsn_ie) { - wpa_printf(MSG_INFO, "TDLS: RSN IE in TPK M1 while " - "security is disabled"); - status = WLAN_STATUS_SECURITY_DISABLED; - goto error; - } - goto skip_rsn; - } - - if (kde.ftie == NULL || kde.ftie_len < sizeof(*ftie) || - kde.rsn_ie == NULL) { - wpa_printf(MSG_INFO, "TDLS: No FTIE or RSN IE in TPK M1"); - status = WLAN_STATUS_INVALID_PARAMETERS; - goto error; - } - - if (kde.rsn_ie_len > TDLS_MAX_IE_LEN) { - wpa_printf(MSG_INFO, "TDLS: Too long Initiator RSN IE in " - "TPK M1"); - status = WLAN_STATUS_INVALID_RSNIE; - goto error; - } - - if (wpa_parse_wpa_ie_rsn(kde.rsn_ie, kde.rsn_ie_len, &ie) < 0) { - wpa_printf(MSG_INFO, "TDLS: Failed to parse RSN IE in TPK M1"); - status = WLAN_STATUS_INVALID_RSNIE; - goto error; - } - - cipher = ie.pairwise_cipher; - if (cipher & WPA_CIPHER_CCMP) { - wpa_printf(MSG_DEBUG, "TDLS: Using CCMP for direct link"); - cipher = WPA_CIPHER_CCMP; - } else { - wpa_printf(MSG_INFO, "TDLS: No acceptable cipher in TPK M1"); - status = WLAN_STATUS_PAIRWISE_CIPHER_NOT_VALID; - goto error; - } - - if ((ie.capabilities & - (WPA_CAPABILITY_NO_PAIRWISE | WPA_CAPABILITY_PEERKEY_ENABLED)) != - WPA_CAPABILITY_PEERKEY_ENABLED) { - wpa_printf(MSG_INFO, "TDLS: Invalid RSN Capabilities in " - "TPK M1"); - status = WLAN_STATUS_INVALID_RSN_IE_CAPAB; - goto error; - } - - /* Lifetime */ - if (kde.key_lifetime == NULL) { - wpa_printf(MSG_INFO, "TDLS: No Key Lifetime IE in TPK M1"); - status = WLAN_STATUS_UNACCEPTABLE_LIFETIME; - goto error; - } - timeoutie = (struct wpa_tdls_timeoutie *) kde.key_lifetime; - lifetime = WPA_GET_LE32(timeoutie->value); - wpa_printf(MSG_DEBUG, "TDLS: TPK lifetime %u seconds", lifetime); - if (lifetime < 300) { - wpa_printf(MSG_INFO, "TDLS: Too short TPK lifetime"); - status = WLAN_STATUS_UNACCEPTABLE_LIFETIME; - goto error; - } - -skip_rsn: - /* Find existing entry and if found, use that instead of adding - * a new one; how to handle the case where both ends initiate at the - * same time? */ - for (peer = sm->tdls; peer; peer = peer->next) { - if (os_memcmp(peer->addr, src_addr, ETH_ALEN) == 0) - break; - } - - if (peer == NULL) { - wpa_printf(MSG_INFO, "TDLS: No matching entry found for " - "peer, creating one for " MACSTR, - MAC2STR(src_addr)); - peer = os_malloc(sizeof(*peer)); - if (peer == NULL) - goto error; - os_memset(peer, 0, sizeof(*peer)); - os_memcpy(peer->addr, src_addr, ETH_ALEN); - peer->next = sm->tdls; - sm->tdls = peer; - } else { - if (peer->tpk_success) { - wpa_printf(MSG_DEBUG, "TDLS: TDLS Setup Request while " - "direct link is enabled - tear down the " - "old link first"); -#if 0 - /* TODO: Disabling the link would be more proper - * operation here, but it seems to trigger a race with - * some drivers handling the new request frame. */ - wpa_sm_tdls_oper(sm, TDLS_DISABLE_LINK, src_addr); -#else - wpa_tdls_del_key(sm, peer); -#endif - wpa_tdls_peer_free(sm, peer); - } - - /* - * An entry is already present, so check if we already sent a - * TDLS Setup Request. If so, compare MAC addresses and let the - * STA with the lower MAC address continue as the initiator. - * The other negotiation is terminated. - */ - if (peer->initiator) { - if (os_memcmp(sm->own_addr, src_addr, ETH_ALEN) < 0) { - wpa_printf(MSG_DEBUG, "TDLS: Discard request " - "from peer with higher address " - MACSTR, MAC2STR(src_addr)); - return -1; - } else { - wpa_printf(MSG_DEBUG, "TDLS: Accept request " - "from peer with lower address " - MACSTR " (terminate previously " - "initiated negotiation", - MAC2STR(src_addr)); - wpa_tdls_peer_free(sm, peer); - } - } - } - - peer->initiator = 0; /* Need to check */ - peer->dtoken = dtoken; - - if (!wpa_tdls_get_privacy(sm)) { - peer->rsnie_i_len = 0; - peer->rsnie_p_len = 0; - peer->cipher = WPA_CIPHER_NONE; - goto skip_rsn_check; - } - - ftie = (struct wpa_tdls_ftie *) kde.ftie; - os_memcpy(peer->inonce, ftie->Snonce, WPA_NONCE_LEN); - os_memcpy(peer->rsnie_i, kde.rsn_ie, kde.rsn_ie_len); - peer->rsnie_i_len = kde.rsn_ie_len; - peer->cipher = cipher; - - if (os_get_random(peer->rnonce, WPA_NONCE_LEN)) { - wpa_msg(sm->ctx->ctx, MSG_WARNING, - "TDLS: Failed to get random data for responder nonce"); - wpa_tdls_peer_free(sm, peer); - goto error; - } - -#if 0 - /* get version info from RSNIE received from Peer */ - hdr = (struct rsn_ie_hdr *) kde.rsn_ie; - rsn_ver = WPA_GET_LE16(hdr->version); - - /* use min(peer's version, out version) */ - if (rsn_ver > RSN_VERSION) - rsn_ver = RSN_VERSION; - - hdr = (struct rsn_ie_hdr *) peer->rsnie_p; - - hdr->elem_id = WLAN_EID_RSN; - WPA_PUT_LE16(hdr->version, rsn_ver); - pos = (u8 *) (hdr + 1); - - RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_NO_GROUP_ADDRESSED); - pos += RSN_SELECTOR_LEN; - /* Include only the selected cipher in pairwise cipher suite */ - WPA_PUT_LE16(pos, 1); - pos += 2; - if (cipher == WPA_CIPHER_CCMP) - RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_CCMP); - pos += RSN_SELECTOR_LEN; - - WPA_PUT_LE16(pos, 1); - pos += 2; - RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_TPK_HANDSHAKE); - pos += RSN_SELECTOR_LEN; - - rsn_capab = WPA_CAPABILITY_PEERKEY_ENABLED; - rsn_capab |= RSN_NUM_REPLAY_COUNTERS_16 << 2; - WPA_PUT_LE16(pos, rsn_capab); - pos += 2; - - hdr->len = (pos - peer->rsnie_p) - 2; - peer->rsnie_p_len = pos - peer->rsnie_p; -#endif - - /* temp fix: validation of RSNIE later */ - os_memcpy(peer->rsnie_p, peer->rsnie_i, peer->rsnie_i_len); - peer->rsnie_p_len = peer->rsnie_i_len; - - wpa_hexdump(MSG_DEBUG, "TDLS: RSN IE for TPK handshake", - peer->rsnie_p, peer->rsnie_p_len); - - peer->lifetime = lifetime; - - wpa_tdls_generate_tpk(peer, sm->own_addr, sm->bssid); - -skip_rsn_check: - wpa_printf(MSG_DEBUG, "TDLS: Sending TDLS Setup Response / TPK M2"); - wpa_tdls_send_tpk_m2(sm, src_addr, dtoken, lnkid, peer); - - return 0; - -error: - wpa_tdls_send_error(sm, src_addr, WLAN_TDLS_SETUP_RESPONSE, dtoken, - status); - return -1; -} - - -static void wpa_tdls_enable_link(struct wpa_sm *sm, struct wpa_tdls_peer *peer) -{ - peer->tpk_success = 1; - eloop_cancel_timeout(wpa_tdls_tpk_timeout, sm, peer); - if (wpa_tdls_get_privacy(sm)) { - u32 lifetime = peer->lifetime; - /* - * Start the initiator process a bit earlier to avoid race - * condition with the responder sending teardown request. - */ - if (lifetime > 3 && peer->initiator) - lifetime -= 3; - eloop_register_timeout(lifetime, 0, wpa_tdls_tpk_timeout, - sm, peer); -#ifdef CONFIG_TDLS_TESTING - if (tdls_testing & TDLS_TESTING_NO_TPK_EXPIRATION) { - wpa_printf(MSG_DEBUG, "TDLS: Testing - disable TPK " - "expiration"); - eloop_cancel_timeout(wpa_tdls_tpk_timeout, sm, peer); - } -#endif /* CONFIG_TDLS_TESTING */ - } - wpa_sm_tdls_oper(sm, TDLS_ENABLE_LINK, peer->addr); -} - - -static int wpa_tdls_process_tpk_m2(struct wpa_sm *sm, const u8 *src_addr, - const u8 *buf, size_t len) -{ - struct wpa_tdls_peer *peer; - struct wpa_eapol_ie_parse kde; - struct wpa_ie_data ie; - int cipher; - struct wpa_tdls_ftie *ftie; - struct wpa_tdls_timeoutie *timeoutie; - struct wpa_tdls_lnkid *lnkid; - u32 lifetime; - u8 dtoken; - int ielen; - u16 status; - const u8 *pos; - - wpa_printf(MSG_DEBUG, "TDLS: Received TDLS Setup Response / TPK M2 " - "(Peer " MACSTR ")", MAC2STR(src_addr)); - for (peer = sm->tdls; peer; peer = peer->next) { - if (os_memcmp(peer->addr, src_addr, ETH_ALEN) == 0) - break; - } - if (peer == NULL) { - wpa_printf(MSG_INFO, "TDLS: No matching peer found for " - "TPK M2: " MACSTR, MAC2STR(src_addr)); - return -1; - } - wpa_tdls_tpk_retry_timeout_cancel(sm, peer, WLAN_TDLS_SETUP_REQUEST); - - if (len < 3 + 2 + 1) - return -1; - pos = buf; - pos += 1 /* pkt_type */ + 1 /* Category */ + 1 /* Action */; - status = WPA_GET_LE16(pos); - pos += 2 /* status code */; - - if (status != WLAN_STATUS_SUCCESS) { - wpa_printf(MSG_INFO, "TDLS: Status code in TPK M2: %u", - status); - return -1; - } - - status = WLAN_STATUS_UNSPECIFIED_FAILURE; - - /* TODO: need to verify dialog token matches here or in kernel */ - dtoken = *pos++; /* dialog token */ - - wpa_printf(MSG_DEBUG, "TDLS: Dialog Token in TPK M2 %d", dtoken); - - if (len < 3 + 2 + 1 + 2) - return -1; - pos += 2; /* capability information */ - - ielen = len - (pos - buf); /* start of IE in buf */ - if (wpa_supplicant_parse_ies(pos, ielen, &kde) < 0) { - wpa_printf(MSG_INFO, "TDLS: Failed to parse IEs in TPK M2"); - goto error; - } - -#ifdef CONFIG_TDLS_TESTING - if (tdls_testing & TDLS_TESTING_DECLINE_RESP) { - wpa_printf(MSG_DEBUG, "TDLS: Testing - decline response"); - status = WLAN_STATUS_REQUEST_DECLINED; - goto error; - } -#endif /* CONFIG_TDLS_TESTING */ - - if (kde.lnkid == NULL || kde.lnkid_len < 3 * ETH_ALEN) { - wpa_printf(MSG_INFO, "TDLS: No valid Link Identifier IE in " - "TPK M2"); - goto error; - } - wpa_hexdump(MSG_DEBUG, "TDLS: Link ID Received from TPK M2", - kde.lnkid, kde.lnkid_len); - lnkid = (struct wpa_tdls_lnkid *) kde.lnkid; - - if (os_memcmp(sm->bssid, lnkid->bssid, ETH_ALEN) != 0) { - wpa_printf(MSG_INFO, "TDLS: TPK M2 from different BSS"); - status = WLAN_STATUS_NOT_IN_SAME_BSS; - goto error; - } - - if (!wpa_tdls_get_privacy(sm)) { - peer->rsnie_p_len = 0; - peer->cipher = WPA_CIPHER_NONE; - goto skip_rsn; - } - - if (kde.ftie == NULL || kde.ftie_len < sizeof(*ftie) || - kde.rsn_ie == NULL) { - wpa_printf(MSG_INFO, "TDLS: No FTIE or RSN IE in TPK M2"); - status = WLAN_STATUS_INVALID_PARAMETERS; - goto error; - } - wpa_hexdump(MSG_DEBUG, "TDLS: RSN IE Received from TPK M2", - kde.rsn_ie, kde.rsn_ie_len); - - /* - * FIX: bitwise comparison of RSN IE is not the correct way of - * validation this. It can be different, but certain fields must - * match. Since we list only a single pairwise cipher in TPK M1, the - * memcmp is likely to work in most cases, though. - */ - if (kde.rsn_ie_len != peer->rsnie_i_len || - os_memcmp(peer->rsnie_i, kde.rsn_ie, peer->rsnie_i_len) != 0) { - wpa_printf(MSG_INFO, "TDLS: RSN IE in TPK M2 does " - "not match with RSN IE used in TPK M1"); - wpa_hexdump(MSG_DEBUG, "TDLS: RSN IE Sent in TPK M1", - peer->rsnie_i, peer->rsnie_i_len); - wpa_hexdump(MSG_DEBUG, "TDLS: RSN IE Received from TPK M2", - kde.rsn_ie, kde.rsn_ie_len); - status = WLAN_STATUS_INVALID_RSNIE; - goto error; - } - - if (wpa_parse_wpa_ie_rsn(kde.rsn_ie, kde.rsn_ie_len, &ie) < 0) { - wpa_printf(MSG_INFO, "TDLS: Failed to parse RSN IE in TPK M2"); - status = WLAN_STATUS_INVALID_RSNIE; - goto error; - } - - cipher = ie.pairwise_cipher; - if (cipher == WPA_CIPHER_CCMP) { - wpa_printf(MSG_DEBUG, "TDLS: Using CCMP for direct link"); - cipher = WPA_CIPHER_CCMP; - } else { - wpa_printf(MSG_INFO, "TDLS: No acceptable cipher in TPK M2"); - status = WLAN_STATUS_PAIRWISE_CIPHER_NOT_VALID; - goto error; - } - - wpa_hexdump(MSG_DEBUG, "TDLS: FTIE Received from TPK M2", - kde.ftie, sizeof(*ftie)); - ftie = (struct wpa_tdls_ftie *) kde.ftie; - - if (!os_memcmp(peer->inonce, ftie->Snonce, WPA_NONCE_LEN) == 0) { - wpa_printf(MSG_INFO, "TDLS: FTIE SNonce in TPK M2 does " - "not match with FTIE SNonce used in TPK M1"); - /* Silently discard the frame */ - return -1; - } - - /* Responder Nonce and RSN IE */ - os_memcpy(peer->rnonce, ftie->Anonce, WPA_NONCE_LEN); - os_memcpy(peer->rsnie_p, kde.rsn_ie, kde.rsn_ie_len); - peer->rsnie_p_len = kde.rsn_ie_len; - peer->cipher = cipher; - - /* Lifetime */ - if (kde.key_lifetime == NULL) { - wpa_printf(MSG_INFO, "TDLS: No Key Lifetime IE in TPK M2"); - status = WLAN_STATUS_UNACCEPTABLE_LIFETIME; - goto error; - } - timeoutie = (struct wpa_tdls_timeoutie *) kde.key_lifetime; - lifetime = WPA_GET_LE32(timeoutie->value); - wpa_printf(MSG_DEBUG, "TDLS: TPK lifetime %u seconds in TPK M2", - lifetime); - if (lifetime != peer->lifetime) { - wpa_printf(MSG_INFO, "TDLS: Unexpected TPK lifetime %u in " - "TPK M2 (expected %u)", lifetime, peer->lifetime); - status = WLAN_STATUS_UNACCEPTABLE_LIFETIME; - goto error; - } - - wpa_tdls_generate_tpk(peer, sm->own_addr, sm->bssid); - - /* Process MIC check to see if TPK M2 is right */ - if (wpa_supplicant_verify_tdls_mic(2, peer, (u8 *) lnkid, - (u8 *) timeoutie, ftie) < 0) { - /* Discard the frame */ - wpa_tdls_del_key(sm, peer); - wpa_tdls_peer_free(sm, peer); - return -1; - } - - wpa_tdls_set_key(sm, peer); - -skip_rsn: - peer->dtoken = dtoken; - - wpa_printf(MSG_DEBUG, "TDLS: Sending TDLS Setup Confirm / " - "TPK Handshake Message 3"); - wpa_tdls_send_tpk_m3(sm, src_addr, dtoken, lnkid, peer); - - wpa_tdls_enable_link(sm, peer); - - return 0; - -error: - wpa_tdls_send_error(sm, src_addr, WLAN_TDLS_SETUP_CONFIRM, dtoken, - status); - return -1; -} - - -static int wpa_tdls_process_tpk_m3(struct wpa_sm *sm, const u8 *src_addr, - const u8 *buf, size_t len) -{ - struct wpa_tdls_peer *peer; - struct wpa_eapol_ie_parse kde; - struct wpa_tdls_ftie *ftie; - struct wpa_tdls_timeoutie *timeoutie; - struct wpa_tdls_lnkid *lnkid; - int ielen; - u16 status; - const u8 *pos; - u32 lifetime; - - wpa_printf(MSG_DEBUG, "TDLS: Received TDLS Setup Confirm / TPK M3 " - "(Peer " MACSTR ")", MAC2STR(src_addr)); - for (peer = sm->tdls; peer; peer = peer->next) { - if (os_memcmp(peer->addr, src_addr, ETH_ALEN) == 0) - break; - } - if (peer == NULL) { - wpa_printf(MSG_INFO, "TDLS: No matching peer found for " - "TPK M3: " MACSTR, MAC2STR(src_addr)); - return -1; - } - wpa_tdls_tpk_retry_timeout_cancel(sm, peer, WLAN_TDLS_SETUP_RESPONSE); - - if (len < 3 + 3) - return -1; - pos = buf; - pos += 1 /* pkt_type */ + 1 /* Category */ + 1 /* Action */; - - status = WPA_GET_LE16(pos); - - if (status != 0) { - wpa_printf(MSG_INFO, "TDLS: Status code in TPK M3: %u", - status); - return -1; - } - pos += 2 /* status code */ + 1 /* dialog token */; - - ielen = len - (pos - buf); /* start of IE in buf */ - if (wpa_supplicant_parse_ies((const u8 *) pos, ielen, &kde) < 0) { - wpa_printf(MSG_INFO, "TDLS: Failed to parse KDEs in TPK M3"); - return -1; - } - - if (kde.lnkid == NULL || kde.lnkid_len < 3 * ETH_ALEN) { - wpa_printf(MSG_INFO, "TDLS: No Link Identifier IE in TPK M3"); - return -1; - } - wpa_hexdump(MSG_DEBUG, "TDLS: Link ID Received from TPK M3", - (u8 *) kde.lnkid, kde.lnkid_len); - lnkid = (struct wpa_tdls_lnkid *) kde.lnkid; - - if (os_memcmp(sm->bssid, lnkid->bssid, ETH_ALEN) != 0) { - wpa_printf(MSG_INFO, "TDLS: TPK M3 from diff BSS"); - return -1; - } - - if (!wpa_tdls_get_privacy(sm)) - goto skip_rsn; - - if (kde.ftie == NULL || kde.ftie_len < sizeof(*ftie)) { - wpa_printf(MSG_INFO, "TDLS: No FTIE in TPK M3"); - return -1; - } - wpa_hexdump(MSG_DEBUG, "TDLS: FTIE Received from TPK M3", - kde.ftie, sizeof(*ftie)); - ftie = (struct wpa_tdls_ftie *) kde.ftie; - - if (kde.rsn_ie == NULL) { - wpa_printf(MSG_INFO, "TDLS: No RSN IE in TPK M3"); - return -1; - } - wpa_hexdump(MSG_DEBUG, "TDLS: RSN IE Received from TPK M3", - kde.rsn_ie, kde.rsn_ie_len); - if (kde.rsn_ie_len != peer->rsnie_p_len || - os_memcmp(kde.rsn_ie, peer->rsnie_p, peer->rsnie_p_len) != 0) { - wpa_printf(MSG_INFO, "TDLS: RSN IE in TPK M3 does not match " - "with the one sent in TPK M2"); - return -1; - } - - if (!os_memcmp(peer->rnonce, ftie->Anonce, WPA_NONCE_LEN) == 0) { - wpa_printf(MSG_INFO, "TDLS: FTIE ANonce in TPK M3 does " - "not match with FTIE ANonce used in TPK M2"); - return -1; - } - - if (!os_memcmp(peer->inonce, ftie->Snonce, WPA_NONCE_LEN) == 0) { - wpa_printf(MSG_INFO, "TDLS: FTIE SNonce in TPK M3 does not " - "match with FTIE SNonce used in TPK M1"); - return -1; - } - - if (kde.key_lifetime == NULL) { - wpa_printf(MSG_INFO, "TDLS: No Key Lifetime IE in TPK M3"); - return -1; - } - timeoutie = (struct wpa_tdls_timeoutie *) kde.key_lifetime; - wpa_hexdump(MSG_DEBUG, "TDLS: Timeout IE Received from TPK M3", - (u8 *) timeoutie, sizeof(*timeoutie)); - lifetime = WPA_GET_LE32(timeoutie->value); - wpa_printf(MSG_DEBUG, "TDLS: TPK lifetime %u seconds in TPK M3", - lifetime); - if (lifetime != peer->lifetime) { - wpa_printf(MSG_INFO, "TDLS: Unexpected TPK lifetime %u in " - "TPK M3 (expected %u)", lifetime, peer->lifetime); - return -1; - } - - if (wpa_supplicant_verify_tdls_mic(3, peer, (u8 *) lnkid, - (u8 *) timeoutie, ftie) < 0) { - wpa_tdls_del_key(sm, peer); - wpa_tdls_peer_free(sm, peer); - return -1; - } - - if (wpa_tdls_set_key(sm, peer) < 0) - return -1; - -skip_rsn: - wpa_tdls_enable_link(sm, peer); - - return 0; -} - - -static u8 * wpa_add_tdls_timeoutie(u8 *pos, u8 *ie, size_t ie_len, u32 tsecs) -{ - struct wpa_tdls_timeoutie *lifetime = (struct wpa_tdls_timeoutie *) ie; - - os_memset(lifetime, 0, ie_len); - lifetime->ie_type = WLAN_EID_TIMEOUT_INTERVAL; - lifetime->ie_len = sizeof(struct wpa_tdls_timeoutie) - 2; - lifetime->interval_type = WLAN_TIMEOUT_KEY_LIFETIME; - WPA_PUT_LE32(lifetime->value, tsecs); - os_memcpy(pos, ie, ie_len); - return pos + ie_len; -} - - -/** - * wpa_tdls_start - Initiate TDLS handshake (send TPK Handshake Message 1) - * @sm: Pointer to WPA state machine data from wpa_sm_init() - * @peer: MAC address of the peer STA - * Returns: 0 on success, or -1 on failure - * - * Send TPK Handshake Message 1 info to driver to start TDLS - * handshake with the peer. - */ -int wpa_tdls_start(struct wpa_sm *sm, const u8 *addr) -{ - struct wpa_tdls_peer *peer; - int tdls_prohibited = sm->tdls_prohibited; - - if (sm->tdls_disabled) - return -1; - -#ifdef CONFIG_TDLS_TESTING - if ((tdls_testing & TDLS_TESTING_IGNORE_AP_PROHIBIT) && - tdls_prohibited) { - wpa_printf(MSG_DEBUG, "TDLS: Testing - ignore AP prohibition " - "on TDLS"); - tdls_prohibited = 0; - } -#endif /* CONFIG_TDLS_TESTING */ - - if (tdls_prohibited) { - wpa_printf(MSG_DEBUG, "TDLS: TDLS is prohibited in this BSS - " - "reject request to start setup"); - return -1; - } - - /* Find existing entry and if found, use that instead of adding - * a new one */ - for (peer = sm->tdls; peer; peer = peer->next) { - if (os_memcmp(peer->addr, addr, ETH_ALEN) == 0) - break; - } - - if (peer == NULL) { - wpa_printf(MSG_INFO, "TDLS: No matching entry found for " - "peer, creating one for " MACSTR, MAC2STR(addr)); - peer = os_malloc(sizeof(*peer)); - if (peer == NULL) - return -1; - os_memset(peer, 0, sizeof(*peer)); - os_memcpy(peer->addr, addr, ETH_ALEN); - peer->next = sm->tdls; - sm->tdls = peer; - } - - peer->initiator = 1; - - return wpa_tdls_send_tpk_m1(sm, peer); -} - - -int wpa_tdls_reneg(struct wpa_sm *sm, const u8 *addr) -{ - struct wpa_tdls_peer *peer; - - if (sm->tdls_disabled) - return -1; - - for (peer = sm->tdls; peer; peer = peer->next) { - if (os_memcmp(peer->addr, addr, ETH_ALEN) == 0) - break; - } - - if (peer == NULL || !peer->tpk_success) - return -1; - - return wpa_tdls_start(sm, addr); -} - - -/** - * wpa_supplicant_rx_tdls - Receive TDLS data frame - * - * This function is called to receive TDLS (ethertype = 0x890d) data frames. - */ -static void wpa_supplicant_rx_tdls(void *ctx, const u8 *src_addr, - const u8 *buf, size_t len) -{ - struct wpa_sm *sm = ctx; - struct wpa_tdls_frame *tf; - - wpa_hexdump(MSG_DEBUG, "TDLS: Received Data frame encapsulation", - buf, len); - - if (sm->tdls_disabled) { - wpa_printf(MSG_DEBUG, "TDLS: Discard message - TDLS disabled"); - return; - } - - if (os_memcmp(src_addr, sm->own_addr, ETH_ALEN) == 0) { - wpa_printf(MSG_DEBUG, "TDLS: Discard copy of own message"); - return; - } - - if (len < sizeof(*tf)) { - wpa_printf(MSG_INFO, "TDLS: Drop too short frame"); - return; - } - - /* Check to make sure its a valid encapsulated TDLS frame */ - tf = (struct wpa_tdls_frame *) buf; - if (tf->payloadtype != 2 /* TDLS_RFTYPE */ || - tf->category != WLAN_ACTION_TDLS) { - wpa_printf(MSG_INFO, "TDLS: Invalid frame - payloadtype=%u " - "category=%u action=%u", - tf->payloadtype, tf->category, tf->action); - return; - } - - switch (tf->action) { - case WLAN_TDLS_SETUP_REQUEST: - wpa_tdls_process_tpk_m1(sm, src_addr, buf, len); - break; - case WLAN_TDLS_SETUP_RESPONSE: - wpa_tdls_process_tpk_m2(sm, src_addr, buf, len); - break; - case WLAN_TDLS_SETUP_CONFIRM: - wpa_tdls_process_tpk_m3(sm, src_addr, buf, len); - break; - case WLAN_TDLS_TEARDOWN: - wpa_tdls_recv_teardown(sm, src_addr, buf, len); - break; - default: - /* Kernel code will process remaining frames */ - wpa_printf(MSG_DEBUG, "TDLS: Ignore TDLS frame action code %u", - tf->action); - break; - } -} - - -/** - * wpa_tdls_init - Initialize driver interface parameters for TDLS - * @wpa_s: Pointer to wpa_supplicant data - * Returns: 0 on success, -1 on failure - * - * This function is called to initialize driver interface parameters for TDLS. - * wpa_drv_init() must have been called before this function to initialize the - * driver interface. - */ -int wpa_tdls_init(struct wpa_sm *sm) -{ - if (sm == NULL) - return -1; - - sm->l2_tdls = l2_packet_init(sm->ifname, sm->own_addr, - ETH_P_80211_ENCAP, wpa_supplicant_rx_tdls, - sm, 0); - if (sm->l2_tdls == NULL) { - wpa_printf(MSG_ERROR, "TDLS: Failed to open l2_packet " - "connection"); - return -1; - } - - return 0; -} - - -static void wpa_tdls_remove_peers(struct wpa_sm *sm) -{ - struct wpa_tdls_peer *peer, *tmp; - - peer = sm->tdls; - sm->tdls = NULL; - - while (peer) { - int res; - tmp = peer->next; - res = wpa_sm_tdls_oper(sm, TDLS_DISABLE_LINK, peer->addr); - wpa_printf(MSG_DEBUG, "TDLS: Remove peer " MACSTR " (res=%d)", - MAC2STR(peer->addr), res); - wpa_tdls_peer_free(sm, peer); - os_free(peer); - peer = tmp; - } -} - - -/** - * wpa_tdls_deinit - Deinitialize driver interface parameters for TDLS - * - * This function is called to recover driver interface parameters for TDLS - * and frees resources allocated for it. - */ -void wpa_tdls_deinit(struct wpa_sm *sm) -{ - if (sm == NULL) - return; - - if (sm->l2_tdls) - l2_packet_deinit(sm->l2_tdls); - sm->l2_tdls = NULL; - - wpa_tdls_remove_peers(sm); -} - - -void wpa_tdls_assoc(struct wpa_sm *sm) -{ - wpa_printf(MSG_DEBUG, "TDLS: Remove peers on association"); - wpa_tdls_remove_peers(sm); -} - - -void wpa_tdls_disassoc(struct wpa_sm *sm) -{ - wpa_printf(MSG_DEBUG, "TDLS: Remove peers on disassociation"); - wpa_tdls_remove_peers(sm); -} - - -static int wpa_tdls_prohibited(const u8 *ies, size_t len) -{ - struct wpa_eapol_ie_parse elems; - - if (ies == NULL) - return 0; - - if (wpa_supplicant_parse_ies(ies, len, &elems) < 0) - return 0; - - if (elems.ext_capab == NULL || elems.ext_capab_len < 2 + 5) - return 0; - - /* bit 38 - TDLS Prohibited */ - return !!(elems.ext_capab[2 + 4] & 0x40); -} - - -void wpa_tdls_ap_ies(struct wpa_sm *sm, const u8 *ies, size_t len) -{ - sm->tdls_prohibited = wpa_tdls_prohibited(ies, len); - wpa_printf(MSG_DEBUG, "TDLS: TDLS is %s in the target BSS", - sm->tdls_prohibited ? "prohibited" : "allowed"); -} - - -void wpa_tdls_assoc_resp_ies(struct wpa_sm *sm, const u8 *ies, size_t len) -{ - if (!sm->tdls_prohibited && wpa_tdls_prohibited(ies, len)) { - wpa_printf(MSG_DEBUG, "TDLS: TDLS prohibited based on " - "(Re)Association Response IEs"); - sm->tdls_prohibited = 1; - } -} - - -void wpa_tdls_enable(struct wpa_sm *sm, int enabled) -{ - wpa_printf(MSG_DEBUG, "TDLS: %s", enabled ? "enabled" : "disabled"); - sm->tdls_disabled = !enabled; -} diff --git a/hostapd-0.8/src/rsn_supp/wpa.c b/hostapd-0.8/src/rsn_supp/wpa.c deleted file mode 100644 index 01a46dc..0000000 --- a/hostapd-0.8/src/rsn_supp/wpa.c +++ /dev/null @@ -1,2644 +0,0 @@ -/* - * WPA Supplicant - WPA state machine and EAPOL-Key processing - * Copyright (c) 2003-2010, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#include "includes.h" - -#include "common.h" -#include "crypto/aes_wrap.h" -#include "crypto/crypto.h" -#include "crypto/random.h" -#include "common/ieee802_11_defs.h" -#include "eapol_supp/eapol_supp_sm.h" -#include "wpa.h" -#include "eloop.h" -#include "preauth.h" -#include "pmksa_cache.h" -#include "wpa_i.h" -#include "wpa_ie.h" -#include "peerkey.h" - - -/** - * wpa_eapol_key_send - Send WPA/RSN EAPOL-Key message - * @sm: Pointer to WPA state machine data from wpa_sm_init() - * @kck: Key Confirmation Key (KCK, part of PTK) - * @ver: Version field from Key Info - * @dest: Destination address for the frame - * @proto: Ethertype (usually ETH_P_EAPOL) - * @msg: EAPOL-Key message - * @msg_len: Length of message - * @key_mic: Pointer to the buffer to which the EAPOL-Key MIC is written - */ -void wpa_eapol_key_send(struct wpa_sm *sm, const u8 *kck, - int ver, const u8 *dest, u16 proto, - u8 *msg, size_t msg_len, u8 *key_mic) -{ - if (is_zero_ether_addr(dest) && is_zero_ether_addr(sm->bssid)) { - /* - * Association event was not yet received; try to fetch - * BSSID from the driver. - */ - if (wpa_sm_get_bssid(sm, sm->bssid) < 0) { - wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG, - "WPA: Failed to read BSSID for " - "EAPOL-Key destination address"); - } else { - dest = sm->bssid; - wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG, - "WPA: Use BSSID (" MACSTR - ") as the destination for EAPOL-Key", - MAC2STR(dest)); - } - } - if (key_mic && - wpa_eapol_key_mic(kck, ver, msg, msg_len, key_mic)) { - wpa_msg(sm->ctx->msg_ctx, MSG_ERROR, - "WPA: Failed to generate EAPOL-Key " - "version %d MIC", ver); - goto out; - } - wpa_hexdump_key(MSG_DEBUG, "WPA: KCK", kck, 16); - wpa_hexdump(MSG_DEBUG, "WPA: Derived Key MIC", key_mic, 16); - wpa_hexdump(MSG_MSGDUMP, "WPA: TX EAPOL-Key", msg, msg_len); - wpa_sm_ether_send(sm, dest, proto, msg, msg_len); - eapol_sm_notify_tx_eapol_key(sm->eapol); -out: - os_free(msg); -} - - -/** - * wpa_sm_key_request - Send EAPOL-Key Request - * @sm: Pointer to WPA state machine data from wpa_sm_init() - * @error: Indicate whether this is an Michael MIC error report - * @pairwise: 1 = error report for pairwise packet, 0 = for group packet - * - * Send an EAPOL-Key Request to the current authenticator. This function is - * used to request rekeying and it is usually called when a local Michael MIC - * failure is detected. - */ -void wpa_sm_key_request(struct wpa_sm *sm, int error, int pairwise) -{ - size_t rlen; - struct wpa_eapol_key *reply; - int key_info, ver; - u8 bssid[ETH_ALEN], *rbuf; - - if (wpa_key_mgmt_ft(sm->key_mgmt) || wpa_key_mgmt_sha256(sm->key_mgmt)) - ver = WPA_KEY_INFO_TYPE_AES_128_CMAC; - else if (sm->pairwise_cipher == WPA_CIPHER_CCMP) - ver = WPA_KEY_INFO_TYPE_HMAC_SHA1_AES; - else - ver = WPA_KEY_INFO_TYPE_HMAC_MD5_RC4; - - if (wpa_sm_get_bssid(sm, bssid) < 0) { - wpa_msg(sm->ctx->msg_ctx, MSG_WARNING, - "Failed to read BSSID for EAPOL-Key request"); - return; - } - - rbuf = wpa_sm_alloc_eapol(sm, IEEE802_1X_TYPE_EAPOL_KEY, NULL, - sizeof(*reply), &rlen, (void *) &reply); - if (rbuf == NULL) - return; - - reply->type = sm->proto == WPA_PROTO_RSN ? - EAPOL_KEY_TYPE_RSN : EAPOL_KEY_TYPE_WPA; - key_info = WPA_KEY_INFO_REQUEST | ver; - if (sm->ptk_set) - key_info |= WPA_KEY_INFO_MIC; - if (error) - key_info |= WPA_KEY_INFO_ERROR; - if (pairwise) - key_info |= WPA_KEY_INFO_KEY_TYPE; - WPA_PUT_BE16(reply->key_info, key_info); - WPA_PUT_BE16(reply->key_length, 0); - os_memcpy(reply->replay_counter, sm->request_counter, - WPA_REPLAY_COUNTER_LEN); - inc_byte_array(sm->request_counter, WPA_REPLAY_COUNTER_LEN); - - WPA_PUT_BE16(reply->key_data_length, 0); - - wpa_msg(sm->ctx->msg_ctx, MSG_INFO, - "WPA: Sending EAPOL-Key Request (error=%d " - "pairwise=%d ptk_set=%d len=%lu)", - error, pairwise, sm->ptk_set, (unsigned long) rlen); - wpa_eapol_key_send(sm, sm->ptk.kck, ver, bssid, ETH_P_EAPOL, - rbuf, rlen, key_info & WPA_KEY_INFO_MIC ? - reply->key_mic : NULL); -} - - -static int wpa_supplicant_get_pmk(struct wpa_sm *sm, - const unsigned char *src_addr, - const u8 *pmkid) -{ - int abort_cached = 0; - - if (pmkid && !sm->cur_pmksa) { - /* When using drivers that generate RSN IE, wpa_supplicant may - * not have enough time to get the association information - * event before receiving this 1/4 message, so try to find a - * matching PMKSA cache entry here. */ - sm->cur_pmksa = pmksa_cache_get(sm->pmksa, src_addr, pmkid); - if (sm->cur_pmksa) { - wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG, - "RSN: found matching PMKID from PMKSA cache"); - } else { - wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG, - "RSN: no matching PMKID found"); - abort_cached = 1; - } - } - - if (pmkid && sm->cur_pmksa && - os_memcmp(pmkid, sm->cur_pmksa->pmkid, PMKID_LEN) == 0) { - wpa_hexdump(MSG_DEBUG, "RSN: matched PMKID", pmkid, PMKID_LEN); - wpa_sm_set_pmk_from_pmksa(sm); - wpa_hexdump_key(MSG_DEBUG, "RSN: PMK from PMKSA cache", - sm->pmk, sm->pmk_len); - eapol_sm_notify_cached(sm->eapol); -#ifdef CONFIG_IEEE80211R - sm->xxkey_len = 0; -#endif /* CONFIG_IEEE80211R */ - } else if (wpa_key_mgmt_wpa_ieee8021x(sm->key_mgmt) && sm->eapol) { - int res, pmk_len; - pmk_len = PMK_LEN; - res = eapol_sm_get_key(sm->eapol, sm->pmk, PMK_LEN); - if (res) { - /* - * EAP-LEAP is an exception from other EAP methods: it - * uses only 16-byte PMK. - */ - res = eapol_sm_get_key(sm->eapol, sm->pmk, 16); - pmk_len = 16; - } else { -#ifdef CONFIG_IEEE80211R - u8 buf[2 * PMK_LEN]; - if (eapol_sm_get_key(sm->eapol, buf, 2 * PMK_LEN) == 0) - { - os_memcpy(sm->xxkey, buf + PMK_LEN, PMK_LEN); - sm->xxkey_len = PMK_LEN; - os_memset(buf, 0, sizeof(buf)); - } -#endif /* CONFIG_IEEE80211R */ - } - if (res == 0) { - wpa_hexdump_key(MSG_DEBUG, "WPA: PMK from EAPOL state " - "machines", sm->pmk, pmk_len); - sm->pmk_len = pmk_len; - if (sm->proto == WPA_PROTO_RSN) { - pmksa_cache_add(sm->pmksa, sm->pmk, pmk_len, - src_addr, sm->own_addr, - sm->network_ctx, sm->key_mgmt); - } - if (!sm->cur_pmksa && pmkid && - pmksa_cache_get(sm->pmksa, src_addr, pmkid)) { - wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG, - "RSN: the new PMK matches with the " - "PMKID"); - abort_cached = 0; - } - } else { - wpa_msg(sm->ctx->msg_ctx, MSG_WARNING, - "WPA: Failed to get master session key from " - "EAPOL state machines - key handshake " - "aborted"); - if (sm->cur_pmksa) { - wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG, - "RSN: Cancelled PMKSA caching " - "attempt"); - sm->cur_pmksa = NULL; - abort_cached = 1; - } else if (!abort_cached) { - return -1; - } - } - } - - if (abort_cached && wpa_key_mgmt_wpa_ieee8021x(sm->key_mgmt)) { - /* Send EAPOL-Start to trigger full EAP authentication. */ - u8 *buf; - size_t buflen; - - wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG, - "RSN: no PMKSA entry found - trigger " - "full EAP authentication"); - buf = wpa_sm_alloc_eapol(sm, IEEE802_1X_TYPE_EAPOL_START, - NULL, 0, &buflen, NULL); - if (buf) { - wpa_sm_ether_send(sm, sm->bssid, ETH_P_EAPOL, - buf, buflen); - os_free(buf); - return -2; - } - - return -1; - } - - return 0; -} - - -/** - * wpa_supplicant_send_2_of_4 - Send message 2 of WPA/RSN 4-Way Handshake - * @sm: Pointer to WPA state machine data from wpa_sm_init() - * @dst: Destination address for the frame - * @key: Pointer to the EAPOL-Key frame header - * @ver: Version bits from EAPOL-Key Key Info - * @nonce: Nonce value for the EAPOL-Key frame - * @wpa_ie: WPA/RSN IE - * @wpa_ie_len: Length of the WPA/RSN IE - * @ptk: PTK to use for keyed hash and encryption - * Returns: 0 on success, -1 on failure - */ -int wpa_supplicant_send_2_of_4(struct wpa_sm *sm, const unsigned char *dst, - const struct wpa_eapol_key *key, - int ver, const u8 *nonce, - const u8 *wpa_ie, size_t wpa_ie_len, - struct wpa_ptk *ptk) -{ - size_t rlen; - struct wpa_eapol_key *reply; - u8 *rbuf; - u8 *rsn_ie_buf = NULL; - - if (wpa_ie == NULL) { - wpa_msg(sm->ctx->msg_ctx, MSG_WARNING, "WPA: No wpa_ie set - " - "cannot generate msg 2/4"); - return -1; - } - -#ifdef CONFIG_IEEE80211R - if (wpa_key_mgmt_ft(sm->key_mgmt)) { - int res; - - /* - * Add PMKR1Name into RSN IE (PMKID-List) and add MDIE and - * FTIE from (Re)Association Response. - */ - rsn_ie_buf = os_malloc(wpa_ie_len + 2 + 2 + PMKID_LEN + - sm->assoc_resp_ies_len); - if (rsn_ie_buf == NULL) - return -1; - os_memcpy(rsn_ie_buf, wpa_ie, wpa_ie_len); - res = wpa_insert_pmkid(rsn_ie_buf, wpa_ie_len, - sm->pmk_r1_name); - if (res < 0) { - os_free(rsn_ie_buf); - return -1; - } - wpa_ie_len += res; - - if (sm->assoc_resp_ies) { - os_memcpy(rsn_ie_buf + wpa_ie_len, sm->assoc_resp_ies, - sm->assoc_resp_ies_len); - wpa_ie_len += sm->assoc_resp_ies_len; - } - - wpa_ie = rsn_ie_buf; - } -#endif /* CONFIG_IEEE80211R */ - - wpa_hexdump(MSG_DEBUG, "WPA: WPA IE for msg 2/4", wpa_ie, wpa_ie_len); - - rbuf = wpa_sm_alloc_eapol(sm, IEEE802_1X_TYPE_EAPOL_KEY, - NULL, sizeof(*reply) + wpa_ie_len, - &rlen, (void *) &reply); - if (rbuf == NULL) { - os_free(rsn_ie_buf); - return -1; - } - - reply->type = sm->proto == WPA_PROTO_RSN ? - EAPOL_KEY_TYPE_RSN : EAPOL_KEY_TYPE_WPA; - WPA_PUT_BE16(reply->key_info, - ver | WPA_KEY_INFO_KEY_TYPE | WPA_KEY_INFO_MIC); - if (sm->proto == WPA_PROTO_RSN) - WPA_PUT_BE16(reply->key_length, 0); - else - os_memcpy(reply->key_length, key->key_length, 2); - os_memcpy(reply->replay_counter, key->replay_counter, - WPA_REPLAY_COUNTER_LEN); - wpa_hexdump(MSG_DEBUG, "WPA: Replay Counter", reply->replay_counter, - WPA_REPLAY_COUNTER_LEN); - - WPA_PUT_BE16(reply->key_data_length, wpa_ie_len); - os_memcpy(reply + 1, wpa_ie, wpa_ie_len); - os_free(rsn_ie_buf); - - os_memcpy(reply->key_nonce, nonce, WPA_NONCE_LEN); - - wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG, "WPA: Sending EAPOL-Key 2/4"); - wpa_eapol_key_send(sm, ptk->kck, ver, dst, ETH_P_EAPOL, - rbuf, rlen, reply->key_mic); - - return 0; -} - - -static int wpa_derive_ptk(struct wpa_sm *sm, const unsigned char *src_addr, - const struct wpa_eapol_key *key, - struct wpa_ptk *ptk) -{ - size_t ptk_len = sm->pairwise_cipher == WPA_CIPHER_CCMP ? 48 : 64; -#ifdef CONFIG_IEEE80211R - if (wpa_key_mgmt_ft(sm->key_mgmt)) - return wpa_derive_ptk_ft(sm, src_addr, key, ptk, ptk_len); -#endif /* CONFIG_IEEE80211R */ - - wpa_pmk_to_ptk(sm->pmk, sm->pmk_len, "Pairwise key expansion", - sm->own_addr, sm->bssid, sm->snonce, key->key_nonce, - (u8 *) ptk, ptk_len, - wpa_key_mgmt_sha256(sm->key_mgmt)); - return 0; -} - - -static void wpa_supplicant_process_1_of_4(struct wpa_sm *sm, - const unsigned char *src_addr, - const struct wpa_eapol_key *key, - u16 ver) -{ - struct wpa_eapol_ie_parse ie; - struct wpa_ptk *ptk; - u8 buf[8]; - int res; - - if (wpa_sm_get_network_ctx(sm) == NULL) { - wpa_msg(sm->ctx->msg_ctx, MSG_WARNING, "WPA: No SSID info " - "found (msg 1 of 4)"); - return; - } - - wpa_sm_set_state(sm, WPA_4WAY_HANDSHAKE); - wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG, "WPA: RX message 1 of 4-Way " - "Handshake from " MACSTR " (ver=%d)", MAC2STR(src_addr), ver); - - os_memset(&ie, 0, sizeof(ie)); - -#ifndef CONFIG_NO_WPA2 - if (sm->proto == WPA_PROTO_RSN) { - /* RSN: msg 1/4 should contain PMKID for the selected PMK */ - const u8 *_buf = (const u8 *) (key + 1); - size_t len = WPA_GET_BE16(key->key_data_length); - wpa_hexdump(MSG_DEBUG, "RSN: msg 1/4 key data", _buf, len); - wpa_supplicant_parse_ies(_buf, len, &ie); - if (ie.pmkid) { - wpa_hexdump(MSG_DEBUG, "RSN: PMKID from " - "Authenticator", ie.pmkid, PMKID_LEN); - } - } -#endif /* CONFIG_NO_WPA2 */ - - res = wpa_supplicant_get_pmk(sm, src_addr, ie.pmkid); - if (res == -2) { - wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG, "RSN: Do not reply to " - "msg 1/4 - requesting full EAP authentication"); - return; - } - if (res) - goto failed; - - if (sm->renew_snonce) { - if (random_get_bytes(sm->snonce, WPA_NONCE_LEN)) { - wpa_msg(sm->ctx->msg_ctx, MSG_WARNING, - "WPA: Failed to get random data for SNonce"); - goto failed; - } - sm->renew_snonce = 0; - wpa_hexdump(MSG_DEBUG, "WPA: Renewed SNonce", - sm->snonce, WPA_NONCE_LEN); - } - - /* Calculate PTK which will be stored as a temporary PTK until it has - * been verified when processing message 3/4. */ - ptk = &sm->tptk; - wpa_derive_ptk(sm, src_addr, key, ptk); - /* Supplicant: swap tx/rx Mic keys */ - os_memcpy(buf, ptk->u.auth.tx_mic_key, 8); - os_memcpy(ptk->u.auth.tx_mic_key, ptk->u.auth.rx_mic_key, 8); - os_memcpy(ptk->u.auth.rx_mic_key, buf, 8); - sm->tptk_set = 1; - - if (wpa_supplicant_send_2_of_4(sm, sm->bssid, key, ver, sm->snonce, - sm->assoc_wpa_ie, sm->assoc_wpa_ie_len, - ptk)) - goto failed; - - os_memcpy(sm->anonce, key->key_nonce, WPA_NONCE_LEN); - return; - -failed: - wpa_sm_deauthenticate(sm, WLAN_REASON_UNSPECIFIED); -} - - -static void wpa_sm_start_preauth(void *eloop_ctx, void *timeout_ctx) -{ - struct wpa_sm *sm = eloop_ctx; - rsn_preauth_candidate_process(sm); -} - - -static void wpa_supplicant_key_neg_complete(struct wpa_sm *sm, - const u8 *addr, int secure) -{ - wpa_msg(sm->ctx->msg_ctx, MSG_INFO, - "WPA: Key negotiation completed with " - MACSTR " [PTK=%s GTK=%s]", MAC2STR(addr), - wpa_cipher_txt(sm->pairwise_cipher), - wpa_cipher_txt(sm->group_cipher)); - wpa_sm_cancel_auth_timeout(sm); - wpa_sm_set_state(sm, WPA_COMPLETED); - - if (secure) { - wpa_sm_mlme_setprotection( - sm, addr, MLME_SETPROTECTION_PROTECT_TYPE_RX_TX, - MLME_SETPROTECTION_KEY_TYPE_PAIRWISE); - eapol_sm_notify_portValid(sm->eapol, TRUE); - if (wpa_key_mgmt_wpa_psk(sm->key_mgmt)) - eapol_sm_notify_eap_success(sm->eapol, TRUE); - /* - * Start preauthentication after a short wait to avoid a - * possible race condition between the data receive and key - * configuration after the 4-Way Handshake. This increases the - * likelyhood of the first preauth EAPOL-Start frame getting to - * the target AP. - */ - eloop_register_timeout(1, 0, wpa_sm_start_preauth, sm, NULL); - } - - if (sm->cur_pmksa && sm->cur_pmksa->opportunistic) { - wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG, - "RSN: Authenticator accepted " - "opportunistic PMKSA entry - marking it valid"); - sm->cur_pmksa->opportunistic = 0; - } - -#ifdef CONFIG_IEEE80211R - if (wpa_key_mgmt_ft(sm->key_mgmt)) { - /* Prepare for the next transition */ - wpa_ft_prepare_auth_request(sm, NULL); - } -#endif /* CONFIG_IEEE80211R */ -} - - -static void wpa_sm_rekey_ptk(void *eloop_ctx, void *timeout_ctx) -{ - struct wpa_sm *sm = eloop_ctx; - wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG, "WPA: Request PTK rekeying"); - wpa_sm_key_request(sm, 0, 1); -} - - -static int wpa_supplicant_install_ptk(struct wpa_sm *sm, - const struct wpa_eapol_key *key) -{ - int keylen, rsclen; - enum wpa_alg alg; - const u8 *key_rsc; - u8 null_rsc[8] = { 0, 0, 0, 0, 0, 0, 0, 0 }; - - wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG, - "WPA: Installing PTK to the driver"); - - switch (sm->pairwise_cipher) { - case WPA_CIPHER_CCMP: - alg = WPA_ALG_CCMP; - keylen = 16; - rsclen = 6; - break; - case WPA_CIPHER_TKIP: - alg = WPA_ALG_TKIP; - keylen = 32; - rsclen = 6; - break; - case WPA_CIPHER_NONE: - wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG, "WPA: Pairwise Cipher " - "Suite: NONE - do not use pairwise keys"); - return 0; - default: - wpa_msg(sm->ctx->msg_ctx, MSG_WARNING, - "WPA: Unsupported pairwise cipher %d", - sm->pairwise_cipher); - return -1; - } - - if (sm->proto == WPA_PROTO_RSN) { - key_rsc = null_rsc; - } else { - key_rsc = key->key_rsc; - wpa_hexdump(MSG_DEBUG, "WPA: RSC", key_rsc, rsclen); - } - - if (wpa_sm_set_key(sm, alg, sm->bssid, 0, 1, key_rsc, rsclen, - (u8 *) sm->ptk.tk1, keylen) < 0) { - wpa_msg(sm->ctx->msg_ctx, MSG_WARNING, - "WPA: Failed to set PTK to the " - "driver (alg=%d keylen=%d bssid=" MACSTR ")", - alg, keylen, MAC2STR(sm->bssid)); - return -1; - } - - if (sm->wpa_ptk_rekey) { - eloop_cancel_timeout(wpa_sm_rekey_ptk, sm, NULL); - eloop_register_timeout(sm->wpa_ptk_rekey, 0, wpa_sm_rekey_ptk, - sm, NULL); - } - - return 0; -} - - -static int wpa_supplicant_check_group_cipher(struct wpa_sm *sm, - int group_cipher, - int keylen, int maxkeylen, - int *key_rsc_len, - enum wpa_alg *alg) -{ - int ret = 0; - - switch (group_cipher) { - case WPA_CIPHER_CCMP: - if (keylen != 16 || maxkeylen < 16) { - ret = -1; - break; - } - *key_rsc_len = 6; - *alg = WPA_ALG_CCMP; - break; - case WPA_CIPHER_TKIP: - if (keylen != 32 || maxkeylen < 32) { - ret = -1; - break; - } - *key_rsc_len = 6; - *alg = WPA_ALG_TKIP; - break; - case WPA_CIPHER_WEP104: - if (keylen != 13 || maxkeylen < 13) { - ret = -1; - break; - } - *key_rsc_len = 0; - *alg = WPA_ALG_WEP; - break; - case WPA_CIPHER_WEP40: - if (keylen != 5 || maxkeylen < 5) { - ret = -1; - break; - } - *key_rsc_len = 0; - *alg = WPA_ALG_WEP; - break; - default: - wpa_msg(sm->ctx->msg_ctx, MSG_WARNING, - "WPA: Unsupported Group Cipher %d", - group_cipher); - return -1; - } - - if (ret < 0 ) { - wpa_msg(sm->ctx->msg_ctx, MSG_WARNING, - "WPA: Unsupported %s Group Cipher key length %d (%d)", - wpa_cipher_txt(group_cipher), keylen, maxkeylen); - } - - return ret; -} - - -struct wpa_gtk_data { - enum wpa_alg alg; - int tx, key_rsc_len, keyidx; - u8 gtk[32]; - int gtk_len; -}; - - -static int wpa_supplicant_install_gtk(struct wpa_sm *sm, - const struct wpa_gtk_data *gd, - const u8 *key_rsc) -{ - const u8 *_gtk = gd->gtk; - u8 gtk_buf[32]; - - wpa_hexdump_key(MSG_DEBUG, "WPA: Group Key", gd->gtk, gd->gtk_len); - wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG, - "WPA: Installing GTK to the driver (keyidx=%d tx=%d len=%d)", - gd->keyidx, gd->tx, gd->gtk_len); - wpa_hexdump(MSG_DEBUG, "WPA: RSC", key_rsc, gd->key_rsc_len); - if (sm->group_cipher == WPA_CIPHER_TKIP) { - /* Swap Tx/Rx keys for Michael MIC */ - os_memcpy(gtk_buf, gd->gtk, 16); - os_memcpy(gtk_buf + 16, gd->gtk + 24, 8); - os_memcpy(gtk_buf + 24, gd->gtk + 16, 8); - _gtk = gtk_buf; - } - if (sm->pairwise_cipher == WPA_CIPHER_NONE) { - if (wpa_sm_set_key(sm, gd->alg, NULL, - gd->keyidx, 1, key_rsc, gd->key_rsc_len, - _gtk, gd->gtk_len) < 0) { - wpa_msg(sm->ctx->msg_ctx, MSG_WARNING, - "WPA: Failed to set GTK to the driver " - "(Group only)"); - return -1; - } - } else if (wpa_sm_set_key(sm, gd->alg, broadcast_ether_addr, - gd->keyidx, gd->tx, key_rsc, gd->key_rsc_len, - _gtk, gd->gtk_len) < 0) { - wpa_msg(sm->ctx->msg_ctx, MSG_WARNING, - "WPA: Failed to set GTK to " - "the driver (alg=%d keylen=%d keyidx=%d)", - gd->alg, gd->gtk_len, gd->keyidx); - return -1; - } - - return 0; -} - - -static int wpa_supplicant_gtk_tx_bit_workaround(const struct wpa_sm *sm, - int tx) -{ - if (tx && sm->pairwise_cipher != WPA_CIPHER_NONE) { - /* Ignore Tx bit for GTK if a pairwise key is used. One AP - * seemed to set this bit (incorrectly, since Tx is only when - * doing Group Key only APs) and without this workaround, the - * data connection does not work because wpa_supplicant - * configured non-zero keyidx to be used for unicast. */ - wpa_msg(sm->ctx->msg_ctx, MSG_INFO, - "WPA: Tx bit set for GTK, but pairwise " - "keys are used - ignore Tx bit"); - return 0; - } - return tx; -} - - -static int wpa_supplicant_pairwise_gtk(struct wpa_sm *sm, - const struct wpa_eapol_key *key, - const u8 *gtk, size_t gtk_len, - int key_info) -{ -#ifndef CONFIG_NO_WPA2 - struct wpa_gtk_data gd; - - /* - * IEEE Std 802.11i-2004 - 8.5.2 EAPOL-Key frames - Figure 43x - * GTK KDE format: - * KeyID[bits 0-1], Tx [bit 2], Reserved [bits 3-7] - * Reserved [bits 0-7] - * GTK - */ - - os_memset(&gd, 0, sizeof(gd)); - wpa_hexdump_key(MSG_DEBUG, "RSN: received GTK in pairwise handshake", - gtk, gtk_len); - - if (gtk_len < 2 || gtk_len - 2 > sizeof(gd.gtk)) - return -1; - - gd.keyidx = gtk[0] & 0x3; - gd.tx = wpa_supplicant_gtk_tx_bit_workaround(sm, - !!(gtk[0] & BIT(2))); - gtk += 2; - gtk_len -= 2; - - os_memcpy(gd.gtk, gtk, gtk_len); - gd.gtk_len = gtk_len; - - if (wpa_supplicant_check_group_cipher(sm, sm->group_cipher, - gtk_len, gtk_len, - &gd.key_rsc_len, &gd.alg) || - wpa_supplicant_install_gtk(sm, &gd, key->key_rsc)) { - wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG, - "RSN: Failed to install GTK"); - return -1; - } - - wpa_supplicant_key_neg_complete(sm, sm->bssid, - key_info & WPA_KEY_INFO_SECURE); - return 0; -#else /* CONFIG_NO_WPA2 */ - return -1; -#endif /* CONFIG_NO_WPA2 */ -} - - -static int ieee80211w_set_keys(struct wpa_sm *sm, - struct wpa_eapol_ie_parse *ie) -{ -#ifdef CONFIG_IEEE80211W - if (sm->mgmt_group_cipher != WPA_CIPHER_AES_128_CMAC) - return 0; - - if (ie->igtk) { - const struct wpa_igtk_kde *igtk; - u16 keyidx; - if (ie->igtk_len != sizeof(*igtk)) - return -1; - igtk = (const struct wpa_igtk_kde *) ie->igtk; - keyidx = WPA_GET_LE16(igtk->keyid); - wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG, "WPA: IGTK keyid %d " - "pn %02x%02x%02x%02x%02x%02x", - keyidx, MAC2STR(igtk->pn)); - wpa_hexdump_key(MSG_DEBUG, "WPA: IGTK", - igtk->igtk, WPA_IGTK_LEN); - if (keyidx > 4095) { - wpa_msg(sm->ctx->msg_ctx, MSG_WARNING, - "WPA: Invalid IGTK KeyID %d", keyidx); - return -1; - } - if (wpa_sm_set_key(sm, WPA_ALG_IGTK, broadcast_ether_addr, - keyidx, 0, igtk->pn, sizeof(igtk->pn), - igtk->igtk, WPA_IGTK_LEN) < 0) { - wpa_msg(sm->ctx->msg_ctx, MSG_WARNING, - "WPA: Failed to configure IGTK to the driver"); - return -1; - } - } - - return 0; -#else /* CONFIG_IEEE80211W */ - return 0; -#endif /* CONFIG_IEEE80211W */ -} - - -static void wpa_report_ie_mismatch(struct wpa_sm *sm, - const char *reason, const u8 *src_addr, - const u8 *wpa_ie, size_t wpa_ie_len, - const u8 *rsn_ie, size_t rsn_ie_len) -{ - wpa_msg(sm->ctx->msg_ctx, MSG_WARNING, "WPA: %s (src=" MACSTR ")", - reason, MAC2STR(src_addr)); - - if (sm->ap_wpa_ie) { - wpa_hexdump(MSG_INFO, "WPA: WPA IE in Beacon/ProbeResp", - sm->ap_wpa_ie, sm->ap_wpa_ie_len); - } - if (wpa_ie) { - if (!sm->ap_wpa_ie) { - wpa_msg(sm->ctx->msg_ctx, MSG_INFO, - "WPA: No WPA IE in Beacon/ProbeResp"); - } - wpa_hexdump(MSG_INFO, "WPA: WPA IE in 3/4 msg", - wpa_ie, wpa_ie_len); - } - - if (sm->ap_rsn_ie) { - wpa_hexdump(MSG_INFO, "WPA: RSN IE in Beacon/ProbeResp", - sm->ap_rsn_ie, sm->ap_rsn_ie_len); - } - if (rsn_ie) { - if (!sm->ap_rsn_ie) { - wpa_msg(sm->ctx->msg_ctx, MSG_INFO, - "WPA: No RSN IE in Beacon/ProbeResp"); - } - wpa_hexdump(MSG_INFO, "WPA: RSN IE in 3/4 msg", - rsn_ie, rsn_ie_len); - } - - wpa_sm_disassociate(sm, WLAN_REASON_IE_IN_4WAY_DIFFERS); -} - - -#ifdef CONFIG_IEEE80211R - -static int ft_validate_mdie(struct wpa_sm *sm, - const unsigned char *src_addr, - struct wpa_eapol_ie_parse *ie, - const u8 *assoc_resp_mdie) -{ - struct rsn_mdie *mdie; - - mdie = (struct rsn_mdie *) (ie->mdie + 2); - if (ie->mdie == NULL || ie->mdie_len < 2 + sizeof(*mdie) || - os_memcmp(mdie->mobility_domain, sm->mobility_domain, - MOBILITY_DOMAIN_ID_LEN) != 0) { - wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG, "FT: MDIE in msg 3/4 did " - "not match with the current mobility domain"); - return -1; - } - - if (assoc_resp_mdie && - (assoc_resp_mdie[1] != ie->mdie[1] || - os_memcmp(assoc_resp_mdie, ie->mdie, 2 + ie->mdie[1]) != 0)) { - wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG, "FT: MDIE mismatch"); - wpa_hexdump(MSG_DEBUG, "FT: MDIE in EAPOL-Key msg 3/4", - ie->mdie, 2 + ie->mdie[1]); - wpa_hexdump(MSG_DEBUG, "FT: MDIE in (Re)Association Response", - assoc_resp_mdie, 2 + assoc_resp_mdie[1]); - return -1; - } - - return 0; -} - - -static int ft_validate_ftie(struct wpa_sm *sm, - const unsigned char *src_addr, - struct wpa_eapol_ie_parse *ie, - const u8 *assoc_resp_ftie) -{ - if (ie->ftie == NULL) { - wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG, - "FT: No FTIE in EAPOL-Key msg 3/4"); - return -1; - } - - if (assoc_resp_ftie == NULL) - return 0; - - if (assoc_resp_ftie[1] != ie->ftie[1] || - os_memcmp(assoc_resp_ftie, ie->ftie, 2 + ie->ftie[1]) != 0) { - wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG, "FT: FTIE mismatch"); - wpa_hexdump(MSG_DEBUG, "FT: FTIE in EAPOL-Key msg 3/4", - ie->ftie, 2 + ie->ftie[1]); - wpa_hexdump(MSG_DEBUG, "FT: FTIE in (Re)Association Response", - assoc_resp_ftie, 2 + assoc_resp_ftie[1]); - return -1; - } - - return 0; -} - - -static int ft_validate_rsnie(struct wpa_sm *sm, - const unsigned char *src_addr, - struct wpa_eapol_ie_parse *ie) -{ - struct wpa_ie_data rsn; - - if (!ie->rsn_ie) - return 0; - - /* - * Verify that PMKR1Name from EAPOL-Key message 3/4 - * matches with the value we derived. - */ - if (wpa_parse_wpa_ie_rsn(ie->rsn_ie, ie->rsn_ie_len, &rsn) < 0 || - rsn.num_pmkid != 1 || rsn.pmkid == NULL) { - wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG, "FT: No PMKR1Name in " - "FT 4-way handshake message 3/4"); - return -1; - } - - if (os_memcmp(rsn.pmkid, sm->pmk_r1_name, WPA_PMK_NAME_LEN) != 0) { - wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG, - "FT: PMKR1Name mismatch in " - "FT 4-way handshake message 3/4"); - wpa_hexdump(MSG_DEBUG, "FT: PMKR1Name from Authenticator", - rsn.pmkid, WPA_PMK_NAME_LEN); - wpa_hexdump(MSG_DEBUG, "FT: Derived PMKR1Name", - sm->pmk_r1_name, WPA_PMK_NAME_LEN); - return -1; - } - - return 0; -} - - -static int wpa_supplicant_validate_ie_ft(struct wpa_sm *sm, - const unsigned char *src_addr, - struct wpa_eapol_ie_parse *ie) -{ - const u8 *pos, *end, *mdie = NULL, *ftie = NULL; - - if (sm->assoc_resp_ies) { - pos = sm->assoc_resp_ies; - end = pos + sm->assoc_resp_ies_len; - while (pos + 2 < end) { - if (pos + 2 + pos[1] > end) - break; - switch (*pos) { - case WLAN_EID_MOBILITY_DOMAIN: - mdie = pos; - break; - case WLAN_EID_FAST_BSS_TRANSITION: - ftie = pos; - break; - } - pos += 2 + pos[1]; - } - } - - if (ft_validate_mdie(sm, src_addr, ie, mdie) < 0 || - ft_validate_ftie(sm, src_addr, ie, ftie) < 0 || - ft_validate_rsnie(sm, src_addr, ie) < 0) - return -1; - - return 0; -} - -#endif /* CONFIG_IEEE80211R */ - - -static int wpa_supplicant_validate_ie(struct wpa_sm *sm, - const unsigned char *src_addr, - struct wpa_eapol_ie_parse *ie) -{ - if (sm->ap_wpa_ie == NULL && sm->ap_rsn_ie == NULL) { - wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG, - "WPA: No WPA/RSN IE for this AP known. " - "Trying to get from scan results"); - if (wpa_sm_get_beacon_ie(sm) < 0) { - wpa_msg(sm->ctx->msg_ctx, MSG_WARNING, - "WPA: Could not find AP from " - "the scan results"); - } else { - wpa_msg(sm->ctx->msg_ctx, MSG_DEBUG, - "WPA: Found the current AP from " - "updated scan results"); - } - } - - if (ie->wpa_ie == NULL && ie->rsn_ie == NULL && - (sm->ap_wpa_ie || sm->ap_rsn_ie)) { - wpa_report_ie_mismatch(sm, "IE in 3/4 msg does not match " - "with IE in Beacon/ProbeResp (no IE?)", - src_addr, ie->wpa_ie, ie->wpa_ie_len, - ie->rsn_ie, ie->rsn_ie_len); - return -1; - } - - if ((ie->wpa_ie && sm->ap_wpa_ie && - (ie->wpa_ie_len != sm->ap_wpa_ie_len || - os_memcmp(ie->wpa_ie, sm->ap_wpa_ie, ie->wpa_ie_len) != 0)) || - (ie->rsn_ie && sm->ap_rsn_ie && - wpa_compare_rsn_ie(wpa_key_mgmt_ft(sm->key_mgmt), - sm->ap_rsn_ie, sm->ap_rsn_ie_len, - ie->rsn_ie, ie->rsn_ie_len))) { - wpa_report_ie_mismatch(sm, "IE in 3/4 msg does not match " - "with IE in Beacon/ProbeResp", - src_addr, ie->wpa_ie, ie->wpa_ie_len, - ie->rsn_ie, ie->rsn_ie_len); - return -1; - } - - if (sm->proto == WPA_PROTO_WPA && - ie->rsn_ie && sm->ap_rsn_ie == NULL && sm->rsn_enabled) { - wpa_report_ie_mismatch(sm, "Possible downgrade attack " - "detected - RSN was enabled and RSN IE " - "was in msg 3/4, but not in " - "Beacon/ProbeResp", - src_addr, ie->wpa_ie, ie->wpa_ie_len, - ie->rsn_ie, ie->rsn_ie_len); - return -1; - } - -#ifdef CONFIG_IEEE80211R - if (wpa_key_mgmt_ft(sm->key_mgmt) && - wpa_supplicant_validate_ie_ft(sm, src_addr, ie) < 0) - return -1; -#endif /* CONFIG_IEEE80211R */ - - return 0; -} - - -/** - * wpa_supplicant_send_4_of_4 - Send message 4 of WPA/RSN 4-Way Handshake - * @sm: Pointer to WPA state machine data from wpa_sm_init() - * @dst: Destination address for the frame - * @key: Pointer to the EAPOL-Key frame header - * @ver: Version bits from EAPOL-Key Key Info - * @key_info: Key Info - * @kde: KDEs to include the EAPOL-Key frame - * @kde_len: Length of KDEs - * @ptk: PTK to use for keyed hash and encryption - * Returns: 0 on success, -1 on failure - */ -int wpa_supplicant_send_4_of_4(struct wpa_sm *sm, const unsigned char *dst, - const struct wpa_eapol_key *key, - u16 ver, u16 key_info, - const u8 *kde, size_t kde_len, - struct wpa_ptk *ptk) -{ - size_t rlen; - struct wpa_eapol_key *reply; - u8 *rbuf; - - if (kde) - wpa_hexdump(MSG_DEBUG, "WPA: KDE for msg 4/4", kde, kde_len); - - rbuf = wpa_sm_alloc_eapol(sm, IEEE802_1X_TYPE_EAPOL_KEY, NULL, - sizeof(*reply) + kde_len, - &rlen, (void *) &reply); - if (rbuf == NULL) - return -1; - - reply->type = sm->proto == WPA_PROTO_RSN ? - EAPOL_KEY_TYPE_RSN : EAPOL_KEY_TYPE_WPA; - key_info &= WPA_KEY_INFO_SECURE; - key_info |= ver | WPA_KEY_INFO_KEY_TYPE | WPA_KEY_INFO_MIC; - WPA_PUT_BE16(reply->key_info, key_info); - if (sm->proto == WPA_PROTO_RSN) - WPA_PUT_BE16(reply->key_length, 0); - else - os_memcpy(reply->key_length, key->key_length, 2); - os_memcpy(reply->replay_counter, key->replay_counter, - WPA_REPLAY_COUNTER_LEN); - - WPA_PUT_BE16(reply->key_data_length, kde_len); - if (kde) - os_memcpy(reply + 1, kde, kde_len); - - wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG, "WPA: Sending EAPOL-Key 4/4"); - wpa_eapol_key_send(sm, ptk->kck, ver, dst, ETH_P_EAPOL, - rbuf, rlen, reply->key_mic); - - return 0; -} - - -static void wpa_supplicant_process_3_of_4(struct wpa_sm *sm, - const struct wpa_eapol_key *key, - u16 ver) -{ - u16 key_info, keylen, len; - const u8 *pos; - struct wpa_eapol_ie_parse ie; - - wpa_sm_set_state(sm, WPA_4WAY_HANDSHAKE); - wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG, "WPA: RX message 3 of 4-Way " - "Handshake from " MACSTR " (ver=%d)", MAC2STR(sm->bssid), ver); - - key_info = WPA_GET_BE16(key->key_info); - - pos = (const u8 *) (key + 1); - len = WPA_GET_BE16(key->key_data_length); - wpa_hexdump(MSG_DEBUG, "WPA: IE KeyData", pos, len); - wpa_supplicant_parse_ies(pos, len, &ie); - if (ie.gtk && !(key_info & WPA_KEY_INFO_ENCR_KEY_DATA)) { - wpa_msg(sm->ctx->msg_ctx, MSG_WARNING, - "WPA: GTK IE in unencrypted key data"); - goto failed; - } -#ifdef CONFIG_IEEE80211W - if (ie.igtk && !(key_info & WPA_KEY_INFO_ENCR_KEY_DATA)) { - wpa_msg(sm->ctx->msg_ctx, MSG_WARNING, - "WPA: IGTK KDE in unencrypted key data"); - goto failed; - } - - if (ie.igtk && ie.igtk_len != sizeof(struct wpa_igtk_kde)) { - wpa_msg(sm->ctx->msg_ctx, MSG_WARNING, - "WPA: Invalid IGTK KDE length %lu", - (unsigned long) ie.igtk_len); - goto failed; - } -#endif /* CONFIG_IEEE80211W */ - - if (wpa_supplicant_validate_ie(sm, sm->bssid, &ie) < 0) - goto failed; - - if (os_memcmp(sm->anonce, key->key_nonce, WPA_NONCE_LEN) != 0) { - wpa_msg(sm->ctx->msg_ctx, MSG_WARNING, - "WPA: ANonce from message 1 of 4-Way Handshake " - "differs from 3 of 4-Way Handshake - drop packet (src=" - MACSTR ")", MAC2STR(sm->bssid)); - goto failed; - } - - keylen = WPA_GET_BE16(key->key_length); - switch (sm->pairwise_cipher) { - case WPA_CIPHER_CCMP: - if (keylen != 16) { - wpa_msg(sm->ctx->msg_ctx, MSG_WARNING, - "WPA: Invalid CCMP key length %d (src=" MACSTR - ")", keylen, MAC2STR(sm->bssid)); - goto failed; - } - break; - case WPA_CIPHER_TKIP: - if (keylen != 32) { - wpa_msg(sm->ctx->msg_ctx, MSG_WARNING, - "WPA: Invalid TKIP key length %d (src=" MACSTR - ")", keylen, MAC2STR(sm->bssid)); - goto failed; - } - break; - } - - if (wpa_supplicant_send_4_of_4(sm, sm->bssid, key, ver, key_info, - NULL, 0, &sm->ptk)) { - goto failed; - } - - /* SNonce was successfully used in msg 3/4, so mark it to be renewed - * for the next 4-Way Handshake. If msg 3 is received again, the old - * SNonce will still be used to avoid changing PTK. */ - sm->renew_snonce = 1; - - if (key_info & WPA_KEY_INFO_INSTALL) { - if (wpa_supplicant_install_ptk(sm, key)) - goto failed; - } - - if (key_info & WPA_KEY_INFO_SECURE) { - wpa_sm_mlme_setprotection( - sm, sm->bssid, MLME_SETPROTECTION_PROTECT_TYPE_RX, - MLME_SETPROTECTION_KEY_TYPE_PAIRWISE); - eapol_sm_notify_portValid(sm->eapol, TRUE); - } - wpa_sm_set_state(sm, WPA_GROUP_HANDSHAKE); - - if (ie.gtk && - wpa_supplicant_pairwise_gtk(sm, key, - ie.gtk, ie.gtk_len, key_info) < 0) { - wpa_msg(sm->ctx->msg_ctx, MSG_INFO, - "RSN: Failed to configure GTK"); - goto failed; - } - - if (ieee80211w_set_keys(sm, &ie) < 0) { - wpa_msg(sm->ctx->msg_ctx, MSG_INFO, - "RSN: Failed to configure IGTK"); - goto failed; - } - - return; - -failed: - wpa_sm_deauthenticate(sm, WLAN_REASON_UNSPECIFIED); -} - - -static int wpa_supplicant_process_1_of_2_rsn(struct wpa_sm *sm, - const u8 *keydata, - size_t keydatalen, - u16 key_info, - struct wpa_gtk_data *gd) -{ - int maxkeylen; - struct wpa_eapol_ie_parse ie; - - wpa_hexdump(MSG_DEBUG, "RSN: msg 1/2 key data", keydata, keydatalen); - wpa_supplicant_parse_ies(keydata, keydatalen, &ie); - if (ie.gtk && !(key_info & WPA_KEY_INFO_ENCR_KEY_DATA)) { - wpa_msg(sm->ctx->msg_ctx, MSG_WARNING, - "WPA: GTK IE in unencrypted key data"); - return -1; - } - if (ie.gtk == NULL) { - wpa_msg(sm->ctx->msg_ctx, MSG_INFO, - "WPA: No GTK IE in Group Key msg 1/2"); - return -1; - } - maxkeylen = gd->gtk_len = ie.gtk_len - 2; - - if (wpa_supplicant_check_group_cipher(sm, sm->group_cipher, - gd->gtk_len, maxkeylen, - &gd->key_rsc_len, &gd->alg)) - return -1; - - wpa_hexdump(MSG_DEBUG, "RSN: received GTK in group key handshake", - ie.gtk, ie.gtk_len); - gd->keyidx = ie.gtk[0] & 0x3; - gd->tx = wpa_supplicant_gtk_tx_bit_workaround(sm, - !!(ie.gtk[0] & BIT(2))); - if (ie.gtk_len - 2 > sizeof(gd->gtk)) { - wpa_msg(sm->ctx->msg_ctx, MSG_INFO, - "RSN: Too long GTK in GTK IE (len=%lu)", - (unsigned long) ie.gtk_len - 2); - return -1; - } - os_memcpy(gd->gtk, ie.gtk + 2, ie.gtk_len - 2); - - if (ieee80211w_set_keys(sm, &ie) < 0) - wpa_msg(sm->ctx->msg_ctx, MSG_INFO, - "RSN: Failed to configure IGTK"); - - return 0; -} - - -static int wpa_supplicant_process_1_of_2_wpa(struct wpa_sm *sm, - const struct wpa_eapol_key *key, - size_t keydatalen, int key_info, - size_t extra_len, u16 ver, - struct wpa_gtk_data *gd) -{ - size_t maxkeylen; - u8 ek[32]; - - gd->gtk_len = WPA_GET_BE16(key->key_length); - maxkeylen = keydatalen; - if (keydatalen > extra_len) { - wpa_msg(sm->ctx->msg_ctx, MSG_INFO, - "WPA: Truncated EAPOL-Key packet: " - "key_data_length=%lu > extra_len=%lu", - (unsigned long) keydatalen, (unsigned long) extra_len); - return -1; - } - if (ver == WPA_KEY_INFO_TYPE_HMAC_SHA1_AES) { - if (maxkeylen < 8) { - wpa_msg(sm->ctx->msg_ctx, MSG_INFO, - "WPA: Too short maxkeylen (%lu)", - (unsigned long) maxkeylen); - return -1; - } - maxkeylen -= 8; - } - - if (wpa_supplicant_check_group_cipher(sm, sm->group_cipher, - gd->gtk_len, maxkeylen, - &gd->key_rsc_len, &gd->alg)) - return -1; - - gd->keyidx = (key_info & WPA_KEY_INFO_KEY_INDEX_MASK) >> - WPA_KEY_INFO_KEY_INDEX_SHIFT; - if (ver == WPA_KEY_INFO_TYPE_HMAC_MD5_RC4) { - os_memcpy(ek, key->key_iv, 16); - os_memcpy(ek + 16, sm->ptk.kek, 16); - if (keydatalen > sizeof(gd->gtk)) { - wpa_msg(sm->ctx->msg_ctx, MSG_WARNING, - "WPA: RC4 key data too long (%lu)", - (unsigned long) keydatalen); - return -1; - } - os_memcpy(gd->gtk, key + 1, keydatalen); - if (rc4_skip(ek, 32, 256, gd->gtk, keydatalen)) { - wpa_msg(sm->ctx->msg_ctx, MSG_ERROR, - "WPA: RC4 failed"); - return -1; - } - } else if (ver == WPA_KEY_INFO_TYPE_HMAC_SHA1_AES) { - if (keydatalen % 8) { - wpa_msg(sm->ctx->msg_ctx, MSG_WARNING, - "WPA: Unsupported AES-WRAP len %lu", - (unsigned long) keydatalen); - return -1; - } - if (maxkeylen > sizeof(gd->gtk)) { - wpa_msg(sm->ctx->msg_ctx, MSG_WARNING, - "WPA: AES-WRAP key data " - "too long (keydatalen=%lu maxkeylen=%lu)", - (unsigned long) keydatalen, - (unsigned long) maxkeylen); - return -1; - } - if (aes_unwrap(sm->ptk.kek, maxkeylen / 8, - (const u8 *) (key + 1), gd->gtk)) { - wpa_msg(sm->ctx->msg_ctx, MSG_WARNING, - "WPA: AES unwrap failed - could not decrypt " - "GTK"); - return -1; - } - } else { - wpa_msg(sm->ctx->msg_ctx, MSG_WARNING, - "WPA: Unsupported key_info type %d", ver); - return -1; - } - gd->tx = wpa_supplicant_gtk_tx_bit_workaround( - sm, !!(key_info & WPA_KEY_INFO_TXRX)); - return 0; -} - - -static int wpa_supplicant_send_2_of_2(struct wpa_sm *sm, - const struct wpa_eapol_key *key, - int ver, u16 key_info) -{ - size_t rlen; - struct wpa_eapol_key *reply; - u8 *rbuf; - - rbuf = wpa_sm_alloc_eapol(sm, IEEE802_1X_TYPE_EAPOL_KEY, NULL, - sizeof(*reply), &rlen, (void *) &reply); - if (rbuf == NULL) - return -1; - - reply->type = sm->proto == WPA_PROTO_RSN ? - EAPOL_KEY_TYPE_RSN : EAPOL_KEY_TYPE_WPA; - key_info &= WPA_KEY_INFO_KEY_INDEX_MASK; - key_info |= ver | WPA_KEY_INFO_MIC | WPA_KEY_INFO_SECURE; - WPA_PUT_BE16(reply->key_info, key_info); - if (sm->proto == WPA_PROTO_RSN) - WPA_PUT_BE16(reply->key_length, 0); - else - os_memcpy(reply->key_length, key->key_length, 2); - os_memcpy(reply->replay_counter, key->replay_counter, - WPA_REPLAY_COUNTER_LEN); - - WPA_PUT_BE16(reply->key_data_length, 0); - - wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG, "WPA: Sending EAPOL-Key 2/2"); - wpa_eapol_key_send(sm, sm->ptk.kck, ver, sm->bssid, ETH_P_EAPOL, - rbuf, rlen, reply->key_mic); - - return 0; -} - - -static void wpa_supplicant_process_1_of_2(struct wpa_sm *sm, - const unsigned char *src_addr, - const struct wpa_eapol_key *key, - int extra_len, u16 ver) -{ - u16 key_info, keydatalen; - int rekey, ret; - struct wpa_gtk_data gd; - - os_memset(&gd, 0, sizeof(gd)); - - rekey = wpa_sm_get_state(sm) == WPA_COMPLETED; - wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG, "WPA: RX message 1 of Group Key " - "Handshake from " MACSTR " (ver=%d)", MAC2STR(src_addr), ver); - - key_info = WPA_GET_BE16(key->key_info); - keydatalen = WPA_GET_BE16(key->key_data_length); - - if (sm->proto == WPA_PROTO_RSN) { - ret = wpa_supplicant_process_1_of_2_rsn(sm, - (const u8 *) (key + 1), - keydatalen, key_info, - &gd); - } else { - ret = wpa_supplicant_process_1_of_2_wpa(sm, key, keydatalen, - key_info, extra_len, - ver, &gd); - } - - wpa_sm_set_state(sm, WPA_GROUP_HANDSHAKE); - - if (ret) - goto failed; - - if (wpa_supplicant_install_gtk(sm, &gd, key->key_rsc) || - wpa_supplicant_send_2_of_2(sm, key, ver, key_info)) - goto failed; - - if (rekey) { - wpa_msg(sm->ctx->msg_ctx, MSG_INFO, "WPA: Group rekeying " - "completed with " MACSTR " [GTK=%s]", - MAC2STR(sm->bssid), wpa_cipher_txt(sm->group_cipher)); - wpa_sm_cancel_auth_timeout(sm); - wpa_sm_set_state(sm, WPA_COMPLETED); - } else { - wpa_supplicant_key_neg_complete(sm, sm->bssid, - key_info & - WPA_KEY_INFO_SECURE); - } - return; - -failed: - wpa_sm_deauthenticate(sm, WLAN_REASON_UNSPECIFIED); -} - - -static int wpa_supplicant_verify_eapol_key_mic(struct wpa_sm *sm, - struct wpa_eapol_key *key, - u16 ver, - const u8 *buf, size_t len) -{ - u8 mic[16]; - int ok = 0; - - os_memcpy(mic, key->key_mic, 16); - if (sm->tptk_set) { - os_memset(key->key_mic, 0, 16); - wpa_eapol_key_mic(sm->tptk.kck, ver, buf, len, - key->key_mic); - if (os_memcmp(mic, key->key_mic, 16) != 0) { - wpa_msg(sm->ctx->msg_ctx, MSG_WARNING, - "WPA: Invalid EAPOL-Key MIC " - "when using TPTK - ignoring TPTK"); - } else { - ok = 1; - sm->tptk_set = 0; - sm->ptk_set = 1; - os_memcpy(&sm->ptk, &sm->tptk, sizeof(sm->ptk)); - } - } - - if (!ok && sm->ptk_set) { - os_memset(key->key_mic, 0, 16); - wpa_eapol_key_mic(sm->ptk.kck, ver, buf, len, - key->key_mic); - if (os_memcmp(mic, key->key_mic, 16) != 0) { - wpa_msg(sm->ctx->msg_ctx, MSG_WARNING, - "WPA: Invalid EAPOL-Key MIC - " - "dropping packet"); - return -1; - } - ok = 1; - } - - if (!ok) { - wpa_msg(sm->ctx->msg_ctx, MSG_WARNING, - "WPA: Could not verify EAPOL-Key MIC - " - "dropping packet"); - return -1; - } - - os_memcpy(sm->rx_replay_counter, key->replay_counter, - WPA_REPLAY_COUNTER_LEN); - sm->rx_replay_counter_set = 1; - return 0; -} - - -/* Decrypt RSN EAPOL-Key key data (RC4 or AES-WRAP) */ -static int wpa_supplicant_decrypt_key_data(struct wpa_sm *sm, - struct wpa_eapol_key *key, u16 ver) -{ - u16 keydatalen = WPA_GET_BE16(key->key_data_length); - - wpa_hexdump(MSG_DEBUG, "RSN: encrypted key data", - (u8 *) (key + 1), keydatalen); - if (!sm->ptk_set) { - wpa_msg(sm->ctx->msg_ctx, MSG_WARNING, - "WPA: PTK not available, cannot decrypt EAPOL-Key Key " - "Data"); - return -1; - } - - /* Decrypt key data here so that this operation does not need - * to be implemented separately for each message type. */ - if (ver == WPA_KEY_INFO_TYPE_HMAC_MD5_RC4) { - u8 ek[32]; - os_memcpy(ek, key->key_iv, 16); - os_memcpy(ek + 16, sm->ptk.kek, 16); - if (rc4_skip(ek, 32, 256, (u8 *) (key + 1), keydatalen)) { - wpa_msg(sm->ctx->msg_ctx, MSG_ERROR, - "WPA: RC4 failed"); - return -1; - } - } else if (ver == WPA_KEY_INFO_TYPE_HMAC_SHA1_AES || - ver == WPA_KEY_INFO_TYPE_AES_128_CMAC) { - u8 *buf; - if (keydatalen % 8) { - wpa_msg(sm->ctx->msg_ctx, MSG_WARNING, - "WPA: Unsupported AES-WRAP len %d", - keydatalen); - return -1; - } - keydatalen -= 8; /* AES-WRAP adds 8 bytes */ - buf = os_malloc(keydatalen); - if (buf == NULL) { - wpa_msg(sm->ctx->msg_ctx, MSG_WARNING, - "WPA: No memory for AES-UNWRAP buffer"); - return -1; - } - if (aes_unwrap(sm->ptk.kek, keydatalen / 8, - (u8 *) (key + 1), buf)) { - os_free(buf); - wpa_msg(sm->ctx->msg_ctx, MSG_WARNING, - "WPA: AES unwrap failed - " - "could not decrypt EAPOL-Key key data"); - return -1; - } - os_memcpy(key + 1, buf, keydatalen); - os_free(buf); - WPA_PUT_BE16(key->key_data_length, keydatalen); - } else { - wpa_msg(sm->ctx->msg_ctx, MSG_WARNING, - "WPA: Unsupported key_info type %d", ver); - return -1; - } - wpa_hexdump_key(MSG_DEBUG, "WPA: decrypted EAPOL-Key key data", - (u8 *) (key + 1), keydatalen); - return 0; -} - - -/** - * wpa_sm_aborted_cached - Notify WPA that PMKSA caching was aborted - * @sm: Pointer to WPA state machine data from wpa_sm_init() - */ -void wpa_sm_aborted_cached(struct wpa_sm *sm) -{ - if (sm && sm->cur_pmksa) { - wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG, - "RSN: Cancelling PMKSA caching attempt"); - sm->cur_pmksa = NULL; - } -} - - -static void wpa_eapol_key_dump(struct wpa_sm *sm, - const struct wpa_eapol_key *key) -{ -#ifndef CONFIG_NO_STDOUT_DEBUG - u16 key_info = WPA_GET_BE16(key->key_info); - - wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG, " EAPOL-Key type=%d", key->type); - wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG, - " key_info 0x%x (ver=%d keyidx=%d rsvd=%d %s%s%s%s%s%s%s%s)", - key_info, key_info & WPA_KEY_INFO_TYPE_MASK, - (key_info & WPA_KEY_INFO_KEY_INDEX_MASK) >> - WPA_KEY_INFO_KEY_INDEX_SHIFT, - (key_info & (BIT(13) | BIT(14) | BIT(15))) >> 13, - key_info & WPA_KEY_INFO_KEY_TYPE ? "Pairwise" : "Group", - key_info & WPA_KEY_INFO_INSTALL ? " Install" : "", - key_info & WPA_KEY_INFO_ACK ? " Ack" : "", - key_info & WPA_KEY_INFO_MIC ? " MIC" : "", - key_info & WPA_KEY_INFO_SECURE ? " Secure" : "", - key_info & WPA_KEY_INFO_ERROR ? " Error" : "", - key_info & WPA_KEY_INFO_REQUEST ? " Request" : "", - key_info & WPA_KEY_INFO_ENCR_KEY_DATA ? " Encr" : ""); - wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG, - " key_length=%u key_data_length=%u", - WPA_GET_BE16(key->key_length), - WPA_GET_BE16(key->key_data_length)); - wpa_hexdump(MSG_DEBUG, " replay_counter", - key->replay_counter, WPA_REPLAY_COUNTER_LEN); - wpa_hexdump(MSG_DEBUG, " key_nonce", key->key_nonce, WPA_NONCE_LEN); - wpa_hexdump(MSG_DEBUG, " key_iv", key->key_iv, 16); - wpa_hexdump(MSG_DEBUG, " key_rsc", key->key_rsc, 8); - wpa_hexdump(MSG_DEBUG, " key_id (reserved)", key->key_id, 8); - wpa_hexdump(MSG_DEBUG, " key_mic", key->key_mic, 16); -#endif /* CONFIG_NO_STDOUT_DEBUG */ -} - - -/** - * wpa_sm_rx_eapol - Process received WPA EAPOL frames - * @sm: Pointer to WPA state machine data from wpa_sm_init() - * @src_addr: Source MAC address of the EAPOL packet - * @buf: Pointer to the beginning of the EAPOL data (EAPOL header) - * @len: Length of the EAPOL frame - * Returns: 1 = WPA EAPOL-Key processed, 0 = not a WPA EAPOL-Key, -1 failure - * - * This function is called for each received EAPOL frame. Other than EAPOL-Key - * frames can be skipped if filtering is done elsewhere. wpa_sm_rx_eapol() is - * only processing WPA and WPA2 EAPOL-Key frames. - * - * The received EAPOL-Key packets are validated and valid packets are replied - * to. In addition, key material (PTK, GTK) is configured at the end of a - * successful key handshake. - */ -int wpa_sm_rx_eapol(struct wpa_sm *sm, const u8 *src_addr, - const u8 *buf, size_t len) -{ - size_t plen, data_len, extra_len; - struct ieee802_1x_hdr *hdr; - struct wpa_eapol_key *key; - u16 key_info, ver; - u8 *tmp; - int ret = -1; - struct wpa_peerkey *peerkey = NULL; - -#ifdef CONFIG_IEEE80211R - sm->ft_completed = 0; -#endif /* CONFIG_IEEE80211R */ - - if (len < sizeof(*hdr) + sizeof(*key)) { - wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG, - "WPA: EAPOL frame too short to be a WPA " - "EAPOL-Key (len %lu, expecting at least %lu)", - (unsigned long) len, - (unsigned long) sizeof(*hdr) + sizeof(*key)); - return 0; - } - - tmp = os_malloc(len); - if (tmp == NULL) - return -1; - os_memcpy(tmp, buf, len); - - hdr = (struct ieee802_1x_hdr *) tmp; - key = (struct wpa_eapol_key *) (hdr + 1); - plen = be_to_host16(hdr->length); - data_len = plen + sizeof(*hdr); - wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG, - "IEEE 802.1X RX: version=%d type=%d length=%lu", - hdr->version, hdr->type, (unsigned long) plen); - - if (hdr->version < EAPOL_VERSION) { - /* TODO: backwards compatibility */ - } - if (hdr->type != IEEE802_1X_TYPE_EAPOL_KEY) { - wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG, - "WPA: EAPOL frame (type %u) discarded, " - "not a Key frame", hdr->type); - ret = 0; - goto out; - } - if (plen > len - sizeof(*hdr) || plen < sizeof(*key)) { - wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG, - "WPA: EAPOL frame payload size %lu " - "invalid (frame size %lu)", - (unsigned long) plen, (unsigned long) len); - ret = 0; - goto out; - } - - if (key->type != EAPOL_KEY_TYPE_WPA && key->type != EAPOL_KEY_TYPE_RSN) - { - wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG, - "WPA: EAPOL-Key type (%d) unknown, discarded", - key->type); - ret = 0; - goto out; - } - wpa_eapol_key_dump(sm, key); - - eapol_sm_notify_lower_layer_success(sm->eapol, 0); - wpa_hexdump(MSG_MSGDUMP, "WPA: RX EAPOL-Key", tmp, len); - if (data_len < len) { - wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG, - "WPA: ignoring %lu bytes after the IEEE 802.1X data", - (unsigned long) len - data_len); - } - key_info = WPA_GET_BE16(key->key_info); - ver = key_info & WPA_KEY_INFO_TYPE_MASK; - if (ver != WPA_KEY_INFO_TYPE_HMAC_MD5_RC4 && -#if defined(CONFIG_IEEE80211R) || defined(CONFIG_IEEE80211W) - ver != WPA_KEY_INFO_TYPE_AES_128_CMAC && -#endif /* CONFIG_IEEE80211R || CONFIG_IEEE80211W */ - ver != WPA_KEY_INFO_TYPE_HMAC_SHA1_AES) { - wpa_msg(sm->ctx->msg_ctx, MSG_INFO, - "WPA: Unsupported EAPOL-Key descriptor version %d", - ver); - goto out; - } - -#ifdef CONFIG_IEEE80211R - if (wpa_key_mgmt_ft(sm->key_mgmt)) { - /* IEEE 802.11r uses a new key_info type (AES-128-CMAC). */ - if (ver != WPA_KEY_INFO_TYPE_AES_128_CMAC) { - wpa_msg(sm->ctx->msg_ctx, MSG_INFO, - "FT: AP did not use AES-128-CMAC"); - goto out; - } - } else -#endif /* CONFIG_IEEE80211R */ -#ifdef CONFIG_IEEE80211W - if (wpa_key_mgmt_sha256(sm->key_mgmt)) { - if (ver != WPA_KEY_INFO_TYPE_AES_128_CMAC) { - wpa_msg(sm->ctx->msg_ctx, MSG_INFO, - "WPA: AP did not use the " - "negotiated AES-128-CMAC"); - goto out; - } - } else -#endif /* CONFIG_IEEE80211W */ - if (sm->pairwise_cipher == WPA_CIPHER_CCMP && - ver != WPA_KEY_INFO_TYPE_HMAC_SHA1_AES) { - wpa_msg(sm->ctx->msg_ctx, MSG_INFO, - "WPA: CCMP is used, but EAPOL-Key " - "descriptor version (%d) is not 2", ver); - if (sm->group_cipher != WPA_CIPHER_CCMP && - !(key_info & WPA_KEY_INFO_KEY_TYPE)) { - /* Earlier versions of IEEE 802.11i did not explicitly - * require version 2 descriptor for all EAPOL-Key - * packets, so allow group keys to use version 1 if - * CCMP is not used for them. */ - wpa_msg(sm->ctx->msg_ctx, MSG_INFO, - "WPA: Backwards compatibility: allow invalid " - "version for non-CCMP group keys"); - } else - goto out; - } - -#ifdef CONFIG_PEERKEY - for (peerkey = sm->peerkey; peerkey; peerkey = peerkey->next) { - if (os_memcmp(peerkey->addr, src_addr, ETH_ALEN) == 0) - break; - } - - if (!(key_info & WPA_KEY_INFO_SMK_MESSAGE) && peerkey) { - if (!peerkey->initiator && peerkey->replay_counter_set && - os_memcmp(key->replay_counter, peerkey->replay_counter, - WPA_REPLAY_COUNTER_LEN) <= 0) { - wpa_msg(sm->ctx->msg_ctx, MSG_WARNING, - "RSN: EAPOL-Key Replay Counter did not " - "increase (STK) - dropping packet"); - goto out; - } else if (peerkey->initiator) { - u8 _tmp[WPA_REPLAY_COUNTER_LEN]; - os_memcpy(_tmp, key->replay_counter, - WPA_REPLAY_COUNTER_LEN); - inc_byte_array(_tmp, WPA_REPLAY_COUNTER_LEN); - if (os_memcmp(_tmp, peerkey->replay_counter, - WPA_REPLAY_COUNTER_LEN) != 0) { - wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG, - "RSN: EAPOL-Key Replay " - "Counter did not match (STK) - " - "dropping packet"); - goto out; - } - } - } - - if (peerkey && peerkey->initiator && (key_info & WPA_KEY_INFO_ACK)) { - wpa_msg(sm->ctx->msg_ctx, MSG_INFO, - "RSN: Ack bit in key_info from STK peer"); - goto out; - } -#endif /* CONFIG_PEERKEY */ - - if (!peerkey && sm->rx_replay_counter_set && - os_memcmp(key->replay_counter, sm->rx_replay_counter, - WPA_REPLAY_COUNTER_LEN) <= 0) { - wpa_msg(sm->ctx->msg_ctx, MSG_WARNING, - "WPA: EAPOL-Key Replay Counter did not increase - " - "dropping packet"); - goto out; - } - - if (!(key_info & (WPA_KEY_INFO_ACK | WPA_KEY_INFO_SMK_MESSAGE)) -#ifdef CONFIG_PEERKEY - && (peerkey == NULL || !peerkey->initiator) -#endif /* CONFIG_PEERKEY */ - ) { - wpa_msg(sm->ctx->msg_ctx, MSG_INFO, - "WPA: No Ack bit in key_info"); - goto out; - } - - if (key_info & WPA_KEY_INFO_REQUEST) { - wpa_msg(sm->ctx->msg_ctx, MSG_INFO, - "WPA: EAPOL-Key with Request bit - dropped"); - goto out; - } - - if ((key_info & WPA_KEY_INFO_MIC) && !peerkey && - wpa_supplicant_verify_eapol_key_mic(sm, key, ver, tmp, data_len)) - goto out; - -#ifdef CONFIG_PEERKEY - if ((key_info & WPA_KEY_INFO_MIC) && peerkey && - peerkey_verify_eapol_key_mic(sm, peerkey, key, ver, tmp, data_len)) - goto out; -#endif /* CONFIG_PEERKEY */ - - extra_len = data_len - sizeof(*hdr) - sizeof(*key); - - if (WPA_GET_BE16(key->key_data_length) > extra_len) { - wpa_msg(sm->ctx->msg_ctx, MSG_INFO, "WPA: Invalid EAPOL-Key " - "frame - key_data overflow (%d > %lu)", - WPA_GET_BE16(key->key_data_length), - (unsigned long) extra_len); - goto out; - } - extra_len = WPA_GET_BE16(key->key_data_length); - - if (sm->proto == WPA_PROTO_RSN && - (key_info & WPA_KEY_INFO_ENCR_KEY_DATA)) { - if (wpa_supplicant_decrypt_key_data(sm, key, ver)) - goto out; - extra_len = WPA_GET_BE16(key->key_data_length); - } - - if (key_info & WPA_KEY_INFO_KEY_TYPE) { - if (key_info & WPA_KEY_INFO_KEY_INDEX_MASK) { - wpa_msg(sm->ctx->msg_ctx, MSG_WARNING, - "WPA: Ignored EAPOL-Key (Pairwise) with " - "non-zero key index"); - goto out; - } - if (peerkey) { - /* PeerKey 4-Way Handshake */ - peerkey_rx_eapol_4way(sm, peerkey, key, key_info, ver); - } else if (key_info & WPA_KEY_INFO_MIC) { - /* 3/4 4-Way Handshake */ - wpa_supplicant_process_3_of_4(sm, key, ver); - } else { - /* 1/4 4-Way Handshake */ - wpa_supplicant_process_1_of_4(sm, src_addr, key, - ver); - } - } else if (key_info & WPA_KEY_INFO_SMK_MESSAGE) { - /* PeerKey SMK Handshake */ - peerkey_rx_eapol_smk(sm, src_addr, key, extra_len, key_info, - ver); - } else { - if (key_info & WPA_KEY_INFO_MIC) { - /* 1/2 Group Key Handshake */ - wpa_supplicant_process_1_of_2(sm, src_addr, key, - extra_len, ver); - } else { - wpa_msg(sm->ctx->msg_ctx, MSG_WARNING, - "WPA: EAPOL-Key (Group) without Mic bit - " - "dropped"); - } - } - - ret = 1; - -out: - os_free(tmp); - return ret; -} - - -#ifdef CONFIG_CTRL_IFACE -static int wpa_cipher_bits(int cipher) -{ - switch (cipher) { - case WPA_CIPHER_CCMP: - return 128; - case WPA_CIPHER_TKIP: - return 256; - case WPA_CIPHER_WEP104: - return 104; - case WPA_CIPHER_WEP40: - return 40; - default: - return 0; - } -} - - -static u32 wpa_key_mgmt_suite(struct wpa_sm *sm) -{ - switch (sm->key_mgmt) { - case WPA_KEY_MGMT_IEEE8021X: - return (sm->proto == WPA_PROTO_RSN ? - RSN_AUTH_KEY_MGMT_UNSPEC_802_1X : - WPA_AUTH_KEY_MGMT_UNSPEC_802_1X); - case WPA_KEY_MGMT_PSK: - return (sm->proto == WPA_PROTO_RSN ? - RSN_AUTH_KEY_MGMT_PSK_OVER_802_1X : - WPA_AUTH_KEY_MGMT_PSK_OVER_802_1X); -#ifdef CONFIG_IEEE80211R - case WPA_KEY_MGMT_FT_IEEE8021X: - return RSN_AUTH_KEY_MGMT_FT_802_1X; - case WPA_KEY_MGMT_FT_PSK: - return RSN_AUTH_KEY_MGMT_FT_PSK; -#endif /* CONFIG_IEEE80211R */ -#ifdef CONFIG_IEEE80211W - case WPA_KEY_MGMT_IEEE8021X_SHA256: - return RSN_AUTH_KEY_MGMT_802_1X_SHA256; - case WPA_KEY_MGMT_PSK_SHA256: - return RSN_AUTH_KEY_MGMT_PSK_SHA256; -#endif /* CONFIG_IEEE80211W */ - case WPA_KEY_MGMT_WPA_NONE: - return WPA_AUTH_KEY_MGMT_NONE; - default: - return 0; - } -} - - -static u32 wpa_cipher_suite(struct wpa_sm *sm, int cipher) -{ - switch (cipher) { - case WPA_CIPHER_CCMP: - return (sm->proto == WPA_PROTO_RSN ? - RSN_CIPHER_SUITE_CCMP : WPA_CIPHER_SUITE_CCMP); - case WPA_CIPHER_TKIP: - return (sm->proto == WPA_PROTO_RSN ? - RSN_CIPHER_SUITE_TKIP : WPA_CIPHER_SUITE_TKIP); - case WPA_CIPHER_WEP104: - return (sm->proto == WPA_PROTO_RSN ? - RSN_CIPHER_SUITE_WEP104 : WPA_CIPHER_SUITE_WEP104); - case WPA_CIPHER_WEP40: - return (sm->proto == WPA_PROTO_RSN ? - RSN_CIPHER_SUITE_WEP40 : WPA_CIPHER_SUITE_WEP40); - case WPA_CIPHER_NONE: - return (sm->proto == WPA_PROTO_RSN ? - RSN_CIPHER_SUITE_NONE : WPA_CIPHER_SUITE_NONE); - default: - return 0; - } -} - - -#define RSN_SUITE "%02x-%02x-%02x-%d" -#define RSN_SUITE_ARG(s) \ -((s) >> 24) & 0xff, ((s) >> 16) & 0xff, ((s) >> 8) & 0xff, (s) & 0xff - -/** - * wpa_sm_get_mib - Dump text list of MIB entries - * @sm: Pointer to WPA state machine data from wpa_sm_init() - * @buf: Buffer for the list - * @buflen: Length of the buffer - * Returns: Number of bytes written to buffer - * - * This function is used fetch dot11 MIB variables. - */ -int wpa_sm_get_mib(struct wpa_sm *sm, char *buf, size_t buflen) -{ - char pmkid_txt[PMKID_LEN * 2 + 1]; - int rsna, ret; - size_t len; - - if (sm->cur_pmksa) { - wpa_snprintf_hex(pmkid_txt, sizeof(pmkid_txt), - sm->cur_pmksa->pmkid, PMKID_LEN); - } else - pmkid_txt[0] = '\0'; - - if ((wpa_key_mgmt_wpa_psk(sm->key_mgmt) || - wpa_key_mgmt_wpa_ieee8021x(sm->key_mgmt)) && - sm->proto == WPA_PROTO_RSN) - rsna = 1; - else - rsna = 0; - - ret = os_snprintf(buf, buflen, - "dot11RSNAOptionImplemented=TRUE\n" - "dot11RSNAPreauthenticationImplemented=TRUE\n" - "dot11RSNAEnabled=%s\n" - "dot11RSNAPreauthenticationEnabled=%s\n" - "dot11RSNAConfigVersion=%d\n" - "dot11RSNAConfigPairwiseKeysSupported=5\n" - "dot11RSNAConfigGroupCipherSize=%d\n" - "dot11RSNAConfigPMKLifetime=%d\n" - "dot11RSNAConfigPMKReauthThreshold=%d\n" - "dot11RSNAConfigNumberOfPTKSAReplayCounters=1\n" - "dot11RSNAConfigSATimeout=%d\n", - rsna ? "TRUE" : "FALSE", - rsna ? "TRUE" : "FALSE", - RSN_VERSION, - wpa_cipher_bits(sm->group_cipher), - sm->dot11RSNAConfigPMKLifetime, - sm->dot11RSNAConfigPMKReauthThreshold, - sm->dot11RSNAConfigSATimeout); - if (ret < 0 || (size_t) ret >= buflen) - return 0; - len = ret; - - ret = os_snprintf( - buf + len, buflen - len, - "dot11RSNAAuthenticationSuiteSelected=" RSN_SUITE "\n" - "dot11RSNAPairwiseCipherSelected=" RSN_SUITE "\n" - "dot11RSNAGroupCipherSelected=" RSN_SUITE "\n" - "dot11RSNAPMKIDUsed=%s\n" - "dot11RSNAAuthenticationSuiteRequested=" RSN_SUITE "\n" - "dot11RSNAPairwiseCipherRequested=" RSN_SUITE "\n" - "dot11RSNAGroupCipherRequested=" RSN_SUITE "\n" - "dot11RSNAConfigNumberOfGTKSAReplayCounters=0\n" - "dot11RSNA4WayHandshakeFailures=%u\n", - RSN_SUITE_ARG(wpa_key_mgmt_suite(sm)), - RSN_SUITE_ARG(wpa_cipher_suite(sm, sm->pairwise_cipher)), - RSN_SUITE_ARG(wpa_cipher_suite(sm, sm->group_cipher)), - pmkid_txt, - RSN_SUITE_ARG(wpa_key_mgmt_suite(sm)), - RSN_SUITE_ARG(wpa_cipher_suite(sm, sm->pairwise_cipher)), - RSN_SUITE_ARG(wpa_cipher_suite(sm, sm->group_cipher)), - sm->dot11RSNA4WayHandshakeFailures); - if (ret >= 0 && (size_t) ret < buflen) - len += ret; - - return (int) len; -} -#endif /* CONFIG_CTRL_IFACE */ - - -static void wpa_sm_pmksa_free_cb(struct rsn_pmksa_cache_entry *entry, - void *ctx, int replace) -{ - struct wpa_sm *sm = ctx; - - if (sm->cur_pmksa == entry || - (sm->pmk_len == entry->pmk_len && - os_memcmp(sm->pmk, entry->pmk, sm->pmk_len) == 0)) { - wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG, - "RSN: removed current PMKSA entry"); - sm->cur_pmksa = NULL; - - if (replace) { - /* A new entry is being added, so no need to - * deauthenticate in this case. This happens when EAP - * authentication is completed again (reauth or failed - * PMKSA caching attempt). */ - return; - } - - os_memset(sm->pmk, 0, sizeof(sm->pmk)); - wpa_sm_deauthenticate(sm, WLAN_REASON_UNSPECIFIED); - } -} - - -/** - * wpa_sm_init - Initialize WPA state machine - * @ctx: Context pointer for callbacks; this needs to be an allocated buffer - * Returns: Pointer to the allocated WPA state machine data - * - * This function is used to allocate a new WPA state machine and the returned - * value is passed to all WPA state machine calls. - */ -struct wpa_sm * wpa_sm_init(struct wpa_sm_ctx *ctx) -{ - struct wpa_sm *sm; - - sm = os_zalloc(sizeof(*sm)); - if (sm == NULL) - return NULL; - dl_list_init(&sm->pmksa_candidates); - sm->renew_snonce = 1; - sm->ctx = ctx; - - sm->dot11RSNAConfigPMKLifetime = 43200; - sm->dot11RSNAConfigPMKReauthThreshold = 70; - sm->dot11RSNAConfigSATimeout = 60; - - sm->pmksa = pmksa_cache_init(wpa_sm_pmksa_free_cb, sm, sm); - if (sm->pmksa == NULL) { - wpa_msg(sm->ctx->msg_ctx, MSG_ERROR, - "RSN: PMKSA cache initialization failed"); - os_free(sm); - return NULL; - } - - return sm; -} - - -/** - * wpa_sm_deinit - Deinitialize WPA state machine - * @sm: Pointer to WPA state machine data from wpa_sm_init() - */ -void wpa_sm_deinit(struct wpa_sm *sm) -{ - if (sm == NULL) - return; - pmksa_cache_deinit(sm->pmksa); - eloop_cancel_timeout(wpa_sm_start_preauth, sm, NULL); - eloop_cancel_timeout(wpa_sm_rekey_ptk, sm, NULL); - os_free(sm->assoc_wpa_ie); - os_free(sm->ap_wpa_ie); - os_free(sm->ap_rsn_ie); - os_free(sm->ctx); - peerkey_deinit(sm); -#ifdef CONFIG_IEEE80211R - os_free(sm->assoc_resp_ies); -#endif /* CONFIG_IEEE80211R */ - os_free(sm); -} - - -/** - * wpa_sm_notify_assoc - Notify WPA state machine about association - * @sm: Pointer to WPA state machine data from wpa_sm_init() - * @bssid: The BSSID of the new association - * - * This function is called to let WPA state machine know that the connection - * was established. - */ -void wpa_sm_notify_assoc(struct wpa_sm *sm, const u8 *bssid) -{ - int clear_ptk = 1; - - if (sm == NULL) - return; - - wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG, - "WPA: Association event - clear replay counter"); - os_memcpy(sm->bssid, bssid, ETH_ALEN); - os_memset(sm->rx_replay_counter, 0, WPA_REPLAY_COUNTER_LEN); - sm->rx_replay_counter_set = 0; - sm->renew_snonce = 1; - if (os_memcmp(sm->preauth_bssid, bssid, ETH_ALEN) == 0) - rsn_preauth_deinit(sm); - -#ifdef CONFIG_IEEE80211R - if (wpa_ft_is_completed(sm)) { - /* - * Clear portValid to kick EAPOL state machine to re-enter - * AUTHENTICATED state to get the EAPOL port Authorized. - */ - eapol_sm_notify_portValid(sm->eapol, FALSE); - wpa_supplicant_key_neg_complete(sm, sm->bssid, 1); - - /* Prepare for the next transition */ - wpa_ft_prepare_auth_request(sm, NULL); - - clear_ptk = 0; - } -#endif /* CONFIG_IEEE80211R */ - - if (clear_ptk) { - /* - * IEEE 802.11, 8.4.10: Delete PTK SA on (re)association if - * this is not part of a Fast BSS Transition. - */ - wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG, "WPA: Clear old PTK"); - sm->ptk_set = 0; - sm->tptk_set = 0; - } - -#ifdef CONFIG_TDLS - wpa_tdls_assoc(sm); -#endif /* CONFIG_TDLS */ -} - - -/** - * wpa_sm_notify_disassoc - Notify WPA state machine about disassociation - * @sm: Pointer to WPA state machine data from wpa_sm_init() - * - * This function is called to let WPA state machine know that the connection - * was lost. This will abort any existing pre-authentication session. - */ -void wpa_sm_notify_disassoc(struct wpa_sm *sm) -{ - rsn_preauth_deinit(sm); - if (wpa_sm_get_state(sm) == WPA_4WAY_HANDSHAKE) - sm->dot11RSNA4WayHandshakeFailures++; -#ifdef CONFIG_TDLS - wpa_tdls_disassoc(sm); -#endif /* CONFIG_TDLS */ -} - - -/** - * wpa_sm_set_pmk - Set PMK - * @sm: Pointer to WPA state machine data from wpa_sm_init() - * @pmk: The new PMK - * @pmk_len: The length of the new PMK in bytes - * - * Configure the PMK for WPA state machine. - */ -void wpa_sm_set_pmk(struct wpa_sm *sm, const u8 *pmk, size_t pmk_len) -{ - if (sm == NULL) - return; - - sm->pmk_len = pmk_len; - os_memcpy(sm->pmk, pmk, pmk_len); - -#ifdef CONFIG_IEEE80211R - /* Set XXKey to be PSK for FT key derivation */ - sm->xxkey_len = pmk_len; - os_memcpy(sm->xxkey, pmk, pmk_len); -#endif /* CONFIG_IEEE80211R */ -} - - -/** - * wpa_sm_set_pmk_from_pmksa - Set PMK based on the current PMKSA - * @sm: Pointer to WPA state machine data from wpa_sm_init() - * - * Take the PMK from the current PMKSA into use. If no PMKSA is active, the PMK - * will be cleared. - */ -void wpa_sm_set_pmk_from_pmksa(struct wpa_sm *sm) -{ - if (sm == NULL) - return; - - if (sm->cur_pmksa) { - sm->pmk_len = sm->cur_pmksa->pmk_len; - os_memcpy(sm->pmk, sm->cur_pmksa->pmk, sm->pmk_len); - } else { - sm->pmk_len = PMK_LEN; - os_memset(sm->pmk, 0, PMK_LEN); - } -} - - -/** - * wpa_sm_set_fast_reauth - Set fast reauthentication (EAP) enabled/disabled - * @sm: Pointer to WPA state machine data from wpa_sm_init() - * @fast_reauth: Whether fast reauthentication (EAP) is allowed - */ -void wpa_sm_set_fast_reauth(struct wpa_sm *sm, int fast_reauth) -{ - if (sm) - sm->fast_reauth = fast_reauth; -} - - -/** - * wpa_sm_set_scard_ctx - Set context pointer for smartcard callbacks - * @sm: Pointer to WPA state machine data from wpa_sm_init() - * @scard_ctx: Context pointer for smartcard related callback functions - */ -void wpa_sm_set_scard_ctx(struct wpa_sm *sm, void *scard_ctx) -{ - if (sm == NULL) - return; - sm->scard_ctx = scard_ctx; - if (sm->preauth_eapol) - eapol_sm_register_scard_ctx(sm->preauth_eapol, scard_ctx); -} - - -/** - * wpa_sm_set_config - Notification of current configration change - * @sm: Pointer to WPA state machine data from wpa_sm_init() - * @config: Pointer to current network configuration - * - * Notify WPA state machine that configuration has changed. config will be - * stored as a backpointer to network configuration. This can be %NULL to clear - * the stored pointed. - */ -void wpa_sm_set_config(struct wpa_sm *sm, struct rsn_supp_config *config) -{ - if (!sm) - return; - - if (config) { - sm->network_ctx = config->network_ctx; - sm->peerkey_enabled = config->peerkey_enabled; - sm->allowed_pairwise_cipher = config->allowed_pairwise_cipher; - sm->proactive_key_caching = config->proactive_key_caching; - sm->eap_workaround = config->eap_workaround; - sm->eap_conf_ctx = config->eap_conf_ctx; - if (config->ssid) { - os_memcpy(sm->ssid, config->ssid, config->ssid_len); - sm->ssid_len = config->ssid_len; - } else - sm->ssid_len = 0; - sm->wpa_ptk_rekey = config->wpa_ptk_rekey; - } else { - sm->network_ctx = NULL; - sm->peerkey_enabled = 0; - sm->allowed_pairwise_cipher = 0; - sm->proactive_key_caching = 0; - sm->eap_workaround = 0; - sm->eap_conf_ctx = NULL; - sm->ssid_len = 0; - sm->wpa_ptk_rekey = 0; - } - if (config == NULL || config->network_ctx != sm->network_ctx) - pmksa_cache_notify_reconfig(sm->pmksa); -} - - -/** - * wpa_sm_set_own_addr - Set own MAC address - * @sm: Pointer to WPA state machine data from wpa_sm_init() - * @addr: Own MAC address - */ -void wpa_sm_set_own_addr(struct wpa_sm *sm, const u8 *addr) -{ - if (sm) - os_memcpy(sm->own_addr, addr, ETH_ALEN); -} - - -/** - * wpa_sm_set_ifname - Set network interface name - * @sm: Pointer to WPA state machine data from wpa_sm_init() - * @ifname: Interface name - * @bridge_ifname: Optional bridge interface name (for pre-auth) - */ -void wpa_sm_set_ifname(struct wpa_sm *sm, const char *ifname, - const char *bridge_ifname) -{ - if (sm) { - sm->ifname = ifname; - sm->bridge_ifname = bridge_ifname; - } -} - - -/** - * wpa_sm_set_eapol - Set EAPOL state machine pointer - * @sm: Pointer to WPA state machine data from wpa_sm_init() - * @eapol: Pointer to EAPOL state machine allocated with eapol_sm_init() - */ -void wpa_sm_set_eapol(struct wpa_sm *sm, struct eapol_sm *eapol) -{ - if (sm) - sm->eapol = eapol; -} - - -/** - * wpa_sm_set_param - Set WPA state machine parameters - * @sm: Pointer to WPA state machine data from wpa_sm_init() - * @param: Parameter field - * @value: Parameter value - * Returns: 0 on success, -1 on failure - */ -int wpa_sm_set_param(struct wpa_sm *sm, enum wpa_sm_conf_params param, - unsigned int value) -{ - int ret = 0; - - if (sm == NULL) - return -1; - - switch (param) { - case RSNA_PMK_LIFETIME: - if (value > 0) - sm->dot11RSNAConfigPMKLifetime = value; - else - ret = -1; - break; - case RSNA_PMK_REAUTH_THRESHOLD: - if (value > 0 && value <= 100) - sm->dot11RSNAConfigPMKReauthThreshold = value; - else - ret = -1; - break; - case RSNA_SA_TIMEOUT: - if (value > 0) - sm->dot11RSNAConfigSATimeout = value; - else - ret = -1; - break; - case WPA_PARAM_PROTO: - sm->proto = value; - break; - case WPA_PARAM_PAIRWISE: - sm->pairwise_cipher = value; - break; - case WPA_PARAM_GROUP: - sm->group_cipher = value; - break; - case WPA_PARAM_KEY_MGMT: - sm->key_mgmt = value; - break; -#ifdef CONFIG_IEEE80211W - case WPA_PARAM_MGMT_GROUP: - sm->mgmt_group_cipher = value; - break; -#endif /* CONFIG_IEEE80211W */ - case WPA_PARAM_RSN_ENABLED: - sm->rsn_enabled = value; - break; - case WPA_PARAM_MFP: - sm->mfp = value; - break; - default: - break; - } - - return ret; -} - - -/** - * wpa_sm_get_param - Get WPA state machine parameters - * @sm: Pointer to WPA state machine data from wpa_sm_init() - * @param: Parameter field - * Returns: Parameter value - */ -unsigned int wpa_sm_get_param(struct wpa_sm *sm, enum wpa_sm_conf_params param) -{ - if (sm == NULL) - return 0; - - switch (param) { - case RSNA_PMK_LIFETIME: - return sm->dot11RSNAConfigPMKLifetime; - case RSNA_PMK_REAUTH_THRESHOLD: - return sm->dot11RSNAConfigPMKReauthThreshold; - case RSNA_SA_TIMEOUT: - return sm->dot11RSNAConfigSATimeout; - case WPA_PARAM_PROTO: - return sm->proto; - case WPA_PARAM_PAIRWISE: - return sm->pairwise_cipher; - case WPA_PARAM_GROUP: - return sm->group_cipher; - case WPA_PARAM_KEY_MGMT: - return sm->key_mgmt; -#ifdef CONFIG_IEEE80211W - case WPA_PARAM_MGMT_GROUP: - return sm->mgmt_group_cipher; -#endif /* CONFIG_IEEE80211W */ - case WPA_PARAM_RSN_ENABLED: - return sm->rsn_enabled; - default: - return 0; - } -} - - -/** - * wpa_sm_get_status - Get WPA state machine - * @sm: Pointer to WPA state machine data from wpa_sm_init() - * @buf: Buffer for status information - * @buflen: Maximum buffer length - * @verbose: Whether to include verbose status information - * Returns: Number of bytes written to buf. - * - * Query WPA state machine for status information. This function fills in - * a text area with current status information. If the buffer (buf) is not - * large enough, status information will be truncated to fit the buffer. - */ -int wpa_sm_get_status(struct wpa_sm *sm, char *buf, size_t buflen, - int verbose) -{ - char *pos = buf, *end = buf + buflen; - int ret; - - ret = os_snprintf(pos, end - pos, - "pairwise_cipher=%s\n" - "group_cipher=%s\n" - "key_mgmt=%s\n", - wpa_cipher_txt(sm->pairwise_cipher), - wpa_cipher_txt(sm->group_cipher), - wpa_key_mgmt_txt(sm->key_mgmt, sm->proto)); - if (ret < 0 || ret >= end - pos) - return pos - buf; - pos += ret; - return pos - buf; -} - - -/** - * wpa_sm_set_assoc_wpa_ie_default - Generate own WPA/RSN IE from configuration - * @sm: Pointer to WPA state machine data from wpa_sm_init() - * @wpa_ie: Pointer to buffer for WPA/RSN IE - * @wpa_ie_len: Pointer to the length of the wpa_ie buffer - * Returns: 0 on success, -1 on failure - */ -int wpa_sm_set_assoc_wpa_ie_default(struct wpa_sm *sm, u8 *wpa_ie, - size_t *wpa_ie_len) -{ - int res; - - if (sm == NULL) - return -1; - - res = wpa_gen_wpa_ie(sm, wpa_ie, *wpa_ie_len); - if (res < 0) - return -1; - *wpa_ie_len = res; - - wpa_hexdump(MSG_DEBUG, "WPA: Set own WPA IE default", - wpa_ie, *wpa_ie_len); - - if (sm->assoc_wpa_ie == NULL) { - /* - * Make a copy of the WPA/RSN IE so that 4-Way Handshake gets - * the correct version of the IE even if PMKSA caching is - * aborted (which would remove PMKID from IE generation). - */ - sm->assoc_wpa_ie = os_malloc(*wpa_ie_len); - if (sm->assoc_wpa_ie == NULL) - return -1; - - os_memcpy(sm->assoc_wpa_ie, wpa_ie, *wpa_ie_len); - sm->assoc_wpa_ie_len = *wpa_ie_len; - } - - return 0; -} - - -/** - * wpa_sm_set_assoc_wpa_ie - Set own WPA/RSN IE from (Re)AssocReq - * @sm: Pointer to WPA state machine data from wpa_sm_init() - * @ie: Pointer to IE data (starting from id) - * @len: IE length - * Returns: 0 on success, -1 on failure - * - * Inform WPA state machine about the WPA/RSN IE used in (Re)Association - * Request frame. The IE will be used to override the default value generated - * with wpa_sm_set_assoc_wpa_ie_default(). - */ -int wpa_sm_set_assoc_wpa_ie(struct wpa_sm *sm, const u8 *ie, size_t len) -{ - if (sm == NULL) - return -1; - - os_free(sm->assoc_wpa_ie); - if (ie == NULL || len == 0) { - wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG, - "WPA: clearing own WPA/RSN IE"); - sm->assoc_wpa_ie = NULL; - sm->assoc_wpa_ie_len = 0; - } else { - wpa_hexdump(MSG_DEBUG, "WPA: set own WPA/RSN IE", ie, len); - sm->assoc_wpa_ie = os_malloc(len); - if (sm->assoc_wpa_ie == NULL) - return -1; - - os_memcpy(sm->assoc_wpa_ie, ie, len); - sm->assoc_wpa_ie_len = len; - } - - return 0; -} - - -/** - * wpa_sm_set_ap_wpa_ie - Set AP WPA IE from Beacon/ProbeResp - * @sm: Pointer to WPA state machine data from wpa_sm_init() - * @ie: Pointer to IE data (starting from id) - * @len: IE length - * Returns: 0 on success, -1 on failure - * - * Inform WPA state machine about the WPA IE used in Beacon / Probe Response - * frame. - */ -int wpa_sm_set_ap_wpa_ie(struct wpa_sm *sm, const u8 *ie, size_t len) -{ - if (sm == NULL) - return -1; - - os_free(sm->ap_wpa_ie); - if (ie == NULL || len == 0) { - wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG, - "WPA: clearing AP WPA IE"); - sm->ap_wpa_ie = NULL; - sm->ap_wpa_ie_len = 0; - } else { - wpa_hexdump(MSG_DEBUG, "WPA: set AP WPA IE", ie, len); - sm->ap_wpa_ie = os_malloc(len); - if (sm->ap_wpa_ie == NULL) - return -1; - - os_memcpy(sm->ap_wpa_ie, ie, len); - sm->ap_wpa_ie_len = len; - } - - return 0; -} - - -/** - * wpa_sm_set_ap_rsn_ie - Set AP RSN IE from Beacon/ProbeResp - * @sm: Pointer to WPA state machine data from wpa_sm_init() - * @ie: Pointer to IE data (starting from id) - * @len: IE length - * Returns: 0 on success, -1 on failure - * - * Inform WPA state machine about the RSN IE used in Beacon / Probe Response - * frame. - */ -int wpa_sm_set_ap_rsn_ie(struct wpa_sm *sm, const u8 *ie, size_t len) -{ - if (sm == NULL) - return -1; - - os_free(sm->ap_rsn_ie); - if (ie == NULL || len == 0) { - wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG, - "WPA: clearing AP RSN IE"); - sm->ap_rsn_ie = NULL; - sm->ap_rsn_ie_len = 0; - } else { - wpa_hexdump(MSG_DEBUG, "WPA: set AP RSN IE", ie, len); - sm->ap_rsn_ie = os_malloc(len); - if (sm->ap_rsn_ie == NULL) - return -1; - - os_memcpy(sm->ap_rsn_ie, ie, len); - sm->ap_rsn_ie_len = len; - } - - return 0; -} - - -/** - * wpa_sm_parse_own_wpa_ie - Parse own WPA/RSN IE - * @sm: Pointer to WPA state machine data from wpa_sm_init() - * @data: Pointer to data area for parsing results - * Returns: 0 on success, -1 if IE is not known, or -2 on parsing failure - * - * Parse the contents of the own WPA or RSN IE from (Re)AssocReq and write the - * parsed data into data. - */ -int wpa_sm_parse_own_wpa_ie(struct wpa_sm *sm, struct wpa_ie_data *data) -{ - if (sm == NULL) - return -1; - - if (sm->assoc_wpa_ie == NULL) { - wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG, - "WPA: No WPA/RSN IE available from association info"); - return -1; - } - if (wpa_parse_wpa_ie(sm->assoc_wpa_ie, sm->assoc_wpa_ie_len, data)) - return -2; - return 0; -} - - -int wpa_sm_pmksa_cache_list(struct wpa_sm *sm, char *buf, size_t len) -{ -#ifndef CONFIG_NO_WPA2 - return pmksa_cache_list(sm->pmksa, buf, len); -#else /* CONFIG_NO_WPA2 */ - return -1; -#endif /* CONFIG_NO_WPA2 */ -} - - -void wpa_sm_drop_sa(struct wpa_sm *sm) -{ - wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG, "WPA: Clear old PMK and PTK"); - sm->ptk_set = 0; - sm->tptk_set = 0; - os_memset(sm->pmk, 0, sizeof(sm->pmk)); - os_memset(&sm->ptk, 0, sizeof(sm->ptk)); - os_memset(&sm->tptk, 0, sizeof(sm->tptk)); -} - - -int wpa_sm_has_ptk(struct wpa_sm *sm) -{ - if (sm == NULL) - return 0; - return sm->ptk_set; -} diff --git a/hostapd-0.8/src/rsn_supp/wpa.h b/hostapd-0.8/src/rsn_supp/wpa.h deleted file mode 100644 index 111597c..0000000 --- a/hostapd-0.8/src/rsn_supp/wpa.h +++ /dev/null @@ -1,351 +0,0 @@ -/* - * wpa_supplicant - WPA definitions - * Copyright (c) 2003-2007, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#ifndef WPA_H -#define WPA_H - -#include "common/defs.h" -#include "common/eapol_common.h" -#include "common/wpa_common.h" - -struct wpa_sm; -struct eapol_sm; -struct wpa_config_blob; - -struct wpa_sm_ctx { - void *ctx; /* pointer to arbitrary upper level context */ - void *msg_ctx; /* upper level context for wpa_msg() calls */ - - void (*set_state)(void *ctx, enum wpa_states state); - enum wpa_states (*get_state)(void *ctx); - void (*deauthenticate)(void * ctx, int reason_code); - void (*disassociate)(void *ctx, int reason_code); - int (*set_key)(void *ctx, enum wpa_alg alg, - const u8 *addr, int key_idx, int set_tx, - const u8 *seq, size_t seq_len, - const u8 *key, size_t key_len); - void * (*get_network_ctx)(void *ctx); - int (*get_bssid)(void *ctx, u8 *bssid); - int (*ether_send)(void *ctx, const u8 *dest, u16 proto, const u8 *buf, - size_t len); - int (*get_beacon_ie)(void *ctx); - void (*cancel_auth_timeout)(void *ctx); - u8 * (*alloc_eapol)(void *ctx, u8 type, const void *data, u16 data_len, - size_t *msg_len, void **data_pos); - int (*add_pmkid)(void *ctx, const u8 *bssid, const u8 *pmkid); - int (*remove_pmkid)(void *ctx, const u8 *bssid, const u8 *pmkid); - void (*set_config_blob)(void *ctx, struct wpa_config_blob *blob); - const struct wpa_config_blob * (*get_config_blob)(void *ctx, - const char *name); - int (*mlme_setprotection)(void *ctx, const u8 *addr, - int protection_type, int key_type); - int (*update_ft_ies)(void *ctx, const u8 *md, const u8 *ies, - size_t ies_len); - int (*send_ft_action)(void *ctx, u8 action, const u8 *target_ap, - const u8 *ies, size_t ies_len); - int (*mark_authenticated)(void *ctx, const u8 *target_ap); -#ifdef CONFIG_TDLS - int (*send_tdls_mgmt)(void *ctx, const u8 *dst, - u8 action_code, u8 dialog_token, - u16 status_code, const u8 *buf, size_t len); - int (*tdls_oper)(void *ctx, int oper, const u8 *peer); -#endif /* CONFIG_TDLS */ -}; - - -enum wpa_sm_conf_params { - RSNA_PMK_LIFETIME /* dot11RSNAConfigPMKLifetime */, - RSNA_PMK_REAUTH_THRESHOLD /* dot11RSNAConfigPMKReauthThreshold */, - RSNA_SA_TIMEOUT /* dot11RSNAConfigSATimeout */, - WPA_PARAM_PROTO, - WPA_PARAM_PAIRWISE, - WPA_PARAM_GROUP, - WPA_PARAM_KEY_MGMT, - WPA_PARAM_MGMT_GROUP, - WPA_PARAM_RSN_ENABLED, - WPA_PARAM_MFP -}; - -struct rsn_supp_config { - void *network_ctx; - int peerkey_enabled; - int allowed_pairwise_cipher; /* bitfield of WPA_CIPHER_* */ - int proactive_key_caching; - int eap_workaround; - void *eap_conf_ctx; - const u8 *ssid; - size_t ssid_len; - int wpa_ptk_rekey; -}; - -#ifndef CONFIG_NO_WPA - -struct wpa_sm * wpa_sm_init(struct wpa_sm_ctx *ctx); -void wpa_sm_deinit(struct wpa_sm *sm); -void wpa_sm_notify_assoc(struct wpa_sm *sm, const u8 *bssid); -void wpa_sm_notify_disassoc(struct wpa_sm *sm); -void wpa_sm_set_pmk(struct wpa_sm *sm, const u8 *pmk, size_t pmk_len); -void wpa_sm_set_pmk_from_pmksa(struct wpa_sm *sm); -void wpa_sm_set_fast_reauth(struct wpa_sm *sm, int fast_reauth); -void wpa_sm_set_scard_ctx(struct wpa_sm *sm, void *scard_ctx); -void wpa_sm_set_config(struct wpa_sm *sm, struct rsn_supp_config *config); -void wpa_sm_set_own_addr(struct wpa_sm *sm, const u8 *addr); -void wpa_sm_set_ifname(struct wpa_sm *sm, const char *ifname, - const char *bridge_ifname); -void wpa_sm_set_eapol(struct wpa_sm *sm, struct eapol_sm *eapol); -int wpa_sm_set_assoc_wpa_ie(struct wpa_sm *sm, const u8 *ie, size_t len); -int wpa_sm_set_assoc_wpa_ie_default(struct wpa_sm *sm, u8 *wpa_ie, - size_t *wpa_ie_len); -int wpa_sm_set_ap_wpa_ie(struct wpa_sm *sm, const u8 *ie, size_t len); -int wpa_sm_set_ap_rsn_ie(struct wpa_sm *sm, const u8 *ie, size_t len); -int wpa_sm_get_mib(struct wpa_sm *sm, char *buf, size_t buflen); - -int wpa_sm_set_param(struct wpa_sm *sm, enum wpa_sm_conf_params param, - unsigned int value); -unsigned int wpa_sm_get_param(struct wpa_sm *sm, - enum wpa_sm_conf_params param); - -int wpa_sm_get_status(struct wpa_sm *sm, char *buf, size_t buflen, - int verbose); - -void wpa_sm_key_request(struct wpa_sm *sm, int error, int pairwise); - -int wpa_parse_wpa_ie(const u8 *wpa_ie, size_t wpa_ie_len, - struct wpa_ie_data *data); - -void wpa_sm_aborted_cached(struct wpa_sm *sm); -int wpa_sm_rx_eapol(struct wpa_sm *sm, const u8 *src_addr, - const u8 *buf, size_t len); -int wpa_sm_parse_own_wpa_ie(struct wpa_sm *sm, struct wpa_ie_data *data); -int wpa_sm_pmksa_cache_list(struct wpa_sm *sm, char *buf, size_t len); -void wpa_sm_drop_sa(struct wpa_sm *sm); -int wpa_sm_has_ptk(struct wpa_sm *sm); - -#else /* CONFIG_NO_WPA */ - -static inline struct wpa_sm * wpa_sm_init(struct wpa_sm_ctx *ctx) -{ - return (struct wpa_sm *) 1; -} - -static inline void wpa_sm_deinit(struct wpa_sm *sm) -{ -} - -static inline void wpa_sm_notify_assoc(struct wpa_sm *sm, const u8 *bssid) -{ -} - -static inline void wpa_sm_notify_disassoc(struct wpa_sm *sm) -{ -} - -static inline void wpa_sm_set_pmk(struct wpa_sm *sm, const u8 *pmk, - size_t pmk_len) -{ -} - -static inline void wpa_sm_set_pmk_from_pmksa(struct wpa_sm *sm) -{ -} - -static inline void wpa_sm_set_fast_reauth(struct wpa_sm *sm, int fast_reauth) -{ -} - -static inline void wpa_sm_set_scard_ctx(struct wpa_sm *sm, void *scard_ctx) -{ -} - -static inline void wpa_sm_set_config(struct wpa_sm *sm, - struct rsn_supp_config *config) -{ -} - -static inline void wpa_sm_set_own_addr(struct wpa_sm *sm, const u8 *addr) -{ -} - -static inline void wpa_sm_set_ifname(struct wpa_sm *sm, const char *ifname, - const char *bridge_ifname) -{ -} - -static inline void wpa_sm_set_eapol(struct wpa_sm *sm, struct eapol_sm *eapol) -{ -} - -static inline int wpa_sm_set_assoc_wpa_ie(struct wpa_sm *sm, const u8 *ie, - size_t len) -{ - return -1; -} - -static inline int wpa_sm_set_assoc_wpa_ie_default(struct wpa_sm *sm, - u8 *wpa_ie, - size_t *wpa_ie_len) -{ - return -1; -} - -static inline int wpa_sm_set_ap_wpa_ie(struct wpa_sm *sm, const u8 *ie, - size_t len) -{ - return -1; -} - -static inline int wpa_sm_set_ap_rsn_ie(struct wpa_sm *sm, const u8 *ie, - size_t len) -{ - return -1; -} - -static inline int wpa_sm_get_mib(struct wpa_sm *sm, char *buf, size_t buflen) -{ - return 0; -} - -static inline int wpa_sm_set_param(struct wpa_sm *sm, - enum wpa_sm_conf_params param, - unsigned int value) -{ - return -1; -} - -static inline unsigned int wpa_sm_get_param(struct wpa_sm *sm, - enum wpa_sm_conf_params param) -{ - return 0; -} - -static inline int wpa_sm_get_status(struct wpa_sm *sm, char *buf, - size_t buflen, int verbose) -{ - return 0; -} - -static inline void wpa_sm_key_request(struct wpa_sm *sm, int error, - int pairwise) -{ -} - -static inline int wpa_parse_wpa_ie(const u8 *wpa_ie, size_t wpa_ie_len, - struct wpa_ie_data *data) -{ - return -1; -} - -static inline void wpa_sm_aborted_cached(struct wpa_sm *sm) -{ -} - -static inline int wpa_sm_rx_eapol(struct wpa_sm *sm, const u8 *src_addr, - const u8 *buf, size_t len) -{ - return -1; -} - -static inline int wpa_sm_parse_own_wpa_ie(struct wpa_sm *sm, - struct wpa_ie_data *data) -{ - return -1; -} - -static inline int wpa_sm_pmksa_cache_list(struct wpa_sm *sm, char *buf, - size_t len) -{ - return -1; -} - -static inline void wpa_sm_drop_sa(struct wpa_sm *sm) -{ -} - -static inline int wpa_sm_has_ptk(struct wpa_sm *sm) -{ - return 0; -} - -#endif /* CONFIG_NO_WPA */ - -#ifdef CONFIG_PEERKEY -int wpa_sm_stkstart(struct wpa_sm *sm, const u8 *peer); -#else /* CONFIG_PEERKEY */ -static inline int wpa_sm_stkstart(struct wpa_sm *sm, const u8 *peer) -{ - return -1; -} -#endif /* CONFIG_PEERKEY */ - -#ifdef CONFIG_IEEE80211R - -int wpa_sm_set_ft_params(struct wpa_sm *sm, const u8 *ies, size_t ies_len); -int wpa_ft_prepare_auth_request(struct wpa_sm *sm, const u8 *mdie); -int wpa_ft_process_response(struct wpa_sm *sm, const u8 *ies, size_t ies_len, - int ft_action, const u8 *target_ap, - const u8 *ric_ies, size_t ric_ies_len); -int wpa_ft_is_completed(struct wpa_sm *sm); -int wpa_ft_validate_reassoc_resp(struct wpa_sm *sm, const u8 *ies, - size_t ies_len, const u8 *src_addr); -int wpa_ft_start_over_ds(struct wpa_sm *sm, const u8 *target_ap, - const u8 *mdie); - -#else /* CONFIG_IEEE80211R */ - -static inline int -wpa_sm_set_ft_params(struct wpa_sm *sm, const u8 *ies, size_t ies_len) -{ - return 0; -} - -static inline int wpa_ft_prepare_auth_request(struct wpa_sm *sm, - const u8 *mdie) -{ - return 0; -} - -static inline int -wpa_ft_process_response(struct wpa_sm *sm, const u8 *ies, size_t ies_len, - int ft_action, const u8 *target_ap) -{ - return 0; -} - -static inline int wpa_ft_is_completed(struct wpa_sm *sm) -{ - return 0; -} - -static inline int -wpa_ft_validate_reassoc_resp(struct wpa_sm *sm, const u8 *ies, size_t ies_len, - const u8 *src_addr) -{ - return -1; -} - -#endif /* CONFIG_IEEE80211R */ - - -/* tdls.c */ -void wpa_tdls_ap_ies(struct wpa_sm *sm, const u8 *ies, size_t len); -void wpa_tdls_assoc_resp_ies(struct wpa_sm *sm, const u8 *ies, size_t len); -int wpa_tdls_start(struct wpa_sm *sm, const u8 *addr); -int wpa_tdls_reneg(struct wpa_sm *sm, const u8 *addr); -int wpa_tdls_recv_teardown_notify(struct wpa_sm *sm, const u8 *addr, - u16 reason_code); -int wpa_tdls_init(struct wpa_sm *sm); -void wpa_tdls_deinit(struct wpa_sm *sm); -void wpa_tdls_enable(struct wpa_sm *sm, int enabled); - -#endif /* WPA_H */ diff --git a/hostapd-0.8/src/rsn_supp/wpa_ft.c b/hostapd-0.8/src/rsn_supp/wpa_ft.c deleted file mode 100644 index da6e966..0000000 --- a/hostapd-0.8/src/rsn_supp/wpa_ft.c +++ /dev/null @@ -1,1039 +0,0 @@ -/* - * WPA Supplicant - IEEE 802.11r - Fast BSS Transition - * Copyright (c) 2006-2007, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#include "includes.h" - -#include "common.h" -#include "crypto/aes_wrap.h" -#include "crypto/random.h" -#include "common/ieee802_11_defs.h" -#include "common/ieee802_11_common.h" -#include "wpa.h" -#include "wpa_i.h" -#include "wpa_ie.h" - -#ifdef CONFIG_IEEE80211R - -struct wpa_ft_ies { - const u8 *mdie; - size_t mdie_len; - const u8 *ftie; - size_t ftie_len; - const u8 *r1kh_id; - const u8 *gtk; - size_t gtk_len; - const u8 *r0kh_id; - size_t r0kh_id_len; - const u8 *rsn; - size_t rsn_len; - const u8 *rsn_pmkid; - const u8 *tie; - size_t tie_len; - const u8 *igtk; - size_t igtk_len; - const u8 *ric; - size_t ric_len; -}; - -static int wpa_ft_parse_ies(const u8 *ies, size_t ies_len, - struct wpa_ft_ies *parse); - - -int wpa_derive_ptk_ft(struct wpa_sm *sm, const unsigned char *src_addr, - const struct wpa_eapol_key *key, - struct wpa_ptk *ptk, size_t ptk_len) -{ - u8 ptk_name[WPA_PMK_NAME_LEN]; - const u8 *anonce = key->key_nonce; - - if (sm->xxkey_len == 0) { - wpa_printf(MSG_DEBUG, "FT: XXKey not available for key " - "derivation"); - return -1; - } - - wpa_derive_pmk_r0(sm->xxkey, sm->xxkey_len, sm->ssid, - sm->ssid_len, sm->mobility_domain, - sm->r0kh_id, sm->r0kh_id_len, sm->own_addr, - sm->pmk_r0, sm->pmk_r0_name); - wpa_hexdump_key(MSG_DEBUG, "FT: PMK-R0", sm->pmk_r0, PMK_LEN); - wpa_hexdump(MSG_DEBUG, "FT: PMKR0Name", - sm->pmk_r0_name, WPA_PMK_NAME_LEN); - wpa_derive_pmk_r1(sm->pmk_r0, sm->pmk_r0_name, sm->r1kh_id, - sm->own_addr, sm->pmk_r1, sm->pmk_r1_name); - wpa_hexdump_key(MSG_DEBUG, "FT: PMK-R1", sm->pmk_r1, PMK_LEN); - wpa_hexdump(MSG_DEBUG, "FT: PMKR1Name", sm->pmk_r1_name, - WPA_PMK_NAME_LEN); - wpa_pmk_r1_to_ptk(sm->pmk_r1, sm->snonce, anonce, sm->own_addr, - sm->bssid, sm->pmk_r1_name, - (u8 *) ptk, ptk_len, ptk_name); - wpa_hexdump_key(MSG_DEBUG, "FT: PTK", (u8 *) ptk, ptk_len); - wpa_hexdump(MSG_DEBUG, "FT: PTKName", ptk_name, WPA_PMK_NAME_LEN); - - return 0; -} - - -/** - * wpa_sm_set_ft_params - Set FT (IEEE 802.11r) parameters - * @sm: Pointer to WPA state machine data from wpa_sm_init() - * @ies: Association Response IEs or %NULL to clear FT parameters - * @ies_len: Length of ies buffer in octets - * Returns: 0 on success, -1 on failure - */ -int wpa_sm_set_ft_params(struct wpa_sm *sm, const u8 *ies, size_t ies_len) -{ - struct wpa_ft_ies ft; - - if (sm == NULL) - return 0; - - if (wpa_ft_parse_ies(ies, ies_len, &ft) < 0) - return -1; - - if (ft.mdie && ft.mdie_len < MOBILITY_DOMAIN_ID_LEN + 1) - return -1; - - if (ft.mdie) { - wpa_hexdump(MSG_DEBUG, "FT: Mobility domain", - ft.mdie, MOBILITY_DOMAIN_ID_LEN); - os_memcpy(sm->mobility_domain, ft.mdie, - MOBILITY_DOMAIN_ID_LEN); - sm->mdie_ft_capab = ft.mdie[MOBILITY_DOMAIN_ID_LEN]; - wpa_printf(MSG_DEBUG, "FT: Capability and Policy: 0x%02x", - sm->mdie_ft_capab); - } else - os_memset(sm->mobility_domain, 0, MOBILITY_DOMAIN_ID_LEN); - - if (ft.r0kh_id) { - wpa_hexdump(MSG_DEBUG, "FT: R0KH-ID", - ft.r0kh_id, ft.r0kh_id_len); - os_memcpy(sm->r0kh_id, ft.r0kh_id, ft.r0kh_id_len); - sm->r0kh_id_len = ft.r0kh_id_len; - } else { - /* FIX: When should R0KH-ID be cleared? We need to keep the - * old R0KH-ID in order to be able to use this during FT. */ - /* - * os_memset(sm->r0kh_id, 0, FT_R0KH_ID_LEN); - * sm->r0kh_id_len = 0; - */ - } - - if (ft.r1kh_id) { - wpa_hexdump(MSG_DEBUG, "FT: R1KH-ID", - ft.r1kh_id, FT_R1KH_ID_LEN); - os_memcpy(sm->r1kh_id, ft.r1kh_id, FT_R1KH_ID_LEN); - } else - os_memset(sm->r1kh_id, 0, FT_R1KH_ID_LEN); - - os_free(sm->assoc_resp_ies); - sm->assoc_resp_ies = os_malloc(ft.mdie_len + 2 + ft.ftie_len + 2); - if (sm->assoc_resp_ies) { - u8 *pos = sm->assoc_resp_ies; - if (ft.mdie) { - os_memcpy(pos, ft.mdie - 2, ft.mdie_len + 2); - pos += ft.mdie_len + 2; - } - if (ft.ftie) { - os_memcpy(pos, ft.ftie - 2, ft.ftie_len + 2); - pos += ft.ftie_len + 2; - } - sm->assoc_resp_ies_len = pos - sm->assoc_resp_ies; - wpa_hexdump(MSG_DEBUG, "FT: Stored MDIE and FTIE from " - "(Re)Association Response", - sm->assoc_resp_ies, sm->assoc_resp_ies_len); - } - - return 0; -} - - -/** - * wpa_ft_gen_req_ies - Generate FT (IEEE 802.11r) IEs for Auth/ReAssoc Request - * @sm: Pointer to WPA state machine data from wpa_sm_init() - * @len: Buffer for returning the length of the IEs - * @anonce: ANonce or %NULL if not yet available - * @pmk_name: PMKR0Name or PMKR1Name to be added into the RSN IE PMKID List - * @kck: 128-bit KCK for MIC or %NULL if no MIC is used - * @target_ap: Target AP address - * @ric_ies: Optional IE(s), e.g., WMM TSPEC(s), for RIC-Request or %NULL - * @ric_ies_len: Length of ric_ies buffer in octets - * @ap_mdie: Mobility Domain IE from the target AP - * Returns: Pointer to buffer with IEs or %NULL on failure - * - * Caller is responsible for freeing the returned buffer with os_free(); - */ -static u8 * wpa_ft_gen_req_ies(struct wpa_sm *sm, size_t *len, - const u8 *anonce, const u8 *pmk_name, - const u8 *kck, const u8 *target_ap, - const u8 *ric_ies, size_t ric_ies_len, - const u8 *ap_mdie) -{ - size_t buf_len; - u8 *buf, *pos, *ftie_len, *ftie_pos; - struct rsn_mdie *mdie; - struct rsn_ftie *ftie; - struct rsn_ie_hdr *rsnie; - u16 capab; - - sm->ft_completed = 0; - - buf_len = 2 + sizeof(struct rsn_mdie) + 2 + sizeof(struct rsn_ftie) + - 2 + sm->r0kh_id_len + ric_ies_len + 100; - buf = os_zalloc(buf_len); - if (buf == NULL) - return NULL; - pos = buf; - - /* RSNIE[PMKR0Name/PMKR1Name] */ - rsnie = (struct rsn_ie_hdr *) pos; - rsnie->elem_id = WLAN_EID_RSN; - WPA_PUT_LE16(rsnie->version, RSN_VERSION); - pos = (u8 *) (rsnie + 1); - - /* Group Suite Selector */ - if (sm->group_cipher == WPA_CIPHER_CCMP) - RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_CCMP); - else if (sm->group_cipher == WPA_CIPHER_TKIP) - RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_TKIP); - else { - wpa_printf(MSG_WARNING, "FT: Invalid group cipher (%d)", - sm->group_cipher); - os_free(buf); - return NULL; - } - pos += RSN_SELECTOR_LEN; - - /* Pairwise Suite Count */ - WPA_PUT_LE16(pos, 1); - pos += 2; - - /* Pairwise Suite List */ - if (sm->pairwise_cipher == WPA_CIPHER_CCMP) - RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_CCMP); - else if (sm->pairwise_cipher == WPA_CIPHER_TKIP) - RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_TKIP); - else { - wpa_printf(MSG_WARNING, "FT: Invalid pairwise cipher (%d)", - sm->pairwise_cipher); - os_free(buf); - return NULL; - } - pos += RSN_SELECTOR_LEN; - - /* Authenticated Key Management Suite Count */ - WPA_PUT_LE16(pos, 1); - pos += 2; - - /* Authenticated Key Management Suite List */ - if (sm->key_mgmt == WPA_KEY_MGMT_FT_IEEE8021X) - RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_FT_802_1X); - else if (sm->key_mgmt == WPA_KEY_MGMT_FT_PSK) - RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_FT_PSK); - else { - wpa_printf(MSG_WARNING, "FT: Invalid key management type (%d)", - sm->key_mgmt); - os_free(buf); - return NULL; - } - pos += RSN_SELECTOR_LEN; - - /* RSN Capabilities */ - capab = 0; -#ifdef CONFIG_IEEE80211W - if (sm->mgmt_group_cipher == WPA_CIPHER_AES_128_CMAC) - capab |= WPA_CAPABILITY_MFPC; -#endif /* CONFIG_IEEE80211W */ - WPA_PUT_LE16(pos, capab); - pos += 2; - - /* PMKID Count */ - WPA_PUT_LE16(pos, 1); - pos += 2; - - /* PMKID List [PMKR0Name/PMKR1Name] */ - os_memcpy(pos, pmk_name, WPA_PMK_NAME_LEN); - pos += WPA_PMK_NAME_LEN; - -#ifdef CONFIG_IEEE80211W - if (sm->mgmt_group_cipher == WPA_CIPHER_AES_128_CMAC) { - /* Management Group Cipher Suite */ - RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_AES_128_CMAC); - pos += RSN_SELECTOR_LEN; - } -#endif /* CONFIG_IEEE80211W */ - - rsnie->len = (pos - (u8 *) rsnie) - 2; - - /* MDIE */ - *pos++ = WLAN_EID_MOBILITY_DOMAIN; - *pos++ = sizeof(*mdie); - mdie = (struct rsn_mdie *) pos; - pos += sizeof(*mdie); - os_memcpy(mdie->mobility_domain, sm->mobility_domain, - MOBILITY_DOMAIN_ID_LEN); - mdie->ft_capab = ap_mdie && ap_mdie[1] >= 3 ? ap_mdie[4] : - sm->mdie_ft_capab; - - /* FTIE[SNonce, [R1KH-ID,] R0KH-ID ] */ - ftie_pos = pos; - *pos++ = WLAN_EID_FAST_BSS_TRANSITION; - ftie_len = pos++; - ftie = (struct rsn_ftie *) pos; - pos += sizeof(*ftie); - os_memcpy(ftie->snonce, sm->snonce, WPA_NONCE_LEN); - if (anonce) - os_memcpy(ftie->anonce, anonce, WPA_NONCE_LEN); - if (kck) { - /* R1KH-ID sub-element in third FT message */ - *pos++ = FTIE_SUBELEM_R1KH_ID; - *pos++ = FT_R1KH_ID_LEN; - os_memcpy(pos, sm->r1kh_id, FT_R1KH_ID_LEN); - pos += FT_R1KH_ID_LEN; - } - /* R0KH-ID sub-element */ - *pos++ = FTIE_SUBELEM_R0KH_ID; - *pos++ = sm->r0kh_id_len; - os_memcpy(pos, sm->r0kh_id, sm->r0kh_id_len); - pos += sm->r0kh_id_len; - *ftie_len = pos - ftie_len - 1; - - if (ric_ies) { - /* RIC Request */ - os_memcpy(pos, ric_ies, ric_ies_len); - pos += ric_ies_len; - } - - if (kck) { - /* - * IEEE Std 802.11r-2008, 11A.8.4 - * MIC shall be calculated over: - * non-AP STA MAC address - * Target AP MAC address - * Transaction seq number (5 for ReassocReq, 3 otherwise) - * RSN IE - * MDIE - * FTIE (with MIC field set to 0) - * RIC-Request (if present) - */ - /* Information element count */ - ftie->mic_control[1] = 3 + ieee802_11_ie_count(ric_ies, - ric_ies_len); - if (wpa_ft_mic(kck, sm->own_addr, target_ap, 5, - ((u8 *) mdie) - 2, 2 + sizeof(*mdie), - ftie_pos, 2 + *ftie_len, - (u8 *) rsnie, 2 + rsnie->len, ric_ies, - ric_ies_len, ftie->mic) < 0) { - wpa_printf(MSG_INFO, "FT: Failed to calculate MIC"); - os_free(buf); - return NULL; - } - } - - *len = pos - buf; - - return buf; -} - - -static int wpa_ft_parse_ftie(const u8 *ie, size_t ie_len, - struct wpa_ft_ies *parse) -{ - const u8 *end, *pos; - - parse->ftie = ie; - parse->ftie_len = ie_len; - - pos = ie + sizeof(struct rsn_ftie); - end = ie + ie_len; - - while (pos + 2 <= end && pos + 2 + pos[1] <= end) { - switch (pos[0]) { - case FTIE_SUBELEM_R1KH_ID: - if (pos[1] != FT_R1KH_ID_LEN) { - wpa_printf(MSG_DEBUG, "FT: Invalid R1KH-ID " - "length in FTIE: %d", pos[1]); - return -1; - } - parse->r1kh_id = pos + 2; - break; - case FTIE_SUBELEM_GTK: - parse->gtk = pos + 2; - parse->gtk_len = pos[1]; - break; - case FTIE_SUBELEM_R0KH_ID: - if (pos[1] < 1 || pos[1] > FT_R0KH_ID_MAX_LEN) { - wpa_printf(MSG_DEBUG, "FT: Invalid R0KH-ID " - "length in FTIE: %d", pos[1]); - return -1; - } - parse->r0kh_id = pos + 2; - parse->r0kh_id_len = pos[1]; - break; -#ifdef CONFIG_IEEE80211W - case FTIE_SUBELEM_IGTK: - parse->igtk = pos + 2; - parse->igtk_len = pos[1]; - break; -#endif /* CONFIG_IEEE80211W */ - } - - pos += 2 + pos[1]; - } - - return 0; -} - - -static int wpa_ft_parse_ies(const u8 *ies, size_t ies_len, - struct wpa_ft_ies *parse) -{ - const u8 *end, *pos; - struct wpa_ie_data data; - int ret; - const struct rsn_ftie *ftie; - int prot_ie_count = 0; - - os_memset(parse, 0, sizeof(*parse)); - if (ies == NULL) - return 0; - - pos = ies; - end = ies + ies_len; - while (pos + 2 <= end && pos + 2 + pos[1] <= end) { - switch (pos[0]) { - case WLAN_EID_RSN: - parse->rsn = pos + 2; - parse->rsn_len = pos[1]; - ret = wpa_parse_wpa_ie_rsn(parse->rsn - 2, - parse->rsn_len + 2, - &data); - if (ret < 0) { - wpa_printf(MSG_DEBUG, "FT: Failed to parse " - "RSN IE: %d", ret); - return -1; - } - if (data.num_pmkid == 1 && data.pmkid) - parse->rsn_pmkid = data.pmkid; - break; - case WLAN_EID_MOBILITY_DOMAIN: - parse->mdie = pos + 2; - parse->mdie_len = pos[1]; - break; - case WLAN_EID_FAST_BSS_TRANSITION: - if (pos[1] < sizeof(*ftie)) - return -1; - ftie = (const struct rsn_ftie *) (pos + 2); - prot_ie_count = ftie->mic_control[1]; - if (wpa_ft_parse_ftie(pos + 2, pos[1], parse) < 0) - return -1; - break; - case WLAN_EID_TIMEOUT_INTERVAL: - parse->tie = pos + 2; - parse->tie_len = pos[1]; - break; - case WLAN_EID_RIC_DATA: - if (parse->ric == NULL) - parse->ric = pos; - } - - pos += 2 + pos[1]; - } - - if (prot_ie_count == 0) - return 0; /* no MIC */ - - /* - * Check that the protected IE count matches with IEs included in the - * frame. - */ - if (parse->rsn) - prot_ie_count--; - if (parse->mdie) - prot_ie_count--; - if (parse->ftie) - prot_ie_count--; - if (parse->tie) - prot_ie_count--; - if (prot_ie_count < 0) { - wpa_printf(MSG_DEBUG, "FT: Some required IEs not included in " - "the protected IE count"); - return -1; - } - - if (prot_ie_count == 0 && parse->ric) { - wpa_printf(MSG_DEBUG, "FT: RIC IE(s) in the frame, but not " - "included in protected IE count"); - return -1; - } - - /* Determine the end of the RIC IE(s) */ - pos = parse->ric; - while (pos && pos + 2 <= end && pos + 2 + pos[1] <= end && - prot_ie_count) { - prot_ie_count--; - pos += 2 + pos[1]; - } - parse->ric_len = pos - parse->ric; - if (prot_ie_count) { - wpa_printf(MSG_DEBUG, "FT: %d protected IEs missing from " - "frame", (int) prot_ie_count); - return -1; - } - - return 0; -} - - -static int wpa_ft_install_ptk(struct wpa_sm *sm, const u8 *bssid) -{ - int keylen; - enum wpa_alg alg; - u8 null_rsc[6] = { 0, 0, 0, 0, 0, 0 }; - - wpa_printf(MSG_DEBUG, "FT: Installing PTK to the driver."); - - switch (sm->pairwise_cipher) { - case WPA_CIPHER_CCMP: - alg = WPA_ALG_CCMP; - keylen = 16; - break; - case WPA_CIPHER_TKIP: - alg = WPA_ALG_TKIP; - keylen = 32; - break; - default: - wpa_printf(MSG_WARNING, "FT: Unsupported pairwise cipher %d", - sm->pairwise_cipher); - return -1; - } - - if (wpa_sm_set_key(sm, alg, bssid, 0, 1, null_rsc, - sizeof(null_rsc), (u8 *) sm->ptk.tk1, keylen) < 0) { - wpa_printf(MSG_WARNING, "FT: Failed to set PTK to the driver"); - return -1; - } - - return 0; -} - - -/** - * wpa_ft_prepare_auth_request - Generate over-the-air auth request - * @sm: Pointer to WPA state machine data from wpa_sm_init() - * @mdie: Target AP MDIE - * Returns: 0 on success, -1 on failure - */ -int wpa_ft_prepare_auth_request(struct wpa_sm *sm, const u8 *mdie) -{ - u8 *ft_ies; - size_t ft_ies_len; - - /* Generate a new SNonce */ - if (random_get_bytes(sm->snonce, WPA_NONCE_LEN)) { - wpa_printf(MSG_INFO, "FT: Failed to generate a new SNonce"); - return -1; - } - - ft_ies = wpa_ft_gen_req_ies(sm, &ft_ies_len, NULL, sm->pmk_r0_name, - NULL, sm->bssid, NULL, 0, mdie); - if (ft_ies) { - wpa_sm_update_ft_ies(sm, sm->mobility_domain, - ft_ies, ft_ies_len); - os_free(ft_ies); - } - - return 0; -} - - -int wpa_ft_process_response(struct wpa_sm *sm, const u8 *ies, size_t ies_len, - int ft_action, const u8 *target_ap, - const u8 *ric_ies, size_t ric_ies_len) -{ - u8 *ft_ies; - size_t ft_ies_len, ptk_len; - struct wpa_ft_ies parse; - struct rsn_mdie *mdie; - struct rsn_ftie *ftie; - u8 ptk_name[WPA_PMK_NAME_LEN]; - int ret; - const u8 *bssid; - - wpa_hexdump(MSG_DEBUG, "FT: Response IEs", ies, ies_len); - wpa_hexdump(MSG_DEBUG, "FT: RIC IEs", ric_ies, ric_ies_len); - - if (ft_action) { - if (!sm->over_the_ds_in_progress) { - wpa_printf(MSG_DEBUG, "FT: No over-the-DS in progress " - "- drop FT Action Response"); - return -1; - } - - if (os_memcmp(target_ap, sm->target_ap, ETH_ALEN) != 0) { - wpa_printf(MSG_DEBUG, "FT: No over-the-DS in progress " - "with this Target AP - drop FT Action " - "Response"); - return -1; - } - } - - if (sm->key_mgmt != WPA_KEY_MGMT_FT_IEEE8021X && - sm->key_mgmt != WPA_KEY_MGMT_FT_PSK) { - wpa_printf(MSG_DEBUG, "FT: Reject FT IEs since FT is not " - "enabled for this connection"); - return -1; - } - - if (wpa_ft_parse_ies(ies, ies_len, &parse) < 0) { - wpa_printf(MSG_DEBUG, "FT: Failed to parse IEs"); - return -1; - } - - mdie = (struct rsn_mdie *) parse.mdie; - if (mdie == NULL || parse.mdie_len < sizeof(*mdie) || - os_memcmp(mdie->mobility_domain, sm->mobility_domain, - MOBILITY_DOMAIN_ID_LEN) != 0) { - wpa_printf(MSG_DEBUG, "FT: Invalid MDIE"); - return -1; - } - - ftie = (struct rsn_ftie *) parse.ftie; - if (ftie == NULL || parse.ftie_len < sizeof(*ftie)) { - wpa_printf(MSG_DEBUG, "FT: Invalid FTIE"); - return -1; - } - - if (os_memcmp(ftie->snonce, sm->snonce, WPA_NONCE_LEN) != 0) { - wpa_printf(MSG_DEBUG, "FT: SNonce mismatch in FTIE"); - wpa_hexdump(MSG_DEBUG, "FT: Received SNonce", - ftie->snonce, WPA_NONCE_LEN); - wpa_hexdump(MSG_DEBUG, "FT: Expected SNonce", - sm->snonce, WPA_NONCE_LEN); - return -1; - } - - if (parse.r0kh_id == NULL) { - wpa_printf(MSG_DEBUG, "FT: No R0KH-ID subelem in FTIE"); - return -1; - } - - if (parse.r0kh_id_len != sm->r0kh_id_len || - os_memcmp(parse.r0kh_id, sm->r0kh_id, parse.r0kh_id_len) != 0) { - wpa_printf(MSG_DEBUG, "FT: R0KH-ID in FTIE did not match with " - "the current R0KH-ID"); - wpa_hexdump(MSG_DEBUG, "FT: R0KH-ID in FTIE", - parse.r0kh_id, parse.r0kh_id_len); - wpa_hexdump(MSG_DEBUG, "FT: The current R0KH-ID", - sm->r0kh_id, sm->r0kh_id_len); - return -1; - } - - if (parse.r1kh_id == NULL) { - wpa_printf(MSG_DEBUG, "FT: No R1KH-ID subelem in FTIE"); - return -1; - } - - if (parse.rsn_pmkid == NULL || - os_memcmp(parse.rsn_pmkid, sm->pmk_r0_name, WPA_PMK_NAME_LEN)) { - wpa_printf(MSG_DEBUG, "FT: No matching PMKR0Name (PMKID) in " - "RSNIE"); - return -1; - } - - os_memcpy(sm->r1kh_id, parse.r1kh_id, FT_R1KH_ID_LEN); - wpa_hexdump(MSG_DEBUG, "FT: R1KH-ID", sm->r1kh_id, FT_R1KH_ID_LEN); - wpa_hexdump(MSG_DEBUG, "FT: SNonce", sm->snonce, WPA_NONCE_LEN); - wpa_hexdump(MSG_DEBUG, "FT: ANonce", ftie->anonce, WPA_NONCE_LEN); - os_memcpy(sm->anonce, ftie->anonce, WPA_NONCE_LEN); - wpa_derive_pmk_r1(sm->pmk_r0, sm->pmk_r0_name, sm->r1kh_id, - sm->own_addr, sm->pmk_r1, sm->pmk_r1_name); - wpa_hexdump_key(MSG_DEBUG, "FT: PMK-R1", sm->pmk_r1, PMK_LEN); - wpa_hexdump(MSG_DEBUG, "FT: PMKR1Name", - sm->pmk_r1_name, WPA_PMK_NAME_LEN); - - bssid = target_ap; - ptk_len = sm->pairwise_cipher == WPA_CIPHER_CCMP ? 48 : 64; - wpa_pmk_r1_to_ptk(sm->pmk_r1, sm->snonce, ftie->anonce, sm->own_addr, - bssid, sm->pmk_r1_name, - (u8 *) &sm->ptk, ptk_len, ptk_name); - wpa_hexdump_key(MSG_DEBUG, "FT: PTK", - (u8 *) &sm->ptk, ptk_len); - wpa_hexdump(MSG_DEBUG, "FT: PTKName", ptk_name, WPA_PMK_NAME_LEN); - - ft_ies = wpa_ft_gen_req_ies(sm, &ft_ies_len, ftie->anonce, - sm->pmk_r1_name, sm->ptk.kck, bssid, - ric_ies, ric_ies_len, - parse.mdie ? parse.mdie - 2 : NULL); - if (ft_ies) { - wpa_sm_update_ft_ies(sm, sm->mobility_domain, - ft_ies, ft_ies_len); - os_free(ft_ies); - } - - wpa_sm_mark_authenticated(sm, bssid); - ret = wpa_ft_install_ptk(sm, bssid); - if (ret) { - /* - * Some drivers do not support key configuration when we are - * not associated with the target AP. Work around this by - * trying again after the following reassociation gets - * completed. - */ - wpa_printf(MSG_DEBUG, "FT: Failed to set PTK prior to " - "association - try again after reassociation"); - sm->set_ptk_after_assoc = 1; - } else - sm->set_ptk_after_assoc = 0; - - sm->ft_completed = 1; - if (ft_action) { - /* - * The caller is expected trigger re-association with the - * Target AP. - */ - os_memcpy(sm->bssid, target_ap, ETH_ALEN); - } - - return 0; -} - - -int wpa_ft_is_completed(struct wpa_sm *sm) -{ - if (sm == NULL) - return 0; - - if (sm->key_mgmt != WPA_KEY_MGMT_FT_IEEE8021X && - sm->key_mgmt != WPA_KEY_MGMT_FT_PSK) - return 0; - - return sm->ft_completed; -} - - -static int wpa_ft_process_gtk_subelem(struct wpa_sm *sm, const u8 *gtk_elem, - size_t gtk_elem_len) -{ - u8 gtk[32]; - int keyidx; - enum wpa_alg alg; - size_t gtk_len, keylen, rsc_len; - - if (gtk_elem == NULL) { - wpa_printf(MSG_DEBUG, "FT: No GTK included in FTIE"); - return 0; - } - - wpa_hexdump_key(MSG_DEBUG, "FT: Received GTK in Reassoc Resp", - gtk_elem, gtk_elem_len); - - if (gtk_elem_len < 11 + 24 || (gtk_elem_len - 11) % 8 || - gtk_elem_len - 19 > sizeof(gtk)) { - wpa_printf(MSG_DEBUG, "FT: Invalid GTK sub-elem " - "length %lu", (unsigned long) gtk_elem_len); - return -1; - } - gtk_len = gtk_elem_len - 19; - if (aes_unwrap(sm->ptk.kek, gtk_len / 8, gtk_elem + 11, gtk)) { - wpa_printf(MSG_WARNING, "FT: AES unwrap failed - could not " - "decrypt GTK"); - return -1; - } - - switch (sm->group_cipher) { - case WPA_CIPHER_CCMP: - keylen = 16; - rsc_len = 6; - alg = WPA_ALG_CCMP; - break; - case WPA_CIPHER_TKIP: - keylen = 32; - rsc_len = 6; - alg = WPA_ALG_TKIP; - break; - case WPA_CIPHER_WEP104: - keylen = 13; - rsc_len = 0; - alg = WPA_ALG_WEP; - break; - case WPA_CIPHER_WEP40: - keylen = 5; - rsc_len = 0; - alg = WPA_ALG_WEP; - break; - default: - wpa_printf(MSG_WARNING, "WPA: Unsupported Group Cipher %d", - sm->group_cipher); - return -1; - } - - if (gtk_len < keylen) { - wpa_printf(MSG_DEBUG, "FT: Too short GTK in FTIE"); - return -1; - } - - /* Key Info[2] | Key Length[1] | RSC[8] | Key[5..32]. */ - - keyidx = WPA_GET_LE16(gtk_elem) & 0x03; - - if (gtk_elem[2] != keylen) { - wpa_printf(MSG_DEBUG, "FT: GTK length mismatch: received %d " - "negotiated %lu", - gtk_elem[2], (unsigned long) keylen); - return -1; - } - - wpa_hexdump_key(MSG_DEBUG, "FT: GTK from Reassoc Resp", gtk, keylen); - if (wpa_sm_set_key(sm, alg, broadcast_ether_addr, keyidx, 0, - gtk_elem + 3, rsc_len, gtk, keylen) < 0) { - wpa_printf(MSG_WARNING, "WPA: Failed to set GTK to the " - "driver."); - return -1; - } - - return 0; -} - - -#ifdef CONFIG_IEEE80211W -static int wpa_ft_process_igtk_subelem(struct wpa_sm *sm, const u8 *igtk_elem, - size_t igtk_elem_len) -{ - u8 igtk[WPA_IGTK_LEN]; - u16 keyidx; - - if (sm->mgmt_group_cipher != WPA_CIPHER_AES_128_CMAC) - return 0; - - if (igtk_elem == NULL) { - wpa_printf(MSG_DEBUG, "FT: No IGTK included in FTIE"); - return 0; - } - - wpa_hexdump_key(MSG_DEBUG, "FT: Received IGTK in Reassoc Resp", - igtk_elem, igtk_elem_len); - - if (igtk_elem_len != 2 + 6 + 1 + WPA_IGTK_LEN + 8) { - wpa_printf(MSG_DEBUG, "FT: Invalid IGTK sub-elem " - "length %lu", (unsigned long) igtk_elem_len); - return -1; - } - if (igtk_elem[8] != WPA_IGTK_LEN) { - wpa_printf(MSG_DEBUG, "FT: Invalid IGTK sub-elem Key Length " - "%d", igtk_elem[8]); - return -1; - } - - if (aes_unwrap(sm->ptk.kek, WPA_IGTK_LEN / 8, igtk_elem + 9, igtk)) { - wpa_printf(MSG_WARNING, "FT: AES unwrap failed - could not " - "decrypt IGTK"); - return -1; - } - - /* KeyID[2] | IPN[6] | Key Length[1] | Key[16+8] */ - - keyidx = WPA_GET_LE16(igtk_elem); - - wpa_hexdump_key(MSG_DEBUG, "FT: IGTK from Reassoc Resp", igtk, - WPA_IGTK_LEN); - if (wpa_sm_set_key(sm, WPA_ALG_IGTK, broadcast_ether_addr, keyidx, 0, - igtk_elem + 2, 6, igtk, WPA_IGTK_LEN) < 0) { - wpa_printf(MSG_WARNING, "WPA: Failed to set IGTK to the " - "driver."); - return -1; - } - - return 0; -} -#endif /* CONFIG_IEEE80211W */ - - -int wpa_ft_validate_reassoc_resp(struct wpa_sm *sm, const u8 *ies, - size_t ies_len, const u8 *src_addr) -{ - struct wpa_ft_ies parse; - struct rsn_mdie *mdie; - struct rsn_ftie *ftie; - unsigned int count; - u8 mic[16]; - - wpa_hexdump(MSG_DEBUG, "FT: Response IEs", ies, ies_len); - - if (sm->key_mgmt != WPA_KEY_MGMT_FT_IEEE8021X && - sm->key_mgmt != WPA_KEY_MGMT_FT_PSK) { - wpa_printf(MSG_DEBUG, "FT: Reject FT IEs since FT is not " - "enabled for this connection"); - return -1; - } - - if (wpa_ft_parse_ies(ies, ies_len, &parse) < 0) { - wpa_printf(MSG_DEBUG, "FT: Failed to parse IEs"); - return -1; - } - - mdie = (struct rsn_mdie *) parse.mdie; - if (mdie == NULL || parse.mdie_len < sizeof(*mdie) || - os_memcmp(mdie->mobility_domain, sm->mobility_domain, - MOBILITY_DOMAIN_ID_LEN) != 0) { - wpa_printf(MSG_DEBUG, "FT: Invalid MDIE"); - return -1; - } - - ftie = (struct rsn_ftie *) parse.ftie; - if (ftie == NULL || parse.ftie_len < sizeof(*ftie)) { - wpa_printf(MSG_DEBUG, "FT: Invalid FTIE"); - return -1; - } - - if (os_memcmp(ftie->snonce, sm->snonce, WPA_NONCE_LEN) != 0) { - wpa_printf(MSG_DEBUG, "FT: SNonce mismatch in FTIE"); - wpa_hexdump(MSG_DEBUG, "FT: Received SNonce", - ftie->snonce, WPA_NONCE_LEN); - wpa_hexdump(MSG_DEBUG, "FT: Expected SNonce", - sm->snonce, WPA_NONCE_LEN); - return -1; - } - - if (os_memcmp(ftie->anonce, sm->anonce, WPA_NONCE_LEN) != 0) { - wpa_printf(MSG_DEBUG, "FT: ANonce mismatch in FTIE"); - wpa_hexdump(MSG_DEBUG, "FT: Received ANonce", - ftie->anonce, WPA_NONCE_LEN); - wpa_hexdump(MSG_DEBUG, "FT: Expected ANonce", - sm->anonce, WPA_NONCE_LEN); - return -1; - } - - if (parse.r0kh_id == NULL) { - wpa_printf(MSG_DEBUG, "FT: No R0KH-ID subelem in FTIE"); - return -1; - } - - if (parse.r0kh_id_len != sm->r0kh_id_len || - os_memcmp(parse.r0kh_id, sm->r0kh_id, parse.r0kh_id_len) != 0) { - wpa_printf(MSG_DEBUG, "FT: R0KH-ID in FTIE did not match with " - "the current R0KH-ID"); - wpa_hexdump(MSG_DEBUG, "FT: R0KH-ID in FTIE", - parse.r0kh_id, parse.r0kh_id_len); - wpa_hexdump(MSG_DEBUG, "FT: The current R0KH-ID", - sm->r0kh_id, sm->r0kh_id_len); - return -1; - } - - if (parse.r1kh_id == NULL) { - wpa_printf(MSG_DEBUG, "FT: No R1KH-ID subelem in FTIE"); - return -1; - } - - if (os_memcmp(parse.r1kh_id, sm->r1kh_id, FT_R1KH_ID_LEN) != 0) { - wpa_printf(MSG_DEBUG, "FT: Unknown R1KH-ID used in " - "ReassocResp"); - return -1; - } - - if (parse.rsn_pmkid == NULL || - os_memcmp(parse.rsn_pmkid, sm->pmk_r1_name, WPA_PMK_NAME_LEN)) { - wpa_printf(MSG_DEBUG, "FT: No matching PMKR1Name (PMKID) in " - "RSNIE (pmkid=%d)", !!parse.rsn_pmkid); - return -1; - } - - count = 3; - if (parse.tie) - count++; - if (ftie->mic_control[1] != count) { - wpa_printf(MSG_DEBUG, "FT: Unexpected IE count in MIC " - "Control: received %u expected %u", - ftie->mic_control[1], count); - return -1; - } - - if (wpa_ft_mic(sm->ptk.kck, sm->own_addr, src_addr, 6, - parse.mdie - 2, parse.mdie_len + 2, - parse.ftie - 2, parse.ftie_len + 2, - parse.rsn - 2, parse.rsn_len + 2, - parse.ric, parse.ric_len, - mic) < 0) { - wpa_printf(MSG_DEBUG, "FT: Failed to calculate MIC"); - return -1; - } - - if (os_memcmp(mic, ftie->mic, 16) != 0) { - wpa_printf(MSG_DEBUG, "FT: Invalid MIC in FTIE"); - wpa_hexdump(MSG_MSGDUMP, "FT: Received MIC", ftie->mic, 16); - wpa_hexdump(MSG_MSGDUMP, "FT: Calculated MIC", mic, 16); - return -1; - } - - if (wpa_ft_process_gtk_subelem(sm, parse.gtk, parse.gtk_len) < 0) - return -1; - -#ifdef CONFIG_IEEE80211W - if (wpa_ft_process_igtk_subelem(sm, parse.igtk, parse.igtk_len) < 0) - return -1; -#endif /* CONFIG_IEEE80211W */ - - if (sm->set_ptk_after_assoc) { - wpa_printf(MSG_DEBUG, "FT: Try to set PTK again now that we " - "are associated"); - if (wpa_ft_install_ptk(sm, src_addr) < 0) - return -1; - sm->set_ptk_after_assoc = 0; - } - - if (parse.ric) { - wpa_hexdump(MSG_MSGDUMP, "FT: RIC Response", - parse.ric, parse.ric_len); - /* TODO: parse response and inform driver about results */ - } - - return 0; -} - - -/** - * wpa_ft_start_over_ds - Generate over-the-DS auth request - * @sm: Pointer to WPA state machine data from wpa_sm_init() - * @target_ap: Target AP Address - * @mdie: Mobility Domain IE from the target AP - * Returns: 0 on success, -1 on failure - */ -int wpa_ft_start_over_ds(struct wpa_sm *sm, const u8 *target_ap, - const u8 *mdie) -{ - u8 *ft_ies; - size_t ft_ies_len; - - wpa_printf(MSG_DEBUG, "FT: Request over-the-DS with " MACSTR, - MAC2STR(target_ap)); - - /* Generate a new SNonce */ - if (random_get_bytes(sm->snonce, WPA_NONCE_LEN)) { - wpa_printf(MSG_INFO, "FT: Failed to generate a new SNonce"); - return -1; - } - - ft_ies = wpa_ft_gen_req_ies(sm, &ft_ies_len, NULL, sm->pmk_r0_name, - NULL, target_ap, NULL, 0, mdie); - if (ft_ies) { - sm->over_the_ds_in_progress = 1; - os_memcpy(sm->target_ap, target_ap, ETH_ALEN); - wpa_sm_send_ft_action(sm, 1, target_ap, ft_ies, ft_ies_len); - os_free(ft_ies); - } - - return 0; -} - -#endif /* CONFIG_IEEE80211R */ diff --git a/hostapd-0.8/src/rsn_supp/wpa_i.h b/hostapd-0.8/src/rsn_supp/wpa_i.h deleted file mode 100644 index 09a2e4f..0000000 --- a/hostapd-0.8/src/rsn_supp/wpa_i.h +++ /dev/null @@ -1,290 +0,0 @@ -/* - * Internal WPA/RSN supplicant state machine definitions - * Copyright (c) 2004-2010, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#ifndef WPA_I_H -#define WPA_I_H - -#include "utils/list.h" - -struct wpa_peerkey; -struct wpa_tdls_peer; -struct wpa_eapol_key; - -/** - * struct wpa_sm - Internal WPA state machine data - */ -struct wpa_sm { - u8 pmk[PMK_LEN]; - size_t pmk_len; - struct wpa_ptk ptk, tptk; - int ptk_set, tptk_set; - u8 snonce[WPA_NONCE_LEN]; - u8 anonce[WPA_NONCE_LEN]; /* ANonce from the last 1/4 msg */ - int renew_snonce; - u8 rx_replay_counter[WPA_REPLAY_COUNTER_LEN]; - int rx_replay_counter_set; - u8 request_counter[WPA_REPLAY_COUNTER_LEN]; - - struct eapol_sm *eapol; /* EAPOL state machine from upper level code */ - - struct rsn_pmksa_cache *pmksa; /* PMKSA cache */ - struct rsn_pmksa_cache_entry *cur_pmksa; /* current PMKSA entry */ - struct dl_list pmksa_candidates; - - struct l2_packet_data *l2_preauth; - struct l2_packet_data *l2_preauth_br; - struct l2_packet_data *l2_tdls; - u8 preauth_bssid[ETH_ALEN]; /* current RSN pre-auth peer or - * 00:00:00:00:00:00 if no pre-auth is - * in progress */ - struct eapol_sm *preauth_eapol; - - struct wpa_sm_ctx *ctx; - - void *scard_ctx; /* context for smartcard callbacks */ - int fast_reauth; /* whether EAP fast re-authentication is enabled */ - - void *network_ctx; - int peerkey_enabled; - int allowed_pairwise_cipher; /* bitfield of WPA_CIPHER_* */ - int proactive_key_caching; - int eap_workaround; - void *eap_conf_ctx; - u8 ssid[32]; - size_t ssid_len; - int wpa_ptk_rekey; - - u8 own_addr[ETH_ALEN]; - const char *ifname; - const char *bridge_ifname; - u8 bssid[ETH_ALEN]; - - unsigned int dot11RSNAConfigPMKLifetime; - unsigned int dot11RSNAConfigPMKReauthThreshold; - unsigned int dot11RSNAConfigSATimeout; - - unsigned int dot11RSNA4WayHandshakeFailures; - - /* Selected configuration (based on Beacon/ProbeResp WPA IE) */ - unsigned int proto; - unsigned int pairwise_cipher; - unsigned int group_cipher; - unsigned int key_mgmt; - unsigned int mgmt_group_cipher; - - int rsn_enabled; /* Whether RSN is enabled in configuration */ - int mfp; /* 0 = disabled, 1 = optional, 2 = mandatory */ - - u8 *assoc_wpa_ie; /* Own WPA/RSN IE from (Re)AssocReq */ - size_t assoc_wpa_ie_len; - u8 *ap_wpa_ie, *ap_rsn_ie; - size_t ap_wpa_ie_len, ap_rsn_ie_len; - -#ifdef CONFIG_PEERKEY - struct wpa_peerkey *peerkey; -#endif /* CONFIG_PEERKEY */ -#ifdef CONFIG_TDLS - struct wpa_tdls_peer *tdls; - int tdls_prohibited; - int tdls_disabled; -#endif /* CONFIG_TDLS */ - -#ifdef CONFIG_IEEE80211R - u8 xxkey[PMK_LEN]; /* PSK or the second 256 bits of MSK */ - size_t xxkey_len; - u8 pmk_r0[PMK_LEN]; - u8 pmk_r0_name[WPA_PMK_NAME_LEN]; - u8 pmk_r1[PMK_LEN]; - u8 pmk_r1_name[WPA_PMK_NAME_LEN]; - u8 mobility_domain[MOBILITY_DOMAIN_ID_LEN]; - u8 r0kh_id[FT_R0KH_ID_MAX_LEN]; - size_t r0kh_id_len; - u8 r1kh_id[FT_R1KH_ID_LEN]; - int ft_completed; - int over_the_ds_in_progress; - u8 target_ap[ETH_ALEN]; /* over-the-DS target AP */ - int set_ptk_after_assoc; - u8 mdie_ft_capab; /* FT Capability and Policy from target AP MDIE */ - u8 *assoc_resp_ies; /* MDIE and FTIE from (Re)Association Response */ - size_t assoc_resp_ies_len; -#endif /* CONFIG_IEEE80211R */ -}; - - -static inline void wpa_sm_set_state(struct wpa_sm *sm, enum wpa_states state) -{ - WPA_ASSERT(sm->ctx->set_state); - sm->ctx->set_state(sm->ctx->ctx, state); -} - -static inline enum wpa_states wpa_sm_get_state(struct wpa_sm *sm) -{ - WPA_ASSERT(sm->ctx->get_state); - return sm->ctx->get_state(sm->ctx->ctx); -} - -static inline void wpa_sm_deauthenticate(struct wpa_sm *sm, int reason_code) -{ - WPA_ASSERT(sm->ctx->deauthenticate); - sm->ctx->deauthenticate(sm->ctx->ctx, reason_code); -} - -static inline void wpa_sm_disassociate(struct wpa_sm *sm, int reason_code) -{ - WPA_ASSERT(sm->ctx->disassociate); - sm->ctx->disassociate(sm->ctx->ctx, reason_code); -} - -static inline int wpa_sm_set_key(struct wpa_sm *sm, enum wpa_alg alg, - const u8 *addr, int key_idx, int set_tx, - const u8 *seq, size_t seq_len, - const u8 *key, size_t key_len) -{ - WPA_ASSERT(sm->ctx->set_key); - return sm->ctx->set_key(sm->ctx->ctx, alg, addr, key_idx, set_tx, - seq, seq_len, key, key_len); -} - -static inline void * wpa_sm_get_network_ctx(struct wpa_sm *sm) -{ - WPA_ASSERT(sm->ctx->get_network_ctx); - return sm->ctx->get_network_ctx(sm->ctx->ctx); -} - -static inline int wpa_sm_get_bssid(struct wpa_sm *sm, u8 *bssid) -{ - WPA_ASSERT(sm->ctx->get_bssid); - return sm->ctx->get_bssid(sm->ctx->ctx, bssid); -} - -static inline int wpa_sm_ether_send(struct wpa_sm *sm, const u8 *dest, - u16 proto, const u8 *buf, size_t len) -{ - WPA_ASSERT(sm->ctx->ether_send); - return sm->ctx->ether_send(sm->ctx->ctx, dest, proto, buf, len); -} - -static inline int wpa_sm_get_beacon_ie(struct wpa_sm *sm) -{ - WPA_ASSERT(sm->ctx->get_beacon_ie); - return sm->ctx->get_beacon_ie(sm->ctx->ctx); -} - -static inline void wpa_sm_cancel_auth_timeout(struct wpa_sm *sm) -{ - WPA_ASSERT(sm->ctx->cancel_auth_timeout); - sm->ctx->cancel_auth_timeout(sm->ctx->ctx); -} - -static inline u8 * wpa_sm_alloc_eapol(struct wpa_sm *sm, u8 type, - const void *data, u16 data_len, - size_t *msg_len, void **data_pos) -{ - WPA_ASSERT(sm->ctx->alloc_eapol); - return sm->ctx->alloc_eapol(sm->ctx->ctx, type, data, data_len, - msg_len, data_pos); -} - -static inline int wpa_sm_add_pmkid(struct wpa_sm *sm, const u8 *bssid, - const u8 *pmkid) -{ - WPA_ASSERT(sm->ctx->add_pmkid); - return sm->ctx->add_pmkid(sm->ctx->ctx, bssid, pmkid); -} - -static inline int wpa_sm_remove_pmkid(struct wpa_sm *sm, const u8 *bssid, - const u8 *pmkid) -{ - WPA_ASSERT(sm->ctx->remove_pmkid); - return sm->ctx->remove_pmkid(sm->ctx->ctx, bssid, pmkid); -} - -static inline int wpa_sm_mlme_setprotection(struct wpa_sm *sm, const u8 *addr, - int protect_type, int key_type) -{ - WPA_ASSERT(sm->ctx->mlme_setprotection); - return sm->ctx->mlme_setprotection(sm->ctx->ctx, addr, protect_type, - key_type); -} - -static inline int wpa_sm_update_ft_ies(struct wpa_sm *sm, const u8 *md, - const u8 *ies, size_t ies_len) -{ - if (sm->ctx->update_ft_ies) - return sm->ctx->update_ft_ies(sm->ctx->ctx, md, ies, ies_len); - return -1; -} - -static inline int wpa_sm_send_ft_action(struct wpa_sm *sm, u8 action, - const u8 *target_ap, - const u8 *ies, size_t ies_len) -{ - if (sm->ctx->send_ft_action) - return sm->ctx->send_ft_action(sm->ctx->ctx, action, target_ap, - ies, ies_len); - return -1; -} - -static inline int wpa_sm_mark_authenticated(struct wpa_sm *sm, - const u8 *target_ap) -{ - if (sm->ctx->mark_authenticated) - return sm->ctx->mark_authenticated(sm->ctx->ctx, target_ap); - return -1; -} - -#ifdef CONFIG_TDLS -static inline int wpa_sm_send_tdls_mgmt(struct wpa_sm *sm, const u8 *dst, - u8 action_code, u8 dialog_token, - u16 status_code, const u8 *buf, - size_t len) -{ - if (sm->ctx->send_tdls_mgmt) - return sm->ctx->send_tdls_mgmt(sm->ctx->ctx, dst, action_code, - dialog_token, status_code, - buf, len); - return -1; -} - -static inline int wpa_sm_tdls_oper(struct wpa_sm *sm, int oper, - const u8 *peer) -{ - if (sm->ctx->tdls_oper) - return sm->ctx->tdls_oper(sm->ctx->ctx, oper, peer); - return -1; -} -#endif /* CONFIG_TDLS */ - -void wpa_eapol_key_send(struct wpa_sm *sm, const u8 *kck, - int ver, const u8 *dest, u16 proto, - u8 *msg, size_t msg_len, u8 *key_mic); -int wpa_supplicant_send_2_of_4(struct wpa_sm *sm, const unsigned char *dst, - const struct wpa_eapol_key *key, - int ver, const u8 *nonce, - const u8 *wpa_ie, size_t wpa_ie_len, - struct wpa_ptk *ptk); -int wpa_supplicant_send_4_of_4(struct wpa_sm *sm, const unsigned char *dst, - const struct wpa_eapol_key *key, - u16 ver, u16 key_info, - const u8 *kde, size_t kde_len, - struct wpa_ptk *ptk); - -int wpa_derive_ptk_ft(struct wpa_sm *sm, const unsigned char *src_addr, - const struct wpa_eapol_key *key, - struct wpa_ptk *ptk, size_t ptk_len); - -void wpa_tdls_assoc(struct wpa_sm *sm); -void wpa_tdls_disassoc(struct wpa_sm *sm); - -#endif /* WPA_I_H */ diff --git a/hostapd-0.8/src/rsn_supp/wpa_ie.c b/hostapd-0.8/src/rsn_supp/wpa_ie.c deleted file mode 100644 index 654cc1f..0000000 --- a/hostapd-0.8/src/rsn_supp/wpa_ie.c +++ /dev/null @@ -1,447 +0,0 @@ -/* - * wpa_supplicant - WPA/RSN IE and KDE processing - * Copyright (c) 2003-2008, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#include "includes.h" - -#include "common.h" -#include "wpa.h" -#include "pmksa_cache.h" -#include "common/ieee802_11_defs.h" -#include "wpa_i.h" -#include "wpa_ie.h" - - -/** - * wpa_parse_wpa_ie - Parse WPA/RSN IE - * @wpa_ie: Pointer to WPA or RSN IE - * @wpa_ie_len: Length of the WPA/RSN IE - * @data: Pointer to data area for parsing results - * Returns: 0 on success, -1 on failure - * - * Parse the contents of WPA or RSN IE and write the parsed data into data. - */ -int wpa_parse_wpa_ie(const u8 *wpa_ie, size_t wpa_ie_len, - struct wpa_ie_data *data) -{ - if (wpa_ie_len >= 1 && wpa_ie[0] == WLAN_EID_RSN) - return wpa_parse_wpa_ie_rsn(wpa_ie, wpa_ie_len, data); - else - return wpa_parse_wpa_ie_wpa(wpa_ie, wpa_ie_len, data); -} - - -static int wpa_gen_wpa_ie_wpa(u8 *wpa_ie, size_t wpa_ie_len, - int pairwise_cipher, int group_cipher, - int key_mgmt) -{ - u8 *pos; - struct wpa_ie_hdr *hdr; - - if (wpa_ie_len < sizeof(*hdr) + WPA_SELECTOR_LEN + - 2 + WPA_SELECTOR_LEN + 2 + WPA_SELECTOR_LEN) - return -1; - - hdr = (struct wpa_ie_hdr *) wpa_ie; - hdr->elem_id = WLAN_EID_VENDOR_SPECIFIC; - RSN_SELECTOR_PUT(hdr->oui, WPA_OUI_TYPE); - WPA_PUT_LE16(hdr->version, WPA_VERSION); - pos = (u8 *) (hdr + 1); - - if (group_cipher == WPA_CIPHER_CCMP) { - RSN_SELECTOR_PUT(pos, WPA_CIPHER_SUITE_CCMP); - } else if (group_cipher == WPA_CIPHER_TKIP) { - RSN_SELECTOR_PUT(pos, WPA_CIPHER_SUITE_TKIP); - } else if (group_cipher == WPA_CIPHER_WEP104) { - RSN_SELECTOR_PUT(pos, WPA_CIPHER_SUITE_WEP104); - } else if (group_cipher == WPA_CIPHER_WEP40) { - RSN_SELECTOR_PUT(pos, WPA_CIPHER_SUITE_WEP40); - } else { - wpa_printf(MSG_WARNING, "Invalid group cipher (%d).", - group_cipher); - return -1; - } - pos += WPA_SELECTOR_LEN; - - *pos++ = 1; - *pos++ = 0; - if (pairwise_cipher == WPA_CIPHER_CCMP) { - RSN_SELECTOR_PUT(pos, WPA_CIPHER_SUITE_CCMP); - } else if (pairwise_cipher == WPA_CIPHER_TKIP) { - RSN_SELECTOR_PUT(pos, WPA_CIPHER_SUITE_TKIP); - } else if (pairwise_cipher == WPA_CIPHER_NONE) { - RSN_SELECTOR_PUT(pos, WPA_CIPHER_SUITE_NONE); - } else { - wpa_printf(MSG_WARNING, "Invalid pairwise cipher (%d).", - pairwise_cipher); - return -1; - } - pos += WPA_SELECTOR_LEN; - - *pos++ = 1; - *pos++ = 0; - if (key_mgmt == WPA_KEY_MGMT_IEEE8021X) { - RSN_SELECTOR_PUT(pos, WPA_AUTH_KEY_MGMT_UNSPEC_802_1X); - } else if (key_mgmt == WPA_KEY_MGMT_PSK) { - RSN_SELECTOR_PUT(pos, WPA_AUTH_KEY_MGMT_PSK_OVER_802_1X); - } else if (key_mgmt == WPA_KEY_MGMT_WPA_NONE) { - RSN_SELECTOR_PUT(pos, WPA_AUTH_KEY_MGMT_NONE); - } else { - wpa_printf(MSG_WARNING, "Invalid key management type (%d).", - key_mgmt); - return -1; - } - pos += WPA_SELECTOR_LEN; - - /* WPA Capabilities; use defaults, so no need to include it */ - - hdr->len = (pos - wpa_ie) - 2; - - WPA_ASSERT((size_t) (pos - wpa_ie) <= wpa_ie_len); - - return pos - wpa_ie; -} - - -static int wpa_gen_wpa_ie_rsn(u8 *rsn_ie, size_t rsn_ie_len, - int pairwise_cipher, int group_cipher, - int key_mgmt, int mgmt_group_cipher, - struct wpa_sm *sm) -{ -#ifndef CONFIG_NO_WPA2 - u8 *pos; - struct rsn_ie_hdr *hdr; - u16 capab; - - if (rsn_ie_len < sizeof(*hdr) + RSN_SELECTOR_LEN + - 2 + RSN_SELECTOR_LEN + 2 + RSN_SELECTOR_LEN + 2 + - (sm->cur_pmksa ? 2 + PMKID_LEN : 0)) { - wpa_printf(MSG_DEBUG, "RSN: Too short IE buffer (%lu bytes)", - (unsigned long) rsn_ie_len); - return -1; - } - - hdr = (struct rsn_ie_hdr *) rsn_ie; - hdr->elem_id = WLAN_EID_RSN; - WPA_PUT_LE16(hdr->version, RSN_VERSION); - pos = (u8 *) (hdr + 1); - - if (group_cipher == WPA_CIPHER_CCMP) { - RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_CCMP); - } else if (group_cipher == WPA_CIPHER_TKIP) { - RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_TKIP); - } else if (group_cipher == WPA_CIPHER_WEP104) { - RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_WEP104); - } else if (group_cipher == WPA_CIPHER_WEP40) { - RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_WEP40); - } else { - wpa_printf(MSG_WARNING, "Invalid group cipher (%d).", - group_cipher); - return -1; - } - pos += RSN_SELECTOR_LEN; - - *pos++ = 1; - *pos++ = 0; - if (pairwise_cipher == WPA_CIPHER_CCMP) { - RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_CCMP); - } else if (pairwise_cipher == WPA_CIPHER_TKIP) { - RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_TKIP); - } else if (pairwise_cipher == WPA_CIPHER_NONE) { - RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_NONE); - } else { - wpa_printf(MSG_WARNING, "Invalid pairwise cipher (%d).", - pairwise_cipher); - return -1; - } - pos += RSN_SELECTOR_LEN; - - *pos++ = 1; - *pos++ = 0; - if (key_mgmt == WPA_KEY_MGMT_IEEE8021X) { - RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_UNSPEC_802_1X); - } else if (key_mgmt == WPA_KEY_MGMT_PSK) { - RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_PSK_OVER_802_1X); -#ifdef CONFIG_IEEE80211R - } else if (key_mgmt == WPA_KEY_MGMT_FT_IEEE8021X) { - RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_FT_802_1X); - } else if (key_mgmt == WPA_KEY_MGMT_FT_PSK) { - RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_FT_PSK); -#endif /* CONFIG_IEEE80211R */ -#ifdef CONFIG_IEEE80211W - } else if (key_mgmt == WPA_KEY_MGMT_IEEE8021X_SHA256) { - RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_802_1X_SHA256); - } else if (key_mgmt == WPA_KEY_MGMT_PSK_SHA256) { - RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_PSK_SHA256); -#endif /* CONFIG_IEEE80211W */ - } else { - wpa_printf(MSG_WARNING, "Invalid key management type (%d).", - key_mgmt); - return -1; - } - pos += RSN_SELECTOR_LEN; - - /* RSN Capabilities */ - capab = 0; -#ifdef CONFIG_IEEE80211W - if (sm->mfp) - capab |= WPA_CAPABILITY_MFPC; - if (sm->mfp == 2) - capab |= WPA_CAPABILITY_MFPR; -#endif /* CONFIG_IEEE80211W */ - WPA_PUT_LE16(pos, capab); - pos += 2; - - if (sm->cur_pmksa) { - /* PMKID Count (2 octets, little endian) */ - *pos++ = 1; - *pos++ = 0; - /* PMKID */ - os_memcpy(pos, sm->cur_pmksa->pmkid, PMKID_LEN); - pos += PMKID_LEN; - } - -#ifdef CONFIG_IEEE80211W - if (mgmt_group_cipher == WPA_CIPHER_AES_128_CMAC) { - if (!sm->cur_pmksa) { - /* PMKID Count */ - WPA_PUT_LE16(pos, 0); - pos += 2; - } - - /* Management Group Cipher Suite */ - RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_AES_128_CMAC); - pos += RSN_SELECTOR_LEN; - } -#endif /* CONFIG_IEEE80211W */ - - hdr->len = (pos - rsn_ie) - 2; - - WPA_ASSERT((size_t) (pos - rsn_ie) <= rsn_ie_len); - - return pos - rsn_ie; -#else /* CONFIG_NO_WPA2 */ - return -1; -#endif /* CONFIG_NO_WPA2 */ -} - - -/** - * wpa_gen_wpa_ie - Generate WPA/RSN IE based on current security policy - * @sm: Pointer to WPA state machine data from wpa_sm_init() - * @wpa_ie: Pointer to memory area for the generated WPA/RSN IE - * @wpa_ie_len: Maximum length of the generated WPA/RSN IE - * Returns: Length of the generated WPA/RSN IE or -1 on failure - */ -int wpa_gen_wpa_ie(struct wpa_sm *sm, u8 *wpa_ie, size_t wpa_ie_len) -{ - if (sm->proto == WPA_PROTO_RSN) - return wpa_gen_wpa_ie_rsn(wpa_ie, wpa_ie_len, - sm->pairwise_cipher, - sm->group_cipher, - sm->key_mgmt, sm->mgmt_group_cipher, - sm); - else - return wpa_gen_wpa_ie_wpa(wpa_ie, wpa_ie_len, - sm->pairwise_cipher, - sm->group_cipher, - sm->key_mgmt); -} - - -/** - * wpa_parse_generic - Parse EAPOL-Key Key Data Generic IEs - * @pos: Pointer to the IE header - * @end: Pointer to the end of the Key Data buffer - * @ie: Pointer to parsed IE data - * Returns: 0 on success, 1 if end mark is found, -1 on failure - */ -static int wpa_parse_generic(const u8 *pos, const u8 *end, - struct wpa_eapol_ie_parse *ie) -{ - if (pos[1] == 0) - return 1; - - if (pos[1] >= 6 && - RSN_SELECTOR_GET(pos + 2) == WPA_OUI_TYPE && - pos[2 + WPA_SELECTOR_LEN] == 1 && - pos[2 + WPA_SELECTOR_LEN + 1] == 0) { - ie->wpa_ie = pos; - ie->wpa_ie_len = pos[1] + 2; - wpa_hexdump(MSG_DEBUG, "WPA: WPA IE in EAPOL-Key", - ie->wpa_ie, ie->wpa_ie_len); - return 0; - } - - if (pos + 1 + RSN_SELECTOR_LEN < end && - pos[1] >= RSN_SELECTOR_LEN + PMKID_LEN && - RSN_SELECTOR_GET(pos + 2) == RSN_KEY_DATA_PMKID) { - ie->pmkid = pos + 2 + RSN_SELECTOR_LEN; - wpa_hexdump(MSG_DEBUG, "WPA: PMKID in EAPOL-Key", - pos, pos[1] + 2); - return 0; - } - - if (pos[1] > RSN_SELECTOR_LEN + 2 && - RSN_SELECTOR_GET(pos + 2) == RSN_KEY_DATA_GROUPKEY) { - ie->gtk = pos + 2 + RSN_SELECTOR_LEN; - ie->gtk_len = pos[1] - RSN_SELECTOR_LEN; - wpa_hexdump_key(MSG_DEBUG, "WPA: GTK in EAPOL-Key", - pos, pos[1] + 2); - return 0; - } - - if (pos[1] > RSN_SELECTOR_LEN + 2 && - RSN_SELECTOR_GET(pos + 2) == RSN_KEY_DATA_MAC_ADDR) { - ie->mac_addr = pos + 2 + RSN_SELECTOR_LEN; - ie->mac_addr_len = pos[1] - RSN_SELECTOR_LEN; - wpa_hexdump(MSG_DEBUG, "WPA: MAC Address in EAPOL-Key", - pos, pos[1] + 2); - return 0; - } - -#ifdef CONFIG_PEERKEY - if (pos[1] > RSN_SELECTOR_LEN + 2 && - RSN_SELECTOR_GET(pos + 2) == RSN_KEY_DATA_SMK) { - ie->smk = pos + 2 + RSN_SELECTOR_LEN; - ie->smk_len = pos[1] - RSN_SELECTOR_LEN; - wpa_hexdump_key(MSG_DEBUG, "WPA: SMK in EAPOL-Key", - pos, pos[1] + 2); - return 0; - } - - if (pos[1] > RSN_SELECTOR_LEN + 2 && - RSN_SELECTOR_GET(pos + 2) == RSN_KEY_DATA_NONCE) { - ie->nonce = pos + 2 + RSN_SELECTOR_LEN; - ie->nonce_len = pos[1] - RSN_SELECTOR_LEN; - wpa_hexdump(MSG_DEBUG, "WPA: Nonce in EAPOL-Key", - pos, pos[1] + 2); - return 0; - } - - if (pos[1] > RSN_SELECTOR_LEN + 2 && - RSN_SELECTOR_GET(pos + 2) == RSN_KEY_DATA_LIFETIME) { - ie->lifetime = pos + 2 + RSN_SELECTOR_LEN; - ie->lifetime_len = pos[1] - RSN_SELECTOR_LEN; - wpa_hexdump(MSG_DEBUG, "WPA: Lifetime in EAPOL-Key", - pos, pos[1] + 2); - return 0; - } - - if (pos[1] > RSN_SELECTOR_LEN + 2 && - RSN_SELECTOR_GET(pos + 2) == RSN_KEY_DATA_ERROR) { - ie->error = pos + 2 + RSN_SELECTOR_LEN; - ie->error_len = pos[1] - RSN_SELECTOR_LEN; - wpa_hexdump(MSG_DEBUG, "WPA: Error in EAPOL-Key", - pos, pos[1] + 2); - return 0; - } -#endif /* CONFIG_PEERKEY */ - -#ifdef CONFIG_IEEE80211W - if (pos[1] > RSN_SELECTOR_LEN + 2 && - RSN_SELECTOR_GET(pos + 2) == RSN_KEY_DATA_IGTK) { - ie->igtk = pos + 2 + RSN_SELECTOR_LEN; - ie->igtk_len = pos[1] - RSN_SELECTOR_LEN; - wpa_hexdump_key(MSG_DEBUG, "WPA: IGTK in EAPOL-Key", - pos, pos[1] + 2); - return 0; - } -#endif /* CONFIG_IEEE80211W */ - - return 0; -} - - -/** - * wpa_supplicant_parse_ies - Parse EAPOL-Key Key Data IEs - * @buf: Pointer to the Key Data buffer - * @len: Key Data Length - * @ie: Pointer to parsed IE data - * Returns: 0 on success, -1 on failure - */ -int wpa_supplicant_parse_ies(const u8 *buf, size_t len, - struct wpa_eapol_ie_parse *ie) -{ - const u8 *pos, *end; - int ret = 0; - - os_memset(ie, 0, sizeof(*ie)); - for (pos = buf, end = pos + len; pos + 1 < end; pos += 2 + pos[1]) { - if (pos[0] == 0xdd && - ((pos == buf + len - 1) || pos[1] == 0)) { - /* Ignore padding */ - break; - } - if (pos + 2 + pos[1] > end) { - wpa_printf(MSG_DEBUG, "WPA: EAPOL-Key Key Data " - "underflow (ie=%d len=%d pos=%d)", - pos[0], pos[1], (int) (pos - buf)); - wpa_hexdump_key(MSG_DEBUG, "WPA: Key Data", - buf, len); - ret = -1; - break; - } - if (*pos == WLAN_EID_RSN) { - ie->rsn_ie = pos; - ie->rsn_ie_len = pos[1] + 2; - wpa_hexdump(MSG_DEBUG, "WPA: RSN IE in EAPOL-Key", - ie->rsn_ie, ie->rsn_ie_len); - } else if (*pos == WLAN_EID_MOBILITY_DOMAIN) { - ie->mdie = pos; - ie->mdie_len = pos[1] + 2; - wpa_hexdump(MSG_DEBUG, "WPA: MDIE in EAPOL-Key", - ie->mdie, ie->mdie_len); - } else if (*pos == WLAN_EID_FAST_BSS_TRANSITION) { - ie->ftie = pos; - ie->ftie_len = pos[1] + 2; - wpa_hexdump(MSG_DEBUG, "WPA: FTIE in EAPOL-Key", - ie->ftie, ie->ftie_len); - } else if (*pos == WLAN_EID_TIMEOUT_INTERVAL && pos[1] >= 5) { - if (pos[2] == WLAN_TIMEOUT_REASSOC_DEADLINE) { - ie->reassoc_deadline = pos; - wpa_hexdump(MSG_DEBUG, "WPA: Reassoc Deadline " - "in EAPOL-Key", - ie->reassoc_deadline, pos[1] + 2); - } else if (pos[2] == WLAN_TIMEOUT_KEY_LIFETIME) { - ie->key_lifetime = pos; - wpa_hexdump(MSG_DEBUG, "WPA: KeyLifetime " - "in EAPOL-Key", - ie->key_lifetime, pos[1] + 2); - } else { - wpa_hexdump(MSG_DEBUG, "WPA: Unrecognized " - "EAPOL-Key Key Data IE", - pos, 2 + pos[1]); - } - } else if (*pos == WLAN_EID_LINK_ID) { - ie->lnkid = pos; - ie->lnkid_len = pos[1] + 2; - } else if (*pos == WLAN_EID_EXT_CAPAB) { - ie->ext_capab = pos; - ie->ext_capab_len = pos[1] + 2; - } else if (*pos == WLAN_EID_VENDOR_SPECIFIC) { - ret = wpa_parse_generic(pos, end, ie); - if (ret < 0) - break; - if (ret > 0) { - ret = 0; - break; - } - } else { - wpa_hexdump(MSG_DEBUG, "WPA: Unrecognized EAPOL-Key " - "Key Data IE", pos, 2 + pos[1]); - } - } - - return ret; -} diff --git a/hostapd-0.8/src/rsn_supp/wpa_ie.h b/hostapd-0.8/src/rsn_supp/wpa_ie.h deleted file mode 100644 index f939b13..0000000 --- a/hostapd-0.8/src/rsn_supp/wpa_ie.h +++ /dev/null @@ -1,60 +0,0 @@ -/* - * wpa_supplicant - WPA/RSN IE and KDE definitions - * Copyright (c) 2004-2007, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#ifndef WPA_IE_H -#define WPA_IE_H - -struct wpa_sm; - -struct wpa_eapol_ie_parse { - const u8 *wpa_ie; - size_t wpa_ie_len; - const u8 *rsn_ie; - size_t rsn_ie_len; - const u8 *pmkid; - const u8 *gtk; - size_t gtk_len; - const u8 *mac_addr; - size_t mac_addr_len; -#ifdef CONFIG_PEERKEY - const u8 *smk; - size_t smk_len; - const u8 *nonce; - size_t nonce_len; - const u8 *lifetime; - size_t lifetime_len; - const u8 *error; - size_t error_len; -#endif /* CONFIG_PEERKEY */ -#ifdef CONFIG_IEEE80211W - const u8 *igtk; - size_t igtk_len; -#endif /* CONFIG_IEEE80211W */ - const u8 *mdie; - size_t mdie_len; - const u8 *ftie; - size_t ftie_len; - const u8 *reassoc_deadline; - const u8 *key_lifetime; - const u8 *lnkid; - size_t lnkid_len; - const u8 *ext_capab; - size_t ext_capab_len; -}; - -int wpa_supplicant_parse_ies(const u8 *buf, size_t len, - struct wpa_eapol_ie_parse *ie); -int wpa_gen_wpa_ie(struct wpa_sm *sm, u8 *wpa_ie, size_t wpa_ie_len); - -#endif /* WPA_IE_H */ diff --git a/hostapd-0.8/src/tls/.gitignore b/hostapd-0.8/src/tls/.gitignore deleted file mode 100644 index d43242d..0000000 --- a/hostapd-0.8/src/tls/.gitignore +++ /dev/null @@ -1 +0,0 @@ -libtls.a diff --git a/hostapd-0.8/src/tls/Makefile b/hostapd-0.8/src/tls/Makefile deleted file mode 100644 index a2da096..0000000 --- a/hostapd-0.8/src/tls/Makefile +++ /dev/null @@ -1,37 +0,0 @@ -all: libtls.a - -clean: - rm -f *~ *.o *.d libtls.a - -install: - @echo Nothing to be made. - - -include ../lib.rules - -CFLAGS += -DCONFIG_INTERNAL_LIBTOMMATH -CFLAGS += -DCONFIG_CRYPTO_INTERNAL - -LIB_OBJS= \ - asn1.o \ - bignum.o \ - pkcs1.o \ - pkcs5.o \ - pkcs8.o \ - rsa.o \ - tlsv1_client.o \ - tlsv1_client_read.o \ - tlsv1_client_write.o \ - tlsv1_common.o \ - tlsv1_cred.o \ - tlsv1_record.o \ - tlsv1_server.o \ - tlsv1_server_read.o \ - tlsv1_server_write.o \ - x509v3.o - - -libtls.a: $(LIB_OBJS) - $(AR) crT $@ $? - --include $(OBJS:%.o=%.d) diff --git a/hostapd-0.8/src/tls/asn1.c b/hostapd-0.8/src/tls/asn1.c deleted file mode 100644 index 3391245..0000000 --- a/hostapd-0.8/src/tls/asn1.c +++ /dev/null @@ -1,212 +0,0 @@ -/* - * ASN.1 DER parsing - * Copyright (c) 2006, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#include "includes.h" - -#include "common.h" -#include "asn1.h" - -int asn1_get_next(const u8 *buf, size_t len, struct asn1_hdr *hdr) -{ - const u8 *pos, *end; - u8 tmp; - - os_memset(hdr, 0, sizeof(*hdr)); - pos = buf; - end = buf + len; - - hdr->identifier = *pos++; - hdr->class = hdr->identifier >> 6; - hdr->constructed = !!(hdr->identifier & (1 << 5)); - - if ((hdr->identifier & 0x1f) == 0x1f) { - hdr->tag = 0; - do { - if (pos >= end) { - wpa_printf(MSG_DEBUG, "ASN.1: Identifier " - "underflow"); - return -1; - } - tmp = *pos++; - wpa_printf(MSG_MSGDUMP, "ASN.1: Extended tag data: " - "0x%02x", tmp); - hdr->tag = (hdr->tag << 7) | (tmp & 0x7f); - } while (tmp & 0x80); - } else - hdr->tag = hdr->identifier & 0x1f; - - tmp = *pos++; - if (tmp & 0x80) { - if (tmp == 0xff) { - wpa_printf(MSG_DEBUG, "ASN.1: Reserved length " - "value 0xff used"); - return -1; - } - tmp &= 0x7f; /* number of subsequent octets */ - hdr->length = 0; - if (tmp > 4) { - wpa_printf(MSG_DEBUG, "ASN.1: Too long length field"); - return -1; - } - while (tmp--) { - if (pos >= end) { - wpa_printf(MSG_DEBUG, "ASN.1: Length " - "underflow"); - return -1; - } - hdr->length = (hdr->length << 8) | *pos++; - } - } else { - /* Short form - length 0..127 in one octet */ - hdr->length = tmp; - } - - if (end < pos || hdr->length > (unsigned int) (end - pos)) { - wpa_printf(MSG_DEBUG, "ASN.1: Contents underflow"); - return -1; - } - - hdr->payload = pos; - return 0; -} - - -int asn1_parse_oid(const u8 *buf, size_t len, struct asn1_oid *oid) -{ - const u8 *pos, *end; - unsigned long val; - u8 tmp; - - os_memset(oid, 0, sizeof(*oid)); - - pos = buf; - end = buf + len; - - while (pos < end) { - val = 0; - - do { - if (pos >= end) - return -1; - tmp = *pos++; - val = (val << 7) | (tmp & 0x7f); - } while (tmp & 0x80); - - if (oid->len >= ASN1_MAX_OID_LEN) { - wpa_printf(MSG_DEBUG, "ASN.1: Too long OID value"); - return -1; - } - if (oid->len == 0) { - /* - * The first octet encodes the first two object - * identifier components in (X*40) + Y formula. - * X = 0..2. - */ - oid->oid[0] = val / 40; - if (oid->oid[0] > 2) - oid->oid[0] = 2; - oid->oid[1] = val - oid->oid[0] * 40; - oid->len = 2; - } else - oid->oid[oid->len++] = val; - } - - return 0; -} - - -int asn1_get_oid(const u8 *buf, size_t len, struct asn1_oid *oid, - const u8 **next) -{ - struct asn1_hdr hdr; - - if (asn1_get_next(buf, len, &hdr) < 0 || hdr.length == 0) - return -1; - - if (hdr.class != ASN1_CLASS_UNIVERSAL || hdr.tag != ASN1_TAG_OID) { - wpa_printf(MSG_DEBUG, "ASN.1: Expected OID - found class %d " - "tag 0x%x", hdr.class, hdr.tag); - return -1; - } - - *next = hdr.payload + hdr.length; - - return asn1_parse_oid(hdr.payload, hdr.length, oid); -} - - -void asn1_oid_to_str(struct asn1_oid *oid, char *buf, size_t len) -{ - char *pos = buf; - size_t i; - int ret; - - if (len == 0) - return; - - buf[0] = '\0'; - - for (i = 0; i < oid->len; i++) { - ret = os_snprintf(pos, buf + len - pos, - "%s%lu", - i == 0 ? "" : ".", oid->oid[i]); - if (ret < 0 || ret >= buf + len - pos) - break; - pos += ret; - } - buf[len - 1] = '\0'; -} - - -static u8 rotate_bits(u8 octet) -{ - int i; - u8 res; - - res = 0; - for (i = 0; i < 8; i++) { - res <<= 1; - if (octet & 1) - res |= 1; - octet >>= 1; - } - - return res; -} - - -unsigned long asn1_bit_string_to_long(const u8 *buf, size_t len) -{ - unsigned long val = 0; - const u8 *pos = buf; - - /* BER requires that unused bits are zero, so we can ignore the number - * of unused bits */ - pos++; - - if (len >= 2) - val |= rotate_bits(*pos++); - if (len >= 3) - val |= ((unsigned long) rotate_bits(*pos++)) << 8; - if (len >= 4) - val |= ((unsigned long) rotate_bits(*pos++)) << 16; - if (len >= 5) - val |= ((unsigned long) rotate_bits(*pos++)) << 24; - if (len >= 6) - wpa_printf(MSG_DEBUG, "X509: %s - some bits ignored " - "(BIT STRING length %lu)", - __func__, (unsigned long) len); - - return val; -} diff --git a/hostapd-0.8/src/tls/asn1.h b/hostapd-0.8/src/tls/asn1.h deleted file mode 100644 index 2ff571e..0000000 --- a/hostapd-0.8/src/tls/asn1.h +++ /dev/null @@ -1,72 +0,0 @@ -/* - * ASN.1 DER parsing - * Copyright (c) 2006, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#ifndef ASN1_H -#define ASN1_H - -#define ASN1_TAG_EOC 0x00 /* not used with DER */ -#define ASN1_TAG_BOOLEAN 0x01 -#define ASN1_TAG_INTEGER 0x02 -#define ASN1_TAG_BITSTRING 0x03 -#define ASN1_TAG_OCTETSTRING 0x04 -#define ASN1_TAG_NULL 0x05 -#define ASN1_TAG_OID 0x06 -#define ASN1_TAG_OBJECT_DESCRIPTOR 0x07 /* not yet parsed */ -#define ASN1_TAG_EXTERNAL 0x08 /* not yet parsed */ -#define ASN1_TAG_REAL 0x09 /* not yet parsed */ -#define ASN1_TAG_ENUMERATED 0x0A /* not yet parsed */ -#define ASN1_TAG_UTF8STRING 0x0C /* not yet parsed */ -#define ANS1_TAG_RELATIVE_OID 0x0D -#define ASN1_TAG_SEQUENCE 0x10 /* shall be constructed */ -#define ASN1_TAG_SET 0x11 -#define ASN1_TAG_NUMERICSTRING 0x12 /* not yet parsed */ -#define ASN1_TAG_PRINTABLESTRING 0x13 -#define ASN1_TAG_TG1STRING 0x14 /* not yet parsed */ -#define ASN1_TAG_VIDEOTEXSTRING 0x15 /* not yet parsed */ -#define ASN1_TAG_IA5STRING 0x16 -#define ASN1_TAG_UTCTIME 0x17 -#define ASN1_TAG_GENERALIZEDTIME 0x18 /* not yet parsed */ -#define ASN1_TAG_GRAPHICSTRING 0x19 /* not yet parsed */ -#define ASN1_TAG_VISIBLESTRING 0x1A -#define ASN1_TAG_GENERALSTRING 0x1B /* not yet parsed */ -#define ASN1_TAG_UNIVERSALSTRING 0x1C /* not yet parsed */ -#define ASN1_TAG_BMPSTRING 0x1D /* not yet parsed */ - -#define ASN1_CLASS_UNIVERSAL 0 -#define ASN1_CLASS_APPLICATION 1 -#define ASN1_CLASS_CONTEXT_SPECIFIC 2 -#define ASN1_CLASS_PRIVATE 3 - - -struct asn1_hdr { - const u8 *payload; - u8 identifier, class, constructed; - unsigned int tag, length; -}; - -#define ASN1_MAX_OID_LEN 20 -struct asn1_oid { - unsigned long oid[ASN1_MAX_OID_LEN]; - size_t len; -}; - - -int asn1_get_next(const u8 *buf, size_t len, struct asn1_hdr *hdr); -int asn1_parse_oid(const u8 *buf, size_t len, struct asn1_oid *oid); -int asn1_get_oid(const u8 *buf, size_t len, struct asn1_oid *oid, - const u8 **next); -void asn1_oid_to_str(struct asn1_oid *oid, char *buf, size_t len); -unsigned long asn1_bit_string_to_long(const u8 *buf, size_t len); - -#endif /* ASN1_H */ diff --git a/hostapd-0.8/src/tls/bignum.c b/hostapd-0.8/src/tls/bignum.c deleted file mode 100644 index 5c0fc62..0000000 --- a/hostapd-0.8/src/tls/bignum.c +++ /dev/null @@ -1,230 +0,0 @@ -/* - * Big number math - * Copyright (c) 2006, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#include "includes.h" - -#include "common.h" -#include "bignum.h" - -#ifdef CONFIG_INTERNAL_LIBTOMMATH -#include "libtommath.c" -#else /* CONFIG_INTERNAL_LIBTOMMATH */ -#include -#endif /* CONFIG_INTERNAL_LIBTOMMATH */ - - -/* - * The current version is just a wrapper for LibTomMath library, so - * struct bignum is just typecast to mp_int. - */ - -/** - * bignum_init - Allocate memory for bignum - * Returns: Pointer to allocated bignum or %NULL on failure - */ -struct bignum * bignum_init(void) -{ - struct bignum *n = os_zalloc(sizeof(mp_int)); - if (n == NULL) - return NULL; - if (mp_init((mp_int *) n) != MP_OKAY) { - os_free(n); - n = NULL; - } - return n; -} - - -/** - * bignum_deinit - Free bignum - * @n: Bignum from bignum_init() - */ -void bignum_deinit(struct bignum *n) -{ - if (n) { - mp_clear((mp_int *) n); - os_free(n); - } -} - - -/** - * bignum_get_unsigned_bin - Get length of bignum as an unsigned binary buffer - * @n: Bignum from bignum_init() - * Returns: Length of n if written to a binary buffer - */ -size_t bignum_get_unsigned_bin_len(struct bignum *n) -{ - return mp_unsigned_bin_size((mp_int *) n); -} - - -/** - * bignum_get_unsigned_bin - Set binary buffer to unsigned bignum - * @n: Bignum from bignum_init() - * @buf: Buffer for the binary number - * @len: Length of the buffer, can be %NULL if buffer is known to be long - * enough. Set to used buffer length on success if not %NULL. - * Returns: 0 on success, -1 on failure - */ -int bignum_get_unsigned_bin(const struct bignum *n, u8 *buf, size_t *len) -{ - size_t need = mp_unsigned_bin_size((mp_int *) n); - if (len && need > *len) { - *len = need; - return -1; - } - if (mp_to_unsigned_bin((mp_int *) n, buf) != MP_OKAY) { - wpa_printf(MSG_DEBUG, "BIGNUM: %s failed", __func__); - return -1; - } - if (len) - *len = need; - return 0; -} - - -/** - * bignum_set_unsigned_bin - Set bignum based on unsigned binary buffer - * @n: Bignum from bignum_init(); to be set to the given value - * @buf: Buffer with unsigned binary value - * @len: Length of buf in octets - * Returns: 0 on success, -1 on failure - */ -int bignum_set_unsigned_bin(struct bignum *n, const u8 *buf, size_t len) -{ - if (mp_read_unsigned_bin((mp_int *) n, (u8 *) buf, len) != MP_OKAY) { - wpa_printf(MSG_DEBUG, "BIGNUM: %s failed", __func__); - return -1; - } - return 0; -} - - -/** - * bignum_cmp - Signed comparison - * @a: Bignum from bignum_init() - * @b: Bignum from bignum_init() - * Returns: 0 on success, -1 on failure - */ -int bignum_cmp(const struct bignum *a, const struct bignum *b) -{ - return mp_cmp((mp_int *) a, (mp_int *) b); -} - - -/** - * bignum_cmd_d - Compare bignum to standard integer - * @a: Bignum from bignum_init() - * @b: Small integer - * Returns: 0 on success, -1 on failure - */ -int bignum_cmp_d(const struct bignum *a, unsigned long b) -{ - return mp_cmp_d((mp_int *) a, b); -} - - -/** - * bignum_add - c = a + b - * @a: Bignum from bignum_init() - * @b: Bignum from bignum_init() - * @c: Bignum from bignum_init(); used to store the result of a + b - * Returns: 0 on success, -1 on failure - */ -int bignum_add(const struct bignum *a, const struct bignum *b, - struct bignum *c) -{ - if (mp_add((mp_int *) a, (mp_int *) b, (mp_int *) c) != MP_OKAY) { - wpa_printf(MSG_DEBUG, "BIGNUM: %s failed", __func__); - return -1; - } - return 0; -} - - -/** - * bignum_sub - c = a - b - * @a: Bignum from bignum_init() - * @b: Bignum from bignum_init() - * @c: Bignum from bignum_init(); used to store the result of a - b - * Returns: 0 on success, -1 on failure - */ -int bignum_sub(const struct bignum *a, const struct bignum *b, - struct bignum *c) -{ - if (mp_sub((mp_int *) a, (mp_int *) b, (mp_int *) c) != MP_OKAY) { - wpa_printf(MSG_DEBUG, "BIGNUM: %s failed", __func__); - return -1; - } - return 0; -} - - -/** - * bignum_mul - c = a * b - * @a: Bignum from bignum_init() - * @b: Bignum from bignum_init() - * @c: Bignum from bignum_init(); used to store the result of a * b - * Returns: 0 on success, -1 on failure - */ -int bignum_mul(const struct bignum *a, const struct bignum *b, - struct bignum *c) -{ - if (mp_mul((mp_int *) a, (mp_int *) b, (mp_int *) c) != MP_OKAY) { - wpa_printf(MSG_DEBUG, "BIGNUM: %s failed", __func__); - return -1; - } - return 0; -} - - -/** - * bignum_mulmod - d = a * b (mod c) - * @a: Bignum from bignum_init() - * @b: Bignum from bignum_init() - * @c: Bignum from bignum_init(); modulus - * @d: Bignum from bignum_init(); used to store the result of a * b (mod c) - * Returns: 0 on success, -1 on failure - */ -int bignum_mulmod(const struct bignum *a, const struct bignum *b, - const struct bignum *c, struct bignum *d) -{ - if (mp_mulmod((mp_int *) a, (mp_int *) b, (mp_int *) c, (mp_int *) d) - != MP_OKAY) { - wpa_printf(MSG_DEBUG, "BIGNUM: %s failed", __func__); - return -1; - } - return 0; -} - - -/** - * bignum_exptmod - Modular exponentiation: d = a^b (mod c) - * @a: Bignum from bignum_init(); base - * @b: Bignum from bignum_init(); exponent - * @c: Bignum from bignum_init(); modulus - * @d: Bignum from bignum_init(); used to store the result of a^b (mod c) - * Returns: 0 on success, -1 on failure - */ -int bignum_exptmod(const struct bignum *a, const struct bignum *b, - const struct bignum *c, struct bignum *d) -{ - if (mp_exptmod((mp_int *) a, (mp_int *) b, (mp_int *) c, (mp_int *) d) - != MP_OKAY) { - wpa_printf(MSG_DEBUG, "BIGNUM: %s failed", __func__); - return -1; - } - return 0; -} diff --git a/hostapd-0.8/src/tls/bignum.h b/hostapd-0.8/src/tls/bignum.h deleted file mode 100644 index f25e267..0000000 --- a/hostapd-0.8/src/tls/bignum.h +++ /dev/null @@ -1,38 +0,0 @@ -/* - * Big number math - * Copyright (c) 2006, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#ifndef BIGNUM_H -#define BIGNUM_H - -struct bignum; - -struct bignum * bignum_init(void); -void bignum_deinit(struct bignum *n); -size_t bignum_get_unsigned_bin_len(struct bignum *n); -int bignum_get_unsigned_bin(const struct bignum *n, u8 *buf, size_t *len); -int bignum_set_unsigned_bin(struct bignum *n, const u8 *buf, size_t len); -int bignum_cmp(const struct bignum *a, const struct bignum *b); -int bignum_cmp_d(const struct bignum *a, unsigned long b); -int bignum_add(const struct bignum *a, const struct bignum *b, - struct bignum *c); -int bignum_sub(const struct bignum *a, const struct bignum *b, - struct bignum *c); -int bignum_mul(const struct bignum *a, const struct bignum *b, - struct bignum *c); -int bignum_mulmod(const struct bignum *a, const struct bignum *b, - const struct bignum *c, struct bignum *d); -int bignum_exptmod(const struct bignum *a, const struct bignum *b, - const struct bignum *c, struct bignum *d); - -#endif /* BIGNUM_H */ diff --git a/hostapd-0.8/src/tls/libtommath.c b/hostapd-0.8/src/tls/libtommath.c deleted file mode 100644 index 2b23f30..0000000 --- a/hostapd-0.8/src/tls/libtommath.c +++ /dev/null @@ -1,3381 +0,0 @@ -/* - * Minimal code for RSA support from LibTomMath 0.41 - * http://libtom.org/ - * http://libtom.org/files/ltm-0.41.tar.bz2 - * This library was released in public domain by Tom St Denis. - * - * The combination in this file may not use all of the optimized algorithms - * from LibTomMath and may be considerable slower than the LibTomMath with its - * default settings. The main purpose of having this version here is to make it - * easier to build bignum.c wrapper without having to install and build an - * external library. - * - * If CONFIG_INTERNAL_LIBTOMMATH is defined, bignum.c includes this - * libtommath.c file instead of using the external LibTomMath library. - */ - -#ifndef CHAR_BIT -#define CHAR_BIT 8 -#endif - -#define BN_MP_INVMOD_C -#define BN_S_MP_EXPTMOD_C /* Note: #undef in tommath_superclass.h; this would - * require BN_MP_EXPTMOD_FAST_C instead */ -#define BN_S_MP_MUL_DIGS_C -#define BN_MP_INVMOD_SLOW_C -#define BN_S_MP_SQR_C -#define BN_S_MP_MUL_HIGH_DIGS_C /* Note: #undef in tommath_superclass.h; this - * would require other than mp_reduce */ - -#ifdef LTM_FAST - -/* Use faster div at the cost of about 1 kB */ -#define BN_MP_MUL_D_C - -/* Include faster exptmod (Montgomery) at the cost of about 2.5 kB in code */ -#define BN_MP_EXPTMOD_FAST_C -#define BN_MP_MONTGOMERY_SETUP_C -#define BN_FAST_MP_MONTGOMERY_REDUCE_C -#define BN_MP_MONTGOMERY_CALC_NORMALIZATION_C -#define BN_MP_MUL_2_C - -/* Include faster sqr at the cost of about 0.5 kB in code */ -#define BN_FAST_S_MP_SQR_C - -#else /* LTM_FAST */ - -#define BN_MP_DIV_SMALL -#define BN_MP_INIT_MULTI_C -#define BN_MP_CLEAR_MULTI_C -#define BN_MP_ABS_C -#endif /* LTM_FAST */ - -/* Current uses do not require support for negative exponent in exptmod, so we - * can save about 1.5 kB in leaving out invmod. */ -#define LTM_NO_NEG_EXP - -/* from tommath.h */ - -#ifndef MIN - #define MIN(x,y) ((x)<(y)?(x):(y)) -#endif - -#ifndef MAX - #define MAX(x,y) ((x)>(y)?(x):(y)) -#endif - -#define OPT_CAST(x) - -typedef unsigned long mp_digit; -typedef u64 mp_word; - -#define DIGIT_BIT 28 -#define MP_28BIT - - -#define XMALLOC os_malloc -#define XFREE os_free -#define XREALLOC os_realloc - - -#define MP_MASK ((((mp_digit)1)<<((mp_digit)DIGIT_BIT))-((mp_digit)1)) - -#define MP_LT -1 /* less than */ -#define MP_EQ 0 /* equal to */ -#define MP_GT 1 /* greater than */ - -#define MP_ZPOS 0 /* positive integer */ -#define MP_NEG 1 /* negative */ - -#define MP_OKAY 0 /* ok result */ -#define MP_MEM -2 /* out of mem */ -#define MP_VAL -3 /* invalid input */ - -#define MP_YES 1 /* yes response */ -#define MP_NO 0 /* no response */ - -typedef int mp_err; - -/* define this to use lower memory usage routines (exptmods mostly) */ -#define MP_LOW_MEM - -/* default precision */ -#ifndef MP_PREC - #ifndef MP_LOW_MEM - #define MP_PREC 32 /* default digits of precision */ - #else - #define MP_PREC 8 /* default digits of precision */ - #endif -#endif - -/* size of comba arrays, should be at least 2 * 2**(BITS_PER_WORD - BITS_PER_DIGIT*2) */ -#define MP_WARRAY (1 << (sizeof(mp_word) * CHAR_BIT - 2 * DIGIT_BIT + 1)) - -/* the infamous mp_int structure */ -typedef struct { - int used, alloc, sign; - mp_digit *dp; -} mp_int; - - -/* ---> Basic Manipulations <--- */ -#define mp_iszero(a) (((a)->used == 0) ? MP_YES : MP_NO) -#define mp_iseven(a) (((a)->used > 0 && (((a)->dp[0] & 1) == 0)) ? MP_YES : MP_NO) -#define mp_isodd(a) (((a)->used > 0 && (((a)->dp[0] & 1) == 1)) ? MP_YES : MP_NO) - - -/* prototypes for copied functions */ -#define s_mp_mul(a, b, c) s_mp_mul_digs(a, b, c, (a)->used + (b)->used + 1) -static int s_mp_exptmod(mp_int * G, mp_int * X, mp_int * P, mp_int * Y, int redmode); -static int s_mp_mul_digs (mp_int * a, mp_int * b, mp_int * c, int digs); -static int s_mp_sqr(mp_int * a, mp_int * b); -static int s_mp_mul_high_digs(mp_int * a, mp_int * b, mp_int * c, int digs); - -static int fast_s_mp_mul_digs (mp_int * a, mp_int * b, mp_int * c, int digs); - -#ifdef BN_MP_INIT_MULTI_C -static int mp_init_multi(mp_int *mp, ...); -#endif -#ifdef BN_MP_CLEAR_MULTI_C -static void mp_clear_multi(mp_int *mp, ...); -#endif -static int mp_lshd(mp_int * a, int b); -static void mp_set(mp_int * a, mp_digit b); -static void mp_clamp(mp_int * a); -static void mp_exch(mp_int * a, mp_int * b); -static void mp_rshd(mp_int * a, int b); -static void mp_zero(mp_int * a); -static int mp_mod_2d(mp_int * a, int b, mp_int * c); -static int mp_div_2d(mp_int * a, int b, mp_int * c, mp_int * d); -static int mp_init_copy(mp_int * a, mp_int * b); -static int mp_mul_2d(mp_int * a, int b, mp_int * c); -#ifndef LTM_NO_NEG_EXP -static int mp_div_2(mp_int * a, mp_int * b); -static int mp_invmod(mp_int * a, mp_int * b, mp_int * c); -static int mp_invmod_slow(mp_int * a, mp_int * b, mp_int * c); -#endif /* LTM_NO_NEG_EXP */ -static int mp_copy(mp_int * a, mp_int * b); -static int mp_count_bits(mp_int * a); -static int mp_div(mp_int * a, mp_int * b, mp_int * c, mp_int * d); -static int mp_mod(mp_int * a, mp_int * b, mp_int * c); -static int mp_grow(mp_int * a, int size); -static int mp_cmp_mag(mp_int * a, mp_int * b); -#ifdef BN_MP_ABS_C -static int mp_abs(mp_int * a, mp_int * b); -#endif -static int mp_sqr(mp_int * a, mp_int * b); -static int mp_reduce_2k_l(mp_int *a, mp_int *n, mp_int *d); -static int mp_reduce_2k_setup_l(mp_int *a, mp_int *d); -static int mp_2expt(mp_int * a, int b); -static int mp_reduce_setup(mp_int * a, mp_int * b); -static int mp_reduce(mp_int * x, mp_int * m, mp_int * mu); -static int mp_init_size(mp_int * a, int size); -#ifdef BN_MP_EXPTMOD_FAST_C -static int mp_exptmod_fast (mp_int * G, mp_int * X, mp_int * P, mp_int * Y, int redmode); -#endif /* BN_MP_EXPTMOD_FAST_C */ -#ifdef BN_FAST_S_MP_SQR_C -static int fast_s_mp_sqr (mp_int * a, mp_int * b); -#endif /* BN_FAST_S_MP_SQR_C */ -#ifdef BN_MP_MUL_D_C -static int mp_mul_d (mp_int * a, mp_digit b, mp_int * c); -#endif /* BN_MP_MUL_D_C */ - - - -/* functions from bn_.c */ - - -/* reverse an array, used for radix code */ -static void bn_reverse (unsigned char *s, int len) -{ - int ix, iy; - unsigned char t; - - ix = 0; - iy = len - 1; - while (ix < iy) { - t = s[ix]; - s[ix] = s[iy]; - s[iy] = t; - ++ix; - --iy; - } -} - - -/* low level addition, based on HAC pp.594, Algorithm 14.7 */ -static int s_mp_add (mp_int * a, mp_int * b, mp_int * c) -{ - mp_int *x; - int olduse, res, min, max; - - /* find sizes, we let |a| <= |b| which means we have to sort - * them. "x" will point to the input with the most digits - */ - if (a->used > b->used) { - min = b->used; - max = a->used; - x = a; - } else { - min = a->used; - max = b->used; - x = b; - } - - /* init result */ - if (c->alloc < max + 1) { - if ((res = mp_grow (c, max + 1)) != MP_OKAY) { - return res; - } - } - - /* get old used digit count and set new one */ - olduse = c->used; - c->used = max + 1; - - { - register mp_digit u, *tmpa, *tmpb, *tmpc; - register int i; - - /* alias for digit pointers */ - - /* first input */ - tmpa = a->dp; - - /* second input */ - tmpb = b->dp; - - /* destination */ - tmpc = c->dp; - - /* zero the carry */ - u = 0; - for (i = 0; i < min; i++) { - /* Compute the sum at one digit, T[i] = A[i] + B[i] + U */ - *tmpc = *tmpa++ + *tmpb++ + u; - - /* U = carry bit of T[i] */ - u = *tmpc >> ((mp_digit)DIGIT_BIT); - - /* take away carry bit from T[i] */ - *tmpc++ &= MP_MASK; - } - - /* now copy higher words if any, that is in A+B - * if A or B has more digits add those in - */ - if (min != max) { - for (; i < max; i++) { - /* T[i] = X[i] + U */ - *tmpc = x->dp[i] + u; - - /* U = carry bit of T[i] */ - u = *tmpc >> ((mp_digit)DIGIT_BIT); - - /* take away carry bit from T[i] */ - *tmpc++ &= MP_MASK; - } - } - - /* add carry */ - *tmpc++ = u; - - /* clear digits above oldused */ - for (i = c->used; i < olduse; i++) { - *tmpc++ = 0; - } - } - - mp_clamp (c); - return MP_OKAY; -} - - -/* low level subtraction (assumes |a| > |b|), HAC pp.595 Algorithm 14.9 */ -static int s_mp_sub (mp_int * a, mp_int * b, mp_int * c) -{ - int olduse, res, min, max; - - /* find sizes */ - min = b->used; - max = a->used; - - /* init result */ - if (c->alloc < max) { - if ((res = mp_grow (c, max)) != MP_OKAY) { - return res; - } - } - olduse = c->used; - c->used = max; - - { - register mp_digit u, *tmpa, *tmpb, *tmpc; - register int i; - - /* alias for digit pointers */ - tmpa = a->dp; - tmpb = b->dp; - tmpc = c->dp; - - /* set carry to zero */ - u = 0; - for (i = 0; i < min; i++) { - /* T[i] = A[i] - B[i] - U */ - *tmpc = *tmpa++ - *tmpb++ - u; - - /* U = carry bit of T[i] - * Note this saves performing an AND operation since - * if a carry does occur it will propagate all the way to the - * MSB. As a result a single shift is enough to get the carry - */ - u = *tmpc >> ((mp_digit)(CHAR_BIT * sizeof (mp_digit) - 1)); - - /* Clear carry from T[i] */ - *tmpc++ &= MP_MASK; - } - - /* now copy higher words if any, e.g. if A has more digits than B */ - for (; i < max; i++) { - /* T[i] = A[i] - U */ - *tmpc = *tmpa++ - u; - - /* U = carry bit of T[i] */ - u = *tmpc >> ((mp_digit)(CHAR_BIT * sizeof (mp_digit) - 1)); - - /* Clear carry from T[i] */ - *tmpc++ &= MP_MASK; - } - - /* clear digits above used (since we may not have grown result above) */ - for (i = c->used; i < olduse; i++) { - *tmpc++ = 0; - } - } - - mp_clamp (c); - return MP_OKAY; -} - - -/* init a new mp_int */ -static int mp_init (mp_int * a) -{ - int i; - - /* allocate memory required and clear it */ - a->dp = OPT_CAST(mp_digit) XMALLOC (sizeof (mp_digit) * MP_PREC); - if (a->dp == NULL) { - return MP_MEM; - } - - /* set the digits to zero */ - for (i = 0; i < MP_PREC; i++) { - a->dp[i] = 0; - } - - /* set the used to zero, allocated digits to the default precision - * and sign to positive */ - a->used = 0; - a->alloc = MP_PREC; - a->sign = MP_ZPOS; - - return MP_OKAY; -} - - -/* clear one (frees) */ -static void mp_clear (mp_int * a) -{ - int i; - - /* only do anything if a hasn't been freed previously */ - if (a->dp != NULL) { - /* first zero the digits */ - for (i = 0; i < a->used; i++) { - a->dp[i] = 0; - } - - /* free ram */ - XFREE(a->dp); - - /* reset members to make debugging easier */ - a->dp = NULL; - a->alloc = a->used = 0; - a->sign = MP_ZPOS; - } -} - - -/* high level addition (handles signs) */ -static int mp_add (mp_int * a, mp_int * b, mp_int * c) -{ - int sa, sb, res; - - /* get sign of both inputs */ - sa = a->sign; - sb = b->sign; - - /* handle two cases, not four */ - if (sa == sb) { - /* both positive or both negative */ - /* add their magnitudes, copy the sign */ - c->sign = sa; - res = s_mp_add (a, b, c); - } else { - /* one positive, the other negative */ - /* subtract the one with the greater magnitude from */ - /* the one of the lesser magnitude. The result gets */ - /* the sign of the one with the greater magnitude. */ - if (mp_cmp_mag (a, b) == MP_LT) { - c->sign = sb; - res = s_mp_sub (b, a, c); - } else { - c->sign = sa; - res = s_mp_sub (a, b, c); - } - } - return res; -} - - -/* high level subtraction (handles signs) */ -static int mp_sub (mp_int * a, mp_int * b, mp_int * c) -{ - int sa, sb, res; - - sa = a->sign; - sb = b->sign; - - if (sa != sb) { - /* subtract a negative from a positive, OR */ - /* subtract a positive from a negative. */ - /* In either case, ADD their magnitudes, */ - /* and use the sign of the first number. */ - c->sign = sa; - res = s_mp_add (a, b, c); - } else { - /* subtract a positive from a positive, OR */ - /* subtract a negative from a negative. */ - /* First, take the difference between their */ - /* magnitudes, then... */ - if (mp_cmp_mag (a, b) != MP_LT) { - /* Copy the sign from the first */ - c->sign = sa; - /* The first has a larger or equal magnitude */ - res = s_mp_sub (a, b, c); - } else { - /* The result has the *opposite* sign from */ - /* the first number. */ - c->sign = (sa == MP_ZPOS) ? MP_NEG : MP_ZPOS; - /* The second has a larger magnitude */ - res = s_mp_sub (b, a, c); - } - } - return res; -} - - -/* high level multiplication (handles sign) */ -static int mp_mul (mp_int * a, mp_int * b, mp_int * c) -{ - int res, neg; - neg = (a->sign == b->sign) ? MP_ZPOS : MP_NEG; - - /* use Toom-Cook? */ -#ifdef BN_MP_TOOM_MUL_C - if (MIN (a->used, b->used) >= TOOM_MUL_CUTOFF) { - res = mp_toom_mul(a, b, c); - } else -#endif -#ifdef BN_MP_KARATSUBA_MUL_C - /* use Karatsuba? */ - if (MIN (a->used, b->used) >= KARATSUBA_MUL_CUTOFF) { - res = mp_karatsuba_mul (a, b, c); - } else -#endif - { - /* can we use the fast multiplier? - * - * The fast multiplier can be used if the output will - * have less than MP_WARRAY digits and the number of - * digits won't affect carry propagation - */ -#ifdef BN_FAST_S_MP_MUL_DIGS_C - int digs = a->used + b->used + 1; - - if ((digs < MP_WARRAY) && - MIN(a->used, b->used) <= - (1 << ((CHAR_BIT * sizeof (mp_word)) - (2 * DIGIT_BIT)))) { - res = fast_s_mp_mul_digs (a, b, c, digs); - } else -#endif -#ifdef BN_S_MP_MUL_DIGS_C - res = s_mp_mul (a, b, c); /* uses s_mp_mul_digs */ -#else -#error mp_mul could fail - res = MP_VAL; -#endif - - } - c->sign = (c->used > 0) ? neg : MP_ZPOS; - return res; -} - - -/* d = a * b (mod c) */ -static int mp_mulmod (mp_int * a, mp_int * b, mp_int * c, mp_int * d) -{ - int res; - mp_int t; - - if ((res = mp_init (&t)) != MP_OKAY) { - return res; - } - - if ((res = mp_mul (a, b, &t)) != MP_OKAY) { - mp_clear (&t); - return res; - } - res = mp_mod (&t, c, d); - mp_clear (&t); - return res; -} - - -/* c = a mod b, 0 <= c < b */ -static int mp_mod (mp_int * a, mp_int * b, mp_int * c) -{ - mp_int t; - int res; - - if ((res = mp_init (&t)) != MP_OKAY) { - return res; - } - - if ((res = mp_div (a, b, NULL, &t)) != MP_OKAY) { - mp_clear (&t); - return res; - } - - if (t.sign != b->sign) { - res = mp_add (b, &t, c); - } else { - res = MP_OKAY; - mp_exch (&t, c); - } - - mp_clear (&t); - return res; -} - - -/* this is a shell function that calls either the normal or Montgomery - * exptmod functions. Originally the call to the montgomery code was - * embedded in the normal function but that wasted alot of stack space - * for nothing (since 99% of the time the Montgomery code would be called) - */ -static int mp_exptmod (mp_int * G, mp_int * X, mp_int * P, mp_int * Y) -{ - int dr = 0; - - /* modulus P must be positive */ - if (P->sign == MP_NEG) { - return MP_VAL; - } - - /* if exponent X is negative we have to recurse */ - if (X->sign == MP_NEG) { -#ifdef LTM_NO_NEG_EXP - return MP_VAL; -#else /* LTM_NO_NEG_EXP */ -#ifdef BN_MP_INVMOD_C - mp_int tmpG, tmpX; - int err; - - /* first compute 1/G mod P */ - if ((err = mp_init(&tmpG)) != MP_OKAY) { - return err; - } - if ((err = mp_invmod(G, P, &tmpG)) != MP_OKAY) { - mp_clear(&tmpG); - return err; - } - - /* now get |X| */ - if ((err = mp_init(&tmpX)) != MP_OKAY) { - mp_clear(&tmpG); - return err; - } - if ((err = mp_abs(X, &tmpX)) != MP_OKAY) { - mp_clear_multi(&tmpG, &tmpX, NULL); - return err; - } - - /* and now compute (1/G)**|X| instead of G**X [X < 0] */ - err = mp_exptmod(&tmpG, &tmpX, P, Y); - mp_clear_multi(&tmpG, &tmpX, NULL); - return err; -#else -#error mp_exptmod would always fail - /* no invmod */ - return MP_VAL; -#endif -#endif /* LTM_NO_NEG_EXP */ - } - -/* modified diminished radix reduction */ -#if defined(BN_MP_REDUCE_IS_2K_L_C) && defined(BN_MP_REDUCE_2K_L_C) && defined(BN_S_MP_EXPTMOD_C) - if (mp_reduce_is_2k_l(P) == MP_YES) { - return s_mp_exptmod(G, X, P, Y, 1); - } -#endif - -#ifdef BN_MP_DR_IS_MODULUS_C - /* is it a DR modulus? */ - dr = mp_dr_is_modulus(P); -#else - /* default to no */ - dr = 0; -#endif - -#ifdef BN_MP_REDUCE_IS_2K_C - /* if not, is it a unrestricted DR modulus? */ - if (dr == 0) { - mp_reduce_is_2k(P) << 1; - } -#endif - - /* if the modulus is odd or dr != 0 use the montgomery method */ -#ifdef BN_MP_EXPTMOD_FAST_C - if (mp_isodd (P) == 1 || dr != 0) { - return mp_exptmod_fast (G, X, P, Y, dr); - } else { -#endif -#ifdef BN_S_MP_EXPTMOD_C - /* otherwise use the generic Barrett reduction technique */ - return s_mp_exptmod (G, X, P, Y, 0); -#else -#error mp_exptmod could fail - /* no exptmod for evens */ - return MP_VAL; -#endif -#ifdef BN_MP_EXPTMOD_FAST_C - } -#endif -} - - -/* compare two ints (signed)*/ -static int mp_cmp (mp_int * a, mp_int * b) -{ - /* compare based on sign */ - if (a->sign != b->sign) { - if (a->sign == MP_NEG) { - return MP_LT; - } else { - return MP_GT; - } - } - - /* compare digits */ - if (a->sign == MP_NEG) { - /* if negative compare opposite direction */ - return mp_cmp_mag(b, a); - } else { - return mp_cmp_mag(a, b); - } -} - - -/* compare a digit */ -static int mp_cmp_d(mp_int * a, mp_digit b) -{ - /* compare based on sign */ - if (a->sign == MP_NEG) { - return MP_LT; - } - - /* compare based on magnitude */ - if (a->used > 1) { - return MP_GT; - } - - /* compare the only digit of a to b */ - if (a->dp[0] > b) { - return MP_GT; - } else if (a->dp[0] < b) { - return MP_LT; - } else { - return MP_EQ; - } -} - - -#ifndef LTM_NO_NEG_EXP -/* hac 14.61, pp608 */ -static int mp_invmod (mp_int * a, mp_int * b, mp_int * c) -{ - /* b cannot be negative */ - if (b->sign == MP_NEG || mp_iszero(b) == 1) { - return MP_VAL; - } - -#ifdef BN_FAST_MP_INVMOD_C - /* if the modulus is odd we can use a faster routine instead */ - if (mp_isodd (b) == 1) { - return fast_mp_invmod (a, b, c); - } -#endif - -#ifdef BN_MP_INVMOD_SLOW_C - return mp_invmod_slow(a, b, c); -#endif - -#ifndef BN_FAST_MP_INVMOD_C -#ifndef BN_MP_INVMOD_SLOW_C -#error mp_invmod would always fail -#endif -#endif - return MP_VAL; -} -#endif /* LTM_NO_NEG_EXP */ - - -/* get the size for an unsigned equivalent */ -static int mp_unsigned_bin_size (mp_int * a) -{ - int size = mp_count_bits (a); - return (size / 8 + ((size & 7) != 0 ? 1 : 0)); -} - - -#ifndef LTM_NO_NEG_EXP -/* hac 14.61, pp608 */ -static int mp_invmod_slow (mp_int * a, mp_int * b, mp_int * c) -{ - mp_int x, y, u, v, A, B, C, D; - int res; - - /* b cannot be negative */ - if (b->sign == MP_NEG || mp_iszero(b) == 1) { - return MP_VAL; - } - - /* init temps */ - if ((res = mp_init_multi(&x, &y, &u, &v, - &A, &B, &C, &D, NULL)) != MP_OKAY) { - return res; - } - - /* x = a, y = b */ - if ((res = mp_mod(a, b, &x)) != MP_OKAY) { - goto LBL_ERR; - } - if ((res = mp_copy (b, &y)) != MP_OKAY) { - goto LBL_ERR; - } - - /* 2. [modified] if x,y are both even then return an error! */ - if (mp_iseven (&x) == 1 && mp_iseven (&y) == 1) { - res = MP_VAL; - goto LBL_ERR; - } - - /* 3. u=x, v=y, A=1, B=0, C=0,D=1 */ - if ((res = mp_copy (&x, &u)) != MP_OKAY) { - goto LBL_ERR; - } - if ((res = mp_copy (&y, &v)) != MP_OKAY) { - goto LBL_ERR; - } - mp_set (&A, 1); - mp_set (&D, 1); - -top: - /* 4. while u is even do */ - while (mp_iseven (&u) == 1) { - /* 4.1 u = u/2 */ - if ((res = mp_div_2 (&u, &u)) != MP_OKAY) { - goto LBL_ERR; - } - /* 4.2 if A or B is odd then */ - if (mp_isodd (&A) == 1 || mp_isodd (&B) == 1) { - /* A = (A+y)/2, B = (B-x)/2 */ - if ((res = mp_add (&A, &y, &A)) != MP_OKAY) { - goto LBL_ERR; - } - if ((res = mp_sub (&B, &x, &B)) != MP_OKAY) { - goto LBL_ERR; - } - } - /* A = A/2, B = B/2 */ - if ((res = mp_div_2 (&A, &A)) != MP_OKAY) { - goto LBL_ERR; - } - if ((res = mp_div_2 (&B, &B)) != MP_OKAY) { - goto LBL_ERR; - } - } - - /* 5. while v is even do */ - while (mp_iseven (&v) == 1) { - /* 5.1 v = v/2 */ - if ((res = mp_div_2 (&v, &v)) != MP_OKAY) { - goto LBL_ERR; - } - /* 5.2 if C or D is odd then */ - if (mp_isodd (&C) == 1 || mp_isodd (&D) == 1) { - /* C = (C+y)/2, D = (D-x)/2 */ - if ((res = mp_add (&C, &y, &C)) != MP_OKAY) { - goto LBL_ERR; - } - if ((res = mp_sub (&D, &x, &D)) != MP_OKAY) { - goto LBL_ERR; - } - } - /* C = C/2, D = D/2 */ - if ((res = mp_div_2 (&C, &C)) != MP_OKAY) { - goto LBL_ERR; - } - if ((res = mp_div_2 (&D, &D)) != MP_OKAY) { - goto LBL_ERR; - } - } - - /* 6. if u >= v then */ - if (mp_cmp (&u, &v) != MP_LT) { - /* u = u - v, A = A - C, B = B - D */ - if ((res = mp_sub (&u, &v, &u)) != MP_OKAY) { - goto LBL_ERR; - } - - if ((res = mp_sub (&A, &C, &A)) != MP_OKAY) { - goto LBL_ERR; - } - - if ((res = mp_sub (&B, &D, &B)) != MP_OKAY) { - goto LBL_ERR; - } - } else { - /* v - v - u, C = C - A, D = D - B */ - if ((res = mp_sub (&v, &u, &v)) != MP_OKAY) { - goto LBL_ERR; - } - - if ((res = mp_sub (&C, &A, &C)) != MP_OKAY) { - goto LBL_ERR; - } - - if ((res = mp_sub (&D, &B, &D)) != MP_OKAY) { - goto LBL_ERR; - } - } - - /* if not zero goto step 4 */ - if (mp_iszero (&u) == 0) - goto top; - - /* now a = C, b = D, gcd == g*v */ - - /* if v != 1 then there is no inverse */ - if (mp_cmp_d (&v, 1) != MP_EQ) { - res = MP_VAL; - goto LBL_ERR; - } - - /* if its too low */ - while (mp_cmp_d(&C, 0) == MP_LT) { - if ((res = mp_add(&C, b, &C)) != MP_OKAY) { - goto LBL_ERR; - } - } - - /* too big */ - while (mp_cmp_mag(&C, b) != MP_LT) { - if ((res = mp_sub(&C, b, &C)) != MP_OKAY) { - goto LBL_ERR; - } - } - - /* C is now the inverse */ - mp_exch (&C, c); - res = MP_OKAY; -LBL_ERR:mp_clear_multi (&x, &y, &u, &v, &A, &B, &C, &D, NULL); - return res; -} -#endif /* LTM_NO_NEG_EXP */ - - -/* compare maginitude of two ints (unsigned) */ -static int mp_cmp_mag (mp_int * a, mp_int * b) -{ - int n; - mp_digit *tmpa, *tmpb; - - /* compare based on # of non-zero digits */ - if (a->used > b->used) { - return MP_GT; - } - - if (a->used < b->used) { - return MP_LT; - } - - /* alias for a */ - tmpa = a->dp + (a->used - 1); - - /* alias for b */ - tmpb = b->dp + (a->used - 1); - - /* compare based on digits */ - for (n = 0; n < a->used; ++n, --tmpa, --tmpb) { - if (*tmpa > *tmpb) { - return MP_GT; - } - - if (*tmpa < *tmpb) { - return MP_LT; - } - } - return MP_EQ; -} - - -/* reads a unsigned char array, assumes the msb is stored first [big endian] */ -static int mp_read_unsigned_bin (mp_int * a, const unsigned char *b, int c) -{ - int res; - - /* make sure there are at least two digits */ - if (a->alloc < 2) { - if ((res = mp_grow(a, 2)) != MP_OKAY) { - return res; - } - } - - /* zero the int */ - mp_zero (a); - - /* read the bytes in */ - while (c-- > 0) { - if ((res = mp_mul_2d (a, 8, a)) != MP_OKAY) { - return res; - } - -#ifndef MP_8BIT - a->dp[0] |= *b++; - a->used += 1; -#else - a->dp[0] = (*b & MP_MASK); - a->dp[1] |= ((*b++ >> 7U) & 1); - a->used += 2; -#endif - } - mp_clamp (a); - return MP_OKAY; -} - - -/* store in unsigned [big endian] format */ -static int mp_to_unsigned_bin (mp_int * a, unsigned char *b) -{ - int x, res; - mp_int t; - - if ((res = mp_init_copy (&t, a)) != MP_OKAY) { - return res; - } - - x = 0; - while (mp_iszero (&t) == 0) { -#ifndef MP_8BIT - b[x++] = (unsigned char) (t.dp[0] & 255); -#else - b[x++] = (unsigned char) (t.dp[0] | ((t.dp[1] & 0x01) << 7)); -#endif - if ((res = mp_div_2d (&t, 8, &t, NULL)) != MP_OKAY) { - mp_clear (&t); - return res; - } - } - bn_reverse (b, x); - mp_clear (&t); - return MP_OKAY; -} - - -/* shift right by a certain bit count (store quotient in c, optional remainder in d) */ -static int mp_div_2d (mp_int * a, int b, mp_int * c, mp_int * d) -{ - mp_digit D, r, rr; - int x, res; - mp_int t; - - - /* if the shift count is <= 0 then we do no work */ - if (b <= 0) { - res = mp_copy (a, c); - if (d != NULL) { - mp_zero (d); - } - return res; - } - - if ((res = mp_init (&t)) != MP_OKAY) { - return res; - } - - /* get the remainder */ - if (d != NULL) { - if ((res = mp_mod_2d (a, b, &t)) != MP_OKAY) { - mp_clear (&t); - return res; - } - } - - /* copy */ - if ((res = mp_copy (a, c)) != MP_OKAY) { - mp_clear (&t); - return res; - } - - /* shift by as many digits in the bit count */ - if (b >= (int)DIGIT_BIT) { - mp_rshd (c, b / DIGIT_BIT); - } - - /* shift any bit count < DIGIT_BIT */ - D = (mp_digit) (b % DIGIT_BIT); - if (D != 0) { - register mp_digit *tmpc, mask, shift; - - /* mask */ - mask = (((mp_digit)1) << D) - 1; - - /* shift for lsb */ - shift = DIGIT_BIT - D; - - /* alias */ - tmpc = c->dp + (c->used - 1); - - /* carry */ - r = 0; - for (x = c->used - 1; x >= 0; x--) { - /* get the lower bits of this word in a temp */ - rr = *tmpc & mask; - - /* shift the current word and mix in the carry bits from the previous word */ - *tmpc = (*tmpc >> D) | (r << shift); - --tmpc; - - /* set the carry to the carry bits of the current word found above */ - r = rr; - } - } - mp_clamp (c); - if (d != NULL) { - mp_exch (&t, d); - } - mp_clear (&t); - return MP_OKAY; -} - - -static int mp_init_copy (mp_int * a, mp_int * b) -{ - int res; - - if ((res = mp_init (a)) != MP_OKAY) { - return res; - } - return mp_copy (b, a); -} - - -/* set to zero */ -static void mp_zero (mp_int * a) -{ - int n; - mp_digit *tmp; - - a->sign = MP_ZPOS; - a->used = 0; - - tmp = a->dp; - for (n = 0; n < a->alloc; n++) { - *tmp++ = 0; - } -} - - -/* copy, b = a */ -static int mp_copy (mp_int * a, mp_int * b) -{ - int res, n; - - /* if dst == src do nothing */ - if (a == b) { - return MP_OKAY; - } - - /* grow dest */ - if (b->alloc < a->used) { - if ((res = mp_grow (b, a->used)) != MP_OKAY) { - return res; - } - } - - /* zero b and copy the parameters over */ - { - register mp_digit *tmpa, *tmpb; - - /* pointer aliases */ - - /* source */ - tmpa = a->dp; - - /* destination */ - tmpb = b->dp; - - /* copy all the digits */ - for (n = 0; n < a->used; n++) { - *tmpb++ = *tmpa++; - } - - /* clear high digits */ - for (; n < b->used; n++) { - *tmpb++ = 0; - } - } - - /* copy used count and sign */ - b->used = a->used; - b->sign = a->sign; - return MP_OKAY; -} - - -/* shift right a certain amount of digits */ -static void mp_rshd (mp_int * a, int b) -{ - int x; - - /* if b <= 0 then ignore it */ - if (b <= 0) { - return; - } - - /* if b > used then simply zero it and return */ - if (a->used <= b) { - mp_zero (a); - return; - } - - { - register mp_digit *bottom, *top; - - /* shift the digits down */ - - /* bottom */ - bottom = a->dp; - - /* top [offset into digits] */ - top = a->dp + b; - - /* this is implemented as a sliding window where - * the window is b-digits long and digits from - * the top of the window are copied to the bottom - * - * e.g. - - b-2 | b-1 | b0 | b1 | b2 | ... | bb | ----> - /\ | ----> - \-------------------/ ----> - */ - for (x = 0; x < (a->used - b); x++) { - *bottom++ = *top++; - } - - /* zero the top digits */ - for (; x < a->used; x++) { - *bottom++ = 0; - } - } - - /* remove excess digits */ - a->used -= b; -} - - -/* swap the elements of two integers, for cases where you can't simply swap the - * mp_int pointers around - */ -static void mp_exch (mp_int * a, mp_int * b) -{ - mp_int t; - - t = *a; - *a = *b; - *b = t; -} - - -/* trim unused digits - * - * This is used to ensure that leading zero digits are - * trimed and the leading "used" digit will be non-zero - * Typically very fast. Also fixes the sign if there - * are no more leading digits - */ -static void mp_clamp (mp_int * a) -{ - /* decrease used while the most significant digit is - * zero. - */ - while (a->used > 0 && a->dp[a->used - 1] == 0) { - --(a->used); - } - - /* reset the sign flag if used == 0 */ - if (a->used == 0) { - a->sign = MP_ZPOS; - } -} - - -/* grow as required */ -static int mp_grow (mp_int * a, int size) -{ - int i; - mp_digit *tmp; - - /* if the alloc size is smaller alloc more ram */ - if (a->alloc < size) { - /* ensure there are always at least MP_PREC digits extra on top */ - size += (MP_PREC * 2) - (size % MP_PREC); - - /* reallocate the array a->dp - * - * We store the return in a temporary variable - * in case the operation failed we don't want - * to overwrite the dp member of a. - */ - tmp = OPT_CAST(mp_digit) XREALLOC (a->dp, sizeof (mp_digit) * size); - if (tmp == NULL) { - /* reallocation failed but "a" is still valid [can be freed] */ - return MP_MEM; - } - - /* reallocation succeeded so set a->dp */ - a->dp = tmp; - - /* zero excess digits */ - i = a->alloc; - a->alloc = size; - for (; i < a->alloc; i++) { - a->dp[i] = 0; - } - } - return MP_OKAY; -} - - -#ifdef BN_MP_ABS_C -/* b = |a| - * - * Simple function copies the input and fixes the sign to positive - */ -static int mp_abs (mp_int * a, mp_int * b) -{ - int res; - - /* copy a to b */ - if (a != b) { - if ((res = mp_copy (a, b)) != MP_OKAY) { - return res; - } - } - - /* force the sign of b to positive */ - b->sign = MP_ZPOS; - - return MP_OKAY; -} -#endif - - -/* set to a digit */ -static void mp_set (mp_int * a, mp_digit b) -{ - mp_zero (a); - a->dp[0] = b & MP_MASK; - a->used = (a->dp[0] != 0) ? 1 : 0; -} - - -#ifndef LTM_NO_NEG_EXP -/* b = a/2 */ -static int mp_div_2(mp_int * a, mp_int * b) -{ - int x, res, oldused; - - /* copy */ - if (b->alloc < a->used) { - if ((res = mp_grow (b, a->used)) != MP_OKAY) { - return res; - } - } - - oldused = b->used; - b->used = a->used; - { - register mp_digit r, rr, *tmpa, *tmpb; - - /* source alias */ - tmpa = a->dp + b->used - 1; - - /* dest alias */ - tmpb = b->dp + b->used - 1; - - /* carry */ - r = 0; - for (x = b->used - 1; x >= 0; x--) { - /* get the carry for the next iteration */ - rr = *tmpa & 1; - - /* shift the current digit, add in carry and store */ - *tmpb-- = (*tmpa-- >> 1) | (r << (DIGIT_BIT - 1)); - - /* forward carry to next iteration */ - r = rr; - } - - /* zero excess digits */ - tmpb = b->dp + b->used; - for (x = b->used; x < oldused; x++) { - *tmpb++ = 0; - } - } - b->sign = a->sign; - mp_clamp (b); - return MP_OKAY; -} -#endif /* LTM_NO_NEG_EXP */ - - -/* shift left by a certain bit count */ -static int mp_mul_2d (mp_int * a, int b, mp_int * c) -{ - mp_digit d; - int res; - - /* copy */ - if (a != c) { - if ((res = mp_copy (a, c)) != MP_OKAY) { - return res; - } - } - - if (c->alloc < (int)(c->used + b/DIGIT_BIT + 1)) { - if ((res = mp_grow (c, c->used + b / DIGIT_BIT + 1)) != MP_OKAY) { - return res; - } - } - - /* shift by as many digits in the bit count */ - if (b >= (int)DIGIT_BIT) { - if ((res = mp_lshd (c, b / DIGIT_BIT)) != MP_OKAY) { - return res; - } - } - - /* shift any bit count < DIGIT_BIT */ - d = (mp_digit) (b % DIGIT_BIT); - if (d != 0) { - register mp_digit *tmpc, shift, mask, r, rr; - register int x; - - /* bitmask for carries */ - mask = (((mp_digit)1) << d) - 1; - - /* shift for msbs */ - shift = DIGIT_BIT - d; - - /* alias */ - tmpc = c->dp; - - /* carry */ - r = 0; - for (x = 0; x < c->used; x++) { - /* get the higher bits of the current word */ - rr = (*tmpc >> shift) & mask; - - /* shift the current word and OR in the carry */ - *tmpc = ((*tmpc << d) | r) & MP_MASK; - ++tmpc; - - /* set the carry to the carry bits of the current word */ - r = rr; - } - - /* set final carry */ - if (r != 0) { - c->dp[(c->used)++] = r; - } - } - mp_clamp (c); - return MP_OKAY; -} - - -#ifdef BN_MP_INIT_MULTI_C -static int mp_init_multi(mp_int *mp, ...) -{ - mp_err res = MP_OKAY; /* Assume ok until proven otherwise */ - int n = 0; /* Number of ok inits */ - mp_int* cur_arg = mp; - va_list args; - - va_start(args, mp); /* init args to next argument from caller */ - while (cur_arg != NULL) { - if (mp_init(cur_arg) != MP_OKAY) { - /* Oops - error! Back-track and mp_clear what we already - succeeded in init-ing, then return error. - */ - va_list clean_args; - - /* end the current list */ - va_end(args); - - /* now start cleaning up */ - cur_arg = mp; - va_start(clean_args, mp); - while (n--) { - mp_clear(cur_arg); - cur_arg = va_arg(clean_args, mp_int*); - } - va_end(clean_args); - res = MP_MEM; - break; - } - n++; - cur_arg = va_arg(args, mp_int*); - } - va_end(args); - return res; /* Assumed ok, if error flagged above. */ -} -#endif - - -#ifdef BN_MP_CLEAR_MULTI_C -static void mp_clear_multi(mp_int *mp, ...) -{ - mp_int* next_mp = mp; - va_list args; - va_start(args, mp); - while (next_mp != NULL) { - mp_clear(next_mp); - next_mp = va_arg(args, mp_int*); - } - va_end(args); -} -#endif - - -/* shift left a certain amount of digits */ -static int mp_lshd (mp_int * a, int b) -{ - int x, res; - - /* if its less than zero return */ - if (b <= 0) { - return MP_OKAY; - } - - /* grow to fit the new digits */ - if (a->alloc < a->used + b) { - if ((res = mp_grow (a, a->used + b)) != MP_OKAY) { - return res; - } - } - - { - register mp_digit *top, *bottom; - - /* increment the used by the shift amount then copy upwards */ - a->used += b; - - /* top */ - top = a->dp + a->used - 1; - - /* base */ - bottom = a->dp + a->used - 1 - b; - - /* much like mp_rshd this is implemented using a sliding window - * except the window goes the otherway around. Copying from - * the bottom to the top. see bn_mp_rshd.c for more info. - */ - for (x = a->used - 1; x >= b; x--) { - *top-- = *bottom--; - } - - /* zero the lower digits */ - top = a->dp; - for (x = 0; x < b; x++) { - *top++ = 0; - } - } - return MP_OKAY; -} - - -/* returns the number of bits in an int */ -static int mp_count_bits (mp_int * a) -{ - int r; - mp_digit q; - - /* shortcut */ - if (a->used == 0) { - return 0; - } - - /* get number of digits and add that */ - r = (a->used - 1) * DIGIT_BIT; - - /* take the last digit and count the bits in it */ - q = a->dp[a->used - 1]; - while (q > ((mp_digit) 0)) { - ++r; - q >>= ((mp_digit) 1); - } - return r; -} - - -/* calc a value mod 2**b */ -static int mp_mod_2d (mp_int * a, int b, mp_int * c) -{ - int x, res; - - /* if b is <= 0 then zero the int */ - if (b <= 0) { - mp_zero (c); - return MP_OKAY; - } - - /* if the modulus is larger than the value than return */ - if (b >= (int) (a->used * DIGIT_BIT)) { - res = mp_copy (a, c); - return res; - } - - /* copy */ - if ((res = mp_copy (a, c)) != MP_OKAY) { - return res; - } - - /* zero digits above the last digit of the modulus */ - for (x = (b / DIGIT_BIT) + ((b % DIGIT_BIT) == 0 ? 0 : 1); x < c->used; x++) { - c->dp[x] = 0; - } - /* clear the digit that is not completely outside/inside the modulus */ - c->dp[b / DIGIT_BIT] &= - (mp_digit) ((((mp_digit) 1) << (((mp_digit) b) % DIGIT_BIT)) - ((mp_digit) 1)); - mp_clamp (c); - return MP_OKAY; -} - - -#ifdef BN_MP_DIV_SMALL - -/* slower bit-bang division... also smaller */ -static int mp_div(mp_int * a, mp_int * b, mp_int * c, mp_int * d) -{ - mp_int ta, tb, tq, q; - int res, n, n2; - - /* is divisor zero ? */ - if (mp_iszero (b) == 1) { - return MP_VAL; - } - - /* if a < b then q=0, r = a */ - if (mp_cmp_mag (a, b) == MP_LT) { - if (d != NULL) { - res = mp_copy (a, d); - } else { - res = MP_OKAY; - } - if (c != NULL) { - mp_zero (c); - } - return res; - } - - /* init our temps */ - if ((res = mp_init_multi(&ta, &tb, &tq, &q, NULL) != MP_OKAY)) { - return res; - } - - - mp_set(&tq, 1); - n = mp_count_bits(a) - mp_count_bits(b); - if (((res = mp_abs(a, &ta)) != MP_OKAY) || - ((res = mp_abs(b, &tb)) != MP_OKAY) || - ((res = mp_mul_2d(&tb, n, &tb)) != MP_OKAY) || - ((res = mp_mul_2d(&tq, n, &tq)) != MP_OKAY)) { - goto LBL_ERR; - } - - while (n-- >= 0) { - if (mp_cmp(&tb, &ta) != MP_GT) { - if (((res = mp_sub(&ta, &tb, &ta)) != MP_OKAY) || - ((res = mp_add(&q, &tq, &q)) != MP_OKAY)) { - goto LBL_ERR; - } - } - if (((res = mp_div_2d(&tb, 1, &tb, NULL)) != MP_OKAY) || - ((res = mp_div_2d(&tq, 1, &tq, NULL)) != MP_OKAY)) { - goto LBL_ERR; - } - } - - /* now q == quotient and ta == remainder */ - n = a->sign; - n2 = (a->sign == b->sign ? MP_ZPOS : MP_NEG); - if (c != NULL) { - mp_exch(c, &q); - c->sign = (mp_iszero(c) == MP_YES) ? MP_ZPOS : n2; - } - if (d != NULL) { - mp_exch(d, &ta); - d->sign = (mp_iszero(d) == MP_YES) ? MP_ZPOS : n; - } -LBL_ERR: - mp_clear_multi(&ta, &tb, &tq, &q, NULL); - return res; -} - -#else - -/* integer signed division. - * c*b + d == a [e.g. a/b, c=quotient, d=remainder] - * HAC pp.598 Algorithm 14.20 - * - * Note that the description in HAC is horribly - * incomplete. For example, it doesn't consider - * the case where digits are removed from 'x' in - * the inner loop. It also doesn't consider the - * case that y has fewer than three digits, etc.. - * - * The overall algorithm is as described as - * 14.20 from HAC but fixed to treat these cases. -*/ -static int mp_div (mp_int * a, mp_int * b, mp_int * c, mp_int * d) -{ - mp_int q, x, y, t1, t2; - int res, n, t, i, norm, neg; - - /* is divisor zero ? */ - if (mp_iszero (b) == 1) { - return MP_VAL; - } - - /* if a < b then q=0, r = a */ - if (mp_cmp_mag (a, b) == MP_LT) { - if (d != NULL) { - res = mp_copy (a, d); - } else { - res = MP_OKAY; - } - if (c != NULL) { - mp_zero (c); - } - return res; - } - - if ((res = mp_init_size (&q, a->used + 2)) != MP_OKAY) { - return res; - } - q.used = a->used + 2; - - if ((res = mp_init (&t1)) != MP_OKAY) { - goto LBL_Q; - } - - if ((res = mp_init (&t2)) != MP_OKAY) { - goto LBL_T1; - } - - if ((res = mp_init_copy (&x, a)) != MP_OKAY) { - goto LBL_T2; - } - - if ((res = mp_init_copy (&y, b)) != MP_OKAY) { - goto LBL_X; - } - - /* fix the sign */ - neg = (a->sign == b->sign) ? MP_ZPOS : MP_NEG; - x.sign = y.sign = MP_ZPOS; - - /* normalize both x and y, ensure that y >= b/2, [b == 2**DIGIT_BIT] */ - norm = mp_count_bits(&y) % DIGIT_BIT; - if (norm < (int)(DIGIT_BIT-1)) { - norm = (DIGIT_BIT-1) - norm; - if ((res = mp_mul_2d (&x, norm, &x)) != MP_OKAY) { - goto LBL_Y; - } - if ((res = mp_mul_2d (&y, norm, &y)) != MP_OKAY) { - goto LBL_Y; - } - } else { - norm = 0; - } - - /* note hac does 0 based, so if used==5 then its 0,1,2,3,4, e.g. use 4 */ - n = x.used - 1; - t = y.used - 1; - - /* while (x >= y*b**n-t) do { q[n-t] += 1; x -= y*b**{n-t} } */ - if ((res = mp_lshd (&y, n - t)) != MP_OKAY) { /* y = y*b**{n-t} */ - goto LBL_Y; - } - - while (mp_cmp (&x, &y) != MP_LT) { - ++(q.dp[n - t]); - if ((res = mp_sub (&x, &y, &x)) != MP_OKAY) { - goto LBL_Y; - } - } - - /* reset y by shifting it back down */ - mp_rshd (&y, n - t); - - /* step 3. for i from n down to (t + 1) */ - for (i = n; i >= (t + 1); i--) { - if (i > x.used) { - continue; - } - - /* step 3.1 if xi == yt then set q{i-t-1} to b-1, - * otherwise set q{i-t-1} to (xi*b + x{i-1})/yt */ - if (x.dp[i] == y.dp[t]) { - q.dp[i - t - 1] = ((((mp_digit)1) << DIGIT_BIT) - 1); - } else { - mp_word tmp; - tmp = ((mp_word) x.dp[i]) << ((mp_word) DIGIT_BIT); - tmp |= ((mp_word) x.dp[i - 1]); - tmp /= ((mp_word) y.dp[t]); - if (tmp > (mp_word) MP_MASK) - tmp = MP_MASK; - q.dp[i - t - 1] = (mp_digit) (tmp & (mp_word) (MP_MASK)); - } - - /* while (q{i-t-1} * (yt * b + y{t-1})) > - xi * b**2 + xi-1 * b + xi-2 - - do q{i-t-1} -= 1; - */ - q.dp[i - t - 1] = (q.dp[i - t - 1] + 1) & MP_MASK; - do { - q.dp[i - t - 1] = (q.dp[i - t - 1] - 1) & MP_MASK; - - /* find left hand */ - mp_zero (&t1); - t1.dp[0] = (t - 1 < 0) ? 0 : y.dp[t - 1]; - t1.dp[1] = y.dp[t]; - t1.used = 2; - if ((res = mp_mul_d (&t1, q.dp[i - t - 1], &t1)) != MP_OKAY) { - goto LBL_Y; - } - - /* find right hand */ - t2.dp[0] = (i - 2 < 0) ? 0 : x.dp[i - 2]; - t2.dp[1] = (i - 1 < 0) ? 0 : x.dp[i - 1]; - t2.dp[2] = x.dp[i]; - t2.used = 3; - } while (mp_cmp_mag(&t1, &t2) == MP_GT); - - /* step 3.3 x = x - q{i-t-1} * y * b**{i-t-1} */ - if ((res = mp_mul_d (&y, q.dp[i - t - 1], &t1)) != MP_OKAY) { - goto LBL_Y; - } - - if ((res = mp_lshd (&t1, i - t - 1)) != MP_OKAY) { - goto LBL_Y; - } - - if ((res = mp_sub (&x, &t1, &x)) != MP_OKAY) { - goto LBL_Y; - } - - /* if x < 0 then { x = x + y*b**{i-t-1}; q{i-t-1} -= 1; } */ - if (x.sign == MP_NEG) { - if ((res = mp_copy (&y, &t1)) != MP_OKAY) { - goto LBL_Y; - } - if ((res = mp_lshd (&t1, i - t - 1)) != MP_OKAY) { - goto LBL_Y; - } - if ((res = mp_add (&x, &t1, &x)) != MP_OKAY) { - goto LBL_Y; - } - - q.dp[i - t - 1] = (q.dp[i - t - 1] - 1UL) & MP_MASK; - } - } - - /* now q is the quotient and x is the remainder - * [which we have to normalize] - */ - - /* get sign before writing to c */ - x.sign = x.used == 0 ? MP_ZPOS : a->sign; - - if (c != NULL) { - mp_clamp (&q); - mp_exch (&q, c); - c->sign = neg; - } - - if (d != NULL) { - mp_div_2d (&x, norm, &x, NULL); - mp_exch (&x, d); - } - - res = MP_OKAY; - -LBL_Y:mp_clear (&y); -LBL_X:mp_clear (&x); -LBL_T2:mp_clear (&t2); -LBL_T1:mp_clear (&t1); -LBL_Q:mp_clear (&q); - return res; -} - -#endif - - -#ifdef MP_LOW_MEM - #define TAB_SIZE 32 -#else - #define TAB_SIZE 256 -#endif - -static int s_mp_exptmod (mp_int * G, mp_int * X, mp_int * P, mp_int * Y, int redmode) -{ - mp_int M[TAB_SIZE], res, mu; - mp_digit buf; - int err, bitbuf, bitcpy, bitcnt, mode, digidx, x, y, winsize; - int (*redux)(mp_int*,mp_int*,mp_int*); - - /* find window size */ - x = mp_count_bits (X); - if (x <= 7) { - winsize = 2; - } else if (x <= 36) { - winsize = 3; - } else if (x <= 140) { - winsize = 4; - } else if (x <= 450) { - winsize = 5; - } else if (x <= 1303) { - winsize = 6; - } else if (x <= 3529) { - winsize = 7; - } else { - winsize = 8; - } - -#ifdef MP_LOW_MEM - if (winsize > 5) { - winsize = 5; - } -#endif - - /* init M array */ - /* init first cell */ - if ((err = mp_init(&M[1])) != MP_OKAY) { - return err; - } - - /* now init the second half of the array */ - for (x = 1<<(winsize-1); x < (1 << winsize); x++) { - if ((err = mp_init(&M[x])) != MP_OKAY) { - for (y = 1<<(winsize-1); y < x; y++) { - mp_clear (&M[y]); - } - mp_clear(&M[1]); - return err; - } - } - - /* create mu, used for Barrett reduction */ - if ((err = mp_init (&mu)) != MP_OKAY) { - goto LBL_M; - } - - if (redmode == 0) { - if ((err = mp_reduce_setup (&mu, P)) != MP_OKAY) { - goto LBL_MU; - } - redux = mp_reduce; - } else { - if ((err = mp_reduce_2k_setup_l (P, &mu)) != MP_OKAY) { - goto LBL_MU; - } - redux = mp_reduce_2k_l; - } - - /* create M table - * - * The M table contains powers of the base, - * e.g. M[x] = G**x mod P - * - * The first half of the table is not - * computed though accept for M[0] and M[1] - */ - if ((err = mp_mod (G, P, &M[1])) != MP_OKAY) { - goto LBL_MU; - } - - /* compute the value at M[1<<(winsize-1)] by squaring - * M[1] (winsize-1) times - */ - if ((err = mp_copy (&M[1], &M[1 << (winsize - 1)])) != MP_OKAY) { - goto LBL_MU; - } - - for (x = 0; x < (winsize - 1); x++) { - /* square it */ - if ((err = mp_sqr (&M[1 << (winsize - 1)], - &M[1 << (winsize - 1)])) != MP_OKAY) { - goto LBL_MU; - } - - /* reduce modulo P */ - if ((err = redux (&M[1 << (winsize - 1)], P, &mu)) != MP_OKAY) { - goto LBL_MU; - } - } - - /* create upper table, that is M[x] = M[x-1] * M[1] (mod P) - * for x = (2**(winsize - 1) + 1) to (2**winsize - 1) - */ - for (x = (1 << (winsize - 1)) + 1; x < (1 << winsize); x++) { - if ((err = mp_mul (&M[x - 1], &M[1], &M[x])) != MP_OKAY) { - goto LBL_MU; - } - if ((err = redux (&M[x], P, &mu)) != MP_OKAY) { - goto LBL_MU; - } - } - - /* setup result */ - if ((err = mp_init (&res)) != MP_OKAY) { - goto LBL_MU; - } - mp_set (&res, 1); - - /* set initial mode and bit cnt */ - mode = 0; - bitcnt = 1; - buf = 0; - digidx = X->used - 1; - bitcpy = 0; - bitbuf = 0; - - for (;;) { - /* grab next digit as required */ - if (--bitcnt == 0) { - /* if digidx == -1 we are out of digits */ - if (digidx == -1) { - break; - } - /* read next digit and reset the bitcnt */ - buf = X->dp[digidx--]; - bitcnt = (int) DIGIT_BIT; - } - - /* grab the next msb from the exponent */ - y = (buf >> (mp_digit)(DIGIT_BIT - 1)) & 1; - buf <<= (mp_digit)1; - - /* if the bit is zero and mode == 0 then we ignore it - * These represent the leading zero bits before the first 1 bit - * in the exponent. Technically this opt is not required but it - * does lower the # of trivial squaring/reductions used - */ - if (mode == 0 && y == 0) { - continue; - } - - /* if the bit is zero and mode == 1 then we square */ - if (mode == 1 && y == 0) { - if ((err = mp_sqr (&res, &res)) != MP_OKAY) { - goto LBL_RES; - } - if ((err = redux (&res, P, &mu)) != MP_OKAY) { - goto LBL_RES; - } - continue; - } - - /* else we add it to the window */ - bitbuf |= (y << (winsize - ++bitcpy)); - mode = 2; - - if (bitcpy == winsize) { - /* ok window is filled so square as required and multiply */ - /* square first */ - for (x = 0; x < winsize; x++) { - if ((err = mp_sqr (&res, &res)) != MP_OKAY) { - goto LBL_RES; - } - if ((err = redux (&res, P, &mu)) != MP_OKAY) { - goto LBL_RES; - } - } - - /* then multiply */ - if ((err = mp_mul (&res, &M[bitbuf], &res)) != MP_OKAY) { - goto LBL_RES; - } - if ((err = redux (&res, P, &mu)) != MP_OKAY) { - goto LBL_RES; - } - - /* empty window and reset */ - bitcpy = 0; - bitbuf = 0; - mode = 1; - } - } - - /* if bits remain then square/multiply */ - if (mode == 2 && bitcpy > 0) { - /* square then multiply if the bit is set */ - for (x = 0; x < bitcpy; x++) { - if ((err = mp_sqr (&res, &res)) != MP_OKAY) { - goto LBL_RES; - } - if ((err = redux (&res, P, &mu)) != MP_OKAY) { - goto LBL_RES; - } - - bitbuf <<= 1; - if ((bitbuf & (1 << winsize)) != 0) { - /* then multiply */ - if ((err = mp_mul (&res, &M[1], &res)) != MP_OKAY) { - goto LBL_RES; - } - if ((err = redux (&res, P, &mu)) != MP_OKAY) { - goto LBL_RES; - } - } - } - } - - mp_exch (&res, Y); - err = MP_OKAY; -LBL_RES:mp_clear (&res); -LBL_MU:mp_clear (&mu); -LBL_M: - mp_clear(&M[1]); - for (x = 1<<(winsize-1); x < (1 << winsize); x++) { - mp_clear (&M[x]); - } - return err; -} - - -/* computes b = a*a */ -static int mp_sqr (mp_int * a, mp_int * b) -{ - int res; - -#ifdef BN_MP_TOOM_SQR_C - /* use Toom-Cook? */ - if (a->used >= TOOM_SQR_CUTOFF) { - res = mp_toom_sqr(a, b); - /* Karatsuba? */ - } else -#endif -#ifdef BN_MP_KARATSUBA_SQR_C -if (a->used >= KARATSUBA_SQR_CUTOFF) { - res = mp_karatsuba_sqr (a, b); - } else -#endif - { -#ifdef BN_FAST_S_MP_SQR_C - /* can we use the fast comba multiplier? */ - if ((a->used * 2 + 1) < MP_WARRAY && - a->used < - (1 << (sizeof(mp_word) * CHAR_BIT - 2*DIGIT_BIT - 1))) { - res = fast_s_mp_sqr (a, b); - } else -#endif -#ifdef BN_S_MP_SQR_C - res = s_mp_sqr (a, b); -#else -#error mp_sqr could fail - res = MP_VAL; -#endif - } - b->sign = MP_ZPOS; - return res; -} - - -/* reduces a modulo n where n is of the form 2**p - d - This differs from reduce_2k since "d" can be larger - than a single digit. -*/ -static int mp_reduce_2k_l(mp_int *a, mp_int *n, mp_int *d) -{ - mp_int q; - int p, res; - - if ((res = mp_init(&q)) != MP_OKAY) { - return res; - } - - p = mp_count_bits(n); -top: - /* q = a/2**p, a = a mod 2**p */ - if ((res = mp_div_2d(a, p, &q, a)) != MP_OKAY) { - goto ERR; - } - - /* q = q * d */ - if ((res = mp_mul(&q, d, &q)) != MP_OKAY) { - goto ERR; - } - - /* a = a + q */ - if ((res = s_mp_add(a, &q, a)) != MP_OKAY) { - goto ERR; - } - - if (mp_cmp_mag(a, n) != MP_LT) { - s_mp_sub(a, n, a); - goto top; - } - -ERR: - mp_clear(&q); - return res; -} - - -/* determines the setup value */ -static int mp_reduce_2k_setup_l(mp_int *a, mp_int *d) -{ - int res; - mp_int tmp; - - if ((res = mp_init(&tmp)) != MP_OKAY) { - return res; - } - - if ((res = mp_2expt(&tmp, mp_count_bits(a))) != MP_OKAY) { - goto ERR; - } - - if ((res = s_mp_sub(&tmp, a, d)) != MP_OKAY) { - goto ERR; - } - -ERR: - mp_clear(&tmp); - return res; -} - - -/* computes a = 2**b - * - * Simple algorithm which zeroes the int, grows it then just sets one bit - * as required. - */ -static int mp_2expt (mp_int * a, int b) -{ - int res; - - /* zero a as per default */ - mp_zero (a); - - /* grow a to accomodate the single bit */ - if ((res = mp_grow (a, b / DIGIT_BIT + 1)) != MP_OKAY) { - return res; - } - - /* set the used count of where the bit will go */ - a->used = b / DIGIT_BIT + 1; - - /* put the single bit in its place */ - a->dp[b / DIGIT_BIT] = ((mp_digit)1) << (b % DIGIT_BIT); - - return MP_OKAY; -} - - -/* pre-calculate the value required for Barrett reduction - * For a given modulus "b" it calulates the value required in "a" - */ -static int mp_reduce_setup (mp_int * a, mp_int * b) -{ - int res; - - if ((res = mp_2expt (a, b->used * 2 * DIGIT_BIT)) != MP_OKAY) { - return res; - } - return mp_div (a, b, a, NULL); -} - - -/* reduces x mod m, assumes 0 < x < m**2, mu is - * precomputed via mp_reduce_setup. - * From HAC pp.604 Algorithm 14.42 - */ -static int mp_reduce (mp_int * x, mp_int * m, mp_int * mu) -{ - mp_int q; - int res, um = m->used; - - /* q = x */ - if ((res = mp_init_copy (&q, x)) != MP_OKAY) { - return res; - } - - /* q1 = x / b**(k-1) */ - mp_rshd (&q, um - 1); - - /* according to HAC this optimization is ok */ - if (((unsigned long) um) > (((mp_digit)1) << (DIGIT_BIT - 1))) { - if ((res = mp_mul (&q, mu, &q)) != MP_OKAY) { - goto CLEANUP; - } - } else { -#ifdef BN_S_MP_MUL_HIGH_DIGS_C - if ((res = s_mp_mul_high_digs (&q, mu, &q, um)) != MP_OKAY) { - goto CLEANUP; - } -#elif defined(BN_FAST_S_MP_MUL_HIGH_DIGS_C) - if ((res = fast_s_mp_mul_high_digs (&q, mu, &q, um)) != MP_OKAY) { - goto CLEANUP; - } -#else - { -#error mp_reduce would always fail - res = MP_VAL; - goto CLEANUP; - } -#endif - } - - /* q3 = q2 / b**(k+1) */ - mp_rshd (&q, um + 1); - - /* x = x mod b**(k+1), quick (no division) */ - if ((res = mp_mod_2d (x, DIGIT_BIT * (um + 1), x)) != MP_OKAY) { - goto CLEANUP; - } - - /* q = q * m mod b**(k+1), quick (no division) */ - if ((res = s_mp_mul_digs (&q, m, &q, um + 1)) != MP_OKAY) { - goto CLEANUP; - } - - /* x = x - q */ - if ((res = mp_sub (x, &q, x)) != MP_OKAY) { - goto CLEANUP; - } - - /* If x < 0, add b**(k+1) to it */ - if (mp_cmp_d (x, 0) == MP_LT) { - mp_set (&q, 1); - if ((res = mp_lshd (&q, um + 1)) != MP_OKAY) { - goto CLEANUP; - } - if ((res = mp_add (x, &q, x)) != MP_OKAY) { - goto CLEANUP; - } - } - - /* Back off if it's too big */ - while (mp_cmp (x, m) != MP_LT) { - if ((res = s_mp_sub (x, m, x)) != MP_OKAY) { - goto CLEANUP; - } - } - -CLEANUP: - mp_clear (&q); - - return res; -} - - -/* multiplies |a| * |b| and only computes upto digs digits of result - * HAC pp. 595, Algorithm 14.12 Modified so you can control how - * many digits of output are created. - */ -static int s_mp_mul_digs (mp_int * a, mp_int * b, mp_int * c, int digs) -{ - mp_int t; - int res, pa, pb, ix, iy; - mp_digit u; - mp_word r; - mp_digit tmpx, *tmpt, *tmpy; - - /* can we use the fast multiplier? */ - if (((digs) < MP_WARRAY) && - MIN (a->used, b->used) < - (1 << ((CHAR_BIT * sizeof (mp_word)) - (2 * DIGIT_BIT)))) { - return fast_s_mp_mul_digs (a, b, c, digs); - } - - if ((res = mp_init_size (&t, digs)) != MP_OKAY) { - return res; - } - t.used = digs; - - /* compute the digits of the product directly */ - pa = a->used; - for (ix = 0; ix < pa; ix++) { - /* set the carry to zero */ - u = 0; - - /* limit ourselves to making digs digits of output */ - pb = MIN (b->used, digs - ix); - - /* setup some aliases */ - /* copy of the digit from a used within the nested loop */ - tmpx = a->dp[ix]; - - /* an alias for the destination shifted ix places */ - tmpt = t.dp + ix; - - /* an alias for the digits of b */ - tmpy = b->dp; - - /* compute the columns of the output and propagate the carry */ - for (iy = 0; iy < pb; iy++) { - /* compute the column as a mp_word */ - r = ((mp_word)*tmpt) + - ((mp_word)tmpx) * ((mp_word)*tmpy++) + - ((mp_word) u); - - /* the new column is the lower part of the result */ - *tmpt++ = (mp_digit) (r & ((mp_word) MP_MASK)); - - /* get the carry word from the result */ - u = (mp_digit) (r >> ((mp_word) DIGIT_BIT)); - } - /* set carry if it is placed below digs */ - if (ix + iy < digs) { - *tmpt = u; - } - } - - mp_clamp (&t); - mp_exch (&t, c); - - mp_clear (&t); - return MP_OKAY; -} - - -/* Fast (comba) multiplier - * - * This is the fast column-array [comba] multiplier. It is - * designed to compute the columns of the product first - * then handle the carries afterwards. This has the effect - * of making the nested loops that compute the columns very - * simple and schedulable on super-scalar processors. - * - * This has been modified to produce a variable number of - * digits of output so if say only a half-product is required - * you don't have to compute the upper half (a feature - * required for fast Barrett reduction). - * - * Based on Algorithm 14.12 on pp.595 of HAC. - * - */ -static int fast_s_mp_mul_digs (mp_int * a, mp_int * b, mp_int * c, int digs) -{ - int olduse, res, pa, ix, iz; - mp_digit W[MP_WARRAY]; - register mp_word _W; - - /* grow the destination as required */ - if (c->alloc < digs) { - if ((res = mp_grow (c, digs)) != MP_OKAY) { - return res; - } - } - - /* number of output digits to produce */ - pa = MIN(digs, a->used + b->used); - - /* clear the carry */ - _W = 0; - for (ix = 0; ix < pa; ix++) { - int tx, ty; - int iy; - mp_digit *tmpx, *tmpy; - - /* get offsets into the two bignums */ - ty = MIN(b->used-1, ix); - tx = ix - ty; - - /* setup temp aliases */ - tmpx = a->dp + tx; - tmpy = b->dp + ty; - - /* this is the number of times the loop will iterrate, essentially - while (tx++ < a->used && ty-- >= 0) { ... } - */ - iy = MIN(a->used-tx, ty+1); - - /* execute loop */ - for (iz = 0; iz < iy; ++iz) { - _W += ((mp_word)*tmpx++)*((mp_word)*tmpy--); - - } - - /* store term */ - W[ix] = ((mp_digit)_W) & MP_MASK; - - /* make next carry */ - _W = _W >> ((mp_word)DIGIT_BIT); - } - - /* setup dest */ - olduse = c->used; - c->used = pa; - - { - register mp_digit *tmpc; - tmpc = c->dp; - for (ix = 0; ix < pa+1; ix++) { - /* now extract the previous digit [below the carry] */ - *tmpc++ = W[ix]; - } - - /* clear unused digits [that existed in the old copy of c] */ - for (; ix < olduse; ix++) { - *tmpc++ = 0; - } - } - mp_clamp (c); - return MP_OKAY; -} - - -/* init an mp_init for a given size */ -static int mp_init_size (mp_int * a, int size) -{ - int x; - - /* pad size so there are always extra digits */ - size += (MP_PREC * 2) - (size % MP_PREC); - - /* alloc mem */ - a->dp = OPT_CAST(mp_digit) XMALLOC (sizeof (mp_digit) * size); - if (a->dp == NULL) { - return MP_MEM; - } - - /* set the members */ - a->used = 0; - a->alloc = size; - a->sign = MP_ZPOS; - - /* zero the digits */ - for (x = 0; x < size; x++) { - a->dp[x] = 0; - } - - return MP_OKAY; -} - - -/* low level squaring, b = a*a, HAC pp.596-597, Algorithm 14.16 */ -static int s_mp_sqr (mp_int * a, mp_int * b) -{ - mp_int t; - int res, ix, iy, pa; - mp_word r; - mp_digit u, tmpx, *tmpt; - - pa = a->used; - if ((res = mp_init_size (&t, 2*pa + 1)) != MP_OKAY) { - return res; - } - - /* default used is maximum possible size */ - t.used = 2*pa + 1; - - for (ix = 0; ix < pa; ix++) { - /* first calculate the digit at 2*ix */ - /* calculate double precision result */ - r = ((mp_word) t.dp[2*ix]) + - ((mp_word)a->dp[ix])*((mp_word)a->dp[ix]); - - /* store lower part in result */ - t.dp[ix+ix] = (mp_digit) (r & ((mp_word) MP_MASK)); - - /* get the carry */ - u = (mp_digit)(r >> ((mp_word) DIGIT_BIT)); - - /* left hand side of A[ix] * A[iy] */ - tmpx = a->dp[ix]; - - /* alias for where to store the results */ - tmpt = t.dp + (2*ix + 1); - - for (iy = ix + 1; iy < pa; iy++) { - /* first calculate the product */ - r = ((mp_word)tmpx) * ((mp_word)a->dp[iy]); - - /* now calculate the double precision result, note we use - * addition instead of *2 since it's easier to optimize - */ - r = ((mp_word) *tmpt) + r + r + ((mp_word) u); - - /* store lower part */ - *tmpt++ = (mp_digit) (r & ((mp_word) MP_MASK)); - - /* get carry */ - u = (mp_digit)(r >> ((mp_word) DIGIT_BIT)); - } - /* propagate upwards */ - while (u != ((mp_digit) 0)) { - r = ((mp_word) *tmpt) + ((mp_word) u); - *tmpt++ = (mp_digit) (r & ((mp_word) MP_MASK)); - u = (mp_digit)(r >> ((mp_word) DIGIT_BIT)); - } - } - - mp_clamp (&t); - mp_exch (&t, b); - mp_clear (&t); - return MP_OKAY; -} - - -/* multiplies |a| * |b| and does not compute the lower digs digits - * [meant to get the higher part of the product] - */ -static int s_mp_mul_high_digs (mp_int * a, mp_int * b, mp_int * c, int digs) -{ - mp_int t; - int res, pa, pb, ix, iy; - mp_digit u; - mp_word r; - mp_digit tmpx, *tmpt, *tmpy; - - /* can we use the fast multiplier? */ -#ifdef BN_FAST_S_MP_MUL_HIGH_DIGS_C - if (((a->used + b->used + 1) < MP_WARRAY) - && MIN (a->used, b->used) < (1 << ((CHAR_BIT * sizeof (mp_word)) - (2 * DIGIT_BIT)))) { - return fast_s_mp_mul_high_digs (a, b, c, digs); - } -#endif - - if ((res = mp_init_size (&t, a->used + b->used + 1)) != MP_OKAY) { - return res; - } - t.used = a->used + b->used + 1; - - pa = a->used; - pb = b->used; - for (ix = 0; ix < pa; ix++) { - /* clear the carry */ - u = 0; - - /* left hand side of A[ix] * B[iy] */ - tmpx = a->dp[ix]; - - /* alias to the address of where the digits will be stored */ - tmpt = &(t.dp[digs]); - - /* alias for where to read the right hand side from */ - tmpy = b->dp + (digs - ix); - - for (iy = digs - ix; iy < pb; iy++) { - /* calculate the double precision result */ - r = ((mp_word)*tmpt) + - ((mp_word)tmpx) * ((mp_word)*tmpy++) + - ((mp_word) u); - - /* get the lower part */ - *tmpt++ = (mp_digit) (r & ((mp_word) MP_MASK)); - - /* carry the carry */ - u = (mp_digit) (r >> ((mp_word) DIGIT_BIT)); - } - *tmpt = u; - } - mp_clamp (&t); - mp_exch (&t, c); - mp_clear (&t); - return MP_OKAY; -} - - -#ifdef BN_MP_MONTGOMERY_SETUP_C -/* setups the montgomery reduction stuff */ -static int -mp_montgomery_setup (mp_int * n, mp_digit * rho) -{ - mp_digit x, b; - -/* fast inversion mod 2**k - * - * Based on the fact that - * - * XA = 1 (mod 2**n) => (X(2-XA)) A = 1 (mod 2**2n) - * => 2*X*A - X*X*A*A = 1 - * => 2*(1) - (1) = 1 - */ - b = n->dp[0]; - - if ((b & 1) == 0) { - return MP_VAL; - } - - x = (((b + 2) & 4) << 1) + b; /* here x*a==1 mod 2**4 */ - x *= 2 - b * x; /* here x*a==1 mod 2**8 */ -#if !defined(MP_8BIT) - x *= 2 - b * x; /* here x*a==1 mod 2**16 */ -#endif -#if defined(MP_64BIT) || !(defined(MP_8BIT) || defined(MP_16BIT)) - x *= 2 - b * x; /* here x*a==1 mod 2**32 */ -#endif -#ifdef MP_64BIT - x *= 2 - b * x; /* here x*a==1 mod 2**64 */ -#endif - - /* rho = -1/m mod b */ - *rho = (unsigned long)(((mp_word)1 << ((mp_word) DIGIT_BIT)) - x) & MP_MASK; - - return MP_OKAY; -} -#endif - - -#ifdef BN_FAST_MP_MONTGOMERY_REDUCE_C -/* computes xR**-1 == x (mod N) via Montgomery Reduction - * - * This is an optimized implementation of montgomery_reduce - * which uses the comba method to quickly calculate the columns of the - * reduction. - * - * Based on Algorithm 14.32 on pp.601 of HAC. -*/ -int fast_mp_montgomery_reduce (mp_int * x, mp_int * n, mp_digit rho) -{ - int ix, res, olduse; - mp_word W[MP_WARRAY]; - - /* get old used count */ - olduse = x->used; - - /* grow a as required */ - if (x->alloc < n->used + 1) { - if ((res = mp_grow (x, n->used + 1)) != MP_OKAY) { - return res; - } - } - - /* first we have to get the digits of the input into - * an array of double precision words W[...] - */ - { - register mp_word *_W; - register mp_digit *tmpx; - - /* alias for the W[] array */ - _W = W; - - /* alias for the digits of x*/ - tmpx = x->dp; - - /* copy the digits of a into W[0..a->used-1] */ - for (ix = 0; ix < x->used; ix++) { - *_W++ = *tmpx++; - } - - /* zero the high words of W[a->used..m->used*2] */ - for (; ix < n->used * 2 + 1; ix++) { - *_W++ = 0; - } - } - - /* now we proceed to zero successive digits - * from the least significant upwards - */ - for (ix = 0; ix < n->used; ix++) { - /* mu = ai * m' mod b - * - * We avoid a double precision multiplication (which isn't required) - * by casting the value down to a mp_digit. Note this requires - * that W[ix-1] have the carry cleared (see after the inner loop) - */ - register mp_digit mu; - mu = (mp_digit) (((W[ix] & MP_MASK) * rho) & MP_MASK); - - /* a = a + mu * m * b**i - * - * This is computed in place and on the fly. The multiplication - * by b**i is handled by offseting which columns the results - * are added to. - * - * Note the comba method normally doesn't handle carries in the - * inner loop In this case we fix the carry from the previous - * column since the Montgomery reduction requires digits of the - * result (so far) [see above] to work. This is - * handled by fixing up one carry after the inner loop. The - * carry fixups are done in order so after these loops the - * first m->used words of W[] have the carries fixed - */ - { - register int iy; - register mp_digit *tmpn; - register mp_word *_W; - - /* alias for the digits of the modulus */ - tmpn = n->dp; - - /* Alias for the columns set by an offset of ix */ - _W = W + ix; - - /* inner loop */ - for (iy = 0; iy < n->used; iy++) { - *_W++ += ((mp_word)mu) * ((mp_word)*tmpn++); - } - } - - /* now fix carry for next digit, W[ix+1] */ - W[ix + 1] += W[ix] >> ((mp_word) DIGIT_BIT); - } - - /* now we have to propagate the carries and - * shift the words downward [all those least - * significant digits we zeroed]. - */ - { - register mp_digit *tmpx; - register mp_word *_W, *_W1; - - /* nox fix rest of carries */ - - /* alias for current word */ - _W1 = W + ix; - - /* alias for next word, where the carry goes */ - _W = W + ++ix; - - for (; ix <= n->used * 2 + 1; ix++) { - *_W++ += *_W1++ >> ((mp_word) DIGIT_BIT); - } - - /* copy out, A = A/b**n - * - * The result is A/b**n but instead of converting from an - * array of mp_word to mp_digit than calling mp_rshd - * we just copy them in the right order - */ - - /* alias for destination word */ - tmpx = x->dp; - - /* alias for shifted double precision result */ - _W = W + n->used; - - for (ix = 0; ix < n->used + 1; ix++) { - *tmpx++ = (mp_digit)(*_W++ & ((mp_word) MP_MASK)); - } - - /* zero oldused digits, if the input a was larger than - * m->used+1 we'll have to clear the digits - */ - for (; ix < olduse; ix++) { - *tmpx++ = 0; - } - } - - /* set the max used and clamp */ - x->used = n->used + 1; - mp_clamp (x); - - /* if A >= m then A = A - m */ - if (mp_cmp_mag (x, n) != MP_LT) { - return s_mp_sub (x, n, x); - } - return MP_OKAY; -} -#endif - - -#ifdef BN_MP_MUL_2_C -/* b = a*2 */ -static int mp_mul_2(mp_int * a, mp_int * b) -{ - int x, res, oldused; - - /* grow to accomodate result */ - if (b->alloc < a->used + 1) { - if ((res = mp_grow (b, a->used + 1)) != MP_OKAY) { - return res; - } - } - - oldused = b->used; - b->used = a->used; - - { - register mp_digit r, rr, *tmpa, *tmpb; - - /* alias for source */ - tmpa = a->dp; - - /* alias for dest */ - tmpb = b->dp; - - /* carry */ - r = 0; - for (x = 0; x < a->used; x++) { - - /* get what will be the *next* carry bit from the - * MSB of the current digit - */ - rr = *tmpa >> ((mp_digit)(DIGIT_BIT - 1)); - - /* now shift up this digit, add in the carry [from the previous] */ - *tmpb++ = ((*tmpa++ << ((mp_digit)1)) | r) & MP_MASK; - - /* copy the carry that would be from the source - * digit into the next iteration - */ - r = rr; - } - - /* new leading digit? */ - if (r != 0) { - /* add a MSB which is always 1 at this point */ - *tmpb = 1; - ++(b->used); - } - - /* now zero any excess digits on the destination - * that we didn't write to - */ - tmpb = b->dp + b->used; - for (x = b->used; x < oldused; x++) { - *tmpb++ = 0; - } - } - b->sign = a->sign; - return MP_OKAY; -} -#endif - - -#ifdef BN_MP_MONTGOMERY_CALC_NORMALIZATION_C -/* - * shifts with subtractions when the result is greater than b. - * - * The method is slightly modified to shift B unconditionally upto just under - * the leading bit of b. This saves alot of multiple precision shifting. - */ -static int mp_montgomery_calc_normalization (mp_int * a, mp_int * b) -{ - int x, bits, res; - - /* how many bits of last digit does b use */ - bits = mp_count_bits (b) % DIGIT_BIT; - - if (b->used > 1) { - if ((res = mp_2expt (a, (b->used - 1) * DIGIT_BIT + bits - 1)) != MP_OKAY) { - return res; - } - } else { - mp_set(a, 1); - bits = 1; - } - - - /* now compute C = A * B mod b */ - for (x = bits - 1; x < (int)DIGIT_BIT; x++) { - if ((res = mp_mul_2 (a, a)) != MP_OKAY) { - return res; - } - if (mp_cmp_mag (a, b) != MP_LT) { - if ((res = s_mp_sub (a, b, a)) != MP_OKAY) { - return res; - } - } - } - - return MP_OKAY; -} -#endif - - -#ifdef BN_MP_EXPTMOD_FAST_C -/* computes Y == G**X mod P, HAC pp.616, Algorithm 14.85 - * - * Uses a left-to-right k-ary sliding window to compute the modular exponentiation. - * The value of k changes based on the size of the exponent. - * - * Uses Montgomery or Diminished Radix reduction [whichever appropriate] - */ - -static int mp_exptmod_fast (mp_int * G, mp_int * X, mp_int * P, mp_int * Y, int redmode) -{ - mp_int M[TAB_SIZE], res; - mp_digit buf, mp; - int err, bitbuf, bitcpy, bitcnt, mode, digidx, x, y, winsize; - - /* use a pointer to the reduction algorithm. This allows us to use - * one of many reduction algorithms without modding the guts of - * the code with if statements everywhere. - */ - int (*redux)(mp_int*,mp_int*,mp_digit); - - /* find window size */ - x = mp_count_bits (X); - if (x <= 7) { - winsize = 2; - } else if (x <= 36) { - winsize = 3; - } else if (x <= 140) { - winsize = 4; - } else if (x <= 450) { - winsize = 5; - } else if (x <= 1303) { - winsize = 6; - } else if (x <= 3529) { - winsize = 7; - } else { - winsize = 8; - } - -#ifdef MP_LOW_MEM - if (winsize > 5) { - winsize = 5; - } -#endif - - /* init M array */ - /* init first cell */ - if ((err = mp_init(&M[1])) != MP_OKAY) { - return err; - } - - /* now init the second half of the array */ - for (x = 1<<(winsize-1); x < (1 << winsize); x++) { - if ((err = mp_init(&M[x])) != MP_OKAY) { - for (y = 1<<(winsize-1); y < x; y++) { - mp_clear (&M[y]); - } - mp_clear(&M[1]); - return err; - } - } - - /* determine and setup reduction code */ - if (redmode == 0) { -#ifdef BN_MP_MONTGOMERY_SETUP_C - /* now setup montgomery */ - if ((err = mp_montgomery_setup (P, &mp)) != MP_OKAY) { - goto LBL_M; - } -#else - err = MP_VAL; - goto LBL_M; -#endif - - /* automatically pick the comba one if available (saves quite a few calls/ifs) */ -#ifdef BN_FAST_MP_MONTGOMERY_REDUCE_C - if (((P->used * 2 + 1) < MP_WARRAY) && - P->used < (1 << ((CHAR_BIT * sizeof (mp_word)) - (2 * DIGIT_BIT)))) { - redux = fast_mp_montgomery_reduce; - } else -#endif - { -#ifdef BN_MP_MONTGOMERY_REDUCE_C - /* use slower baseline Montgomery method */ - redux = mp_montgomery_reduce; -#else - err = MP_VAL; - goto LBL_M; -#endif - } - } else if (redmode == 1) { -#if defined(BN_MP_DR_SETUP_C) && defined(BN_MP_DR_REDUCE_C) - /* setup DR reduction for moduli of the form B**k - b */ - mp_dr_setup(P, &mp); - redux = mp_dr_reduce; -#else - err = MP_VAL; - goto LBL_M; -#endif - } else { -#if defined(BN_MP_REDUCE_2K_SETUP_C) && defined(BN_MP_REDUCE_2K_C) - /* setup DR reduction for moduli of the form 2**k - b */ - if ((err = mp_reduce_2k_setup(P, &mp)) != MP_OKAY) { - goto LBL_M; - } - redux = mp_reduce_2k; -#else - err = MP_VAL; - goto LBL_M; -#endif - } - - /* setup result */ - if ((err = mp_init (&res)) != MP_OKAY) { - goto LBL_M; - } - - /* create M table - * - - * - * The first half of the table is not computed though accept for M[0] and M[1] - */ - - if (redmode == 0) { -#ifdef BN_MP_MONTGOMERY_CALC_NORMALIZATION_C - /* now we need R mod m */ - if ((err = mp_montgomery_calc_normalization (&res, P)) != MP_OKAY) { - goto LBL_RES; - } -#else - err = MP_VAL; - goto LBL_RES; -#endif - - /* now set M[1] to G * R mod m */ - if ((err = mp_mulmod (G, &res, P, &M[1])) != MP_OKAY) { - goto LBL_RES; - } - } else { - mp_set(&res, 1); - if ((err = mp_mod(G, P, &M[1])) != MP_OKAY) { - goto LBL_RES; - } - } - - /* compute the value at M[1<<(winsize-1)] by squaring M[1] (winsize-1) times */ - if ((err = mp_copy (&M[1], &M[1 << (winsize - 1)])) != MP_OKAY) { - goto LBL_RES; - } - - for (x = 0; x < (winsize - 1); x++) { - if ((err = mp_sqr (&M[1 << (winsize - 1)], &M[1 << (winsize - 1)])) != MP_OKAY) { - goto LBL_RES; - } - if ((err = redux (&M[1 << (winsize - 1)], P, mp)) != MP_OKAY) { - goto LBL_RES; - } - } - - /* create upper table */ - for (x = (1 << (winsize - 1)) + 1; x < (1 << winsize); x++) { - if ((err = mp_mul (&M[x - 1], &M[1], &M[x])) != MP_OKAY) { - goto LBL_RES; - } - if ((err = redux (&M[x], P, mp)) != MP_OKAY) { - goto LBL_RES; - } - } - - /* set initial mode and bit cnt */ - mode = 0; - bitcnt = 1; - buf = 0; - digidx = X->used - 1; - bitcpy = 0; - bitbuf = 0; - - for (;;) { - /* grab next digit as required */ - if (--bitcnt == 0) { - /* if digidx == -1 we are out of digits so break */ - if (digidx == -1) { - break; - } - /* read next digit and reset bitcnt */ - buf = X->dp[digidx--]; - bitcnt = (int)DIGIT_BIT; - } - - /* grab the next msb from the exponent */ - y = (mp_digit)(buf >> (DIGIT_BIT - 1)) & 1; - buf <<= (mp_digit)1; - - /* if the bit is zero and mode == 0 then we ignore it - * These represent the leading zero bits before the first 1 bit - * in the exponent. Technically this opt is not required but it - * does lower the # of trivial squaring/reductions used - */ - if (mode == 0 && y == 0) { - continue; - } - - /* if the bit is zero and mode == 1 then we square */ - if (mode == 1 && y == 0) { - if ((err = mp_sqr (&res, &res)) != MP_OKAY) { - goto LBL_RES; - } - if ((err = redux (&res, P, mp)) != MP_OKAY) { - goto LBL_RES; - } - continue; - } - - /* else we add it to the window */ - bitbuf |= (y << (winsize - ++bitcpy)); - mode = 2; - - if (bitcpy == winsize) { - /* ok window is filled so square as required and multiply */ - /* square first */ - for (x = 0; x < winsize; x++) { - if ((err = mp_sqr (&res, &res)) != MP_OKAY) { - goto LBL_RES; - } - if ((err = redux (&res, P, mp)) != MP_OKAY) { - goto LBL_RES; - } - } - - /* then multiply */ - if ((err = mp_mul (&res, &M[bitbuf], &res)) != MP_OKAY) { - goto LBL_RES; - } - if ((err = redux (&res, P, mp)) != MP_OKAY) { - goto LBL_RES; - } - - /* empty window and reset */ - bitcpy = 0; - bitbuf = 0; - mode = 1; - } - } - - /* if bits remain then square/multiply */ - if (mode == 2 && bitcpy > 0) { - /* square then multiply if the bit is set */ - for (x = 0; x < bitcpy; x++) { - if ((err = mp_sqr (&res, &res)) != MP_OKAY) { - goto LBL_RES; - } - if ((err = redux (&res, P, mp)) != MP_OKAY) { - goto LBL_RES; - } - - /* get next bit of the window */ - bitbuf <<= 1; - if ((bitbuf & (1 << winsize)) != 0) { - /* then multiply */ - if ((err = mp_mul (&res, &M[1], &res)) != MP_OKAY) { - goto LBL_RES; - } - if ((err = redux (&res, P, mp)) != MP_OKAY) { - goto LBL_RES; - } - } - } - } - - if (redmode == 0) { - /* fixup result if Montgomery reduction is used - * recall that any value in a Montgomery system is - * actually multiplied by R mod n. So we have - * to reduce one more time to cancel out the factor - * of R. - */ - if ((err = redux(&res, P, mp)) != MP_OKAY) { - goto LBL_RES; - } - } - - /* swap res with Y */ - mp_exch (&res, Y); - err = MP_OKAY; -LBL_RES:mp_clear (&res); -LBL_M: - mp_clear(&M[1]); - for (x = 1<<(winsize-1); x < (1 << winsize); x++) { - mp_clear (&M[x]); - } - return err; -} -#endif - - -#ifdef BN_FAST_S_MP_SQR_C -/* the jist of squaring... - * you do like mult except the offset of the tmpx [one that - * starts closer to zero] can't equal the offset of tmpy. - * So basically you set up iy like before then you min it with - * (ty-tx) so that it never happens. You double all those - * you add in the inner loop - -After that loop you do the squares and add them in. -*/ - -static int fast_s_mp_sqr (mp_int * a, mp_int * b) -{ - int olduse, res, pa, ix, iz; - mp_digit W[MP_WARRAY], *tmpx; - mp_word W1; - - /* grow the destination as required */ - pa = a->used + a->used; - if (b->alloc < pa) { - if ((res = mp_grow (b, pa)) != MP_OKAY) { - return res; - } - } - - /* number of output digits to produce */ - W1 = 0; - for (ix = 0; ix < pa; ix++) { - int tx, ty, iy; - mp_word _W; - mp_digit *tmpy; - - /* clear counter */ - _W = 0; - - /* get offsets into the two bignums */ - ty = MIN(a->used-1, ix); - tx = ix - ty; - - /* setup temp aliases */ - tmpx = a->dp + tx; - tmpy = a->dp + ty; - - /* this is the number of times the loop will iterrate, essentially - while (tx++ < a->used && ty-- >= 0) { ... } - */ - iy = MIN(a->used-tx, ty+1); - - /* now for squaring tx can never equal ty - * we halve the distance since they approach at a rate of 2x - * and we have to round because odd cases need to be executed - */ - iy = MIN(iy, (ty-tx+1)>>1); - - /* execute loop */ - for (iz = 0; iz < iy; iz++) { - _W += ((mp_word)*tmpx++)*((mp_word)*tmpy--); - } - - /* double the inner product and add carry */ - _W = _W + _W + W1; - - /* even columns have the square term in them */ - if ((ix&1) == 0) { - _W += ((mp_word)a->dp[ix>>1])*((mp_word)a->dp[ix>>1]); - } - - /* store it */ - W[ix] = (mp_digit)(_W & MP_MASK); - - /* make next carry */ - W1 = _W >> ((mp_word)DIGIT_BIT); - } - - /* setup dest */ - olduse = b->used; - b->used = a->used+a->used; - - { - mp_digit *tmpb; - tmpb = b->dp; - for (ix = 0; ix < pa; ix++) { - *tmpb++ = W[ix] & MP_MASK; - } - - /* clear unused digits [that existed in the old copy of c] */ - for (; ix < olduse; ix++) { - *tmpb++ = 0; - } - } - mp_clamp (b); - return MP_OKAY; -} -#endif - - -#ifdef BN_MP_MUL_D_C -/* multiply by a digit */ -static int -mp_mul_d (mp_int * a, mp_digit b, mp_int * c) -{ - mp_digit u, *tmpa, *tmpc; - mp_word r; - int ix, res, olduse; - - /* make sure c is big enough to hold a*b */ - if (c->alloc < a->used + 1) { - if ((res = mp_grow (c, a->used + 1)) != MP_OKAY) { - return res; - } - } - - /* get the original destinations used count */ - olduse = c->used; - - /* set the sign */ - c->sign = a->sign; - - /* alias for a->dp [source] */ - tmpa = a->dp; - - /* alias for c->dp [dest] */ - tmpc = c->dp; - - /* zero carry */ - u = 0; - - /* compute columns */ - for (ix = 0; ix < a->used; ix++) { - /* compute product and carry sum for this term */ - r = ((mp_word) u) + ((mp_word)*tmpa++) * ((mp_word)b); - - /* mask off higher bits to get a single digit */ - *tmpc++ = (mp_digit) (r & ((mp_word) MP_MASK)); - - /* send carry into next iteration */ - u = (mp_digit) (r >> ((mp_word) DIGIT_BIT)); - } - - /* store final carry [if any] and increment ix offset */ - *tmpc++ = u; - ++ix; - - /* now zero digits above the top */ - while (ix++ < olduse) { - *tmpc++ = 0; - } - - /* set used count */ - c->used = a->used + 1; - mp_clamp(c); - - return MP_OKAY; -} -#endif diff --git a/hostapd-0.8/src/tls/pkcs1.c b/hostapd-0.8/src/tls/pkcs1.c deleted file mode 100644 index 72ebd87..0000000 --- a/hostapd-0.8/src/tls/pkcs1.c +++ /dev/null @@ -1,201 +0,0 @@ -/* - * PKCS #1 (RSA Encryption) - * Copyright (c) 2006-2009, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#include "includes.h" - -#include "common.h" -#include "rsa.h" -#include "pkcs1.h" - - -static int pkcs1_generate_encryption_block(u8 block_type, size_t modlen, - const u8 *in, size_t inlen, - u8 *out, size_t *outlen) -{ - size_t ps_len; - u8 *pos; - - /* - * PKCS #1 v1.5, 8.1: - * - * EB = 00 || BT || PS || 00 || D - * BT = 00 or 01 for private-key operation; 02 for public-key operation - * PS = k-3-||D||; at least eight octets - * (BT=0: PS=0x00, BT=1: PS=0xff, BT=2: PS=pseudorandom non-zero) - * k = length of modulus in octets (modlen) - */ - - if (modlen < 12 || modlen > *outlen || inlen > modlen - 11) { - wpa_printf(MSG_DEBUG, "PKCS #1: %s - Invalid buffer " - "lengths (modlen=%lu outlen=%lu inlen=%lu)", - __func__, (unsigned long) modlen, - (unsigned long) *outlen, - (unsigned long) inlen); - return -1; - } - - pos = out; - *pos++ = 0x00; - *pos++ = block_type; /* BT */ - ps_len = modlen - inlen - 3; - switch (block_type) { - case 0: - os_memset(pos, 0x00, ps_len); - pos += ps_len; - break; - case 1: - os_memset(pos, 0xff, ps_len); - pos += ps_len; - break; - case 2: - if (os_get_random(pos, ps_len) < 0) { - wpa_printf(MSG_DEBUG, "PKCS #1: %s - Failed to get " - "random data for PS", __func__); - return -1; - } - while (ps_len--) { - if (*pos == 0x00) - *pos = 0x01; - pos++; - } - break; - default: - wpa_printf(MSG_DEBUG, "PKCS #1: %s - Unsupported block type " - "%d", __func__, block_type); - return -1; - } - *pos++ = 0x00; - os_memcpy(pos, in, inlen); /* D */ - - return 0; -} - - -int pkcs1_encrypt(int block_type, struct crypto_rsa_key *key, - int use_private, const u8 *in, size_t inlen, - u8 *out, size_t *outlen) -{ - size_t modlen; - - modlen = crypto_rsa_get_modulus_len(key); - - if (pkcs1_generate_encryption_block(block_type, modlen, in, inlen, - out, outlen) < 0) - return -1; - - return crypto_rsa_exptmod(out, modlen, out, outlen, key, use_private); -} - - -int pkcs1_v15_private_key_decrypt(struct crypto_rsa_key *key, - const u8 *in, size_t inlen, - u8 *out, size_t *outlen) -{ - int res; - u8 *pos, *end; - - res = crypto_rsa_exptmod(in, inlen, out, outlen, key, 1); - if (res) - return res; - - if (*outlen < 2 || out[0] != 0 || out[1] != 2) - return -1; - - /* Skip PS (pseudorandom non-zero octets) */ - pos = out + 2; - end = out + *outlen; - while (*pos && pos < end) - pos++; - if (pos == end) - return -1; - pos++; - - *outlen -= pos - out; - - /* Strip PKCS #1 header */ - os_memmove(out, pos, *outlen); - - return 0; -} - - -int pkcs1_decrypt_public_key(struct crypto_rsa_key *key, - const u8 *crypt, size_t crypt_len, - u8 *plain, size_t *plain_len) -{ - size_t len; - u8 *pos; - - len = *plain_len; - if (crypto_rsa_exptmod(crypt, crypt_len, plain, &len, key, 0) < 0) - return -1; - - /* - * PKCS #1 v1.5, 8.1: - * - * EB = 00 || BT || PS || 00 || D - * BT = 00 or 01 - * PS = k-3-||D|| times (00 if BT=00) or (FF if BT=01) - * k = length of modulus in octets - */ - - if (len < 3 + 8 + 16 /* min hash len */ || - plain[0] != 0x00 || (plain[1] != 0x00 && plain[1] != 0x01)) { - wpa_printf(MSG_INFO, "LibTomCrypt: Invalid signature EB " - "structure"); - return -1; - } - - pos = plain + 3; - if (plain[1] == 0x00) { - /* BT = 00 */ - if (plain[2] != 0x00) { - wpa_printf(MSG_INFO, "LibTomCrypt: Invalid signature " - "PS (BT=00)"); - return -1; - } - while (pos + 1 < plain + len && *pos == 0x00 && pos[1] == 0x00) - pos++; - } else { - /* BT = 01 */ - if (plain[2] != 0xff) { - wpa_printf(MSG_INFO, "LibTomCrypt: Invalid signature " - "PS (BT=01)"); - return -1; - } - while (pos < plain + len && *pos == 0xff) - pos++; - } - - if (pos - plain - 2 < 8) { - /* PKCS #1 v1.5, 8.1: At least eight octets long PS */ - wpa_printf(MSG_INFO, "LibTomCrypt: Too short signature " - "padding"); - return -1; - } - - if (pos + 16 /* min hash len */ >= plain + len || *pos != 0x00) { - wpa_printf(MSG_INFO, "LibTomCrypt: Invalid signature EB " - "structure (2)"); - return -1; - } - pos++; - len -= pos - plain; - - /* Strip PKCS #1 header */ - os_memmove(plain, pos, len); - *plain_len = len; - - return 0; -} diff --git a/hostapd-0.8/src/tls/pkcs1.h b/hostapd-0.8/src/tls/pkcs1.h deleted file mode 100644 index 68872b1..0000000 --- a/hostapd-0.8/src/tls/pkcs1.h +++ /dev/null @@ -1,28 +0,0 @@ -/* - * PKCS #1 (RSA Encryption) - * Copyright (c) 2006-2009, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#ifndef PKCS1_H -#define PKCS1_H - -int pkcs1_encrypt(int block_type, struct crypto_rsa_key *key, - int use_private, const u8 *in, size_t inlen, - u8 *out, size_t *outlen); -int pkcs1_v15_private_key_decrypt(struct crypto_rsa_key *key, - const u8 *in, size_t inlen, - u8 *out, size_t *outlen); -int pkcs1_decrypt_public_key(struct crypto_rsa_key *key, - const u8 *crypt, size_t crypt_len, - u8 *plain, size_t *plain_len); - -#endif /* PKCS1_H */ diff --git a/hostapd-0.8/src/tls/pkcs5.c b/hostapd-0.8/src/tls/pkcs5.c deleted file mode 100644 index 4291b84..0000000 --- a/hostapd-0.8/src/tls/pkcs5.c +++ /dev/null @@ -1,238 +0,0 @@ -/* - * PKCS #5 (Password-based Encryption) - * Copyright (c) 2009, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#include "includes.h" - -#include "common.h" -#include "crypto/crypto.h" -#include "crypto/md5.h" -#include "asn1.h" -#include "pkcs5.h" - - -struct pkcs5_params { - enum pkcs5_alg { - PKCS5_ALG_UNKNOWN, - PKCS5_ALG_MD5_DES_CBC - } alg; - u8 salt[8]; - size_t salt_len; - unsigned int iter_count; -}; - - -enum pkcs5_alg pkcs5_get_alg(struct asn1_oid *oid) -{ - if (oid->len == 7 && - oid->oid[0] == 1 /* iso */ && - oid->oid[1] == 2 /* member-body */ && - oid->oid[2] == 840 /* us */ && - oid->oid[3] == 113549 /* rsadsi */ && - oid->oid[4] == 1 /* pkcs */ && - oid->oid[5] == 5 /* pkcs-5 */ && - oid->oid[6] == 3 /* pbeWithMD5AndDES-CBC */) - return PKCS5_ALG_MD5_DES_CBC; - - return PKCS5_ALG_UNKNOWN; -} - - -static int pkcs5_get_params(const u8 *enc_alg, size_t enc_alg_len, - struct pkcs5_params *params) -{ - struct asn1_hdr hdr; - const u8 *enc_alg_end, *pos, *end; - struct asn1_oid oid; - char obuf[80]; - - /* AlgorithmIdentifier */ - - enc_alg_end = enc_alg + enc_alg_len; - - os_memset(params, 0, sizeof(*params)); - - if (asn1_get_oid(enc_alg, enc_alg_end - enc_alg, &oid, &pos)) { - wpa_printf(MSG_DEBUG, "PKCS #5: Failed to parse OID " - "(algorithm)"); - return -1; - } - - asn1_oid_to_str(&oid, obuf, sizeof(obuf)); - wpa_printf(MSG_DEBUG, "PKCS #5: encryption algorithm %s", obuf); - params->alg = pkcs5_get_alg(&oid); - if (params->alg == PKCS5_ALG_UNKNOWN) { - wpa_printf(MSG_INFO, "PKCS #5: unsupported encryption " - "algorithm %s", obuf); - return -1; - } - - /* - * PKCS#5, Section 8 - * PBEParameter ::= SEQUENCE { - * salt OCTET STRING SIZE(8), - * iterationCount INTEGER } - */ - - if (asn1_get_next(pos, enc_alg_end - pos, &hdr) < 0 || - hdr.class != ASN1_CLASS_UNIVERSAL || - hdr.tag != ASN1_TAG_SEQUENCE) { - wpa_printf(MSG_DEBUG, "PKCS #5: Expected SEQUENCE " - "(PBEParameter) - found class %d tag 0x%x", - hdr.class, hdr.tag); - return -1; - } - pos = hdr.payload; - end = hdr.payload + hdr.length; - - /* salt OCTET STRING SIZE(8) */ - if (asn1_get_next(pos, end - pos, &hdr) < 0 || - hdr.class != ASN1_CLASS_UNIVERSAL || - hdr.tag != ASN1_TAG_OCTETSTRING || - hdr.length != 8) { - wpa_printf(MSG_DEBUG, "PKCS #5: Expected OCTETSTRING SIZE(8) " - "(salt) - found class %d tag 0x%x size %d", - hdr.class, hdr.tag, hdr.length); - return -1; - } - pos = hdr.payload + hdr.length; - os_memcpy(params->salt, hdr.payload, hdr.length); - params->salt_len = hdr.length; - wpa_hexdump(MSG_DEBUG, "PKCS #5: salt", - params->salt, params->salt_len); - - /* iterationCount INTEGER */ - if (asn1_get_next(pos, end - pos, &hdr) < 0 || - hdr.class != ASN1_CLASS_UNIVERSAL || hdr.tag != ASN1_TAG_INTEGER) { - wpa_printf(MSG_DEBUG, "PKCS #5: Expected INTEGER - found " - "class %d tag 0x%x", hdr.class, hdr.tag); - return -1; - } - if (hdr.length == 1) - params->iter_count = *hdr.payload; - else if (hdr.length == 2) - params->iter_count = WPA_GET_BE16(hdr.payload); - else if (hdr.length == 4) - params->iter_count = WPA_GET_BE32(hdr.payload); - else { - wpa_hexdump(MSG_DEBUG, "PKCS #5: Unsupported INTEGER value " - " (iterationCount)", - hdr.payload, hdr.length); - return -1; - } - wpa_printf(MSG_DEBUG, "PKCS #5: iterationCount=0x%x", - params->iter_count); - if (params->iter_count == 0 || params->iter_count > 0xffff) { - wpa_printf(MSG_INFO, "PKCS #5: Unsupported " - "iterationCount=0x%x", params->iter_count); - return -1; - } - - return 0; -} - - -static struct crypto_cipher * pkcs5_crypto_init(struct pkcs5_params *params, - const char *passwd) -{ - unsigned int i; - u8 hash[MD5_MAC_LEN]; - const u8 *addr[2]; - size_t len[2]; - - if (params->alg != PKCS5_ALG_MD5_DES_CBC) - return NULL; - - addr[0] = (const u8 *) passwd; - len[0] = os_strlen(passwd); - addr[1] = params->salt; - len[1] = params->salt_len; - if (md5_vector(2, addr, len, hash) < 0) - return NULL; - addr[0] = hash; - len[0] = MD5_MAC_LEN; - for (i = 1; i < params->iter_count; i++) { - if (md5_vector(1, addr, len, hash) < 0) - return NULL; - } - /* TODO: DES key parity bits(?) */ - wpa_hexdump_key(MSG_DEBUG, "PKCS #5: DES key", hash, 8); - wpa_hexdump_key(MSG_DEBUG, "PKCS #5: DES IV", hash + 8, 8); - - return crypto_cipher_init(CRYPTO_CIPHER_ALG_DES, hash + 8, hash, 8); -} - - -u8 * pkcs5_decrypt(const u8 *enc_alg, size_t enc_alg_len, - const u8 *enc_data, size_t enc_data_len, - const char *passwd, size_t *data_len) -{ - struct crypto_cipher *ctx; - u8 *eb, pad; - struct pkcs5_params params; - unsigned int i; - - if (pkcs5_get_params(enc_alg, enc_alg_len, ¶ms) < 0) { - wpa_printf(MSG_DEBUG, "PKCS #5: Unsupported parameters"); - return NULL; - } - - ctx = pkcs5_crypto_init(¶ms, passwd); - if (ctx == NULL) { - wpa_printf(MSG_DEBUG, "PKCS #5: Failed to initialize crypto"); - return NULL; - } - - /* PKCS #5, Section 7 - Decryption process */ - if (enc_data_len < 16 || enc_data_len % 8) { - wpa_printf(MSG_INFO, "PKCS #5: invalid length of ciphertext " - "%d", (int) enc_data_len); - crypto_cipher_deinit(ctx); - return NULL; - } - - eb = os_malloc(enc_data_len); - if (eb == NULL) { - crypto_cipher_deinit(ctx); - return NULL; - } - - if (crypto_cipher_decrypt(ctx, enc_data, eb, enc_data_len) < 0) { - wpa_printf(MSG_DEBUG, "PKCS #5: Failed to decrypt EB"); - crypto_cipher_deinit(ctx); - os_free(eb); - return NULL; - } - crypto_cipher_deinit(ctx); - - pad = eb[enc_data_len - 1]; - if (pad > 8) { - wpa_printf(MSG_INFO, "PKCS #5: Invalid PS octet 0x%x", pad); - os_free(eb); - return NULL; - } - for (i = enc_data_len - pad; i < enc_data_len; i++) { - if (eb[i] != pad) { - wpa_hexdump(MSG_INFO, "PKCS #5: Invalid PS", - eb + enc_data_len - pad, pad); - os_free(eb); - return NULL; - } - } - - wpa_hexdump_key(MSG_MSGDUMP, "PKCS #5: message M (encrypted key)", - eb, enc_data_len - pad); - - *data_len = enc_data_len - pad; - return eb; -} diff --git a/hostapd-0.8/src/tls/pkcs5.h b/hostapd-0.8/src/tls/pkcs5.h deleted file mode 100644 index 6ed3923..0000000 --- a/hostapd-0.8/src/tls/pkcs5.h +++ /dev/null @@ -1,22 +0,0 @@ -/* - * PKCS #5 (Password-based Encryption) - * Copyright (c) 2009, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#ifndef PKCS5_H -#define PKCS5_H - -u8 * pkcs5_decrypt(const u8 *enc_alg, size_t enc_alg_len, - const u8 *enc_data, size_t enc_data_len, - const char *passwd, size_t *data_len); - -#endif /* PKCS5_H */ diff --git a/hostapd-0.8/src/tls/pkcs8.c b/hostapd-0.8/src/tls/pkcs8.c deleted file mode 100644 index 69ab262..0000000 --- a/hostapd-0.8/src/tls/pkcs8.c +++ /dev/null @@ -1,193 +0,0 @@ -/* - * PKCS #8 (Private-key information syntax) - * Copyright (c) 2006-2009, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#include "includes.h" - -#include "common.h" -#include "asn1.h" -#include "bignum.h" -#include "rsa.h" -#include "pkcs5.h" -#include "pkcs8.h" - - -struct crypto_private_key * pkcs8_key_import(const u8 *buf, size_t len) -{ - struct asn1_hdr hdr; - const u8 *pos, *end; - struct bignum *zero; - struct asn1_oid oid; - char obuf[80]; - - /* PKCS #8, Chapter 6 */ - - /* PrivateKeyInfo ::= SEQUENCE */ - if (asn1_get_next(buf, len, &hdr) < 0 || - hdr.class != ASN1_CLASS_UNIVERSAL || - hdr.tag != ASN1_TAG_SEQUENCE) { - wpa_printf(MSG_DEBUG, "PKCS #8: Does not start with PKCS #8 " - "header (SEQUENCE); assume PKCS #8 not used"); - return NULL; - } - pos = hdr.payload; - end = pos + hdr.length; - - /* version Version (Version ::= INTEGER) */ - if (asn1_get_next(pos, end - pos, &hdr) < 0 || - hdr.class != ASN1_CLASS_UNIVERSAL || hdr.tag != ASN1_TAG_INTEGER) { - wpa_printf(MSG_DEBUG, "PKCS #8: Expected INTEGER - found " - "class %d tag 0x%x; assume PKCS #8 not used", - hdr.class, hdr.tag); - return NULL; - } - - zero = bignum_init(); - if (zero == NULL) - return NULL; - - if (bignum_set_unsigned_bin(zero, hdr.payload, hdr.length) < 0) { - wpa_printf(MSG_DEBUG, "PKCS #8: Failed to parse INTEGER"); - bignum_deinit(zero); - return NULL; - } - pos = hdr.payload + hdr.length; - - if (bignum_cmp_d(zero, 0) != 0) { - wpa_printf(MSG_DEBUG, "PKCS #8: Expected zero INTEGER in the " - "beginning of private key; not found; assume " - "PKCS #8 not used"); - bignum_deinit(zero); - return NULL; - } - bignum_deinit(zero); - - /* privateKeyAlgorithm PrivateKeyAlgorithmIdentifier - * (PrivateKeyAlgorithmIdentifier ::= AlgorithmIdentifier) */ - if (asn1_get_next(pos, len, &hdr) < 0 || - hdr.class != ASN1_CLASS_UNIVERSAL || - hdr.tag != ASN1_TAG_SEQUENCE) { - wpa_printf(MSG_DEBUG, "PKCS #8: Expected SEQUENCE " - "(AlgorithmIdentifier) - found class %d tag 0x%x; " - "assume PKCS #8 not used", - hdr.class, hdr.tag); - return NULL; - } - - if (asn1_get_oid(hdr.payload, hdr.length, &oid, &pos)) { - wpa_printf(MSG_DEBUG, "PKCS #8: Failed to parse OID " - "(algorithm); assume PKCS #8 not used"); - return NULL; - } - - asn1_oid_to_str(&oid, obuf, sizeof(obuf)); - wpa_printf(MSG_DEBUG, "PKCS #8: algorithm=%s", obuf); - - if (oid.len != 7 || - oid.oid[0] != 1 /* iso */ || - oid.oid[1] != 2 /* member-body */ || - oid.oid[2] != 840 /* us */ || - oid.oid[3] != 113549 /* rsadsi */ || - oid.oid[4] != 1 /* pkcs */ || - oid.oid[5] != 1 /* pkcs-1 */ || - oid.oid[6] != 1 /* rsaEncryption */) { - wpa_printf(MSG_DEBUG, "PKCS #8: Unsupported private key " - "algorithm %s", obuf); - return NULL; - } - - pos = hdr.payload + hdr.length; - - /* privateKey PrivateKey (PrivateKey ::= OCTET STRING) */ - if (asn1_get_next(pos, end - pos, &hdr) < 0 || - hdr.class != ASN1_CLASS_UNIVERSAL || - hdr.tag != ASN1_TAG_OCTETSTRING) { - wpa_printf(MSG_DEBUG, "PKCS #8: Expected OCTETSTRING " - "(privateKey) - found class %d tag 0x%x", - hdr.class, hdr.tag); - return NULL; - } - wpa_printf(MSG_DEBUG, "PKCS #8: Try to parse RSAPrivateKey"); - - return (struct crypto_private_key *) - crypto_rsa_import_private_key(hdr.payload, hdr.length); -} - - -struct crypto_private_key * -pkcs8_enc_key_import(const u8 *buf, size_t len, const char *passwd) -{ - struct asn1_hdr hdr; - const u8 *pos, *end, *enc_alg; - size_t enc_alg_len; - u8 *data; - size_t data_len; - - if (passwd == NULL) - return NULL; - - /* - * PKCS #8, Chapter 7 - * EncryptedPrivateKeyInfo ::= SEQUENCE { - * encryptionAlgorithm EncryptionAlgorithmIdentifier, - * encryptedData EncryptedData } - * EncryptionAlgorithmIdentifier ::= AlgorithmIdentifier - * EncryptedData ::= OCTET STRING - */ - - if (asn1_get_next(buf, len, &hdr) < 0 || - hdr.class != ASN1_CLASS_UNIVERSAL || - hdr.tag != ASN1_TAG_SEQUENCE) { - wpa_printf(MSG_DEBUG, "PKCS #8: Does not start with PKCS #8 " - "header (SEQUENCE); assume encrypted PKCS #8 not " - "used"); - return NULL; - } - pos = hdr.payload; - end = pos + hdr.length; - - /* encryptionAlgorithm EncryptionAlgorithmIdentifier */ - if (asn1_get_next(pos, end - pos, &hdr) < 0 || - hdr.class != ASN1_CLASS_UNIVERSAL || - hdr.tag != ASN1_TAG_SEQUENCE) { - wpa_printf(MSG_DEBUG, "PKCS #8: Expected SEQUENCE " - "(AlgorithmIdentifier) - found class %d tag 0x%x; " - "assume encrypted PKCS #8 not used", - hdr.class, hdr.tag); - return NULL; - } - enc_alg = hdr.payload; - enc_alg_len = hdr.length; - pos = hdr.payload + hdr.length; - - /* encryptedData EncryptedData */ - if (asn1_get_next(pos, end - pos, &hdr) < 0 || - hdr.class != ASN1_CLASS_UNIVERSAL || - hdr.tag != ASN1_TAG_OCTETSTRING) { - wpa_printf(MSG_DEBUG, "PKCS #8: Expected OCTETSTRING " - "(encryptedData) - found class %d tag 0x%x", - hdr.class, hdr.tag); - return NULL; - } - - data = pkcs5_decrypt(enc_alg, enc_alg_len, hdr.payload, hdr.length, - passwd, &data_len); - if (data) { - struct crypto_private_key *key; - key = pkcs8_key_import(data, data_len); - os_free(data); - return key; - } - - return NULL; -} diff --git a/hostapd-0.8/src/tls/pkcs8.h b/hostapd-0.8/src/tls/pkcs8.h deleted file mode 100644 index dac517c..0000000 --- a/hostapd-0.8/src/tls/pkcs8.h +++ /dev/null @@ -1,22 +0,0 @@ -/* - * PKCS #8 (Private-key information syntax) - * Copyright (c) 2006-2009, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#ifndef PKCS8_H -#define PKCS8_H - -struct crypto_private_key * pkcs8_key_import(const u8 *buf, size_t len); -struct crypto_private_key * -pkcs8_enc_key_import(const u8 *buf, size_t len, const char *passwd); - -#endif /* PKCS8_H */ diff --git a/hostapd-0.8/src/tls/rsa.c b/hostapd-0.8/src/tls/rsa.c deleted file mode 100644 index 3084adc..0000000 --- a/hostapd-0.8/src/tls/rsa.c +++ /dev/null @@ -1,358 +0,0 @@ -/* - * RSA - * Copyright (c) 2006, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#include "includes.h" - -#include "common.h" -#include "asn1.h" -#include "bignum.h" -#include "rsa.h" - - -struct crypto_rsa_key { - int private_key; /* whether private key is set */ - struct bignum *n; /* modulus (p * q) */ - struct bignum *e; /* public exponent */ - /* The following parameters are available only if private_key is set */ - struct bignum *d; /* private exponent */ - struct bignum *p; /* prime p (factor of n) */ - struct bignum *q; /* prime q (factor of n) */ - struct bignum *dmp1; /* d mod (p - 1); CRT exponent */ - struct bignum *dmq1; /* d mod (q - 1); CRT exponent */ - struct bignum *iqmp; /* 1 / q mod p; CRT coefficient */ -}; - - -static const u8 * crypto_rsa_parse_integer(const u8 *pos, const u8 *end, - struct bignum *num) -{ - struct asn1_hdr hdr; - - if (pos == NULL) - return NULL; - - if (asn1_get_next(pos, end - pos, &hdr) < 0 || - hdr.class != ASN1_CLASS_UNIVERSAL || hdr.tag != ASN1_TAG_INTEGER) { - wpa_printf(MSG_DEBUG, "RSA: Expected INTEGER - found class %d " - "tag 0x%x", hdr.class, hdr.tag); - return NULL; - } - - if (bignum_set_unsigned_bin(num, hdr.payload, hdr.length) < 0) { - wpa_printf(MSG_DEBUG, "RSA: Failed to parse INTEGER"); - return NULL; - } - - return hdr.payload + hdr.length; -} - - -/** - * crypto_rsa_import_public_key - Import an RSA public key - * @buf: Key buffer (DER encoded RSA public key) - * @len: Key buffer length in bytes - * Returns: Pointer to the public key or %NULL on failure - */ -struct crypto_rsa_key * -crypto_rsa_import_public_key(const u8 *buf, size_t len) -{ - struct crypto_rsa_key *key; - struct asn1_hdr hdr; - const u8 *pos, *end; - - key = os_zalloc(sizeof(*key)); - if (key == NULL) - return NULL; - - key->n = bignum_init(); - key->e = bignum_init(); - if (key->n == NULL || key->e == NULL) { - crypto_rsa_free(key); - return NULL; - } - - /* - * PKCS #1, 7.1: - * RSAPublicKey ::= SEQUENCE { - * modulus INTEGER, -- n - * publicExponent INTEGER -- e - * } - */ - - if (asn1_get_next(buf, len, &hdr) < 0 || - hdr.class != ASN1_CLASS_UNIVERSAL || - hdr.tag != ASN1_TAG_SEQUENCE) { - wpa_printf(MSG_DEBUG, "RSA: Expected SEQUENCE " - "(public key) - found class %d tag 0x%x", - hdr.class, hdr.tag); - goto error; - } - pos = hdr.payload; - end = pos + hdr.length; - - pos = crypto_rsa_parse_integer(pos, end, key->n); - pos = crypto_rsa_parse_integer(pos, end, key->e); - - if (pos == NULL) - goto error; - - if (pos != end) { - wpa_hexdump(MSG_DEBUG, - "RSA: Extra data in public key SEQUENCE", - pos, end - pos); - goto error; - } - - return key; - -error: - crypto_rsa_free(key); - return NULL; -} - - -/** - * crypto_rsa_import_private_key - Import an RSA private key - * @buf: Key buffer (DER encoded RSA private key) - * @len: Key buffer length in bytes - * Returns: Pointer to the private key or %NULL on failure - */ -struct crypto_rsa_key * -crypto_rsa_import_private_key(const u8 *buf, size_t len) -{ - struct crypto_rsa_key *key; - struct bignum *zero; - struct asn1_hdr hdr; - const u8 *pos, *end; - - key = os_zalloc(sizeof(*key)); - if (key == NULL) - return NULL; - - key->private_key = 1; - - key->n = bignum_init(); - key->e = bignum_init(); - key->d = bignum_init(); - key->p = bignum_init(); - key->q = bignum_init(); - key->dmp1 = bignum_init(); - key->dmq1 = bignum_init(); - key->iqmp = bignum_init(); - - if (key->n == NULL || key->e == NULL || key->d == NULL || - key->p == NULL || key->q == NULL || key->dmp1 == NULL || - key->dmq1 == NULL || key->iqmp == NULL) { - crypto_rsa_free(key); - return NULL; - } - - /* - * PKCS #1, 7.2: - * RSAPrivateKey ::= SEQUENCE { - * version Version, - * modulus INTEGER, -- n - * publicExponent INTEGER, -- e - * privateExponent INTEGER, -- d - * prime1 INTEGER, -- p - * prime2 INTEGER, -- q - * exponent1 INTEGER, -- d mod (p-1) - * exponent2 INTEGER, -- d mod (q-1) - * coefficient INTEGER -- (inverse of q) mod p - * } - * - * Version ::= INTEGER -- shall be 0 for this version of the standard - */ - if (asn1_get_next(buf, len, &hdr) < 0 || - hdr.class != ASN1_CLASS_UNIVERSAL || - hdr.tag != ASN1_TAG_SEQUENCE) { - wpa_printf(MSG_DEBUG, "RSA: Expected SEQUENCE " - "(public key) - found class %d tag 0x%x", - hdr.class, hdr.tag); - goto error; - } - pos = hdr.payload; - end = pos + hdr.length; - - zero = bignum_init(); - if (zero == NULL) - goto error; - pos = crypto_rsa_parse_integer(pos, end, zero); - if (pos == NULL || bignum_cmp_d(zero, 0) != 0) { - wpa_printf(MSG_DEBUG, "RSA: Expected zero INTEGER in the " - "beginning of private key; not found"); - bignum_deinit(zero); - goto error; - } - bignum_deinit(zero); - - pos = crypto_rsa_parse_integer(pos, end, key->n); - pos = crypto_rsa_parse_integer(pos, end, key->e); - pos = crypto_rsa_parse_integer(pos, end, key->d); - pos = crypto_rsa_parse_integer(pos, end, key->p); - pos = crypto_rsa_parse_integer(pos, end, key->q); - pos = crypto_rsa_parse_integer(pos, end, key->dmp1); - pos = crypto_rsa_parse_integer(pos, end, key->dmq1); - pos = crypto_rsa_parse_integer(pos, end, key->iqmp); - - if (pos == NULL) - goto error; - - if (pos != end) { - wpa_hexdump(MSG_DEBUG, - "RSA: Extra data in public key SEQUENCE", - pos, end - pos); - goto error; - } - - return key; - -error: - crypto_rsa_free(key); - return NULL; -} - - -/** - * crypto_rsa_get_modulus_len - Get the modulus length of the RSA key - * @key: RSA key - * Returns: Modulus length of the key - */ -size_t crypto_rsa_get_modulus_len(struct crypto_rsa_key *key) -{ - return bignum_get_unsigned_bin_len(key->n); -} - - -/** - * crypto_rsa_exptmod - RSA modular exponentiation - * @in: Input data - * @inlen: Input data length - * @out: Buffer for output data - * @outlen: Maximum size of the output buffer and used size on success - * @key: RSA key - * @use_private: 1 = Use RSA private key, 0 = Use RSA public key - * Returns: 0 on success, -1 on failure - */ -int crypto_rsa_exptmod(const u8 *in, size_t inlen, u8 *out, size_t *outlen, - struct crypto_rsa_key *key, int use_private) -{ - struct bignum *tmp, *a = NULL, *b = NULL; - int ret = -1; - size_t modlen; - - if (use_private && !key->private_key) - return -1; - - tmp = bignum_init(); - if (tmp == NULL) - return -1; - - if (bignum_set_unsigned_bin(tmp, in, inlen) < 0) - goto error; - if (bignum_cmp(key->n, tmp) < 0) { - /* Too large input value for the RSA key modulus */ - goto error; - } - - if (use_private) { - /* - * Decrypt (or sign) using Chinese remainer theorem to speed - * up calculation. This is equivalent to tmp = tmp^d mod n - * (which would require more CPU to calculate directly). - * - * dmp1 = (1/e) mod (p-1) - * dmq1 = (1/e) mod (q-1) - * iqmp = (1/q) mod p, where p > q - * m1 = c^dmp1 mod p - * m2 = c^dmq1 mod q - * h = q^-1 (m1 - m2) mod p - * m = m2 + hq - */ - a = bignum_init(); - b = bignum_init(); - if (a == NULL || b == NULL) - goto error; - - /* a = tmp^dmp1 mod p */ - if (bignum_exptmod(tmp, key->dmp1, key->p, a) < 0) - goto error; - - /* b = tmp^dmq1 mod q */ - if (bignum_exptmod(tmp, key->dmq1, key->q, b) < 0) - goto error; - - /* tmp = (a - b) * (1/q mod p) (mod p) */ - if (bignum_sub(a, b, tmp) < 0 || - bignum_mulmod(tmp, key->iqmp, key->p, tmp) < 0) - goto error; - - /* tmp = b + q * tmp */ - if (bignum_mul(tmp, key->q, tmp) < 0 || - bignum_add(tmp, b, tmp) < 0) - goto error; - } else { - /* Encrypt (or verify signature) */ - /* tmp = tmp^e mod N */ - if (bignum_exptmod(tmp, key->e, key->n, tmp) < 0) - goto error; - } - - modlen = crypto_rsa_get_modulus_len(key); - if (modlen > *outlen) { - *outlen = modlen; - goto error; - } - - if (bignum_get_unsigned_bin_len(tmp) > modlen) - goto error; /* should never happen */ - - *outlen = modlen; - os_memset(out, 0, modlen); - if (bignum_get_unsigned_bin( - tmp, out + - (modlen - bignum_get_unsigned_bin_len(tmp)), NULL) < 0) - goto error; - - ret = 0; - -error: - bignum_deinit(tmp); - bignum_deinit(a); - bignum_deinit(b); - return ret; -} - - -/** - * crypto_rsa_free - Free RSA key - * @key: RSA key to be freed - * - * This function frees an RSA key imported with either - * crypto_rsa_import_public_key() or crypto_rsa_import_private_key(). - */ -void crypto_rsa_free(struct crypto_rsa_key *key) -{ - if (key) { - bignum_deinit(key->n); - bignum_deinit(key->e); - bignum_deinit(key->d); - bignum_deinit(key->p); - bignum_deinit(key->q); - bignum_deinit(key->dmp1); - bignum_deinit(key->dmq1); - bignum_deinit(key->iqmp); - os_free(key); - } -} diff --git a/hostapd-0.8/src/tls/rsa.h b/hostapd-0.8/src/tls/rsa.h deleted file mode 100644 index ac50dfd..0000000 --- a/hostapd-0.8/src/tls/rsa.h +++ /dev/null @@ -1,29 +0,0 @@ -/* - * RSA - * Copyright (c) 2006, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#ifndef RSA_H -#define RSA_H - -struct crypto_rsa_key; - -struct crypto_rsa_key * -crypto_rsa_import_public_key(const u8 *buf, size_t len); -struct crypto_rsa_key * -crypto_rsa_import_private_key(const u8 *buf, size_t len); -size_t crypto_rsa_get_modulus_len(struct crypto_rsa_key *key); -int crypto_rsa_exptmod(const u8 *in, size_t inlen, u8 *out, size_t *outlen, - struct crypto_rsa_key *key, int use_private); -void crypto_rsa_free(struct crypto_rsa_key *key); - -#endif /* RSA_H */ diff --git a/hostapd-0.8/src/tls/tlsv1_client.c b/hostapd-0.8/src/tls/tlsv1_client.c deleted file mode 100644 index afb6031..0000000 --- a/hostapd-0.8/src/tls/tlsv1_client.c +++ /dev/null @@ -1,667 +0,0 @@ -/* - * TLSv1 client (RFC 2246) - * Copyright (c) 2006-2007, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#include "includes.h" - -#include "common.h" -#include "crypto/sha1.h" -#include "crypto/tls.h" -#include "tlsv1_common.h" -#include "tlsv1_record.h" -#include "tlsv1_client.h" -#include "tlsv1_client_i.h" - -/* TODO: - * Support for a message fragmented across several records (RFC 2246, 6.2.1) - */ - - -void tls_alert(struct tlsv1_client *conn, u8 level, u8 description) -{ - conn->alert_level = level; - conn->alert_description = description; -} - - -void tlsv1_client_free_dh(struct tlsv1_client *conn) -{ - os_free(conn->dh_p); - os_free(conn->dh_g); - os_free(conn->dh_ys); - conn->dh_p = conn->dh_g = conn->dh_ys = NULL; -} - - -int tls_derive_pre_master_secret(u8 *pre_master_secret) -{ - WPA_PUT_BE16(pre_master_secret, TLS_VERSION); - if (os_get_random(pre_master_secret + 2, - TLS_PRE_MASTER_SECRET_LEN - 2)) - return -1; - return 0; -} - - -int tls_derive_keys(struct tlsv1_client *conn, - const u8 *pre_master_secret, size_t pre_master_secret_len) -{ - u8 seed[2 * TLS_RANDOM_LEN]; - u8 key_block[TLS_MAX_KEY_BLOCK_LEN]; - u8 *pos; - size_t key_block_len; - - if (pre_master_secret) { - wpa_hexdump_key(MSG_MSGDUMP, "TLSv1: pre_master_secret", - pre_master_secret, pre_master_secret_len); - os_memcpy(seed, conn->client_random, TLS_RANDOM_LEN); - os_memcpy(seed + TLS_RANDOM_LEN, conn->server_random, - TLS_RANDOM_LEN); - if (tls_prf(pre_master_secret, pre_master_secret_len, - "master secret", seed, 2 * TLS_RANDOM_LEN, - conn->master_secret, TLS_MASTER_SECRET_LEN)) { - wpa_printf(MSG_DEBUG, "TLSv1: Failed to derive " - "master_secret"); - return -1; - } - wpa_hexdump_key(MSG_MSGDUMP, "TLSv1: master_secret", - conn->master_secret, TLS_MASTER_SECRET_LEN); - } - - os_memcpy(seed, conn->server_random, TLS_RANDOM_LEN); - os_memcpy(seed + TLS_RANDOM_LEN, conn->client_random, TLS_RANDOM_LEN); - key_block_len = 2 * (conn->rl.hash_size + conn->rl.key_material_len + - conn->rl.iv_size); - if (tls_prf(conn->master_secret, TLS_MASTER_SECRET_LEN, - "key expansion", seed, 2 * TLS_RANDOM_LEN, - key_block, key_block_len)) { - wpa_printf(MSG_DEBUG, "TLSv1: Failed to derive key_block"); - return -1; - } - wpa_hexdump_key(MSG_MSGDUMP, "TLSv1: key_block", - key_block, key_block_len); - - pos = key_block; - - /* client_write_MAC_secret */ - os_memcpy(conn->rl.write_mac_secret, pos, conn->rl.hash_size); - pos += conn->rl.hash_size; - /* server_write_MAC_secret */ - os_memcpy(conn->rl.read_mac_secret, pos, conn->rl.hash_size); - pos += conn->rl.hash_size; - - /* client_write_key */ - os_memcpy(conn->rl.write_key, pos, conn->rl.key_material_len); - pos += conn->rl.key_material_len; - /* server_write_key */ - os_memcpy(conn->rl.read_key, pos, conn->rl.key_material_len); - pos += conn->rl.key_material_len; - - /* client_write_IV */ - os_memcpy(conn->rl.write_iv, pos, conn->rl.iv_size); - pos += conn->rl.iv_size; - /* server_write_IV */ - os_memcpy(conn->rl.read_iv, pos, conn->rl.iv_size); - pos += conn->rl.iv_size; - - return 0; -} - - -/** - * tlsv1_client_handshake - Process TLS handshake - * @conn: TLSv1 client connection data from tlsv1_client_init() - * @in_data: Input data from TLS peer - * @in_len: Input data length - * @out_len: Length of the output buffer. - * @appl_data: Pointer to application data pointer, or %NULL if dropped - * @appl_data_len: Pointer to variable that is set to appl_data length - * Returns: Pointer to output data, %NULL on failure - */ -u8 * tlsv1_client_handshake(struct tlsv1_client *conn, - const u8 *in_data, size_t in_len, - size_t *out_len, u8 **appl_data, - size_t *appl_data_len) -{ - const u8 *pos, *end; - u8 *msg = NULL, *in_msg, *in_pos, *in_end, alert, ct; - size_t in_msg_len; - int no_appl_data; - - if (conn->state == CLIENT_HELLO) { - if (in_len) - return NULL; - return tls_send_client_hello(conn, out_len); - } - - if (in_data == NULL || in_len == 0) - return NULL; - - pos = in_data; - end = in_data + in_len; - in_msg = os_malloc(in_len); - if (in_msg == NULL) - return NULL; - - /* Each received packet may include multiple records */ - while (pos < end) { - in_msg_len = in_len; - if (tlsv1_record_receive(&conn->rl, pos, end - pos, - in_msg, &in_msg_len, &alert)) { - wpa_printf(MSG_DEBUG, "TLSv1: Processing received " - "record failed"); - tls_alert(conn, TLS_ALERT_LEVEL_FATAL, alert); - goto failed; - } - ct = pos[0]; - - in_pos = in_msg; - in_end = in_msg + in_msg_len; - - /* Each received record may include multiple messages of the - * same ContentType. */ - while (in_pos < in_end) { - in_msg_len = in_end - in_pos; - if (tlsv1_client_process_handshake(conn, ct, in_pos, - &in_msg_len, - appl_data, - appl_data_len) < 0) - goto failed; - in_pos += in_msg_len; - } - - pos += TLS_RECORD_HEADER_LEN + WPA_GET_BE16(pos + 3); - } - - os_free(in_msg); - in_msg = NULL; - - no_appl_data = appl_data == NULL || *appl_data == NULL; - msg = tlsv1_client_handshake_write(conn, out_len, no_appl_data); - -failed: - os_free(in_msg); - if (conn->alert_level) { - conn->state = FAILED; - os_free(msg); - msg = tlsv1_client_send_alert(conn, conn->alert_level, - conn->alert_description, - out_len); - } else if (msg == NULL) { - msg = os_zalloc(1); - *out_len = 0; - } - - return msg; -} - - -/** - * tlsv1_client_encrypt - Encrypt data into TLS tunnel - * @conn: TLSv1 client connection data from tlsv1_client_init() - * @in_data: Pointer to plaintext data to be encrypted - * @in_len: Input buffer length - * @out_data: Pointer to output buffer (encrypted TLS data) - * @out_len: Maximum out_data length - * Returns: Number of bytes written to out_data, -1 on failure - * - * This function is used after TLS handshake has been completed successfully to - * send data in the encrypted tunnel. - */ -int tlsv1_client_encrypt(struct tlsv1_client *conn, - const u8 *in_data, size_t in_len, - u8 *out_data, size_t out_len) -{ - size_t rlen; - - wpa_hexdump_key(MSG_MSGDUMP, "TLSv1: Plaintext AppData", - in_data, in_len); - - os_memcpy(out_data + TLS_RECORD_HEADER_LEN, in_data, in_len); - - if (tlsv1_record_send(&conn->rl, TLS_CONTENT_TYPE_APPLICATION_DATA, - out_data, out_len, in_len, &rlen) < 0) { - wpa_printf(MSG_DEBUG, "TLSv1: Failed to create a record"); - tls_alert(conn, TLS_ALERT_LEVEL_FATAL, - TLS_ALERT_INTERNAL_ERROR); - return -1; - } - - return rlen; -} - - -/** - * tlsv1_client_decrypt - Decrypt data from TLS tunnel - * @conn: TLSv1 client connection data from tlsv1_client_init() - * @in_data: Pointer to input buffer (encrypted TLS data) - * @in_len: Input buffer length - * @out_data: Pointer to output buffer (decrypted data from TLS tunnel) - * @out_len: Maximum out_data length - * Returns: Number of bytes written to out_data, -1 on failure - * - * This function is used after TLS handshake has been completed successfully to - * receive data from the encrypted tunnel. - */ -int tlsv1_client_decrypt(struct tlsv1_client *conn, - const u8 *in_data, size_t in_len, - u8 *out_data, size_t out_len) -{ - const u8 *in_end, *pos; - int res; - u8 alert, *out_end, *out_pos; - size_t olen; - - pos = in_data; - in_end = in_data + in_len; - out_pos = out_data; - out_end = out_data + out_len; - - while (pos < in_end) { - if (pos[0] != TLS_CONTENT_TYPE_APPLICATION_DATA) { - wpa_printf(MSG_DEBUG, "TLSv1: Unexpected content type " - "0x%x", pos[0]); - tls_alert(conn, TLS_ALERT_LEVEL_FATAL, - TLS_ALERT_UNEXPECTED_MESSAGE); - return -1; - } - - olen = out_end - out_pos; - res = tlsv1_record_receive(&conn->rl, pos, in_end - pos, - out_pos, &olen, &alert); - if (res < 0) { - wpa_printf(MSG_DEBUG, "TLSv1: Record layer processing " - "failed"); - tls_alert(conn, TLS_ALERT_LEVEL_FATAL, alert); - return -1; - } - out_pos += olen; - if (out_pos > out_end) { - wpa_printf(MSG_DEBUG, "TLSv1: Buffer not large enough " - "for processing the received record"); - tls_alert(conn, TLS_ALERT_LEVEL_FATAL, - TLS_ALERT_INTERNAL_ERROR); - return -1; - } - - pos += TLS_RECORD_HEADER_LEN + WPA_GET_BE16(pos + 3); - } - - return out_pos - out_data; -} - - -/** - * tlsv1_client_global_init - Initialize TLSv1 client - * Returns: 0 on success, -1 on failure - * - * This function must be called before using any other TLSv1 client functions. - */ -int tlsv1_client_global_init(void) -{ - return crypto_global_init(); -} - - -/** - * tlsv1_client_global_deinit - Deinitialize TLSv1 client - * - * This function can be used to deinitialize the TLSv1 client that was - * initialized by calling tlsv1_client_global_init(). No TLSv1 client functions - * can be called after this before calling tlsv1_client_global_init() again. - */ -void tlsv1_client_global_deinit(void) -{ - crypto_global_deinit(); -} - - -/** - * tlsv1_client_init - Initialize TLSv1 client connection - * Returns: Pointer to TLSv1 client connection data or %NULL on failure - */ -struct tlsv1_client * tlsv1_client_init(void) -{ - struct tlsv1_client *conn; - size_t count; - u16 *suites; - - conn = os_zalloc(sizeof(*conn)); - if (conn == NULL) - return NULL; - - conn->state = CLIENT_HELLO; - - if (tls_verify_hash_init(&conn->verify) < 0) { - wpa_printf(MSG_DEBUG, "TLSv1: Failed to initialize verify " - "hash"); - os_free(conn); - return NULL; - } - - count = 0; - suites = conn->cipher_suites; -#ifndef CONFIG_CRYPTO_INTERNAL - suites[count++] = TLS_RSA_WITH_AES_256_CBC_SHA; -#endif /* CONFIG_CRYPTO_INTERNAL */ - suites[count++] = TLS_RSA_WITH_AES_128_CBC_SHA; - suites[count++] = TLS_RSA_WITH_3DES_EDE_CBC_SHA; - suites[count++] = TLS_RSA_WITH_RC4_128_SHA; - suites[count++] = TLS_RSA_WITH_RC4_128_MD5; - conn->num_cipher_suites = count; - - return conn; -} - - -/** - * tlsv1_client_deinit - Deinitialize TLSv1 client connection - * @conn: TLSv1 client connection data from tlsv1_client_init() - */ -void tlsv1_client_deinit(struct tlsv1_client *conn) -{ - crypto_public_key_free(conn->server_rsa_key); - tlsv1_record_set_cipher_suite(&conn->rl, TLS_NULL_WITH_NULL_NULL); - tlsv1_record_change_write_cipher(&conn->rl); - tlsv1_record_change_read_cipher(&conn->rl); - tls_verify_hash_free(&conn->verify); - os_free(conn->client_hello_ext); - tlsv1_client_free_dh(conn); - tlsv1_cred_free(conn->cred); - os_free(conn); -} - - -/** - * tlsv1_client_established - Check whether connection has been established - * @conn: TLSv1 client connection data from tlsv1_client_init() - * Returns: 1 if connection is established, 0 if not - */ -int tlsv1_client_established(struct tlsv1_client *conn) -{ - return conn->state == ESTABLISHED; -} - - -/** - * tlsv1_client_prf - Use TLS-PRF to derive keying material - * @conn: TLSv1 client connection data from tlsv1_client_init() - * @label: Label (e.g., description of the key) for PRF - * @server_random_first: seed is 0 = client_random|server_random, - * 1 = server_random|client_random - * @out: Buffer for output data from TLS-PRF - * @out_len: Length of the output buffer - * Returns: 0 on success, -1 on failure - */ -int tlsv1_client_prf(struct tlsv1_client *conn, const char *label, - int server_random_first, u8 *out, size_t out_len) -{ - u8 seed[2 * TLS_RANDOM_LEN]; - - if (conn->state != ESTABLISHED) - return -1; - - if (server_random_first) { - os_memcpy(seed, conn->server_random, TLS_RANDOM_LEN); - os_memcpy(seed + TLS_RANDOM_LEN, conn->client_random, - TLS_RANDOM_LEN); - } else { - os_memcpy(seed, conn->client_random, TLS_RANDOM_LEN); - os_memcpy(seed + TLS_RANDOM_LEN, conn->server_random, - TLS_RANDOM_LEN); - } - - return tls_prf(conn->master_secret, TLS_MASTER_SECRET_LEN, - label, seed, 2 * TLS_RANDOM_LEN, out, out_len); -} - - -/** - * tlsv1_client_get_cipher - Get current cipher name - * @conn: TLSv1 client connection data from tlsv1_client_init() - * @buf: Buffer for the cipher name - * @buflen: buf size - * Returns: 0 on success, -1 on failure - * - * Get the name of the currently used cipher. - */ -int tlsv1_client_get_cipher(struct tlsv1_client *conn, char *buf, - size_t buflen) -{ - char *cipher; - - switch (conn->rl.cipher_suite) { - case TLS_RSA_WITH_RC4_128_MD5: - cipher = "RC4-MD5"; - break; - case TLS_RSA_WITH_RC4_128_SHA: - cipher = "RC4-SHA"; - break; - case TLS_RSA_WITH_DES_CBC_SHA: - cipher = "DES-CBC-SHA"; - break; - case TLS_RSA_WITH_3DES_EDE_CBC_SHA: - cipher = "DES-CBC3-SHA"; - break; - case TLS_DH_anon_WITH_AES_128_CBC_SHA: - cipher = "ADH-AES-128-SHA"; - break; - case TLS_RSA_WITH_AES_256_CBC_SHA: - cipher = "AES-256-SHA"; - break; - case TLS_RSA_WITH_AES_128_CBC_SHA: - cipher = "AES-128-SHA"; - break; - default: - return -1; - } - - if (os_strlcpy(buf, cipher, buflen) >= buflen) - return -1; - return 0; -} - - -/** - * tlsv1_client_shutdown - Shutdown TLS connection - * @conn: TLSv1 client connection data from tlsv1_client_init() - * Returns: 0 on success, -1 on failure - */ -int tlsv1_client_shutdown(struct tlsv1_client *conn) -{ - conn->state = CLIENT_HELLO; - - if (tls_verify_hash_init(&conn->verify) < 0) { - wpa_printf(MSG_DEBUG, "TLSv1: Failed to re-initialize verify " - "hash"); - return -1; - } - - tlsv1_record_set_cipher_suite(&conn->rl, TLS_NULL_WITH_NULL_NULL); - tlsv1_record_change_write_cipher(&conn->rl); - tlsv1_record_change_read_cipher(&conn->rl); - - conn->certificate_requested = 0; - crypto_public_key_free(conn->server_rsa_key); - conn->server_rsa_key = NULL; - conn->session_resumed = 0; - - return 0; -} - - -/** - * tlsv1_client_resumed - Was session resumption used - * @conn: TLSv1 client connection data from tlsv1_client_init() - * Returns: 1 if current session used session resumption, 0 if not - */ -int tlsv1_client_resumed(struct tlsv1_client *conn) -{ - return !!conn->session_resumed; -} - - -/** - * tlsv1_client_hello_ext - Set TLS extension for ClientHello - * @conn: TLSv1 client connection data from tlsv1_client_init() - * @ext_type: Extension type - * @data: Extension payload (%NULL to remove extension) - * @data_len: Extension payload length - * Returns: 0 on success, -1 on failure - */ -int tlsv1_client_hello_ext(struct tlsv1_client *conn, int ext_type, - const u8 *data, size_t data_len) -{ - u8 *pos; - - conn->session_ticket_included = 0; - os_free(conn->client_hello_ext); - conn->client_hello_ext = NULL; - conn->client_hello_ext_len = 0; - - if (data == NULL || data_len == 0) - return 0; - - pos = conn->client_hello_ext = os_malloc(6 + data_len); - if (pos == NULL) - return -1; - - WPA_PUT_BE16(pos, 4 + data_len); - pos += 2; - WPA_PUT_BE16(pos, ext_type); - pos += 2; - WPA_PUT_BE16(pos, data_len); - pos += 2; - os_memcpy(pos, data, data_len); - conn->client_hello_ext_len = 6 + data_len; - - if (ext_type == TLS_EXT_PAC_OPAQUE) { - conn->session_ticket_included = 1; - wpa_printf(MSG_DEBUG, "TLSv1: Using session ticket"); - } - - return 0; -} - - -/** - * tlsv1_client_get_keys - Get master key and random data from TLS connection - * @conn: TLSv1 client connection data from tlsv1_client_init() - * @keys: Structure of key/random data (filled on success) - * Returns: 0 on success, -1 on failure - */ -int tlsv1_client_get_keys(struct tlsv1_client *conn, struct tls_keys *keys) -{ - os_memset(keys, 0, sizeof(*keys)); - if (conn->state == CLIENT_HELLO) - return -1; - - keys->client_random = conn->client_random; - keys->client_random_len = TLS_RANDOM_LEN; - - if (conn->state != SERVER_HELLO) { - keys->server_random = conn->server_random; - keys->server_random_len = TLS_RANDOM_LEN; - keys->master_key = conn->master_secret; - keys->master_key_len = TLS_MASTER_SECRET_LEN; - } - - return 0; -} - - -/** - * tlsv1_client_get_keyblock_size - Get TLS key_block size - * @conn: TLSv1 client connection data from tlsv1_client_init() - * Returns: Size of the key_block for the negotiated cipher suite or -1 on - * failure - */ -int tlsv1_client_get_keyblock_size(struct tlsv1_client *conn) -{ - if (conn->state == CLIENT_HELLO || conn->state == SERVER_HELLO) - return -1; - - return 2 * (conn->rl.hash_size + conn->rl.key_material_len + - conn->rl.iv_size); -} - - -/** - * tlsv1_client_set_cipher_list - Configure acceptable cipher suites - * @conn: TLSv1 client connection data from tlsv1_client_init() - * @ciphers: Zero (TLS_CIPHER_NONE) terminated list of allowed ciphers - * (TLS_CIPHER_*). - * Returns: 0 on success, -1 on failure - */ -int tlsv1_client_set_cipher_list(struct tlsv1_client *conn, u8 *ciphers) -{ - size_t count; - u16 *suites; - - /* TODO: implement proper configuration of cipher suites */ - if (ciphers[0] == TLS_CIPHER_ANON_DH_AES128_SHA) { - count = 0; - suites = conn->cipher_suites; -#ifndef CONFIG_CRYPTO_INTERNAL - suites[count++] = TLS_DH_anon_WITH_AES_256_CBC_SHA; -#endif /* CONFIG_CRYPTO_INTERNAL */ - suites[count++] = TLS_DH_anon_WITH_AES_128_CBC_SHA; - suites[count++] = TLS_DH_anon_WITH_3DES_EDE_CBC_SHA; - suites[count++] = TLS_DH_anon_WITH_RC4_128_MD5; - suites[count++] = TLS_DH_anon_WITH_DES_CBC_SHA; - - /* - * Cisco AP (at least 350 and 1200 series) local authentication - * server does not know how to search cipher suites from the - * list and seem to require that the last entry in the list is - * the one that it wants to use. However, TLS specification - * requires the list to be in the client preference order. As a - * workaround, add anon-DH AES-128-SHA1 again at the end of the - * list to allow the Cisco code to find it. - */ - suites[count++] = TLS_DH_anon_WITH_AES_128_CBC_SHA; - conn->num_cipher_suites = count; - } - - return 0; -} - - -/** - * tlsv1_client_set_cred - Set client credentials - * @conn: TLSv1 client connection data from tlsv1_client_init() - * @cred: Credentials from tlsv1_cred_alloc() - * Returns: 0 on success, -1 on failure - * - * On success, the client takes ownership of the credentials block and caller - * must not free it. On failure, caller is responsible for freeing the - * credential block. - */ -int tlsv1_client_set_cred(struct tlsv1_client *conn, - struct tlsv1_credentials *cred) -{ - tlsv1_cred_free(conn->cred); - conn->cred = cred; - return 0; -} - - -void tlsv1_client_set_session_ticket_cb(struct tlsv1_client *conn, - tlsv1_client_session_ticket_cb cb, - void *ctx) -{ - wpa_printf(MSG_DEBUG, "TLSv1: SessionTicket callback set %p (ctx %p)", - cb, ctx); - conn->session_ticket_cb = cb; - conn->session_ticket_cb_ctx = ctx; -} diff --git a/hostapd-0.8/src/tls/tlsv1_client.h b/hostapd-0.8/src/tls/tlsv1_client.h deleted file mode 100644 index 16ad57d..0000000 --- a/hostapd-0.8/src/tls/tlsv1_client.h +++ /dev/null @@ -1,59 +0,0 @@ -/* - * TLSv1 client (RFC 2246) - * Copyright (c) 2006-2007, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#ifndef TLSV1_CLIENT_H -#define TLSV1_CLIENT_H - -#include "tlsv1_cred.h" - -struct tlsv1_client; - -int tlsv1_client_global_init(void); -void tlsv1_client_global_deinit(void); -struct tlsv1_client * tlsv1_client_init(void); -void tlsv1_client_deinit(struct tlsv1_client *conn); -int tlsv1_client_established(struct tlsv1_client *conn); -int tlsv1_client_prf(struct tlsv1_client *conn, const char *label, - int server_random_first, u8 *out, size_t out_len); -u8 * tlsv1_client_handshake(struct tlsv1_client *conn, - const u8 *in_data, size_t in_len, - size_t *out_len, u8 **appl_data, - size_t *appl_data_len); -int tlsv1_client_encrypt(struct tlsv1_client *conn, - const u8 *in_data, size_t in_len, - u8 *out_data, size_t out_len); -int tlsv1_client_decrypt(struct tlsv1_client *conn, - const u8 *in_data, size_t in_len, - u8 *out_data, size_t out_len); -int tlsv1_client_get_cipher(struct tlsv1_client *conn, char *buf, - size_t buflen); -int tlsv1_client_shutdown(struct tlsv1_client *conn); -int tlsv1_client_resumed(struct tlsv1_client *conn); -int tlsv1_client_hello_ext(struct tlsv1_client *conn, int ext_type, - const u8 *data, size_t data_len); -int tlsv1_client_get_keys(struct tlsv1_client *conn, struct tls_keys *keys); -int tlsv1_client_get_keyblock_size(struct tlsv1_client *conn); -int tlsv1_client_set_cipher_list(struct tlsv1_client *conn, u8 *ciphers); -int tlsv1_client_set_cred(struct tlsv1_client *conn, - struct tlsv1_credentials *cred); - -typedef int (*tlsv1_client_session_ticket_cb) -(void *ctx, const u8 *ticket, size_t len, const u8 *client_random, - const u8 *server_random, u8 *master_secret); - -void tlsv1_client_set_session_ticket_cb(struct tlsv1_client *conn, - tlsv1_client_session_ticket_cb cb, - void *ctx); - -#endif /* TLSV1_CLIENT_H */ diff --git a/hostapd-0.8/src/tls/tlsv1_client_i.h b/hostapd-0.8/src/tls/tlsv1_client_i.h deleted file mode 100644 index 7fe179f..0000000 --- a/hostapd-0.8/src/tls/tlsv1_client_i.h +++ /dev/null @@ -1,87 +0,0 @@ -/* - * TLSv1 client - internal structures - * Copyright (c) 2006-2007, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#ifndef TLSV1_CLIENT_I_H -#define TLSV1_CLIENT_I_H - -struct tlsv1_client { - enum { - CLIENT_HELLO, SERVER_HELLO, SERVER_CERTIFICATE, - SERVER_KEY_EXCHANGE, SERVER_CERTIFICATE_REQUEST, - SERVER_HELLO_DONE, CLIENT_KEY_EXCHANGE, CHANGE_CIPHER_SPEC, - SERVER_CHANGE_CIPHER_SPEC, SERVER_FINISHED, ACK_FINISHED, - ESTABLISHED, FAILED - } state; - - struct tlsv1_record_layer rl; - - u8 session_id[TLS_SESSION_ID_MAX_LEN]; - size_t session_id_len; - u8 client_random[TLS_RANDOM_LEN]; - u8 server_random[TLS_RANDOM_LEN]; - u8 master_secret[TLS_MASTER_SECRET_LEN]; - - u8 alert_level; - u8 alert_description; - - unsigned int certificate_requested:1; - unsigned int session_resumed:1; - unsigned int session_ticket_included:1; - unsigned int use_session_ticket:1; - - struct crypto_public_key *server_rsa_key; - - struct tls_verify_hash verify; - -#define MAX_CIPHER_COUNT 30 - u16 cipher_suites[MAX_CIPHER_COUNT]; - size_t num_cipher_suites; - - u16 prev_cipher_suite; - - u8 *client_hello_ext; - size_t client_hello_ext_len; - - /* The prime modulus used for Diffie-Hellman */ - u8 *dh_p; - size_t dh_p_len; - /* The generator used for Diffie-Hellman */ - u8 *dh_g; - size_t dh_g_len; - /* The server's Diffie-Hellman public value */ - u8 *dh_ys; - size_t dh_ys_len; - - struct tlsv1_credentials *cred; - - tlsv1_client_session_ticket_cb session_ticket_cb; - void *session_ticket_cb_ctx; -}; - - -void tls_alert(struct tlsv1_client *conn, u8 level, u8 description); -void tlsv1_client_free_dh(struct tlsv1_client *conn); -int tls_derive_pre_master_secret(u8 *pre_master_secret); -int tls_derive_keys(struct tlsv1_client *conn, - const u8 *pre_master_secret, size_t pre_master_secret_len); -u8 * tls_send_client_hello(struct tlsv1_client *conn, size_t *out_len); -u8 * tlsv1_client_send_alert(struct tlsv1_client *conn, u8 level, - u8 description, size_t *out_len); -u8 * tlsv1_client_handshake_write(struct tlsv1_client *conn, size_t *out_len, - int no_appl_data); -int tlsv1_client_process_handshake(struct tlsv1_client *conn, u8 ct, - const u8 *buf, size_t *len, - u8 **out_data, size_t *out_len); - -#endif /* TLSV1_CLIENT_I_H */ diff --git a/hostapd-0.8/src/tls/tlsv1_client_read.c b/hostapd-0.8/src/tls/tlsv1_client_read.c deleted file mode 100644 index ed3f260..0000000 --- a/hostapd-0.8/src/tls/tlsv1_client_read.c +++ /dev/null @@ -1,976 +0,0 @@ -/* - * TLSv1 client - read handshake message - * Copyright (c) 2006-2007, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#include "includes.h" - -#include "common.h" -#include "crypto/md5.h" -#include "crypto/sha1.h" -#include "crypto/tls.h" -#include "x509v3.h" -#include "tlsv1_common.h" -#include "tlsv1_record.h" -#include "tlsv1_client.h" -#include "tlsv1_client_i.h" - -static int tls_process_server_key_exchange(struct tlsv1_client *conn, u8 ct, - const u8 *in_data, size_t *in_len); -static int tls_process_certificate_request(struct tlsv1_client *conn, u8 ct, - const u8 *in_data, size_t *in_len); -static int tls_process_server_hello_done(struct tlsv1_client *conn, u8 ct, - const u8 *in_data, size_t *in_len); - - -static int tls_process_server_hello(struct tlsv1_client *conn, u8 ct, - const u8 *in_data, size_t *in_len) -{ - const u8 *pos, *end; - size_t left, len, i; - u16 cipher_suite; - - if (ct != TLS_CONTENT_TYPE_HANDSHAKE) { - wpa_printf(MSG_DEBUG, "TLSv1: Expected Handshake; " - "received content type 0x%x", ct); - tls_alert(conn, TLS_ALERT_LEVEL_FATAL, - TLS_ALERT_UNEXPECTED_MESSAGE); - return -1; - } - - pos = in_data; - left = *in_len; - - if (left < 4) - goto decode_error; - - /* HandshakeType msg_type */ - if (*pos != TLS_HANDSHAKE_TYPE_SERVER_HELLO) { - wpa_printf(MSG_DEBUG, "TLSv1: Received unexpected handshake " - "message %d (expected ServerHello)", *pos); - tls_alert(conn, TLS_ALERT_LEVEL_FATAL, - TLS_ALERT_UNEXPECTED_MESSAGE); - return -1; - } - wpa_printf(MSG_DEBUG, "TLSv1: Received ServerHello"); - pos++; - /* uint24 length */ - len = WPA_GET_BE24(pos); - pos += 3; - left -= 4; - - if (len > left) - goto decode_error; - - /* body - ServerHello */ - - wpa_hexdump(MSG_MSGDUMP, "TLSv1: ServerHello", pos, len); - end = pos + len; - - /* ProtocolVersion server_version */ - if (end - pos < 2) - goto decode_error; - if (WPA_GET_BE16(pos) != TLS_VERSION) { - wpa_printf(MSG_DEBUG, "TLSv1: Unexpected protocol version in " - "ServerHello"); - tls_alert(conn, TLS_ALERT_LEVEL_FATAL, - TLS_ALERT_PROTOCOL_VERSION); - return -1; - } - pos += 2; - - /* Random random */ - if (end - pos < TLS_RANDOM_LEN) - goto decode_error; - - os_memcpy(conn->server_random, pos, TLS_RANDOM_LEN); - pos += TLS_RANDOM_LEN; - wpa_hexdump(MSG_MSGDUMP, "TLSv1: server_random", - conn->server_random, TLS_RANDOM_LEN); - - /* SessionID session_id */ - if (end - pos < 1) - goto decode_error; - if (end - pos < 1 + *pos || *pos > TLS_SESSION_ID_MAX_LEN) - goto decode_error; - if (conn->session_id_len && conn->session_id_len == *pos && - os_memcmp(conn->session_id, pos + 1, conn->session_id_len) == 0) { - pos += 1 + conn->session_id_len; - wpa_printf(MSG_DEBUG, "TLSv1: Resuming old session"); - conn->session_resumed = 1; - } else { - conn->session_id_len = *pos; - pos++; - os_memcpy(conn->session_id, pos, conn->session_id_len); - pos += conn->session_id_len; - } - wpa_hexdump(MSG_MSGDUMP, "TLSv1: session_id", - conn->session_id, conn->session_id_len); - - /* CipherSuite cipher_suite */ - if (end - pos < 2) - goto decode_error; - cipher_suite = WPA_GET_BE16(pos); - pos += 2; - for (i = 0; i < conn->num_cipher_suites; i++) { - if (cipher_suite == conn->cipher_suites[i]) - break; - } - if (i == conn->num_cipher_suites) { - wpa_printf(MSG_INFO, "TLSv1: Server selected unexpected " - "cipher suite 0x%04x", cipher_suite); - tls_alert(conn, TLS_ALERT_LEVEL_FATAL, - TLS_ALERT_ILLEGAL_PARAMETER); - return -1; - } - - if (conn->session_resumed && cipher_suite != conn->prev_cipher_suite) { - wpa_printf(MSG_DEBUG, "TLSv1: Server selected a different " - "cipher suite for a resumed connection (0x%04x != " - "0x%04x)", cipher_suite, conn->prev_cipher_suite); - tls_alert(conn, TLS_ALERT_LEVEL_FATAL, - TLS_ALERT_ILLEGAL_PARAMETER); - return -1; - } - - if (tlsv1_record_set_cipher_suite(&conn->rl, cipher_suite) < 0) { - wpa_printf(MSG_DEBUG, "TLSv1: Failed to set CipherSuite for " - "record layer"); - tls_alert(conn, TLS_ALERT_LEVEL_FATAL, - TLS_ALERT_INTERNAL_ERROR); - return -1; - } - - conn->prev_cipher_suite = cipher_suite; - - /* CompressionMethod compression_method */ - if (end - pos < 1) - goto decode_error; - if (*pos != TLS_COMPRESSION_NULL) { - wpa_printf(MSG_INFO, "TLSv1: Server selected unexpected " - "compression 0x%02x", *pos); - tls_alert(conn, TLS_ALERT_LEVEL_FATAL, - TLS_ALERT_ILLEGAL_PARAMETER); - return -1; - } - pos++; - - if (end != pos) { - /* TODO: ServerHello extensions */ - wpa_hexdump(MSG_DEBUG, "TLSv1: Unexpected extra data in the " - "end of ServerHello", pos, end - pos); - goto decode_error; - } - - if (conn->session_ticket_included && conn->session_ticket_cb) { - /* TODO: include SessionTicket extension if one was included in - * ServerHello */ - int res = conn->session_ticket_cb( - conn->session_ticket_cb_ctx, NULL, 0, - conn->client_random, conn->server_random, - conn->master_secret); - if (res < 0) { - wpa_printf(MSG_DEBUG, "TLSv1: SessionTicket callback " - "indicated failure"); - tls_alert(conn, TLS_ALERT_LEVEL_FATAL, - TLS_ALERT_HANDSHAKE_FAILURE); - return -1; - } - conn->use_session_ticket = !!res; - } - - if ((conn->session_resumed || conn->use_session_ticket) && - tls_derive_keys(conn, NULL, 0)) { - wpa_printf(MSG_DEBUG, "TLSv1: Failed to derive keys"); - tls_alert(conn, TLS_ALERT_LEVEL_FATAL, - TLS_ALERT_INTERNAL_ERROR); - return -1; - } - - *in_len = end - in_data; - - conn->state = (conn->session_resumed || conn->use_session_ticket) ? - SERVER_CHANGE_CIPHER_SPEC : SERVER_CERTIFICATE; - - return 0; - -decode_error: - wpa_printf(MSG_DEBUG, "TLSv1: Failed to decode ServerHello"); - tls_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_DECODE_ERROR); - return -1; -} - - -static int tls_process_certificate(struct tlsv1_client *conn, u8 ct, - const u8 *in_data, size_t *in_len) -{ - const u8 *pos, *end; - size_t left, len, list_len, cert_len, idx; - u8 type; - struct x509_certificate *chain = NULL, *last = NULL, *cert; - int reason; - - if (ct != TLS_CONTENT_TYPE_HANDSHAKE) { - wpa_printf(MSG_DEBUG, "TLSv1: Expected Handshake; " - "received content type 0x%x", ct); - tls_alert(conn, TLS_ALERT_LEVEL_FATAL, - TLS_ALERT_UNEXPECTED_MESSAGE); - return -1; - } - - pos = in_data; - left = *in_len; - - if (left < 4) { - wpa_printf(MSG_DEBUG, "TLSv1: Too short Certificate message " - "(len=%lu)", (unsigned long) left); - tls_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_DECODE_ERROR); - return -1; - } - - type = *pos++; - len = WPA_GET_BE24(pos); - pos += 3; - left -= 4; - - if (len > left) { - wpa_printf(MSG_DEBUG, "TLSv1: Unexpected Certificate message " - "length (len=%lu != left=%lu)", - (unsigned long) len, (unsigned long) left); - tls_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_DECODE_ERROR); - return -1; - } - - if (type == TLS_HANDSHAKE_TYPE_SERVER_KEY_EXCHANGE) - return tls_process_server_key_exchange(conn, ct, in_data, - in_len); - if (type == TLS_HANDSHAKE_TYPE_CERTIFICATE_REQUEST) - return tls_process_certificate_request(conn, ct, in_data, - in_len); - if (type == TLS_HANDSHAKE_TYPE_SERVER_HELLO_DONE) - return tls_process_server_hello_done(conn, ct, in_data, - in_len); - if (type != TLS_HANDSHAKE_TYPE_CERTIFICATE) { - wpa_printf(MSG_DEBUG, "TLSv1: Received unexpected handshake " - "message %d (expected Certificate/" - "ServerKeyExchange/CertificateRequest/" - "ServerHelloDone)", type); - tls_alert(conn, TLS_ALERT_LEVEL_FATAL, - TLS_ALERT_UNEXPECTED_MESSAGE); - return -1; - } - - wpa_printf(MSG_DEBUG, - "TLSv1: Received Certificate (certificate_list len %lu)", - (unsigned long) len); - - /* - * opaque ASN.1Cert<2^24-1>; - * - * struct { - * ASN.1Cert certificate_list<1..2^24-1>; - * } Certificate; - */ - - end = pos + len; - - if (end - pos < 3) { - wpa_printf(MSG_DEBUG, "TLSv1: Too short Certificate " - "(left=%lu)", (unsigned long) left); - tls_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_DECODE_ERROR); - return -1; - } - - list_len = WPA_GET_BE24(pos); - pos += 3; - - if ((size_t) (end - pos) != list_len) { - wpa_printf(MSG_DEBUG, "TLSv1: Unexpected certificate_list " - "length (len=%lu left=%lu)", - (unsigned long) list_len, - (unsigned long) (end - pos)); - tls_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_DECODE_ERROR); - return -1; - } - - idx = 0; - while (pos < end) { - if (end - pos < 3) { - wpa_printf(MSG_DEBUG, "TLSv1: Failed to parse " - "certificate_list"); - tls_alert(conn, TLS_ALERT_LEVEL_FATAL, - TLS_ALERT_DECODE_ERROR); - x509_certificate_chain_free(chain); - return -1; - } - - cert_len = WPA_GET_BE24(pos); - pos += 3; - - if ((size_t) (end - pos) < cert_len) { - wpa_printf(MSG_DEBUG, "TLSv1: Unexpected certificate " - "length (len=%lu left=%lu)", - (unsigned long) cert_len, - (unsigned long) (end - pos)); - tls_alert(conn, TLS_ALERT_LEVEL_FATAL, - TLS_ALERT_DECODE_ERROR); - x509_certificate_chain_free(chain); - return -1; - } - - wpa_printf(MSG_DEBUG, "TLSv1: Certificate %lu (len %lu)", - (unsigned long) idx, (unsigned long) cert_len); - - if (idx == 0) { - crypto_public_key_free(conn->server_rsa_key); - if (tls_parse_cert(pos, cert_len, - &conn->server_rsa_key)) { - wpa_printf(MSG_DEBUG, "TLSv1: Failed to parse " - "the certificate"); - tls_alert(conn, TLS_ALERT_LEVEL_FATAL, - TLS_ALERT_BAD_CERTIFICATE); - x509_certificate_chain_free(chain); - return -1; - } - } - - cert = x509_certificate_parse(pos, cert_len); - if (cert == NULL) { - wpa_printf(MSG_DEBUG, "TLSv1: Failed to parse " - "the certificate"); - tls_alert(conn, TLS_ALERT_LEVEL_FATAL, - TLS_ALERT_BAD_CERTIFICATE); - x509_certificate_chain_free(chain); - return -1; - } - - if (last == NULL) - chain = cert; - else - last->next = cert; - last = cert; - - idx++; - pos += cert_len; - } - - if (conn->cred && - x509_certificate_chain_validate(conn->cred->trusted_certs, chain, - &reason) < 0) { - int tls_reason; - wpa_printf(MSG_DEBUG, "TLSv1: Server certificate chain " - "validation failed (reason=%d)", reason); - switch (reason) { - case X509_VALIDATE_BAD_CERTIFICATE: - tls_reason = TLS_ALERT_BAD_CERTIFICATE; - break; - case X509_VALIDATE_UNSUPPORTED_CERTIFICATE: - tls_reason = TLS_ALERT_UNSUPPORTED_CERTIFICATE; - break; - case X509_VALIDATE_CERTIFICATE_REVOKED: - tls_reason = TLS_ALERT_CERTIFICATE_REVOKED; - break; - case X509_VALIDATE_CERTIFICATE_EXPIRED: - tls_reason = TLS_ALERT_CERTIFICATE_EXPIRED; - break; - case X509_VALIDATE_CERTIFICATE_UNKNOWN: - tls_reason = TLS_ALERT_CERTIFICATE_UNKNOWN; - break; - case X509_VALIDATE_UNKNOWN_CA: - tls_reason = TLS_ALERT_UNKNOWN_CA; - break; - default: - tls_reason = TLS_ALERT_BAD_CERTIFICATE; - break; - } - tls_alert(conn, TLS_ALERT_LEVEL_FATAL, tls_reason); - x509_certificate_chain_free(chain); - return -1; - } - - x509_certificate_chain_free(chain); - - *in_len = end - in_data; - - conn->state = SERVER_KEY_EXCHANGE; - - return 0; -} - - -static int tlsv1_process_diffie_hellman(struct tlsv1_client *conn, - const u8 *buf, size_t len) -{ - const u8 *pos, *end; - - tlsv1_client_free_dh(conn); - - pos = buf; - end = buf + len; - - if (end - pos < 3) - goto fail; - conn->dh_p_len = WPA_GET_BE16(pos); - pos += 2; - if (conn->dh_p_len == 0 || end - pos < (int) conn->dh_p_len) { - wpa_printf(MSG_DEBUG, "TLSv1: Invalid dh_p length %lu", - (unsigned long) conn->dh_p_len); - goto fail; - } - conn->dh_p = os_malloc(conn->dh_p_len); - if (conn->dh_p == NULL) - goto fail; - os_memcpy(conn->dh_p, pos, conn->dh_p_len); - pos += conn->dh_p_len; - wpa_hexdump(MSG_DEBUG, "TLSv1: DH p (prime)", - conn->dh_p, conn->dh_p_len); - - if (end - pos < 3) - goto fail; - conn->dh_g_len = WPA_GET_BE16(pos); - pos += 2; - if (conn->dh_g_len == 0 || end - pos < (int) conn->dh_g_len) - goto fail; - conn->dh_g = os_malloc(conn->dh_g_len); - if (conn->dh_g == NULL) - goto fail; - os_memcpy(conn->dh_g, pos, conn->dh_g_len); - pos += conn->dh_g_len; - wpa_hexdump(MSG_DEBUG, "TLSv1: DH g (generator)", - conn->dh_g, conn->dh_g_len); - if (conn->dh_g_len == 1 && conn->dh_g[0] < 2) - goto fail; - - if (end - pos < 3) - goto fail; - conn->dh_ys_len = WPA_GET_BE16(pos); - pos += 2; - if (conn->dh_ys_len == 0 || end - pos < (int) conn->dh_ys_len) - goto fail; - conn->dh_ys = os_malloc(conn->dh_ys_len); - if (conn->dh_ys == NULL) - goto fail; - os_memcpy(conn->dh_ys, pos, conn->dh_ys_len); - pos += conn->dh_ys_len; - wpa_hexdump(MSG_DEBUG, "TLSv1: DH Ys (server's public value)", - conn->dh_ys, conn->dh_ys_len); - - return 0; - -fail: - wpa_printf(MSG_DEBUG, "TLSv1: Processing DH params failed"); - tlsv1_client_free_dh(conn); - return -1; -} - - -static int tls_process_server_key_exchange(struct tlsv1_client *conn, u8 ct, - const u8 *in_data, size_t *in_len) -{ - const u8 *pos, *end; - size_t left, len; - u8 type; - const struct tls_cipher_suite *suite; - - if (ct != TLS_CONTENT_TYPE_HANDSHAKE) { - wpa_printf(MSG_DEBUG, "TLSv1: Expected Handshake; " - "received content type 0x%x", ct); - tls_alert(conn, TLS_ALERT_LEVEL_FATAL, - TLS_ALERT_UNEXPECTED_MESSAGE); - return -1; - } - - pos = in_data; - left = *in_len; - - if (left < 4) { - wpa_printf(MSG_DEBUG, "TLSv1: Too short ServerKeyExchange " - "(Left=%lu)", (unsigned long) left); - tls_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_DECODE_ERROR); - return -1; - } - - type = *pos++; - len = WPA_GET_BE24(pos); - pos += 3; - left -= 4; - - if (len > left) { - wpa_printf(MSG_DEBUG, "TLSv1: Mismatch in ServerKeyExchange " - "length (len=%lu != left=%lu)", - (unsigned long) len, (unsigned long) left); - tls_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_DECODE_ERROR); - return -1; - } - - end = pos + len; - - if (type == TLS_HANDSHAKE_TYPE_CERTIFICATE_REQUEST) - return tls_process_certificate_request(conn, ct, in_data, - in_len); - if (type == TLS_HANDSHAKE_TYPE_SERVER_HELLO_DONE) - return tls_process_server_hello_done(conn, ct, in_data, - in_len); - if (type != TLS_HANDSHAKE_TYPE_SERVER_KEY_EXCHANGE) { - wpa_printf(MSG_DEBUG, "TLSv1: Received unexpected handshake " - "message %d (expected ServerKeyExchange/" - "CertificateRequest/ServerHelloDone)", type); - tls_alert(conn, TLS_ALERT_LEVEL_FATAL, - TLS_ALERT_UNEXPECTED_MESSAGE); - return -1; - } - - wpa_printf(MSG_DEBUG, "TLSv1: Received ServerKeyExchange"); - - if (!tls_server_key_exchange_allowed(conn->rl.cipher_suite)) { - wpa_printf(MSG_DEBUG, "TLSv1: ServerKeyExchange not allowed " - "with the selected cipher suite"); - tls_alert(conn, TLS_ALERT_LEVEL_FATAL, - TLS_ALERT_UNEXPECTED_MESSAGE); - return -1; - } - - wpa_hexdump(MSG_DEBUG, "TLSv1: ServerKeyExchange", pos, len); - suite = tls_get_cipher_suite(conn->rl.cipher_suite); - if (suite && suite->key_exchange == TLS_KEY_X_DH_anon) { - if (tlsv1_process_diffie_hellman(conn, pos, len) < 0) { - tls_alert(conn, TLS_ALERT_LEVEL_FATAL, - TLS_ALERT_DECODE_ERROR); - return -1; - } - } else { - wpa_printf(MSG_DEBUG, "TLSv1: UnexpectedServerKeyExchange"); - tls_alert(conn, TLS_ALERT_LEVEL_FATAL, - TLS_ALERT_UNEXPECTED_MESSAGE); - return -1; - } - - *in_len = end - in_data; - - conn->state = SERVER_CERTIFICATE_REQUEST; - - return 0; -} - - -static int tls_process_certificate_request(struct tlsv1_client *conn, u8 ct, - const u8 *in_data, size_t *in_len) -{ - const u8 *pos, *end; - size_t left, len; - u8 type; - - if (ct != TLS_CONTENT_TYPE_HANDSHAKE) { - wpa_printf(MSG_DEBUG, "TLSv1: Expected Handshake; " - "received content type 0x%x", ct); - tls_alert(conn, TLS_ALERT_LEVEL_FATAL, - TLS_ALERT_UNEXPECTED_MESSAGE); - return -1; - } - - pos = in_data; - left = *in_len; - - if (left < 4) { - wpa_printf(MSG_DEBUG, "TLSv1: Too short CertificateRequest " - "(left=%lu)", (unsigned long) left); - tls_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_DECODE_ERROR); - return -1; - } - - type = *pos++; - len = WPA_GET_BE24(pos); - pos += 3; - left -= 4; - - if (len > left) { - wpa_printf(MSG_DEBUG, "TLSv1: Mismatch in CertificateRequest " - "length (len=%lu != left=%lu)", - (unsigned long) len, (unsigned long) left); - tls_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_DECODE_ERROR); - return -1; - } - - end = pos + len; - - if (type == TLS_HANDSHAKE_TYPE_SERVER_HELLO_DONE) - return tls_process_server_hello_done(conn, ct, in_data, - in_len); - if (type != TLS_HANDSHAKE_TYPE_CERTIFICATE_REQUEST) { - wpa_printf(MSG_DEBUG, "TLSv1: Received unexpected handshake " - "message %d (expected CertificateRequest/" - "ServerHelloDone)", type); - tls_alert(conn, TLS_ALERT_LEVEL_FATAL, - TLS_ALERT_UNEXPECTED_MESSAGE); - return -1; - } - - wpa_printf(MSG_DEBUG, "TLSv1: Received CertificateRequest"); - - conn->certificate_requested = 1; - - *in_len = end - in_data; - - conn->state = SERVER_HELLO_DONE; - - return 0; -} - - -static int tls_process_server_hello_done(struct tlsv1_client *conn, u8 ct, - const u8 *in_data, size_t *in_len) -{ - const u8 *pos, *end; - size_t left, len; - u8 type; - - if (ct != TLS_CONTENT_TYPE_HANDSHAKE) { - wpa_printf(MSG_DEBUG, "TLSv1: Expected Handshake; " - "received content type 0x%x", ct); - tls_alert(conn, TLS_ALERT_LEVEL_FATAL, - TLS_ALERT_UNEXPECTED_MESSAGE); - return -1; - } - - pos = in_data; - left = *in_len; - - if (left < 4) { - wpa_printf(MSG_DEBUG, "TLSv1: Too short ServerHelloDone " - "(left=%lu)", (unsigned long) left); - tls_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_DECODE_ERROR); - return -1; - } - - type = *pos++; - len = WPA_GET_BE24(pos); - pos += 3; - left -= 4; - - if (len > left) { - wpa_printf(MSG_DEBUG, "TLSv1: Mismatch in ServerHelloDone " - "length (len=%lu != left=%lu)", - (unsigned long) len, (unsigned long) left); - tls_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_DECODE_ERROR); - return -1; - } - end = pos + len; - - if (type != TLS_HANDSHAKE_TYPE_SERVER_HELLO_DONE) { - wpa_printf(MSG_DEBUG, "TLSv1: Received unexpected handshake " - "message %d (expected ServerHelloDone)", type); - tls_alert(conn, TLS_ALERT_LEVEL_FATAL, - TLS_ALERT_UNEXPECTED_MESSAGE); - return -1; - } - - wpa_printf(MSG_DEBUG, "TLSv1: Received ServerHelloDone"); - - *in_len = end - in_data; - - conn->state = CLIENT_KEY_EXCHANGE; - - return 0; -} - - -static int tls_process_server_change_cipher_spec(struct tlsv1_client *conn, - u8 ct, const u8 *in_data, - size_t *in_len) -{ - const u8 *pos; - size_t left; - - if (ct != TLS_CONTENT_TYPE_CHANGE_CIPHER_SPEC) { - wpa_printf(MSG_DEBUG, "TLSv1: Expected ChangeCipherSpec; " - "received content type 0x%x", ct); - if (conn->use_session_ticket) { - int res; - wpa_printf(MSG_DEBUG, "TLSv1: Server may have " - "rejected SessionTicket"); - conn->use_session_ticket = 0; - - /* Notify upper layers that SessionTicket failed */ - res = conn->session_ticket_cb( - conn->session_ticket_cb_ctx, NULL, 0, NULL, - NULL, NULL); - if (res < 0) { - wpa_printf(MSG_DEBUG, "TLSv1: SessionTicket " - "callback indicated failure"); - tls_alert(conn, TLS_ALERT_LEVEL_FATAL, - TLS_ALERT_HANDSHAKE_FAILURE); - return -1; - } - - conn->state = SERVER_CERTIFICATE; - return tls_process_certificate(conn, ct, in_data, - in_len); - } - tls_alert(conn, TLS_ALERT_LEVEL_FATAL, - TLS_ALERT_UNEXPECTED_MESSAGE); - return -1; - } - - pos = in_data; - left = *in_len; - - if (left < 1) { - wpa_printf(MSG_DEBUG, "TLSv1: Too short ChangeCipherSpec"); - tls_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_DECODE_ERROR); - return -1; - } - - if (*pos != TLS_CHANGE_CIPHER_SPEC) { - wpa_printf(MSG_DEBUG, "TLSv1: Expected ChangeCipherSpec; " - "received data 0x%x", *pos); - tls_alert(conn, TLS_ALERT_LEVEL_FATAL, - TLS_ALERT_UNEXPECTED_MESSAGE); - return -1; - } - - wpa_printf(MSG_DEBUG, "TLSv1: Received ChangeCipherSpec"); - if (tlsv1_record_change_read_cipher(&conn->rl) < 0) { - wpa_printf(MSG_DEBUG, "TLSv1: Failed to change read cipher " - "for record layer"); - tls_alert(conn, TLS_ALERT_LEVEL_FATAL, - TLS_ALERT_INTERNAL_ERROR); - return -1; - } - - *in_len = pos + 1 - in_data; - - conn->state = SERVER_FINISHED; - - return 0; -} - - -static int tls_process_server_finished(struct tlsv1_client *conn, u8 ct, - const u8 *in_data, size_t *in_len) -{ - const u8 *pos, *end; - size_t left, len, hlen; - u8 verify_data[TLS_VERIFY_DATA_LEN]; - u8 hash[MD5_MAC_LEN + SHA1_MAC_LEN]; - - if (ct != TLS_CONTENT_TYPE_HANDSHAKE) { - wpa_printf(MSG_DEBUG, "TLSv1: Expected Finished; " - "received content type 0x%x", ct); - tls_alert(conn, TLS_ALERT_LEVEL_FATAL, - TLS_ALERT_UNEXPECTED_MESSAGE); - return -1; - } - - pos = in_data; - left = *in_len; - - if (left < 4) { - wpa_printf(MSG_DEBUG, "TLSv1: Too short record (left=%lu) for " - "Finished", - (unsigned long) left); - tls_alert(conn, TLS_ALERT_LEVEL_FATAL, - TLS_ALERT_DECODE_ERROR); - return -1; - } - - if (pos[0] != TLS_HANDSHAKE_TYPE_FINISHED) { - wpa_printf(MSG_DEBUG, "TLSv1: Expected Finished; received " - "type 0x%x", pos[0]); - tls_alert(conn, TLS_ALERT_LEVEL_FATAL, - TLS_ALERT_UNEXPECTED_MESSAGE); - return -1; - } - - len = WPA_GET_BE24(pos + 1); - - pos += 4; - left -= 4; - - if (len > left) { - wpa_printf(MSG_DEBUG, "TLSv1: Too short buffer for Finished " - "(len=%lu > left=%lu)", - (unsigned long) len, (unsigned long) left); - tls_alert(conn, TLS_ALERT_LEVEL_FATAL, - TLS_ALERT_DECODE_ERROR); - return -1; - } - end = pos + len; - if (len != TLS_VERIFY_DATA_LEN) { - wpa_printf(MSG_DEBUG, "TLSv1: Unexpected verify_data length " - "in Finished: %lu (expected %d)", - (unsigned long) len, TLS_VERIFY_DATA_LEN); - tls_alert(conn, TLS_ALERT_LEVEL_FATAL, - TLS_ALERT_DECODE_ERROR); - return -1; - } - wpa_hexdump(MSG_MSGDUMP, "TLSv1: verify_data in Finished", - pos, TLS_VERIFY_DATA_LEN); - - hlen = MD5_MAC_LEN; - if (conn->verify.md5_server == NULL || - crypto_hash_finish(conn->verify.md5_server, hash, &hlen) < 0) { - tls_alert(conn, TLS_ALERT_LEVEL_FATAL, - TLS_ALERT_INTERNAL_ERROR); - conn->verify.md5_server = NULL; - crypto_hash_finish(conn->verify.sha1_server, NULL, NULL); - conn->verify.sha1_server = NULL; - return -1; - } - conn->verify.md5_server = NULL; - hlen = SHA1_MAC_LEN; - if (conn->verify.sha1_server == NULL || - crypto_hash_finish(conn->verify.sha1_server, hash + MD5_MAC_LEN, - &hlen) < 0) { - conn->verify.sha1_server = NULL; - tls_alert(conn, TLS_ALERT_LEVEL_FATAL, - TLS_ALERT_INTERNAL_ERROR); - return -1; - } - conn->verify.sha1_server = NULL; - - if (tls_prf(conn->master_secret, TLS_MASTER_SECRET_LEN, - "server finished", hash, MD5_MAC_LEN + SHA1_MAC_LEN, - verify_data, TLS_VERIFY_DATA_LEN)) { - wpa_printf(MSG_DEBUG, "TLSv1: Failed to derive verify_data"); - tls_alert(conn, TLS_ALERT_LEVEL_FATAL, - TLS_ALERT_DECRYPT_ERROR); - return -1; - } - wpa_hexdump_key(MSG_DEBUG, "TLSv1: verify_data (server)", - verify_data, TLS_VERIFY_DATA_LEN); - - if (os_memcmp(pos, verify_data, TLS_VERIFY_DATA_LEN) != 0) { - wpa_printf(MSG_INFO, "TLSv1: Mismatch in verify_data"); - return -1; - } - - wpa_printf(MSG_DEBUG, "TLSv1: Received Finished"); - - *in_len = end - in_data; - - conn->state = (conn->session_resumed || conn->use_session_ticket) ? - CHANGE_CIPHER_SPEC : ACK_FINISHED; - - return 0; -} - - -static int tls_process_application_data(struct tlsv1_client *conn, u8 ct, - const u8 *in_data, size_t *in_len, - u8 **out_data, size_t *out_len) -{ - const u8 *pos; - size_t left; - - if (ct != TLS_CONTENT_TYPE_APPLICATION_DATA) { - wpa_printf(MSG_DEBUG, "TLSv1: Expected Application Data; " - "received content type 0x%x", ct); - tls_alert(conn, TLS_ALERT_LEVEL_FATAL, - TLS_ALERT_UNEXPECTED_MESSAGE); - return -1; - } - - pos = in_data; - left = *in_len; - - wpa_hexdump(MSG_DEBUG, "TLSv1: Application Data included in Handshake", - pos, left); - - *out_data = os_malloc(left); - if (*out_data) { - os_memcpy(*out_data, pos, left); - *out_len = left; - } - - return 0; -} - - -int tlsv1_client_process_handshake(struct tlsv1_client *conn, u8 ct, - const u8 *buf, size_t *len, - u8 **out_data, size_t *out_len) -{ - if (ct == TLS_CONTENT_TYPE_ALERT) { - if (*len < 2) { - wpa_printf(MSG_DEBUG, "TLSv1: Alert underflow"); - tls_alert(conn, TLS_ALERT_LEVEL_FATAL, - TLS_ALERT_DECODE_ERROR); - return -1; - } - wpa_printf(MSG_DEBUG, "TLSv1: Received alert %d:%d", - buf[0], buf[1]); - *len = 2; - conn->state = FAILED; - return -1; - } - - if (ct == TLS_CONTENT_TYPE_HANDSHAKE && *len >= 4 && - buf[0] == TLS_HANDSHAKE_TYPE_HELLO_REQUEST) { - size_t hr_len = WPA_GET_BE24(buf + 1); - if (hr_len > *len - 4) { - wpa_printf(MSG_DEBUG, "TLSv1: HelloRequest underflow"); - tls_alert(conn, TLS_ALERT_LEVEL_FATAL, - TLS_ALERT_DECODE_ERROR); - return -1; - } - wpa_printf(MSG_DEBUG, "TLSv1: Ignored HelloRequest"); - *len = 4 + hr_len; - return 0; - } - - switch (conn->state) { - case SERVER_HELLO: - if (tls_process_server_hello(conn, ct, buf, len)) - return -1; - break; - case SERVER_CERTIFICATE: - if (tls_process_certificate(conn, ct, buf, len)) - return -1; - break; - case SERVER_KEY_EXCHANGE: - if (tls_process_server_key_exchange(conn, ct, buf, len)) - return -1; - break; - case SERVER_CERTIFICATE_REQUEST: - if (tls_process_certificate_request(conn, ct, buf, len)) - return -1; - break; - case SERVER_HELLO_DONE: - if (tls_process_server_hello_done(conn, ct, buf, len)) - return -1; - break; - case SERVER_CHANGE_CIPHER_SPEC: - if (tls_process_server_change_cipher_spec(conn, ct, buf, len)) - return -1; - break; - case SERVER_FINISHED: - if (tls_process_server_finished(conn, ct, buf, len)) - return -1; - break; - case ACK_FINISHED: - if (out_data && - tls_process_application_data(conn, ct, buf, len, out_data, - out_len)) - return -1; - break; - default: - wpa_printf(MSG_DEBUG, "TLSv1: Unexpected state %d " - "while processing received message", - conn->state); - return -1; - } - - if (ct == TLS_CONTENT_TYPE_HANDSHAKE) - tls_verify_hash_add(&conn->verify, buf, *len); - - return 0; -} diff --git a/hostapd-0.8/src/tls/tlsv1_client_write.c b/hostapd-0.8/src/tls/tlsv1_client_write.c deleted file mode 100644 index 0898df9..0000000 --- a/hostapd-0.8/src/tls/tlsv1_client_write.c +++ /dev/null @@ -1,798 +0,0 @@ -/* - * TLSv1 client - write handshake message - * Copyright (c) 2006-2007, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#include "includes.h" - -#include "common.h" -#include "crypto/md5.h" -#include "crypto/sha1.h" -#include "crypto/tls.h" -#include "crypto/random.h" -#include "x509v3.h" -#include "tlsv1_common.h" -#include "tlsv1_record.h" -#include "tlsv1_client.h" -#include "tlsv1_client_i.h" - - -static size_t tls_client_cert_chain_der_len(struct tlsv1_client *conn) -{ - size_t len = 0; - struct x509_certificate *cert; - - if (conn->cred == NULL) - return 0; - - cert = conn->cred->cert; - while (cert) { - len += 3 + cert->cert_len; - if (x509_certificate_self_signed(cert)) - break; - cert = x509_certificate_get_subject(conn->cred->trusted_certs, - &cert->issuer); - } - - return len; -} - - -u8 * tls_send_client_hello(struct tlsv1_client *conn, size_t *out_len) -{ - u8 *hello, *end, *pos, *hs_length, *hs_start, *rhdr; - struct os_time now; - size_t len, i; - - wpa_printf(MSG_DEBUG, "TLSv1: Send ClientHello"); - *out_len = 0; - - os_get_time(&now); - WPA_PUT_BE32(conn->client_random, now.sec); - if (random_get_bytes(conn->client_random + 4, TLS_RANDOM_LEN - 4)) { - wpa_printf(MSG_ERROR, "TLSv1: Could not generate " - "client_random"); - return NULL; - } - wpa_hexdump(MSG_MSGDUMP, "TLSv1: client_random", - conn->client_random, TLS_RANDOM_LEN); - - len = 100 + conn->num_cipher_suites * 2 + conn->client_hello_ext_len; - hello = os_malloc(len); - if (hello == NULL) - return NULL; - end = hello + len; - - rhdr = hello; - pos = rhdr + TLS_RECORD_HEADER_LEN; - - /* opaque fragment[TLSPlaintext.length] */ - - /* Handshake */ - hs_start = pos; - /* HandshakeType msg_type */ - *pos++ = TLS_HANDSHAKE_TYPE_CLIENT_HELLO; - /* uint24 length (to be filled) */ - hs_length = pos; - pos += 3; - /* body - ClientHello */ - /* ProtocolVersion client_version */ - WPA_PUT_BE16(pos, TLS_VERSION); - pos += 2; - /* Random random: uint32 gmt_unix_time, opaque random_bytes */ - os_memcpy(pos, conn->client_random, TLS_RANDOM_LEN); - pos += TLS_RANDOM_LEN; - /* SessionID session_id */ - *pos++ = conn->session_id_len; - os_memcpy(pos, conn->session_id, conn->session_id_len); - pos += conn->session_id_len; - /* CipherSuite cipher_suites<2..2^16-1> */ - WPA_PUT_BE16(pos, 2 * conn->num_cipher_suites); - pos += 2; - for (i = 0; i < conn->num_cipher_suites; i++) { - WPA_PUT_BE16(pos, conn->cipher_suites[i]); - pos += 2; - } - /* CompressionMethod compression_methods<1..2^8-1> */ - *pos++ = 1; - *pos++ = TLS_COMPRESSION_NULL; - - if (conn->client_hello_ext) { - os_memcpy(pos, conn->client_hello_ext, - conn->client_hello_ext_len); - pos += conn->client_hello_ext_len; - } - - WPA_PUT_BE24(hs_length, pos - hs_length - 3); - tls_verify_hash_add(&conn->verify, hs_start, pos - hs_start); - - if (tlsv1_record_send(&conn->rl, TLS_CONTENT_TYPE_HANDSHAKE, - rhdr, end - rhdr, pos - hs_start, out_len) < 0) { - wpa_printf(MSG_DEBUG, "TLSv1: Failed to create TLS record"); - tls_alert(conn, TLS_ALERT_LEVEL_FATAL, - TLS_ALERT_INTERNAL_ERROR); - os_free(hello); - return NULL; - } - - conn->state = SERVER_HELLO; - - return hello; -} - - -static int tls_write_client_certificate(struct tlsv1_client *conn, - u8 **msgpos, u8 *end) -{ - u8 *pos, *rhdr, *hs_start, *hs_length, *cert_start; - size_t rlen; - struct x509_certificate *cert; - - pos = *msgpos; - - wpa_printf(MSG_DEBUG, "TLSv1: Send Certificate"); - rhdr = pos; - pos += TLS_RECORD_HEADER_LEN; - - /* opaque fragment[TLSPlaintext.length] */ - - /* Handshake */ - hs_start = pos; - /* HandshakeType msg_type */ - *pos++ = TLS_HANDSHAKE_TYPE_CERTIFICATE; - /* uint24 length (to be filled) */ - hs_length = pos; - pos += 3; - /* body - Certificate */ - /* uint24 length (to be filled) */ - cert_start = pos; - pos += 3; - cert = conn->cred ? conn->cred->cert : NULL; - while (cert) { - if (pos + 3 + cert->cert_len > end) { - wpa_printf(MSG_DEBUG, "TLSv1: Not enough buffer space " - "for Certificate (cert_len=%lu left=%lu)", - (unsigned long) cert->cert_len, - (unsigned long) (end - pos)); - tls_alert(conn, TLS_ALERT_LEVEL_FATAL, - TLS_ALERT_INTERNAL_ERROR); - return -1; - } - WPA_PUT_BE24(pos, cert->cert_len); - pos += 3; - os_memcpy(pos, cert->cert_start, cert->cert_len); - pos += cert->cert_len; - - if (x509_certificate_self_signed(cert)) - break; - cert = x509_certificate_get_subject(conn->cred->trusted_certs, - &cert->issuer); - } - if (conn->cred == NULL || cert == conn->cred->cert || cert == NULL) { - /* - * Client was not configured with all the needed certificates - * to form a full certificate chain. The server may fail to - * validate the chain unless it is configured with all the - * missing CA certificates. - */ - wpa_printf(MSG_DEBUG, "TLSv1: Full client certificate chain " - "not configured - validation may fail"); - } - WPA_PUT_BE24(cert_start, pos - cert_start - 3); - - WPA_PUT_BE24(hs_length, pos - hs_length - 3); - - if (tlsv1_record_send(&conn->rl, TLS_CONTENT_TYPE_HANDSHAKE, - rhdr, end - rhdr, pos - hs_start, &rlen) < 0) { - wpa_printf(MSG_DEBUG, "TLSv1: Failed to generate a record"); - tls_alert(conn, TLS_ALERT_LEVEL_FATAL, - TLS_ALERT_INTERNAL_ERROR); - return -1; - } - pos = rhdr + rlen; - - tls_verify_hash_add(&conn->verify, hs_start, pos - hs_start); - - *msgpos = pos; - - return 0; -} - - -static int tlsv1_key_x_anon_dh(struct tlsv1_client *conn, u8 **pos, u8 *end) -{ - /* ClientDiffieHellmanPublic */ - u8 *csecret, *csecret_start, *dh_yc, *shared; - size_t csecret_len, dh_yc_len, shared_len; - - csecret_len = conn->dh_p_len; - csecret = os_malloc(csecret_len); - if (csecret == NULL) { - wpa_printf(MSG_DEBUG, "TLSv1: Failed to allocate " - "memory for Yc (Diffie-Hellman)"); - tls_alert(conn, TLS_ALERT_LEVEL_FATAL, - TLS_ALERT_INTERNAL_ERROR); - return -1; - } - if (random_get_bytes(csecret, csecret_len)) { - wpa_printf(MSG_DEBUG, "TLSv1: Failed to get random " - "data for Diffie-Hellman"); - tls_alert(conn, TLS_ALERT_LEVEL_FATAL, - TLS_ALERT_INTERNAL_ERROR); - os_free(csecret); - return -1; - } - - if (os_memcmp(csecret, conn->dh_p, csecret_len) > 0) - csecret[0] = 0; /* make sure Yc < p */ - - csecret_start = csecret; - while (csecret_len > 1 && *csecret_start == 0) { - csecret_start++; - csecret_len--; - } - wpa_hexdump_key(MSG_DEBUG, "TLSv1: DH client's secret value", - csecret_start, csecret_len); - - /* Yc = g^csecret mod p */ - dh_yc_len = conn->dh_p_len; - dh_yc = os_malloc(dh_yc_len); - if (dh_yc == NULL) { - wpa_printf(MSG_DEBUG, "TLSv1: Failed to allocate " - "memory for Diffie-Hellman"); - tls_alert(conn, TLS_ALERT_LEVEL_FATAL, - TLS_ALERT_INTERNAL_ERROR); - os_free(csecret); - return -1; - } - if (crypto_mod_exp(conn->dh_g, conn->dh_g_len, - csecret_start, csecret_len, - conn->dh_p, conn->dh_p_len, - dh_yc, &dh_yc_len)) { - tls_alert(conn, TLS_ALERT_LEVEL_FATAL, - TLS_ALERT_INTERNAL_ERROR); - os_free(csecret); - os_free(dh_yc); - return -1; - } - - wpa_hexdump(MSG_DEBUG, "TLSv1: DH Yc (client's public value)", - dh_yc, dh_yc_len); - - WPA_PUT_BE16(*pos, dh_yc_len); - *pos += 2; - if (*pos + dh_yc_len > end) { - wpa_printf(MSG_DEBUG, "TLSv1: Not enough room in the " - "message buffer for Yc"); - tls_alert(conn, TLS_ALERT_LEVEL_FATAL, - TLS_ALERT_INTERNAL_ERROR); - os_free(csecret); - os_free(dh_yc); - return -1; - } - os_memcpy(*pos, dh_yc, dh_yc_len); - *pos += dh_yc_len; - os_free(dh_yc); - - shared_len = conn->dh_p_len; - shared = os_malloc(shared_len); - if (shared == NULL) { - wpa_printf(MSG_DEBUG, "TLSv1: Could not allocate memory for " - "DH"); - tls_alert(conn, TLS_ALERT_LEVEL_FATAL, - TLS_ALERT_INTERNAL_ERROR); - os_free(csecret); - return -1; - } - - /* shared = Ys^csecret mod p */ - if (crypto_mod_exp(conn->dh_ys, conn->dh_ys_len, - csecret_start, csecret_len, - conn->dh_p, conn->dh_p_len, - shared, &shared_len)) { - tls_alert(conn, TLS_ALERT_LEVEL_FATAL, - TLS_ALERT_INTERNAL_ERROR); - os_free(csecret); - os_free(shared); - return -1; - } - wpa_hexdump_key(MSG_DEBUG, "TLSv1: Shared secret from DH key exchange", - shared, shared_len); - - os_memset(csecret_start, 0, csecret_len); - os_free(csecret); - if (tls_derive_keys(conn, shared, shared_len)) { - wpa_printf(MSG_DEBUG, "TLSv1: Failed to derive keys"); - tls_alert(conn, TLS_ALERT_LEVEL_FATAL, - TLS_ALERT_INTERNAL_ERROR); - os_free(shared); - return -1; - } - os_memset(shared, 0, shared_len); - os_free(shared); - tlsv1_client_free_dh(conn); - return 0; -} - - -static int tlsv1_key_x_rsa(struct tlsv1_client *conn, u8 **pos, u8 *end) -{ - u8 pre_master_secret[TLS_PRE_MASTER_SECRET_LEN]; - size_t clen; - int res; - - if (tls_derive_pre_master_secret(pre_master_secret) < 0 || - tls_derive_keys(conn, pre_master_secret, - TLS_PRE_MASTER_SECRET_LEN)) { - wpa_printf(MSG_DEBUG, "TLSv1: Failed to derive keys"); - tls_alert(conn, TLS_ALERT_LEVEL_FATAL, - TLS_ALERT_INTERNAL_ERROR); - return -1; - } - - /* EncryptedPreMasterSecret */ - if (conn->server_rsa_key == NULL) { - wpa_printf(MSG_DEBUG, "TLSv1: No server RSA key to " - "use for encrypting pre-master secret"); - tls_alert(conn, TLS_ALERT_LEVEL_FATAL, - TLS_ALERT_INTERNAL_ERROR); - return -1; - } - - /* RSA encrypted value is encoded with PKCS #1 v1.5 block type 2. */ - *pos += 2; - clen = end - *pos; - res = crypto_public_key_encrypt_pkcs1_v15( - conn->server_rsa_key, - pre_master_secret, TLS_PRE_MASTER_SECRET_LEN, - *pos, &clen); - os_memset(pre_master_secret, 0, TLS_PRE_MASTER_SECRET_LEN); - if (res < 0) { - wpa_printf(MSG_DEBUG, "TLSv1: RSA encryption failed"); - tls_alert(conn, TLS_ALERT_LEVEL_FATAL, - TLS_ALERT_INTERNAL_ERROR); - return -1; - } - WPA_PUT_BE16(*pos - 2, clen); - wpa_hexdump(MSG_MSGDUMP, "TLSv1: Encrypted pre_master_secret", - *pos, clen); - *pos += clen; - - return 0; -} - - -static int tls_write_client_key_exchange(struct tlsv1_client *conn, - u8 **msgpos, u8 *end) -{ - u8 *pos, *rhdr, *hs_start, *hs_length; - size_t rlen; - tls_key_exchange keyx; - const struct tls_cipher_suite *suite; - - suite = tls_get_cipher_suite(conn->rl.cipher_suite); - if (suite == NULL) - keyx = TLS_KEY_X_NULL; - else - keyx = suite->key_exchange; - - pos = *msgpos; - - wpa_printf(MSG_DEBUG, "TLSv1: Send ClientKeyExchange"); - - rhdr = pos; - pos += TLS_RECORD_HEADER_LEN; - - /* opaque fragment[TLSPlaintext.length] */ - - /* Handshake */ - hs_start = pos; - /* HandshakeType msg_type */ - *pos++ = TLS_HANDSHAKE_TYPE_CLIENT_KEY_EXCHANGE; - /* uint24 length (to be filled) */ - hs_length = pos; - pos += 3; - /* body - ClientKeyExchange */ - if (keyx == TLS_KEY_X_DH_anon) { - if (tlsv1_key_x_anon_dh(conn, &pos, end) < 0) - return -1; - } else { - if (tlsv1_key_x_rsa(conn, &pos, end) < 0) - return -1; - } - - WPA_PUT_BE24(hs_length, pos - hs_length - 3); - - if (tlsv1_record_send(&conn->rl, TLS_CONTENT_TYPE_HANDSHAKE, - rhdr, end - rhdr, pos - hs_start, &rlen) < 0) { - wpa_printf(MSG_DEBUG, "TLSv1: Failed to create a record"); - tls_alert(conn, TLS_ALERT_LEVEL_FATAL, - TLS_ALERT_INTERNAL_ERROR); - return -1; - } - pos = rhdr + rlen; - tls_verify_hash_add(&conn->verify, hs_start, pos - hs_start); - - *msgpos = pos; - - return 0; -} - - -static int tls_write_client_certificate_verify(struct tlsv1_client *conn, - u8 **msgpos, u8 *end) -{ - u8 *pos, *rhdr, *hs_start, *hs_length, *signed_start; - size_t rlen, hlen, clen; - u8 hash[MD5_MAC_LEN + SHA1_MAC_LEN], *hpos; - enum { SIGN_ALG_RSA, SIGN_ALG_DSA } alg = SIGN_ALG_RSA; - - pos = *msgpos; - - wpa_printf(MSG_DEBUG, "TLSv1: Send CertificateVerify"); - rhdr = pos; - pos += TLS_RECORD_HEADER_LEN; - - /* Handshake */ - hs_start = pos; - /* HandshakeType msg_type */ - *pos++ = TLS_HANDSHAKE_TYPE_CERTIFICATE_VERIFY; - /* uint24 length (to be filled) */ - hs_length = pos; - pos += 3; - - /* - * RFC 2246: 7.4.3 and 7.4.8: - * Signature signature - * - * RSA: - * digitally-signed struct { - * opaque md5_hash[16]; - * opaque sha_hash[20]; - * }; - * - * DSA: - * digitally-signed struct { - * opaque sha_hash[20]; - * }; - * - * The hash values are calculated over all handshake messages sent or - * received starting at ClientHello up to, but not including, this - * CertificateVerify message, including the type and length fields of - * the handshake messages. - */ - - hpos = hash; - - if (alg == SIGN_ALG_RSA) { - hlen = MD5_MAC_LEN; - if (conn->verify.md5_cert == NULL || - crypto_hash_finish(conn->verify.md5_cert, hpos, &hlen) < 0) - { - tls_alert(conn, TLS_ALERT_LEVEL_FATAL, - TLS_ALERT_INTERNAL_ERROR); - conn->verify.md5_cert = NULL; - crypto_hash_finish(conn->verify.sha1_cert, NULL, NULL); - conn->verify.sha1_cert = NULL; - return -1; - } - hpos += MD5_MAC_LEN; - } else - crypto_hash_finish(conn->verify.md5_cert, NULL, NULL); - - conn->verify.md5_cert = NULL; - hlen = SHA1_MAC_LEN; - if (conn->verify.sha1_cert == NULL || - crypto_hash_finish(conn->verify.sha1_cert, hpos, &hlen) < 0) { - conn->verify.sha1_cert = NULL; - tls_alert(conn, TLS_ALERT_LEVEL_FATAL, - TLS_ALERT_INTERNAL_ERROR); - return -1; - } - conn->verify.sha1_cert = NULL; - - if (alg == SIGN_ALG_RSA) - hlen += MD5_MAC_LEN; - - wpa_hexdump(MSG_MSGDUMP, "TLSv1: CertificateVerify hash", hash, hlen); - - /* - * RFC 2246, 4.7: - * In digital signing, one-way hash functions are used as input for a - * signing algorithm. A digitally-signed element is encoded as an - * opaque vector <0..2^16-1>, where the length is specified by the - * signing algorithm and key. - * - * In RSA signing, a 36-byte structure of two hashes (one SHA and one - * MD5) is signed (encrypted with the private key). It is encoded with - * PKCS #1 block type 0 or type 1 as described in [PKCS1]. - */ - signed_start = pos; /* length to be filled */ - pos += 2; - clen = end - pos; - if (conn->cred == NULL || - crypto_private_key_sign_pkcs1(conn->cred->key, hash, hlen, - pos, &clen) < 0) { - wpa_printf(MSG_DEBUG, "TLSv1: Failed to sign hash (PKCS #1)"); - tls_alert(conn, TLS_ALERT_LEVEL_FATAL, - TLS_ALERT_INTERNAL_ERROR); - return -1; - } - WPA_PUT_BE16(signed_start, clen); - - pos += clen; - - WPA_PUT_BE24(hs_length, pos - hs_length - 3); - - if (tlsv1_record_send(&conn->rl, TLS_CONTENT_TYPE_HANDSHAKE, - rhdr, end - rhdr, pos - hs_start, &rlen) < 0) { - wpa_printf(MSG_DEBUG, "TLSv1: Failed to generate a record"); - tls_alert(conn, TLS_ALERT_LEVEL_FATAL, - TLS_ALERT_INTERNAL_ERROR); - return -1; - } - pos = rhdr + rlen; - - tls_verify_hash_add(&conn->verify, hs_start, pos - hs_start); - - *msgpos = pos; - - return 0; -} - - -static int tls_write_client_change_cipher_spec(struct tlsv1_client *conn, - u8 **msgpos, u8 *end) -{ - u8 *pos, *rhdr; - size_t rlen; - - pos = *msgpos; - - wpa_printf(MSG_DEBUG, "TLSv1: Send ChangeCipherSpec"); - rhdr = pos; - pos += TLS_RECORD_HEADER_LEN; - *pos = TLS_CHANGE_CIPHER_SPEC; - if (tlsv1_record_send(&conn->rl, TLS_CONTENT_TYPE_CHANGE_CIPHER_SPEC, - rhdr, end - rhdr, 1, &rlen) < 0) { - wpa_printf(MSG_DEBUG, "TLSv1: Failed to create a record"); - tls_alert(conn, TLS_ALERT_LEVEL_FATAL, - TLS_ALERT_INTERNAL_ERROR); - return -1; - } - - if (tlsv1_record_change_write_cipher(&conn->rl) < 0) { - wpa_printf(MSG_DEBUG, "TLSv1: Failed to set write cipher for " - "record layer"); - tls_alert(conn, TLS_ALERT_LEVEL_FATAL, - TLS_ALERT_INTERNAL_ERROR); - return -1; - } - - *msgpos = rhdr + rlen; - - return 0; -} - - -static int tls_write_client_finished(struct tlsv1_client *conn, - u8 **msgpos, u8 *end) -{ - u8 *pos, *rhdr, *hs_start, *hs_length; - size_t rlen, hlen; - u8 verify_data[TLS_VERIFY_DATA_LEN]; - u8 hash[MD5_MAC_LEN + SHA1_MAC_LEN]; - - pos = *msgpos; - - wpa_printf(MSG_DEBUG, "TLSv1: Send Finished"); - - /* Encrypted Handshake Message: Finished */ - - hlen = MD5_MAC_LEN; - if (conn->verify.md5_client == NULL || - crypto_hash_finish(conn->verify.md5_client, hash, &hlen) < 0) { - tls_alert(conn, TLS_ALERT_LEVEL_FATAL, - TLS_ALERT_INTERNAL_ERROR); - conn->verify.md5_client = NULL; - crypto_hash_finish(conn->verify.sha1_client, NULL, NULL); - conn->verify.sha1_client = NULL; - return -1; - } - conn->verify.md5_client = NULL; - hlen = SHA1_MAC_LEN; - if (conn->verify.sha1_client == NULL || - crypto_hash_finish(conn->verify.sha1_client, hash + MD5_MAC_LEN, - &hlen) < 0) { - conn->verify.sha1_client = NULL; - tls_alert(conn, TLS_ALERT_LEVEL_FATAL, - TLS_ALERT_INTERNAL_ERROR); - return -1; - } - conn->verify.sha1_client = NULL; - - if (tls_prf(conn->master_secret, TLS_MASTER_SECRET_LEN, - "client finished", hash, MD5_MAC_LEN + SHA1_MAC_LEN, - verify_data, TLS_VERIFY_DATA_LEN)) { - wpa_printf(MSG_DEBUG, "TLSv1: Failed to generate verify_data"); - tls_alert(conn, TLS_ALERT_LEVEL_FATAL, - TLS_ALERT_INTERNAL_ERROR); - return -1; - } - wpa_hexdump_key(MSG_DEBUG, "TLSv1: verify_data (client)", - verify_data, TLS_VERIFY_DATA_LEN); - - rhdr = pos; - pos += TLS_RECORD_HEADER_LEN; - /* Handshake */ - hs_start = pos; - /* HandshakeType msg_type */ - *pos++ = TLS_HANDSHAKE_TYPE_FINISHED; - /* uint24 length (to be filled) */ - hs_length = pos; - pos += 3; - os_memcpy(pos, verify_data, TLS_VERIFY_DATA_LEN); - pos += TLS_VERIFY_DATA_LEN; - WPA_PUT_BE24(hs_length, pos - hs_length - 3); - tls_verify_hash_add(&conn->verify, hs_start, pos - hs_start); - - if (tlsv1_record_send(&conn->rl, TLS_CONTENT_TYPE_HANDSHAKE, - rhdr, end - rhdr, pos - hs_start, &rlen) < 0) { - wpa_printf(MSG_DEBUG, "TLSv1: Failed to create a record"); - tls_alert(conn, TLS_ALERT_LEVEL_FATAL, - TLS_ALERT_INTERNAL_ERROR); - return -1; - } - - pos = rhdr + rlen; - - *msgpos = pos; - - return 0; -} - - -static u8 * tls_send_client_key_exchange(struct tlsv1_client *conn, - size_t *out_len) -{ - u8 *msg, *end, *pos; - size_t msglen; - - *out_len = 0; - - msglen = 2000; - if (conn->certificate_requested) - msglen += tls_client_cert_chain_der_len(conn); - - msg = os_malloc(msglen); - if (msg == NULL) - return NULL; - - pos = msg; - end = msg + msglen; - - if (conn->certificate_requested) { - if (tls_write_client_certificate(conn, &pos, end) < 0) { - os_free(msg); - return NULL; - } - } - - if (tls_write_client_key_exchange(conn, &pos, end) < 0 || - (conn->certificate_requested && conn->cred && conn->cred->key && - tls_write_client_certificate_verify(conn, &pos, end) < 0) || - tls_write_client_change_cipher_spec(conn, &pos, end) < 0 || - tls_write_client_finished(conn, &pos, end) < 0) { - os_free(msg); - return NULL; - } - - *out_len = pos - msg; - - conn->state = SERVER_CHANGE_CIPHER_SPEC; - - return msg; -} - - -static u8 * tls_send_change_cipher_spec(struct tlsv1_client *conn, - size_t *out_len) -{ - u8 *msg, *end, *pos; - - *out_len = 0; - - msg = os_malloc(1000); - if (msg == NULL) - return NULL; - - pos = msg; - end = msg + 1000; - - if (tls_write_client_change_cipher_spec(conn, &pos, end) < 0 || - tls_write_client_finished(conn, &pos, end) < 0) { - os_free(msg); - return NULL; - } - - *out_len = pos - msg; - - wpa_printf(MSG_DEBUG, "TLSv1: Session resumption completed " - "successfully"); - conn->state = ESTABLISHED; - - return msg; -} - - -u8 * tlsv1_client_handshake_write(struct tlsv1_client *conn, size_t *out_len, - int no_appl_data) -{ - switch (conn->state) { - case CLIENT_KEY_EXCHANGE: - return tls_send_client_key_exchange(conn, out_len); - case CHANGE_CIPHER_SPEC: - return tls_send_change_cipher_spec(conn, out_len); - case ACK_FINISHED: - wpa_printf(MSG_DEBUG, "TLSv1: Handshake completed " - "successfully"); - conn->state = ESTABLISHED; - *out_len = 0; - if (no_appl_data) { - /* Need to return something to get final TLS ACK. */ - return os_malloc(1); - } - return NULL; - default: - wpa_printf(MSG_DEBUG, "TLSv1: Unexpected state %d while " - "generating reply", conn->state); - return NULL; - } -} - - -u8 * tlsv1_client_send_alert(struct tlsv1_client *conn, u8 level, - u8 description, size_t *out_len) -{ - u8 *alert, *pos, *length; - - wpa_printf(MSG_DEBUG, "TLSv1: Send Alert(%d:%d)", level, description); - *out_len = 0; - - alert = os_malloc(10); - if (alert == NULL) - return NULL; - - pos = alert; - - /* TLSPlaintext */ - /* ContentType type */ - *pos++ = TLS_CONTENT_TYPE_ALERT; - /* ProtocolVersion version */ - WPA_PUT_BE16(pos, TLS_VERSION); - pos += 2; - /* uint16 length (to be filled) */ - length = pos; - pos += 2; - /* opaque fragment[TLSPlaintext.length] */ - - /* Alert */ - /* AlertLevel level */ - *pos++ = level; - /* AlertDescription description */ - *pos++ = description; - - WPA_PUT_BE16(length, pos - length - 2); - *out_len = pos - alert; - - return alert; -} diff --git a/hostapd-0.8/src/tls/tlsv1_common.c b/hostapd-0.8/src/tls/tlsv1_common.c deleted file mode 100644 index 2f9dd0f..0000000 --- a/hostapd-0.8/src/tls/tlsv1_common.c +++ /dev/null @@ -1,241 +0,0 @@ -/* - * TLSv1 common routines - * Copyright (c) 2006-2007, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#include "includes.h" - -#include "common.h" -#include "x509v3.h" -#include "tlsv1_common.h" - - -/* - * TODO: - * RFC 2246 Section 9: Mandatory to implement TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA - * Add support for commonly used cipher suites; don't bother with exportable - * suites. - */ - -static const struct tls_cipher_suite tls_cipher_suites[] = { - { TLS_NULL_WITH_NULL_NULL, TLS_KEY_X_NULL, TLS_CIPHER_NULL, - TLS_HASH_NULL }, - { TLS_RSA_WITH_RC4_128_MD5, TLS_KEY_X_RSA, TLS_CIPHER_RC4_128, - TLS_HASH_MD5 }, - { TLS_RSA_WITH_RC4_128_SHA, TLS_KEY_X_RSA, TLS_CIPHER_RC4_128, - TLS_HASH_SHA }, - { TLS_RSA_WITH_DES_CBC_SHA, TLS_KEY_X_RSA, TLS_CIPHER_DES_CBC, - TLS_HASH_SHA }, - { TLS_RSA_WITH_3DES_EDE_CBC_SHA, TLS_KEY_X_RSA, - TLS_CIPHER_3DES_EDE_CBC, TLS_HASH_SHA }, - { TLS_DH_anon_WITH_RC4_128_MD5, TLS_KEY_X_DH_anon, - TLS_CIPHER_RC4_128, TLS_HASH_MD5 }, - { TLS_DH_anon_WITH_DES_CBC_SHA, TLS_KEY_X_DH_anon, - TLS_CIPHER_DES_CBC, TLS_HASH_SHA }, - { TLS_DH_anon_WITH_3DES_EDE_CBC_SHA, TLS_KEY_X_DH_anon, - TLS_CIPHER_3DES_EDE_CBC, TLS_HASH_SHA }, - { TLS_RSA_WITH_AES_128_CBC_SHA, TLS_KEY_X_RSA, TLS_CIPHER_AES_128_CBC, - TLS_HASH_SHA }, - { TLS_DH_anon_WITH_AES_128_CBC_SHA, TLS_KEY_X_DH_anon, - TLS_CIPHER_AES_128_CBC, TLS_HASH_SHA }, - { TLS_RSA_WITH_AES_256_CBC_SHA, TLS_KEY_X_RSA, TLS_CIPHER_AES_256_CBC, - TLS_HASH_SHA }, - { TLS_DH_anon_WITH_AES_256_CBC_SHA, TLS_KEY_X_DH_anon, - TLS_CIPHER_AES_256_CBC, TLS_HASH_SHA } -}; - -#define NUM_ELEMS(a) (sizeof(a) / sizeof((a)[0])) -#define NUM_TLS_CIPHER_SUITES NUM_ELEMS(tls_cipher_suites) - - -static const struct tls_cipher_data tls_ciphers[] = { - { TLS_CIPHER_NULL, TLS_CIPHER_STREAM, 0, 0, 0, - CRYPTO_CIPHER_NULL }, - { TLS_CIPHER_IDEA_CBC, TLS_CIPHER_BLOCK, 16, 16, 8, - CRYPTO_CIPHER_NULL }, - { TLS_CIPHER_RC2_CBC_40, TLS_CIPHER_BLOCK, 5, 16, 0, - CRYPTO_CIPHER_ALG_RC2 }, - { TLS_CIPHER_RC4_40, TLS_CIPHER_STREAM, 5, 16, 0, - CRYPTO_CIPHER_ALG_RC4 }, - { TLS_CIPHER_RC4_128, TLS_CIPHER_STREAM, 16, 16, 0, - CRYPTO_CIPHER_ALG_RC4 }, - { TLS_CIPHER_DES40_CBC, TLS_CIPHER_BLOCK, 5, 8, 8, - CRYPTO_CIPHER_ALG_DES }, - { TLS_CIPHER_DES_CBC, TLS_CIPHER_BLOCK, 8, 8, 8, - CRYPTO_CIPHER_ALG_DES }, - { TLS_CIPHER_3DES_EDE_CBC, TLS_CIPHER_BLOCK, 24, 24, 8, - CRYPTO_CIPHER_ALG_3DES }, - { TLS_CIPHER_AES_128_CBC, TLS_CIPHER_BLOCK, 16, 16, 16, - CRYPTO_CIPHER_ALG_AES }, - { TLS_CIPHER_AES_256_CBC, TLS_CIPHER_BLOCK, 32, 32, 16, - CRYPTO_CIPHER_ALG_AES } -}; - -#define NUM_TLS_CIPHER_DATA NUM_ELEMS(tls_ciphers) - - -/** - * tls_get_cipher_suite - Get TLS cipher suite - * @suite: Cipher suite identifier - * Returns: Pointer to the cipher data or %NULL if not found - */ -const struct tls_cipher_suite * tls_get_cipher_suite(u16 suite) -{ - size_t i; - for (i = 0; i < NUM_TLS_CIPHER_SUITES; i++) - if (tls_cipher_suites[i].suite == suite) - return &tls_cipher_suites[i]; - return NULL; -} - - -const struct tls_cipher_data * tls_get_cipher_data(tls_cipher cipher) -{ - size_t i; - for (i = 0; i < NUM_TLS_CIPHER_DATA; i++) - if (tls_ciphers[i].cipher == cipher) - return &tls_ciphers[i]; - return NULL; -} - - -int tls_server_key_exchange_allowed(tls_cipher cipher) -{ - const struct tls_cipher_suite *suite; - - /* RFC 2246, Section 7.4.3 */ - suite = tls_get_cipher_suite(cipher); - if (suite == NULL) - return 0; - - switch (suite->key_exchange) { - case TLS_KEY_X_DHE_DSS: - case TLS_KEY_X_DHE_DSS_EXPORT: - case TLS_KEY_X_DHE_RSA: - case TLS_KEY_X_DHE_RSA_EXPORT: - case TLS_KEY_X_DH_anon_EXPORT: - case TLS_KEY_X_DH_anon: - return 1; - case TLS_KEY_X_RSA_EXPORT: - return 1 /* FIX: public key len > 512 bits */; - default: - return 0; - } -} - - -/** - * tls_parse_cert - Parse DER encoded X.509 certificate and get public key - * @buf: ASN.1 DER encoded certificate - * @len: Length of the buffer - * @pk: Buffer for returning the allocated public key - * Returns: 0 on success, -1 on failure - * - * This functions parses an ASN.1 DER encoded X.509 certificate and retrieves - * the public key from it. The caller is responsible for freeing the public key - * by calling crypto_public_key_free(). - */ -int tls_parse_cert(const u8 *buf, size_t len, struct crypto_public_key **pk) -{ - struct x509_certificate *cert; - - wpa_hexdump(MSG_MSGDUMP, "TLSv1: Parse ASN.1 DER certificate", - buf, len); - - *pk = crypto_public_key_from_cert(buf, len); - if (*pk) - return 0; - - cert = x509_certificate_parse(buf, len); - if (cert == NULL) { - wpa_printf(MSG_DEBUG, "TLSv1: Failed to parse X.509 " - "certificate"); - return -1; - } - - /* TODO - * verify key usage (must allow encryption) - * - * All certificate profiles, key and cryptographic formats are - * defined by the IETF PKIX working group [PKIX]. When a key - * usage extension is present, the digitalSignature bit must be - * set for the key to be eligible for signing, as described - * above, and the keyEncipherment bit must be present to allow - * encryption, as described above. The keyAgreement bit must be - * set on Diffie-Hellman certificates. (PKIX: RFC 3280) - */ - - *pk = crypto_public_key_import(cert->public_key, cert->public_key_len); - x509_certificate_free(cert); - - if (*pk == NULL) { - wpa_printf(MSG_ERROR, "TLSv1: Failed to import " - "server public key"); - return -1; - } - - return 0; -} - - -int tls_verify_hash_init(struct tls_verify_hash *verify) -{ - tls_verify_hash_free(verify); - verify->md5_client = crypto_hash_init(CRYPTO_HASH_ALG_MD5, NULL, 0); - verify->md5_server = crypto_hash_init(CRYPTO_HASH_ALG_MD5, NULL, 0); - verify->md5_cert = crypto_hash_init(CRYPTO_HASH_ALG_MD5, NULL, 0); - verify->sha1_client = crypto_hash_init(CRYPTO_HASH_ALG_SHA1, NULL, 0); - verify->sha1_server = crypto_hash_init(CRYPTO_HASH_ALG_SHA1, NULL, 0); - verify->sha1_cert = crypto_hash_init(CRYPTO_HASH_ALG_SHA1, NULL, 0); - if (verify->md5_client == NULL || verify->md5_server == NULL || - verify->md5_cert == NULL || verify->sha1_client == NULL || - verify->sha1_server == NULL || verify->sha1_cert == NULL) { - tls_verify_hash_free(verify); - return -1; - } - return 0; -} - - -void tls_verify_hash_add(struct tls_verify_hash *verify, const u8 *buf, - size_t len) -{ - if (verify->md5_client && verify->sha1_client) { - crypto_hash_update(verify->md5_client, buf, len); - crypto_hash_update(verify->sha1_client, buf, len); - } - if (verify->md5_server && verify->sha1_server) { - crypto_hash_update(verify->md5_server, buf, len); - crypto_hash_update(verify->sha1_server, buf, len); - } - if (verify->md5_cert && verify->sha1_cert) { - crypto_hash_update(verify->md5_cert, buf, len); - crypto_hash_update(verify->sha1_cert, buf, len); - } -} - - -void tls_verify_hash_free(struct tls_verify_hash *verify) -{ - crypto_hash_finish(verify->md5_client, NULL, NULL); - crypto_hash_finish(verify->md5_server, NULL, NULL); - crypto_hash_finish(verify->md5_cert, NULL, NULL); - crypto_hash_finish(verify->sha1_client, NULL, NULL); - crypto_hash_finish(verify->sha1_server, NULL, NULL); - crypto_hash_finish(verify->sha1_cert, NULL, NULL); - verify->md5_client = NULL; - verify->md5_server = NULL; - verify->md5_cert = NULL; - verify->sha1_client = NULL; - verify->sha1_server = NULL; - verify->sha1_cert = NULL; -} diff --git a/hostapd-0.8/src/tls/tlsv1_common.h b/hostapd-0.8/src/tls/tlsv1_common.h deleted file mode 100644 index 763a4af..0000000 --- a/hostapd-0.8/src/tls/tlsv1_common.h +++ /dev/null @@ -1,216 +0,0 @@ -/* - * TLSv1 common definitions - * Copyright (c) 2006-2007, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#ifndef TLSV1_COMMON_H -#define TLSV1_COMMON_H - -#include "crypto/crypto.h" - -#define TLS_VERSION 0x0301 /* TLSv1 */ -#define TLS_RANDOM_LEN 32 -#define TLS_PRE_MASTER_SECRET_LEN 48 -#define TLS_MASTER_SECRET_LEN 48 -#define TLS_SESSION_ID_MAX_LEN 32 -#define TLS_VERIFY_DATA_LEN 12 - -/* HandshakeType */ -enum { - TLS_HANDSHAKE_TYPE_HELLO_REQUEST = 0, - TLS_HANDSHAKE_TYPE_CLIENT_HELLO = 1, - TLS_HANDSHAKE_TYPE_SERVER_HELLO = 2, - TLS_HANDSHAKE_TYPE_NEW_SESSION_TICKET = 4 /* RFC 4507 */, - TLS_HANDSHAKE_TYPE_CERTIFICATE = 11, - TLS_HANDSHAKE_TYPE_SERVER_KEY_EXCHANGE = 12, - TLS_HANDSHAKE_TYPE_CERTIFICATE_REQUEST = 13, - TLS_HANDSHAKE_TYPE_SERVER_HELLO_DONE = 14, - TLS_HANDSHAKE_TYPE_CERTIFICATE_VERIFY = 15, - TLS_HANDSHAKE_TYPE_CLIENT_KEY_EXCHANGE = 16, - TLS_HANDSHAKE_TYPE_FINISHED = 20, - TLS_HANDSHAKE_TYPE_CERTIFICATE_URL = 21 /* RFC 4366 */, - TLS_HANDSHAKE_TYPE_CERTIFICATE_STATUS = 22 /* RFC 4366 */ -}; - -/* CipherSuite */ -#define TLS_NULL_WITH_NULL_NULL 0x0000 /* RFC 2246 */ -#define TLS_RSA_WITH_NULL_MD5 0x0001 /* RFC 2246 */ -#define TLS_RSA_WITH_NULL_SHA 0x0002 /* RFC 2246 */ -#define TLS_RSA_EXPORT_WITH_RC4_40_MD5 0x0003 /* RFC 2246 */ -#define TLS_RSA_WITH_RC4_128_MD5 0x0004 /* RFC 2246 */ -#define TLS_RSA_WITH_RC4_128_SHA 0x0005 /* RFC 2246 */ -#define TLS_RSA_EXPORT_WITH_RC2_CBC_40_MD5 0x0006 /* RFC 2246 */ -#define TLS_RSA_WITH_IDEA_CBC_SHA 0x0007 /* RFC 2246 */ -#define TLS_RSA_EXPORT_WITH_DES40_CBC_SHA 0x0008 /* RFC 2246 */ -#define TLS_RSA_WITH_DES_CBC_SHA 0x0009 /* RFC 2246 */ -#define TLS_RSA_WITH_3DES_EDE_CBC_SHA 0x000A /* RFC 2246 */ -#define TLS_DH_DSS_EXPORT_WITH_DES40_CBC_SHA 0x000B /* RFC 2246 */ -#define TLS_DH_DSS_WITH_DES_CBC_SHA 0x000C /* RFC 2246 */ -#define TLS_DH_DSS_WITH_3DES_EDE_CBC_SHA 0x000D /* RFC 2246 */ -#define TLS_DH_RSA_EXPORT_WITH_DES40_CBC_SHA 0x000E /* RFC 2246 */ -#define TLS_DH_RSA_WITH_DES_CBC_SHA 0x000F /* RFC 2246 */ -#define TLS_DH_RSA_WITH_3DES_EDE_CBC_SHA 0x0010 /* RFC 2246 */ -#define TLS_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA 0x0011 /* RFC 2246 */ -#define TLS_DHE_DSS_WITH_DES_CBC_SHA 0x0012 /* RFC 2246 */ -#define TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA 0x0013 /* RFC 2246 */ -#define TLS_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA 0x0014 /* RFC 2246 */ -#define TLS_DHE_RSA_WITH_DES_CBC_SHA 0x0015 /* RFC 2246 */ -#define TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA 0x0016 /* RFC 2246 */ -#define TLS_DH_anon_EXPORT_WITH_RC4_40_MD5 0x0017 /* RFC 2246 */ -#define TLS_DH_anon_WITH_RC4_128_MD5 0x0018 /* RFC 2246 */ -#define TLS_DH_anon_EXPORT_WITH_DES40_CBC_SHA 0x0019 /* RFC 2246 */ -#define TLS_DH_anon_WITH_DES_CBC_SHA 0x001A /* RFC 2246 */ -#define TLS_DH_anon_WITH_3DES_EDE_CBC_SHA 0x001B /* RFC 2246 */ -#define TLS_RSA_WITH_AES_128_CBC_SHA 0x002F /* RFC 3268 */ -#define TLS_DH_DSS_WITH_AES_128_CBC_SHA 0x0030 /* RFC 3268 */ -#define TLS_DH_RSA_WITH_AES_128_CBC_SHA 0x0031 /* RFC 3268 */ -#define TLS_DHE_DSS_WITH_AES_128_CBC_SHA 0x0032 /* RFC 3268 */ -#define TLS_DHE_RSA_WITH_AES_128_CBC_SHA 0x0033 /* RFC 3268 */ -#define TLS_DH_anon_WITH_AES_128_CBC_SHA 0x0034 /* RFC 3268 */ -#define TLS_RSA_WITH_AES_256_CBC_SHA 0x0035 /* RFC 3268 */ -#define TLS_DH_DSS_WITH_AES_256_CBC_SHA 0x0036 /* RFC 3268 */ -#define TLS_DH_RSA_WITH_AES_256_CBC_SHA 0x0037 /* RFC 3268 */ -#define TLS_DHE_DSS_WITH_AES_256_CBC_SHA 0x0038 /* RFC 3268 */ -#define TLS_DHE_RSA_WITH_AES_256_CBC_SHA 0x0039 /* RFC 3268 */ -#define TLS_DH_anon_WITH_AES_256_CBC_SHA 0x003A /* RFC 3268 */ - -/* CompressionMethod */ -#define TLS_COMPRESSION_NULL 0 - -/* AlertLevel */ -#define TLS_ALERT_LEVEL_WARNING 1 -#define TLS_ALERT_LEVEL_FATAL 2 - -/* AlertDescription */ -#define TLS_ALERT_CLOSE_NOTIFY 0 -#define TLS_ALERT_UNEXPECTED_MESSAGE 10 -#define TLS_ALERT_BAD_RECORD_MAC 20 -#define TLS_ALERT_DECRYPTION_FAILED 21 -#define TLS_ALERT_RECORD_OVERFLOW 22 -#define TLS_ALERT_DECOMPRESSION_FAILURE 30 -#define TLS_ALERT_HANDSHAKE_FAILURE 40 -#define TLS_ALERT_BAD_CERTIFICATE 42 -#define TLS_ALERT_UNSUPPORTED_CERTIFICATE 43 -#define TLS_ALERT_CERTIFICATE_REVOKED 44 -#define TLS_ALERT_CERTIFICATE_EXPIRED 45 -#define TLS_ALERT_CERTIFICATE_UNKNOWN 46 -#define TLS_ALERT_ILLEGAL_PARAMETER 47 -#define TLS_ALERT_UNKNOWN_CA 48 -#define TLS_ALERT_ACCESS_DENIED 49 -#define TLS_ALERT_DECODE_ERROR 50 -#define TLS_ALERT_DECRYPT_ERROR 51 -#define TLS_ALERT_EXPORT_RESTRICTION 60 -#define TLS_ALERT_PROTOCOL_VERSION 70 -#define TLS_ALERT_INSUFFICIENT_SECURITY 71 -#define TLS_ALERT_INTERNAL_ERROR 80 -#define TLS_ALERT_USER_CANCELED 90 -#define TLS_ALERT_NO_RENEGOTIATION 100 -#define TLS_ALERT_UNSUPPORTED_EXTENSION 110 /* RFC 4366 */ -#define TLS_ALERT_CERTIFICATE_UNOBTAINABLE 111 /* RFC 4366 */ -#define TLS_ALERT_UNRECOGNIZED_NAME 112 /* RFC 4366 */ -#define TLS_ALERT_BAD_CERTIFICATE_STATUS_RESPONSE 113 /* RFC 4366 */ -#define TLS_ALERT_BAD_CERTIFICATE_HASH_VALUE 114 /* RFC 4366 */ - -/* ChangeCipherSpec */ -enum { - TLS_CHANGE_CIPHER_SPEC = 1 -}; - -/* TLS Extensions */ -#define TLS_EXT_SERVER_NAME 0 /* RFC 4366 */ -#define TLS_EXT_MAX_FRAGMENT_LENGTH 1 /* RFC 4366 */ -#define TLS_EXT_CLIENT_CERTIFICATE_URL 2 /* RFC 4366 */ -#define TLS_EXT_TRUSTED_CA_KEYS 3 /* RFC 4366 */ -#define TLS_EXT_TRUNCATED_HMAC 4 /* RFC 4366 */ -#define TLS_EXT_STATUS_REQUEST 5 /* RFC 4366 */ -#define TLS_EXT_SESSION_TICKET 35 /* RFC 4507 */ - -#define TLS_EXT_PAC_OPAQUE TLS_EXT_SESSION_TICKET /* EAP-FAST terminology */ - - -typedef enum { - TLS_KEY_X_NULL, - TLS_KEY_X_RSA, - TLS_KEY_X_RSA_EXPORT, - TLS_KEY_X_DH_DSS_EXPORT, - TLS_KEY_X_DH_DSS, - TLS_KEY_X_DH_RSA_EXPORT, - TLS_KEY_X_DH_RSA, - TLS_KEY_X_DHE_DSS_EXPORT, - TLS_KEY_X_DHE_DSS, - TLS_KEY_X_DHE_RSA_EXPORT, - TLS_KEY_X_DHE_RSA, - TLS_KEY_X_DH_anon_EXPORT, - TLS_KEY_X_DH_anon -} tls_key_exchange; - -typedef enum { - TLS_CIPHER_NULL, - TLS_CIPHER_RC4_40, - TLS_CIPHER_RC4_128, - TLS_CIPHER_RC2_CBC_40, - TLS_CIPHER_IDEA_CBC, - TLS_CIPHER_DES40_CBC, - TLS_CIPHER_DES_CBC, - TLS_CIPHER_3DES_EDE_CBC, - TLS_CIPHER_AES_128_CBC, - TLS_CIPHER_AES_256_CBC -} tls_cipher; - -typedef enum { - TLS_HASH_NULL, - TLS_HASH_MD5, - TLS_HASH_SHA -} tls_hash; - -struct tls_cipher_suite { - u16 suite; - tls_key_exchange key_exchange; - tls_cipher cipher; - tls_hash hash; -}; - -typedef enum { - TLS_CIPHER_STREAM, - TLS_CIPHER_BLOCK -} tls_cipher_type; - -struct tls_cipher_data { - tls_cipher cipher; - tls_cipher_type type; - size_t key_material; - size_t expanded_key_material; - size_t block_size; /* also iv_size */ - enum crypto_cipher_alg alg; -}; - - -struct tls_verify_hash { - struct crypto_hash *md5_client; - struct crypto_hash *sha1_client; - struct crypto_hash *md5_server; - struct crypto_hash *sha1_server; - struct crypto_hash *md5_cert; - struct crypto_hash *sha1_cert; -}; - - -const struct tls_cipher_suite * tls_get_cipher_suite(u16 suite); -const struct tls_cipher_data * tls_get_cipher_data(tls_cipher cipher); -int tls_server_key_exchange_allowed(tls_cipher cipher); -int tls_parse_cert(const u8 *buf, size_t len, struct crypto_public_key **pk); -int tls_verify_hash_init(struct tls_verify_hash *verify); -void tls_verify_hash_add(struct tls_verify_hash *verify, const u8 *buf, - size_t len); -void tls_verify_hash_free(struct tls_verify_hash *verify); - -#endif /* TLSV1_COMMON_H */ diff --git a/hostapd-0.8/src/tls/tlsv1_cred.c b/hostapd-0.8/src/tls/tlsv1_cred.c deleted file mode 100644 index aa467ef..0000000 --- a/hostapd-0.8/src/tls/tlsv1_cred.c +++ /dev/null @@ -1,493 +0,0 @@ -/* - * TLSv1 credentials - * Copyright (c) 2006-2009, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#include "includes.h" - -#include "common.h" -#include "base64.h" -#include "crypto/crypto.h" -#include "x509v3.h" -#include "tlsv1_cred.h" - - -struct tlsv1_credentials * tlsv1_cred_alloc(void) -{ - struct tlsv1_credentials *cred; - cred = os_zalloc(sizeof(*cred)); - return cred; -} - - -void tlsv1_cred_free(struct tlsv1_credentials *cred) -{ - if (cred == NULL) - return; - - x509_certificate_chain_free(cred->trusted_certs); - x509_certificate_chain_free(cred->cert); - crypto_private_key_free(cred->key); - os_free(cred->dh_p); - os_free(cred->dh_g); - os_free(cred); -} - - -static int tlsv1_add_cert_der(struct x509_certificate **chain, - const u8 *buf, size_t len) -{ - struct x509_certificate *cert; - char name[128]; - - cert = x509_certificate_parse(buf, len); - if (cert == NULL) { - wpa_printf(MSG_INFO, "TLSv1: %s - failed to parse certificate", - __func__); - return -1; - } - - cert->next = *chain; - *chain = cert; - - x509_name_string(&cert->subject, name, sizeof(name)); - wpa_printf(MSG_DEBUG, "TLSv1: Added certificate: %s", name); - - return 0; -} - - -static const char *pem_cert_begin = "-----BEGIN CERTIFICATE-----"; -static const char *pem_cert_end = "-----END CERTIFICATE-----"; -static const char *pem_key_begin = "-----BEGIN RSA PRIVATE KEY-----"; -static const char *pem_key_end = "-----END RSA PRIVATE KEY-----"; -static const char *pem_key2_begin = "-----BEGIN PRIVATE KEY-----"; -static const char *pem_key2_end = "-----END PRIVATE KEY-----"; -static const char *pem_key_enc_begin = "-----BEGIN ENCRYPTED PRIVATE KEY-----"; -static const char *pem_key_enc_end = "-----END ENCRYPTED PRIVATE KEY-----"; - - -static const u8 * search_tag(const char *tag, const u8 *buf, size_t len) -{ - size_t i, plen; - - plen = os_strlen(tag); - if (len < plen) - return NULL; - - for (i = 0; i < len - plen; i++) { - if (os_memcmp(buf + i, tag, plen) == 0) - return buf + i; - } - - return NULL; -} - - -static int tlsv1_add_cert(struct x509_certificate **chain, - const u8 *buf, size_t len) -{ - const u8 *pos, *end; - unsigned char *der; - size_t der_len; - - pos = search_tag(pem_cert_begin, buf, len); - if (!pos) { - wpa_printf(MSG_DEBUG, "TLSv1: No PEM certificate tag found - " - "assume DER format"); - return tlsv1_add_cert_der(chain, buf, len); - } - - wpa_printf(MSG_DEBUG, "TLSv1: Converting PEM format certificate into " - "DER format"); - - while (pos) { - pos += os_strlen(pem_cert_begin); - end = search_tag(pem_cert_end, pos, buf + len - pos); - if (end == NULL) { - wpa_printf(MSG_INFO, "TLSv1: Could not find PEM " - "certificate end tag (%s)", pem_cert_end); - return -1; - } - - der = base64_decode(pos, end - pos, &der_len); - if (der == NULL) { - wpa_printf(MSG_INFO, "TLSv1: Could not decode PEM " - "certificate"); - return -1; - } - - if (tlsv1_add_cert_der(chain, der, der_len) < 0) { - wpa_printf(MSG_INFO, "TLSv1: Failed to parse PEM " - "certificate after DER conversion"); - os_free(der); - return -1; - } - - os_free(der); - - end += os_strlen(pem_cert_end); - pos = search_tag(pem_cert_begin, end, buf + len - end); - } - - return 0; -} - - -static int tlsv1_set_cert_chain(struct x509_certificate **chain, - const char *cert, const u8 *cert_blob, - size_t cert_blob_len) -{ - if (cert_blob) - return tlsv1_add_cert(chain, cert_blob, cert_blob_len); - - if (cert) { - u8 *buf; - size_t len; - int ret; - - buf = (u8 *) os_readfile(cert, &len); - if (buf == NULL) { - wpa_printf(MSG_INFO, "TLSv1: Failed to read '%s'", - cert); - return -1; - } - - ret = tlsv1_add_cert(chain, buf, len); - os_free(buf); - return ret; - } - - return 0; -} - - -/** - * tlsv1_set_ca_cert - Set trusted CA certificate(s) - * @cred: TLSv1 credentials from tlsv1_cred_alloc() - * @cert: File or reference name for X.509 certificate in PEM or DER format - * @cert_blob: cert as inlined data or %NULL if not used - * @cert_blob_len: ca_cert_blob length - * @path: Path to CA certificates (not yet supported) - * Returns: 0 on success, -1 on failure - */ -int tlsv1_set_ca_cert(struct tlsv1_credentials *cred, const char *cert, - const u8 *cert_blob, size_t cert_blob_len, - const char *path) -{ - if (tlsv1_set_cert_chain(&cred->trusted_certs, cert, - cert_blob, cert_blob_len) < 0) - return -1; - - if (path) { - /* TODO: add support for reading number of certificate files */ - wpa_printf(MSG_INFO, "TLSv1: Use of CA certificate directory " - "not yet supported"); - return -1; - } - - return 0; -} - - -/** - * tlsv1_set_cert - Set certificate - * @cred: TLSv1 credentials from tlsv1_cred_alloc() - * @cert: File or reference name for X.509 certificate in PEM or DER format - * @cert_blob: cert as inlined data or %NULL if not used - * @cert_blob_len: cert_blob length - * Returns: 0 on success, -1 on failure - */ -int tlsv1_set_cert(struct tlsv1_credentials *cred, const char *cert, - const u8 *cert_blob, size_t cert_blob_len) -{ - return tlsv1_set_cert_chain(&cred->cert, cert, - cert_blob, cert_blob_len); -} - - -static struct crypto_private_key * tlsv1_set_key_pem(const u8 *key, size_t len) -{ - const u8 *pos, *end; - unsigned char *der; - size_t der_len; - struct crypto_private_key *pkey; - - pos = search_tag(pem_key_begin, key, len); - if (!pos) { - pos = search_tag(pem_key2_begin, key, len); - if (!pos) - return NULL; - pos += os_strlen(pem_key2_begin); - end = search_tag(pem_key2_end, pos, key + len - pos); - if (!end) - return NULL; - } else { - pos += os_strlen(pem_key_begin); - end = search_tag(pem_key_end, pos, key + len - pos); - if (!end) - return NULL; - } - - der = base64_decode(pos, end - pos, &der_len); - if (!der) - return NULL; - pkey = crypto_private_key_import(der, der_len, NULL); - os_free(der); - return pkey; -} - - -static struct crypto_private_key * tlsv1_set_key_enc_pem(const u8 *key, - size_t len, - const char *passwd) -{ - const u8 *pos, *end; - unsigned char *der; - size_t der_len; - struct crypto_private_key *pkey; - - if (passwd == NULL) - return NULL; - pos = search_tag(pem_key_enc_begin, key, len); - if (!pos) - return NULL; - pos += os_strlen(pem_key_enc_begin); - end = search_tag(pem_key_enc_end, pos, key + len - pos); - if (!end) - return NULL; - - der = base64_decode(pos, end - pos, &der_len); - if (!der) - return NULL; - pkey = crypto_private_key_import(der, der_len, passwd); - os_free(der); - return pkey; -} - - -static int tlsv1_set_key(struct tlsv1_credentials *cred, - const u8 *key, size_t len, const char *passwd) -{ - cred->key = crypto_private_key_import(key, len, passwd); - if (cred->key == NULL) - cred->key = tlsv1_set_key_pem(key, len); - if (cred->key == NULL) - cred->key = tlsv1_set_key_enc_pem(key, len, passwd); - if (cred->key == NULL) { - wpa_printf(MSG_INFO, "TLSv1: Failed to parse private key"); - return -1; - } - return 0; -} - - -/** - * tlsv1_set_private_key - Set private key - * @cred: TLSv1 credentials from tlsv1_cred_alloc() - * @private_key: File or reference name for the key in PEM or DER format - * @private_key_passwd: Passphrase for decrypted private key, %NULL if no - * passphrase is used. - * @private_key_blob: private_key as inlined data or %NULL if not used - * @private_key_blob_len: private_key_blob length - * Returns: 0 on success, -1 on failure - */ -int tlsv1_set_private_key(struct tlsv1_credentials *cred, - const char *private_key, - const char *private_key_passwd, - const u8 *private_key_blob, - size_t private_key_blob_len) -{ - crypto_private_key_free(cred->key); - cred->key = NULL; - - if (private_key_blob) - return tlsv1_set_key(cred, private_key_blob, - private_key_blob_len, - private_key_passwd); - - if (private_key) { - u8 *buf; - size_t len; - int ret; - - buf = (u8 *) os_readfile(private_key, &len); - if (buf == NULL) { - wpa_printf(MSG_INFO, "TLSv1: Failed to read '%s'", - private_key); - return -1; - } - - ret = tlsv1_set_key(cred, buf, len, private_key_passwd); - os_free(buf); - return ret; - } - - return 0; -} - - -static int tlsv1_set_dhparams_der(struct tlsv1_credentials *cred, - const u8 *dh, size_t len) -{ - struct asn1_hdr hdr; - const u8 *pos, *end; - - pos = dh; - end = dh + len; - - /* - * DHParameter ::= SEQUENCE { - * prime INTEGER, -- p - * base INTEGER, -- g - * privateValueLength INTEGER OPTIONAL } - */ - - /* DHParamer ::= SEQUENCE */ - if (asn1_get_next(pos, len, &hdr) < 0 || - hdr.class != ASN1_CLASS_UNIVERSAL || - hdr.tag != ASN1_TAG_SEQUENCE) { - wpa_printf(MSG_DEBUG, "DH: DH parameters did not start with a " - "valid SEQUENCE - found class %d tag 0x%x", - hdr.class, hdr.tag); - return -1; - } - pos = hdr.payload; - - /* prime INTEGER */ - if (asn1_get_next(pos, end - pos, &hdr) < 0) - return -1; - - if (hdr.class != ASN1_CLASS_UNIVERSAL || - hdr.tag != ASN1_TAG_INTEGER) { - wpa_printf(MSG_DEBUG, "DH: No INTEGER tag found for p; " - "class=%d tag=0x%x", hdr.class, hdr.tag); - return -1; - } - - wpa_hexdump(MSG_MSGDUMP, "DH: prime (p)", hdr.payload, hdr.length); - if (hdr.length == 0) - return -1; - os_free(cred->dh_p); - cred->dh_p = os_malloc(hdr.length); - if (cred->dh_p == NULL) - return -1; - os_memcpy(cred->dh_p, hdr.payload, hdr.length); - cred->dh_p_len = hdr.length; - pos = hdr.payload + hdr.length; - - /* base INTEGER */ - if (asn1_get_next(pos, end - pos, &hdr) < 0) - return -1; - - if (hdr.class != ASN1_CLASS_UNIVERSAL || - hdr.tag != ASN1_TAG_INTEGER) { - wpa_printf(MSG_DEBUG, "DH: No INTEGER tag found for g; " - "class=%d tag=0x%x", hdr.class, hdr.tag); - return -1; - } - - wpa_hexdump(MSG_MSGDUMP, "DH: base (g)", hdr.payload, hdr.length); - if (hdr.length == 0) - return -1; - os_free(cred->dh_g); - cred->dh_g = os_malloc(hdr.length); - if (cred->dh_g == NULL) - return -1; - os_memcpy(cred->dh_g, hdr.payload, hdr.length); - cred->dh_g_len = hdr.length; - - return 0; -} - - -static const char *pem_dhparams_begin = "-----BEGIN DH PARAMETERS-----"; -static const char *pem_dhparams_end = "-----END DH PARAMETERS-----"; - - -static int tlsv1_set_dhparams_blob(struct tlsv1_credentials *cred, - const u8 *buf, size_t len) -{ - const u8 *pos, *end; - unsigned char *der; - size_t der_len; - - pos = search_tag(pem_dhparams_begin, buf, len); - if (!pos) { - wpa_printf(MSG_DEBUG, "TLSv1: No PEM dhparams tag found - " - "assume DER format"); - return tlsv1_set_dhparams_der(cred, buf, len); - } - - wpa_printf(MSG_DEBUG, "TLSv1: Converting PEM format dhparams into DER " - "format"); - - pos += os_strlen(pem_dhparams_begin); - end = search_tag(pem_dhparams_end, pos, buf + len - pos); - if (end == NULL) { - wpa_printf(MSG_INFO, "TLSv1: Could not find PEM dhparams end " - "tag (%s)", pem_dhparams_end); - return -1; - } - - der = base64_decode(pos, end - pos, &der_len); - if (der == NULL) { - wpa_printf(MSG_INFO, "TLSv1: Could not decode PEM dhparams"); - return -1; - } - - if (tlsv1_set_dhparams_der(cred, der, der_len) < 0) { - wpa_printf(MSG_INFO, "TLSv1: Failed to parse PEM dhparams " - "DER conversion"); - os_free(der); - return -1; - } - - os_free(der); - - return 0; -} - - -/** - * tlsv1_set_dhparams - Set Diffie-Hellman parameters - * @cred: TLSv1 credentials from tlsv1_cred_alloc() - * @dh_file: File or reference name for the DH params in PEM or DER format - * @dh_blob: DH params as inlined data or %NULL if not used - * @dh_blob_len: dh_blob length - * Returns: 0 on success, -1 on failure - */ -int tlsv1_set_dhparams(struct tlsv1_credentials *cred, const char *dh_file, - const u8 *dh_blob, size_t dh_blob_len) -{ - if (dh_blob) - return tlsv1_set_dhparams_blob(cred, dh_blob, dh_blob_len); - - if (dh_file) { - u8 *buf; - size_t len; - int ret; - - buf = (u8 *) os_readfile(dh_file, &len); - if (buf == NULL) { - wpa_printf(MSG_INFO, "TLSv1: Failed to read '%s'", - dh_file); - return -1; - } - - ret = tlsv1_set_dhparams_blob(cred, buf, len); - os_free(buf); - return ret; - } - - return 0; -} diff --git a/hostapd-0.8/src/tls/tlsv1_cred.h b/hostapd-0.8/src/tls/tlsv1_cred.h deleted file mode 100644 index 8425fe4..0000000 --- a/hostapd-0.8/src/tls/tlsv1_cred.h +++ /dev/null @@ -1,46 +0,0 @@ -/* - * TLSv1 credentials - * Copyright (c) 2006-2007, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#ifndef TLSV1_CRED_H -#define TLSV1_CRED_H - -struct tlsv1_credentials { - struct x509_certificate *trusted_certs; - struct x509_certificate *cert; - struct crypto_private_key *key; - - /* Diffie-Hellman parameters */ - u8 *dh_p; /* prime */ - size_t dh_p_len; - u8 *dh_g; /* generator */ - size_t dh_g_len; -}; - - -struct tlsv1_credentials * tlsv1_cred_alloc(void); -void tlsv1_cred_free(struct tlsv1_credentials *cred); -int tlsv1_set_ca_cert(struct tlsv1_credentials *cred, const char *cert, - const u8 *cert_blob, size_t cert_blob_len, - const char *path); -int tlsv1_set_cert(struct tlsv1_credentials *cred, const char *cert, - const u8 *cert_blob, size_t cert_blob_len); -int tlsv1_set_private_key(struct tlsv1_credentials *cred, - const char *private_key, - const char *private_key_passwd, - const u8 *private_key_blob, - size_t private_key_blob_len); -int tlsv1_set_dhparams(struct tlsv1_credentials *cred, const char *dh_file, - const u8 *dh_blob, size_t dh_blob_len); - -#endif /* TLSV1_CRED_H */ diff --git a/hostapd-0.8/src/tls/tlsv1_record.c b/hostapd-0.8/src/tls/tlsv1_record.c deleted file mode 100644 index e811f0e..0000000 --- a/hostapd-0.8/src/tls/tlsv1_record.c +++ /dev/null @@ -1,409 +0,0 @@ -/* - * TLSv1 Record Protocol - * Copyright (c) 2006-2007, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#include "includes.h" - -#include "common.h" -#include "crypto/md5.h" -#include "crypto/sha1.h" -#include "tlsv1_common.h" -#include "tlsv1_record.h" - - -/** - * tlsv1_record_set_cipher_suite - TLS record layer: Set cipher suite - * @rl: Pointer to TLS record layer data - * @cipher_suite: New cipher suite - * Returns: 0 on success, -1 on failure - * - * This function is used to prepare TLS record layer for cipher suite change. - * tlsv1_record_change_write_cipher() and - * tlsv1_record_change_read_cipher() functions can then be used to change the - * currently used ciphers. - */ -int tlsv1_record_set_cipher_suite(struct tlsv1_record_layer *rl, - u16 cipher_suite) -{ - const struct tls_cipher_suite *suite; - const struct tls_cipher_data *data; - - wpa_printf(MSG_DEBUG, "TLSv1: Selected cipher suite: 0x%04x", - cipher_suite); - rl->cipher_suite = cipher_suite; - - suite = tls_get_cipher_suite(cipher_suite); - if (suite == NULL) - return -1; - - if (suite->hash == TLS_HASH_MD5) { - rl->hash_alg = CRYPTO_HASH_ALG_HMAC_MD5; - rl->hash_size = MD5_MAC_LEN; - } else if (suite->hash == TLS_HASH_SHA) { - rl->hash_alg = CRYPTO_HASH_ALG_HMAC_SHA1; - rl->hash_size = SHA1_MAC_LEN; - } - - data = tls_get_cipher_data(suite->cipher); - if (data == NULL) - return -1; - - rl->key_material_len = data->key_material; - rl->iv_size = data->block_size; - rl->cipher_alg = data->alg; - - return 0; -} - - -/** - * tlsv1_record_change_write_cipher - TLS record layer: Change write cipher - * @rl: Pointer to TLS record layer data - * Returns: 0 on success (cipher changed), -1 on failure - * - * This function changes TLS record layer to use the new cipher suite - * configured with tlsv1_record_set_cipher_suite() for writing. - */ -int tlsv1_record_change_write_cipher(struct tlsv1_record_layer *rl) -{ - wpa_printf(MSG_DEBUG, "TLSv1: Record Layer - New write cipher suite " - "0x%04x", rl->cipher_suite); - rl->write_cipher_suite = rl->cipher_suite; - os_memset(rl->write_seq_num, 0, TLS_SEQ_NUM_LEN); - - if (rl->write_cbc) { - crypto_cipher_deinit(rl->write_cbc); - rl->write_cbc = NULL; - } - if (rl->cipher_alg != CRYPTO_CIPHER_NULL) { - rl->write_cbc = crypto_cipher_init(rl->cipher_alg, - rl->write_iv, rl->write_key, - rl->key_material_len); - if (rl->write_cbc == NULL) { - wpa_printf(MSG_DEBUG, "TLSv1: Failed to initialize " - "cipher"); - return -1; - } - } - - return 0; -} - - -/** - * tlsv1_record_change_read_cipher - TLS record layer: Change read cipher - * @rl: Pointer to TLS record layer data - * Returns: 0 on success (cipher changed), -1 on failure - * - * This function changes TLS record layer to use the new cipher suite - * configured with tlsv1_record_set_cipher_suite() for reading. - */ -int tlsv1_record_change_read_cipher(struct tlsv1_record_layer *rl) -{ - wpa_printf(MSG_DEBUG, "TLSv1: Record Layer - New read cipher suite " - "0x%04x", rl->cipher_suite); - rl->read_cipher_suite = rl->cipher_suite; - os_memset(rl->read_seq_num, 0, TLS_SEQ_NUM_LEN); - - if (rl->read_cbc) { - crypto_cipher_deinit(rl->read_cbc); - rl->read_cbc = NULL; - } - if (rl->cipher_alg != CRYPTO_CIPHER_NULL) { - rl->read_cbc = crypto_cipher_init(rl->cipher_alg, - rl->read_iv, rl->read_key, - rl->key_material_len); - if (rl->read_cbc == NULL) { - wpa_printf(MSG_DEBUG, "TLSv1: Failed to initialize " - "cipher"); - return -1; - } - } - - return 0; -} - - -/** - * tlsv1_record_send - TLS record layer: Send a message - * @rl: Pointer to TLS record layer data - * @content_type: Content type (TLS_CONTENT_TYPE_*) - * @buf: Buffer to send (with TLS_RECORD_HEADER_LEN octets reserved in the - * beginning for record layer to fill in; payload filled in after this and - * extra space in the end for HMAC). - * @buf_size: Maximum buf size - * @payload_len: Length of the payload - * @out_len: Buffer for returning the used buf length - * Returns: 0 on success, -1 on failure - * - * This function fills in the TLS record layer header, adds HMAC, and encrypts - * the data using the current write cipher. - */ -int tlsv1_record_send(struct tlsv1_record_layer *rl, u8 content_type, u8 *buf, - size_t buf_size, size_t payload_len, size_t *out_len) -{ - u8 *pos, *ct_start, *length, *payload; - struct crypto_hash *hmac; - size_t clen; - - pos = buf; - /* ContentType type */ - ct_start = pos; - *pos++ = content_type; - /* ProtocolVersion version */ - WPA_PUT_BE16(pos, TLS_VERSION); - pos += 2; - /* uint16 length */ - length = pos; - WPA_PUT_BE16(length, payload_len); - pos += 2; - - /* opaque fragment[TLSPlaintext.length] */ - payload = pos; - pos += payload_len; - - if (rl->write_cipher_suite != TLS_NULL_WITH_NULL_NULL) { - hmac = crypto_hash_init(rl->hash_alg, rl->write_mac_secret, - rl->hash_size); - if (hmac == NULL) { - wpa_printf(MSG_DEBUG, "TLSv1: Record Layer - Failed " - "to initialize HMAC"); - return -1; - } - crypto_hash_update(hmac, rl->write_seq_num, TLS_SEQ_NUM_LEN); - /* type + version + length + fragment */ - crypto_hash_update(hmac, ct_start, pos - ct_start); - clen = buf + buf_size - pos; - if (clen < rl->hash_size) { - wpa_printf(MSG_DEBUG, "TLSv1: Record Layer - Not " - "enough room for MAC"); - crypto_hash_finish(hmac, NULL, NULL); - return -1; - } - - if (crypto_hash_finish(hmac, pos, &clen) < 0) { - wpa_printf(MSG_DEBUG, "TLSv1: Record Layer - Failed " - "to calculate HMAC"); - return -1; - } - wpa_hexdump(MSG_MSGDUMP, "TLSv1: Record Layer - Write HMAC", - pos, clen); - pos += clen; - if (rl->iv_size) { - size_t len = pos - payload; - size_t pad; - pad = (len + 1) % rl->iv_size; - if (pad) - pad = rl->iv_size - pad; - if (pos + pad + 1 > buf + buf_size) { - wpa_printf(MSG_DEBUG, "TLSv1: No room for " - "block cipher padding"); - return -1; - } - os_memset(pos, pad, pad + 1); - pos += pad + 1; - } - - if (crypto_cipher_encrypt(rl->write_cbc, payload, - payload, pos - payload) < 0) - return -1; - } - - WPA_PUT_BE16(length, pos - length - 2); - inc_byte_array(rl->write_seq_num, TLS_SEQ_NUM_LEN); - - *out_len = pos - buf; - - return 0; -} - - -/** - * tlsv1_record_receive - TLS record layer: Process a received message - * @rl: Pointer to TLS record layer data - * @in_data: Received data - * @in_len: Length of the received data - * @out_data: Buffer for output data (must be at least as long as in_data) - * @out_len: Set to maximum out_data length by caller; used to return the - * length of the used data - * @alert: Buffer for returning an alert value on failure - * Returns: 0 on success, -1 on failure - * - * This function decrypts the received message, verifies HMAC and TLS record - * layer header. - */ -int tlsv1_record_receive(struct tlsv1_record_layer *rl, - const u8 *in_data, size_t in_len, - u8 *out_data, size_t *out_len, u8 *alert) -{ - size_t i, rlen, hlen; - u8 padlen; - struct crypto_hash *hmac; - u8 len[2], hash[100]; - - wpa_hexdump(MSG_MSGDUMP, "TLSv1: Record Layer - Received", - in_data, in_len); - - if (in_len < TLS_RECORD_HEADER_LEN) { - wpa_printf(MSG_DEBUG, "TLSv1: Too short record (in_len=%lu)", - (unsigned long) in_len); - *alert = TLS_ALERT_DECODE_ERROR; - return -1; - } - - wpa_printf(MSG_DEBUG, "TLSv1: Received content type %d version %d.%d " - "length %d", in_data[0], in_data[1], in_data[2], - WPA_GET_BE16(in_data + 3)); - - if (in_data[0] != TLS_CONTENT_TYPE_HANDSHAKE && - in_data[0] != TLS_CONTENT_TYPE_CHANGE_CIPHER_SPEC && - in_data[0] != TLS_CONTENT_TYPE_ALERT && - in_data[0] != TLS_CONTENT_TYPE_APPLICATION_DATA) { - wpa_printf(MSG_DEBUG, "TLSv1: Unexpected content type 0x%x", - in_data[0]); - *alert = TLS_ALERT_UNEXPECTED_MESSAGE; - return -1; - } - - if (WPA_GET_BE16(in_data + 1) != TLS_VERSION) { - wpa_printf(MSG_DEBUG, "TLSv1: Unexpected protocol version " - "%d.%d", in_data[1], in_data[2]); - *alert = TLS_ALERT_PROTOCOL_VERSION; - return -1; - } - - rlen = WPA_GET_BE16(in_data + 3); - - /* TLSCiphertext must not be more than 2^14+2048 bytes */ - if (TLS_RECORD_HEADER_LEN + rlen > 18432) { - wpa_printf(MSG_DEBUG, "TLSv1: Record overflow (len=%lu)", - (unsigned long) (TLS_RECORD_HEADER_LEN + rlen)); - *alert = TLS_ALERT_RECORD_OVERFLOW; - return -1; - } - - in_data += TLS_RECORD_HEADER_LEN; - in_len -= TLS_RECORD_HEADER_LEN; - - if (rlen > in_len) { - wpa_printf(MSG_DEBUG, "TLSv1: Not all record data included " - "(rlen=%lu > in_len=%lu)", - (unsigned long) rlen, (unsigned long) in_len); - *alert = TLS_ALERT_DECODE_ERROR; - return -1; - } - - in_len = rlen; - - if (*out_len < in_len) { - wpa_printf(MSG_DEBUG, "TLSv1: Not enough output buffer for " - "processing received record"); - *alert = TLS_ALERT_INTERNAL_ERROR; - return -1; - } - - os_memcpy(out_data, in_data, in_len); - *out_len = in_len; - - if (rl->read_cipher_suite != TLS_NULL_WITH_NULL_NULL) { - if (crypto_cipher_decrypt(rl->read_cbc, out_data, - out_data, in_len) < 0) { - *alert = TLS_ALERT_DECRYPTION_FAILED; - return -1; - } - if (rl->iv_size) { - if (in_len == 0) { - wpa_printf(MSG_DEBUG, "TLSv1: Too short record" - " (no pad)"); - *alert = TLS_ALERT_DECODE_ERROR; - return -1; - } - padlen = out_data[in_len - 1]; - if (padlen >= in_len) { - wpa_printf(MSG_DEBUG, "TLSv1: Incorrect pad " - "length (%u, in_len=%lu) in " - "received record", - padlen, (unsigned long) in_len); - *alert = TLS_ALERT_DECRYPTION_FAILED; - return -1; - } - for (i = in_len - padlen; i < in_len; i++) { - if (out_data[i] != padlen) { - wpa_hexdump(MSG_DEBUG, - "TLSv1: Invalid pad in " - "received record", - out_data + in_len - padlen, - padlen); - *alert = TLS_ALERT_DECRYPTION_FAILED; - return -1; - } - } - - *out_len -= padlen + 1; - } - - wpa_hexdump(MSG_MSGDUMP, - "TLSv1: Record Layer - Decrypted data", - out_data, in_len); - - if (*out_len < rl->hash_size) { - wpa_printf(MSG_DEBUG, "TLSv1: Too short record; no " - "hash value"); - *alert = TLS_ALERT_INTERNAL_ERROR; - return -1; - } - - *out_len -= rl->hash_size; - - hmac = crypto_hash_init(rl->hash_alg, rl->read_mac_secret, - rl->hash_size); - if (hmac == NULL) { - wpa_printf(MSG_DEBUG, "TLSv1: Record Layer - Failed " - "to initialize HMAC"); - *alert = TLS_ALERT_INTERNAL_ERROR; - return -1; - } - - crypto_hash_update(hmac, rl->read_seq_num, TLS_SEQ_NUM_LEN); - /* type + version + length + fragment */ - crypto_hash_update(hmac, in_data - TLS_RECORD_HEADER_LEN, 3); - WPA_PUT_BE16(len, *out_len); - crypto_hash_update(hmac, len, 2); - crypto_hash_update(hmac, out_data, *out_len); - hlen = sizeof(hash); - if (crypto_hash_finish(hmac, hash, &hlen) < 0) { - wpa_printf(MSG_DEBUG, "TLSv1: Record Layer - Failed " - "to calculate HMAC"); - return -1; - } - if (hlen != rl->hash_size || - os_memcmp(hash, out_data + *out_len, hlen) != 0) { - wpa_printf(MSG_DEBUG, "TLSv1: Invalid HMAC value in " - "received message"); - *alert = TLS_ALERT_BAD_RECORD_MAC; - return -1; - } - } - - /* TLSCompressed must not be more than 2^14+1024 bytes */ - if (TLS_RECORD_HEADER_LEN + *out_len > 17408) { - wpa_printf(MSG_DEBUG, "TLSv1: Record overflow (len=%lu)", - (unsigned long) (TLS_RECORD_HEADER_LEN + *out_len)); - *alert = TLS_ALERT_RECORD_OVERFLOW; - return -1; - } - - inc_byte_array(rl->read_seq_num, TLS_SEQ_NUM_LEN); - - return 0; -} diff --git a/hostapd-0.8/src/tls/tlsv1_record.h b/hostapd-0.8/src/tls/tlsv1_record.h deleted file mode 100644 index 9c7c0a4..0000000 --- a/hostapd-0.8/src/tls/tlsv1_record.h +++ /dev/null @@ -1,74 +0,0 @@ -/* - * TLSv1 Record Protocol - * Copyright (c) 2006-2007, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#ifndef TLSV1_RECORD_H -#define TLSV1_RECORD_H - -#include "crypto/crypto.h" - -#define TLS_MAX_WRITE_MAC_SECRET_LEN 20 -#define TLS_MAX_WRITE_KEY_LEN 32 -#define TLS_MAX_IV_LEN 16 -#define TLS_MAX_KEY_BLOCK_LEN (2 * (TLS_MAX_WRITE_MAC_SECRET_LEN + \ - TLS_MAX_WRITE_KEY_LEN + TLS_MAX_IV_LEN)) - -#define TLS_SEQ_NUM_LEN 8 -#define TLS_RECORD_HEADER_LEN 5 - -/* ContentType */ -enum { - TLS_CONTENT_TYPE_CHANGE_CIPHER_SPEC = 20, - TLS_CONTENT_TYPE_ALERT = 21, - TLS_CONTENT_TYPE_HANDSHAKE = 22, - TLS_CONTENT_TYPE_APPLICATION_DATA = 23 -}; - -struct tlsv1_record_layer { - u8 write_mac_secret[TLS_MAX_WRITE_MAC_SECRET_LEN]; - u8 read_mac_secret[TLS_MAX_WRITE_MAC_SECRET_LEN]; - u8 write_key[TLS_MAX_WRITE_KEY_LEN]; - u8 read_key[TLS_MAX_WRITE_KEY_LEN]; - u8 write_iv[TLS_MAX_IV_LEN]; - u8 read_iv[TLS_MAX_IV_LEN]; - - size_t hash_size; - size_t key_material_len; - size_t iv_size; /* also block_size */ - - enum crypto_hash_alg hash_alg; - enum crypto_cipher_alg cipher_alg; - - u8 write_seq_num[TLS_SEQ_NUM_LEN]; - u8 read_seq_num[TLS_SEQ_NUM_LEN]; - - u16 cipher_suite; - u16 write_cipher_suite; - u16 read_cipher_suite; - - struct crypto_cipher *write_cbc; - struct crypto_cipher *read_cbc; -}; - - -int tlsv1_record_set_cipher_suite(struct tlsv1_record_layer *rl, - u16 cipher_suite); -int tlsv1_record_change_write_cipher(struct tlsv1_record_layer *rl); -int tlsv1_record_change_read_cipher(struct tlsv1_record_layer *rl); -int tlsv1_record_send(struct tlsv1_record_layer *rl, u8 content_type, u8 *buf, - size_t buf_size, size_t payload_len, size_t *out_len); -int tlsv1_record_receive(struct tlsv1_record_layer *rl, - const u8 *in_data, size_t in_len, - u8 *out_data, size_t *out_len, u8 *alert); - -#endif /* TLSV1_RECORD_H */ diff --git a/hostapd-0.8/src/tls/tlsv1_server.c b/hostapd-0.8/src/tls/tlsv1_server.c deleted file mode 100644 index 6a61235..0000000 --- a/hostapd-0.8/src/tls/tlsv1_server.c +++ /dev/null @@ -1,592 +0,0 @@ -/* - * TLSv1 server (RFC 2246) - * Copyright (c) 2006-2007, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#include "includes.h" - -#include "common.h" -#include "crypto/sha1.h" -#include "crypto/tls.h" -#include "tlsv1_common.h" -#include "tlsv1_record.h" -#include "tlsv1_server.h" -#include "tlsv1_server_i.h" - -/* TODO: - * Support for a message fragmented across several records (RFC 2246, 6.2.1) - */ - - -void tlsv1_server_alert(struct tlsv1_server *conn, u8 level, u8 description) -{ - conn->alert_level = level; - conn->alert_description = description; -} - - -int tlsv1_server_derive_keys(struct tlsv1_server *conn, - const u8 *pre_master_secret, - size_t pre_master_secret_len) -{ - u8 seed[2 * TLS_RANDOM_LEN]; - u8 key_block[TLS_MAX_KEY_BLOCK_LEN]; - u8 *pos; - size_t key_block_len; - - if (pre_master_secret) { - wpa_hexdump_key(MSG_MSGDUMP, "TLSv1: pre_master_secret", - pre_master_secret, pre_master_secret_len); - os_memcpy(seed, conn->client_random, TLS_RANDOM_LEN); - os_memcpy(seed + TLS_RANDOM_LEN, conn->server_random, - TLS_RANDOM_LEN); - if (tls_prf(pre_master_secret, pre_master_secret_len, - "master secret", seed, 2 * TLS_RANDOM_LEN, - conn->master_secret, TLS_MASTER_SECRET_LEN)) { - wpa_printf(MSG_DEBUG, "TLSv1: Failed to derive " - "master_secret"); - return -1; - } - wpa_hexdump_key(MSG_MSGDUMP, "TLSv1: master_secret", - conn->master_secret, TLS_MASTER_SECRET_LEN); - } - - os_memcpy(seed, conn->server_random, TLS_RANDOM_LEN); - os_memcpy(seed + TLS_RANDOM_LEN, conn->client_random, TLS_RANDOM_LEN); - key_block_len = 2 * (conn->rl.hash_size + conn->rl.key_material_len + - conn->rl.iv_size); - if (tls_prf(conn->master_secret, TLS_MASTER_SECRET_LEN, - "key expansion", seed, 2 * TLS_RANDOM_LEN, - key_block, key_block_len)) { - wpa_printf(MSG_DEBUG, "TLSv1: Failed to derive key_block"); - return -1; - } - wpa_hexdump_key(MSG_MSGDUMP, "TLSv1: key_block", - key_block, key_block_len); - - pos = key_block; - - /* client_write_MAC_secret */ - os_memcpy(conn->rl.read_mac_secret, pos, conn->rl.hash_size); - pos += conn->rl.hash_size; - /* server_write_MAC_secret */ - os_memcpy(conn->rl.write_mac_secret, pos, conn->rl.hash_size); - pos += conn->rl.hash_size; - - /* client_write_key */ - os_memcpy(conn->rl.read_key, pos, conn->rl.key_material_len); - pos += conn->rl.key_material_len; - /* server_write_key */ - os_memcpy(conn->rl.write_key, pos, conn->rl.key_material_len); - pos += conn->rl.key_material_len; - - /* client_write_IV */ - os_memcpy(conn->rl.read_iv, pos, conn->rl.iv_size); - pos += conn->rl.iv_size; - /* server_write_IV */ - os_memcpy(conn->rl.write_iv, pos, conn->rl.iv_size); - pos += conn->rl.iv_size; - - return 0; -} - - -/** - * tlsv1_server_handshake - Process TLS handshake - * @conn: TLSv1 server connection data from tlsv1_server_init() - * @in_data: Input data from TLS peer - * @in_len: Input data length - * @out_len: Length of the output buffer. - * Returns: Pointer to output data, %NULL on failure - */ -u8 * tlsv1_server_handshake(struct tlsv1_server *conn, - const u8 *in_data, size_t in_len, - size_t *out_len) -{ - const u8 *pos, *end; - u8 *msg = NULL, *in_msg, *in_pos, *in_end, alert, ct; - size_t in_msg_len; - - if (in_data == NULL || in_len == 0) { - wpa_printf(MSG_DEBUG, "TLSv1: No input data to server"); - return NULL; - } - - pos = in_data; - end = in_data + in_len; - in_msg = os_malloc(in_len); - if (in_msg == NULL) - return NULL; - - /* Each received packet may include multiple records */ - while (pos < end) { - in_msg_len = in_len; - if (tlsv1_record_receive(&conn->rl, pos, end - pos, - in_msg, &in_msg_len, &alert)) { - wpa_printf(MSG_DEBUG, "TLSv1: Processing received " - "record failed"); - tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, alert); - goto failed; - } - ct = pos[0]; - - in_pos = in_msg; - in_end = in_msg + in_msg_len; - - /* Each received record may include multiple messages of the - * same ContentType. */ - while (in_pos < in_end) { - in_msg_len = in_end - in_pos; - if (tlsv1_server_process_handshake(conn, ct, in_pos, - &in_msg_len) < 0) - goto failed; - in_pos += in_msg_len; - } - - pos += TLS_RECORD_HEADER_LEN + WPA_GET_BE16(pos + 3); - } - - os_free(in_msg); - in_msg = NULL; - - msg = tlsv1_server_handshake_write(conn, out_len); - -failed: - os_free(in_msg); - if (conn->alert_level) { - if (conn->state == FAILED) { - /* Avoid alert loops */ - wpa_printf(MSG_DEBUG, "TLSv1: Drop alert loop"); - os_free(msg); - return NULL; - } - conn->state = FAILED; - os_free(msg); - msg = tlsv1_server_send_alert(conn, conn->alert_level, - conn->alert_description, - out_len); - } - - return msg; -} - - -/** - * tlsv1_server_encrypt - Encrypt data into TLS tunnel - * @conn: TLSv1 server connection data from tlsv1_server_init() - * @in_data: Pointer to plaintext data to be encrypted - * @in_len: Input buffer length - * @out_data: Pointer to output buffer (encrypted TLS data) - * @out_len: Maximum out_data length - * Returns: Number of bytes written to out_data, -1 on failure - * - * This function is used after TLS handshake has been completed successfully to - * send data in the encrypted tunnel. - */ -int tlsv1_server_encrypt(struct tlsv1_server *conn, - const u8 *in_data, size_t in_len, - u8 *out_data, size_t out_len) -{ - size_t rlen; - - wpa_hexdump_key(MSG_MSGDUMP, "TLSv1: Plaintext AppData", - in_data, in_len); - - os_memcpy(out_data + TLS_RECORD_HEADER_LEN, in_data, in_len); - - if (tlsv1_record_send(&conn->rl, TLS_CONTENT_TYPE_APPLICATION_DATA, - out_data, out_len, in_len, &rlen) < 0) { - wpa_printf(MSG_DEBUG, "TLSv1: Failed to create a record"); - tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, - TLS_ALERT_INTERNAL_ERROR); - return -1; - } - - return rlen; -} - - -/** - * tlsv1_server_decrypt - Decrypt data from TLS tunnel - * @conn: TLSv1 server connection data from tlsv1_server_init() - * @in_data: Pointer to input buffer (encrypted TLS data) - * @in_len: Input buffer length - * @out_data: Pointer to output buffer (decrypted data from TLS tunnel) - * @out_len: Maximum out_data length - * Returns: Number of bytes written to out_data, -1 on failure - * - * This function is used after TLS handshake has been completed successfully to - * receive data from the encrypted tunnel. - */ -int tlsv1_server_decrypt(struct tlsv1_server *conn, - const u8 *in_data, size_t in_len, - u8 *out_data, size_t out_len) -{ - const u8 *in_end, *pos; - int res; - u8 alert, *out_end, *out_pos; - size_t olen; - - pos = in_data; - in_end = in_data + in_len; - out_pos = out_data; - out_end = out_data + out_len; - - while (pos < in_end) { - if (pos[0] != TLS_CONTENT_TYPE_APPLICATION_DATA) { - wpa_printf(MSG_DEBUG, "TLSv1: Unexpected content type " - "0x%x", pos[0]); - tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, - TLS_ALERT_UNEXPECTED_MESSAGE); - return -1; - } - - olen = out_end - out_pos; - res = tlsv1_record_receive(&conn->rl, pos, in_end - pos, - out_pos, &olen, &alert); - if (res < 0) { - wpa_printf(MSG_DEBUG, "TLSv1: Record layer processing " - "failed"); - tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, alert); - return -1; - } - out_pos += olen; - if (out_pos > out_end) { - wpa_printf(MSG_DEBUG, "TLSv1: Buffer not large enough " - "for processing the received record"); - tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, - TLS_ALERT_INTERNAL_ERROR); - return -1; - } - - pos += TLS_RECORD_HEADER_LEN + WPA_GET_BE16(pos + 3); - } - - return out_pos - out_data; -} - - -/** - * tlsv1_server_global_init - Initialize TLSv1 server - * Returns: 0 on success, -1 on failure - * - * This function must be called before using any other TLSv1 server functions. - */ -int tlsv1_server_global_init(void) -{ - return crypto_global_init(); -} - - -/** - * tlsv1_server_global_deinit - Deinitialize TLSv1 server - * - * This function can be used to deinitialize the TLSv1 server that was - * initialized by calling tlsv1_server_global_init(). No TLSv1 server functions - * can be called after this before calling tlsv1_server_global_init() again. - */ -void tlsv1_server_global_deinit(void) -{ - crypto_global_deinit(); -} - - -/** - * tlsv1_server_init - Initialize TLSv1 server connection - * @cred: Pointer to server credentials from tlsv1_server_cred_alloc() - * Returns: Pointer to TLSv1 server connection data or %NULL on failure - */ -struct tlsv1_server * tlsv1_server_init(struct tlsv1_credentials *cred) -{ - struct tlsv1_server *conn; - size_t count; - u16 *suites; - - conn = os_zalloc(sizeof(*conn)); - if (conn == NULL) - return NULL; - - conn->cred = cred; - - conn->state = CLIENT_HELLO; - - if (tls_verify_hash_init(&conn->verify) < 0) { - wpa_printf(MSG_DEBUG, "TLSv1: Failed to initialize verify " - "hash"); - os_free(conn); - return NULL; - } - - count = 0; - suites = conn->cipher_suites; -#ifndef CONFIG_CRYPTO_INTERNAL - suites[count++] = TLS_RSA_WITH_AES_256_CBC_SHA; -#endif /* CONFIG_CRYPTO_INTERNAL */ - suites[count++] = TLS_RSA_WITH_AES_128_CBC_SHA; - suites[count++] = TLS_RSA_WITH_3DES_EDE_CBC_SHA; - suites[count++] = TLS_RSA_WITH_RC4_128_SHA; - suites[count++] = TLS_RSA_WITH_RC4_128_MD5; - conn->num_cipher_suites = count; - - return conn; -} - - -static void tlsv1_server_clear_data(struct tlsv1_server *conn) -{ - tlsv1_record_set_cipher_suite(&conn->rl, TLS_NULL_WITH_NULL_NULL); - tlsv1_record_change_write_cipher(&conn->rl); - tlsv1_record_change_read_cipher(&conn->rl); - tls_verify_hash_free(&conn->verify); - - crypto_public_key_free(conn->client_rsa_key); - conn->client_rsa_key = NULL; - - os_free(conn->session_ticket); - conn->session_ticket = NULL; - conn->session_ticket_len = 0; - conn->use_session_ticket = 0; - - os_free(conn->dh_secret); - conn->dh_secret = NULL; - conn->dh_secret_len = 0; -} - - -/** - * tlsv1_server_deinit - Deinitialize TLSv1 server connection - * @conn: TLSv1 server connection data from tlsv1_server_init() - */ -void tlsv1_server_deinit(struct tlsv1_server *conn) -{ - tlsv1_server_clear_data(conn); - os_free(conn); -} - - -/** - * tlsv1_server_established - Check whether connection has been established - * @conn: TLSv1 server connection data from tlsv1_server_init() - * Returns: 1 if connection is established, 0 if not - */ -int tlsv1_server_established(struct tlsv1_server *conn) -{ - return conn->state == ESTABLISHED; -} - - -/** - * tlsv1_server_prf - Use TLS-PRF to derive keying material - * @conn: TLSv1 server connection data from tlsv1_server_init() - * @label: Label (e.g., description of the key) for PRF - * @server_random_first: seed is 0 = client_random|server_random, - * 1 = server_random|client_random - * @out: Buffer for output data from TLS-PRF - * @out_len: Length of the output buffer - * Returns: 0 on success, -1 on failure - */ -int tlsv1_server_prf(struct tlsv1_server *conn, const char *label, - int server_random_first, u8 *out, size_t out_len) -{ - u8 seed[2 * TLS_RANDOM_LEN]; - - if (conn->state != ESTABLISHED) - return -1; - - if (server_random_first) { - os_memcpy(seed, conn->server_random, TLS_RANDOM_LEN); - os_memcpy(seed + TLS_RANDOM_LEN, conn->client_random, - TLS_RANDOM_LEN); - } else { - os_memcpy(seed, conn->client_random, TLS_RANDOM_LEN); - os_memcpy(seed + TLS_RANDOM_LEN, conn->server_random, - TLS_RANDOM_LEN); - } - - return tls_prf(conn->master_secret, TLS_MASTER_SECRET_LEN, - label, seed, 2 * TLS_RANDOM_LEN, out, out_len); -} - - -/** - * tlsv1_server_get_cipher - Get current cipher name - * @conn: TLSv1 server connection data from tlsv1_server_init() - * @buf: Buffer for the cipher name - * @buflen: buf size - * Returns: 0 on success, -1 on failure - * - * Get the name of the currently used cipher. - */ -int tlsv1_server_get_cipher(struct tlsv1_server *conn, char *buf, - size_t buflen) -{ - char *cipher; - - switch (conn->rl.cipher_suite) { - case TLS_RSA_WITH_RC4_128_MD5: - cipher = "RC4-MD5"; - break; - case TLS_RSA_WITH_RC4_128_SHA: - cipher = "RC4-SHA"; - break; - case TLS_RSA_WITH_DES_CBC_SHA: - cipher = "DES-CBC-SHA"; - break; - case TLS_RSA_WITH_3DES_EDE_CBC_SHA: - cipher = "DES-CBC3-SHA"; - break; - case TLS_DH_anon_WITH_AES_128_CBC_SHA: - cipher = "ADH-AES-128-SHA"; - break; - case TLS_RSA_WITH_AES_256_CBC_SHA: - cipher = "AES-256-SHA"; - break; - case TLS_RSA_WITH_AES_128_CBC_SHA: - cipher = "AES-128-SHA"; - break; - default: - return -1; - } - - if (os_strlcpy(buf, cipher, buflen) >= buflen) - return -1; - return 0; -} - - -/** - * tlsv1_server_shutdown - Shutdown TLS connection - * @conn: TLSv1 server connection data from tlsv1_server_init() - * Returns: 0 on success, -1 on failure - */ -int tlsv1_server_shutdown(struct tlsv1_server *conn) -{ - conn->state = CLIENT_HELLO; - - if (tls_verify_hash_init(&conn->verify) < 0) { - wpa_printf(MSG_DEBUG, "TLSv1: Failed to re-initialize verify " - "hash"); - return -1; - } - - tlsv1_server_clear_data(conn); - - return 0; -} - - -/** - * tlsv1_server_resumed - Was session resumption used - * @conn: TLSv1 server connection data from tlsv1_server_init() - * Returns: 1 if current session used session resumption, 0 if not - */ -int tlsv1_server_resumed(struct tlsv1_server *conn) -{ - return 0; -} - - -/** - * tlsv1_server_get_keys - Get master key and random data from TLS connection - * @conn: TLSv1 server connection data from tlsv1_server_init() - * @keys: Structure of key/random data (filled on success) - * Returns: 0 on success, -1 on failure - */ -int tlsv1_server_get_keys(struct tlsv1_server *conn, struct tls_keys *keys) -{ - os_memset(keys, 0, sizeof(*keys)); - if (conn->state == CLIENT_HELLO) - return -1; - - keys->client_random = conn->client_random; - keys->client_random_len = TLS_RANDOM_LEN; - - if (conn->state != SERVER_HELLO) { - keys->server_random = conn->server_random; - keys->server_random_len = TLS_RANDOM_LEN; - keys->master_key = conn->master_secret; - keys->master_key_len = TLS_MASTER_SECRET_LEN; - } - - return 0; -} - - -/** - * tlsv1_server_get_keyblock_size - Get TLS key_block size - * @conn: TLSv1 server connection data from tlsv1_server_init() - * Returns: Size of the key_block for the negotiated cipher suite or -1 on - * failure - */ -int tlsv1_server_get_keyblock_size(struct tlsv1_server *conn) -{ - if (conn->state == CLIENT_HELLO || conn->state == SERVER_HELLO) - return -1; - - return 2 * (conn->rl.hash_size + conn->rl.key_material_len + - conn->rl.iv_size); -} - - -/** - * tlsv1_server_set_cipher_list - Configure acceptable cipher suites - * @conn: TLSv1 server connection data from tlsv1_server_init() - * @ciphers: Zero (TLS_CIPHER_NONE) terminated list of allowed ciphers - * (TLS_CIPHER_*). - * Returns: 0 on success, -1 on failure - */ -int tlsv1_server_set_cipher_list(struct tlsv1_server *conn, u8 *ciphers) -{ - size_t count; - u16 *suites; - - /* TODO: implement proper configuration of cipher suites */ - if (ciphers[0] == TLS_CIPHER_ANON_DH_AES128_SHA) { - count = 0; - suites = conn->cipher_suites; -#ifndef CONFIG_CRYPTO_INTERNAL - suites[count++] = TLS_RSA_WITH_AES_256_CBC_SHA; -#endif /* CONFIG_CRYPTO_INTERNAL */ - suites[count++] = TLS_RSA_WITH_AES_128_CBC_SHA; - suites[count++] = TLS_RSA_WITH_3DES_EDE_CBC_SHA; - suites[count++] = TLS_RSA_WITH_RC4_128_SHA; - suites[count++] = TLS_RSA_WITH_RC4_128_MD5; -#ifndef CONFIG_CRYPTO_INTERNAL - suites[count++] = TLS_DH_anon_WITH_AES_256_CBC_SHA; -#endif /* CONFIG_CRYPTO_INTERNAL */ - suites[count++] = TLS_DH_anon_WITH_AES_128_CBC_SHA; - suites[count++] = TLS_DH_anon_WITH_3DES_EDE_CBC_SHA; - suites[count++] = TLS_DH_anon_WITH_RC4_128_MD5; - suites[count++] = TLS_DH_anon_WITH_DES_CBC_SHA; - conn->num_cipher_suites = count; - } - - return 0; -} - - -int tlsv1_server_set_verify(struct tlsv1_server *conn, int verify_peer) -{ - conn->verify_peer = verify_peer; - return 0; -} - - -void tlsv1_server_set_session_ticket_cb(struct tlsv1_server *conn, - tlsv1_server_session_ticket_cb cb, - void *ctx) -{ - wpa_printf(MSG_DEBUG, "TLSv1: SessionTicket callback set %p (ctx %p)", - cb, ctx); - conn->session_ticket_cb = cb; - conn->session_ticket_cb_ctx = ctx; -} diff --git a/hostapd-0.8/src/tls/tlsv1_server.h b/hostapd-0.8/src/tls/tlsv1_server.h deleted file mode 100644 index 00c536c..0000000 --- a/hostapd-0.8/src/tls/tlsv1_server.h +++ /dev/null @@ -1,54 +0,0 @@ -/* - * TLSv1 server (RFC 2246) - * Copyright (c) 2006-2007, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#ifndef TLSV1_SERVER_H -#define TLSV1_SERVER_H - -#include "tlsv1_cred.h" - -struct tlsv1_server; - -int tlsv1_server_global_init(void); -void tlsv1_server_global_deinit(void); -struct tlsv1_server * tlsv1_server_init(struct tlsv1_credentials *cred); -void tlsv1_server_deinit(struct tlsv1_server *conn); -int tlsv1_server_established(struct tlsv1_server *conn); -int tlsv1_server_prf(struct tlsv1_server *conn, const char *label, - int server_random_first, u8 *out, size_t out_len); -u8 * tlsv1_server_handshake(struct tlsv1_server *conn, - const u8 *in_data, size_t in_len, size_t *out_len); -int tlsv1_server_encrypt(struct tlsv1_server *conn, - const u8 *in_data, size_t in_len, - u8 *out_data, size_t out_len); -int tlsv1_server_decrypt(struct tlsv1_server *conn, - const u8 *in_data, size_t in_len, - u8 *out_data, size_t out_len); -int tlsv1_server_get_cipher(struct tlsv1_server *conn, char *buf, - size_t buflen); -int tlsv1_server_shutdown(struct tlsv1_server *conn); -int tlsv1_server_resumed(struct tlsv1_server *conn); -int tlsv1_server_get_keys(struct tlsv1_server *conn, struct tls_keys *keys); -int tlsv1_server_get_keyblock_size(struct tlsv1_server *conn); -int tlsv1_server_set_cipher_list(struct tlsv1_server *conn, u8 *ciphers); -int tlsv1_server_set_verify(struct tlsv1_server *conn, int verify_peer); - -typedef int (*tlsv1_server_session_ticket_cb) -(void *ctx, const u8 *ticket, size_t len, const u8 *client_random, - const u8 *server_random, u8 *master_secret); - -void tlsv1_server_set_session_ticket_cb(struct tlsv1_server *conn, - tlsv1_server_session_ticket_cb cb, - void *ctx); - -#endif /* TLSV1_SERVER_H */ diff --git a/hostapd-0.8/src/tls/tlsv1_server_i.h b/hostapd-0.8/src/tls/tlsv1_server_i.h deleted file mode 100644 index d11ea75..0000000 --- a/hostapd-0.8/src/tls/tlsv1_server_i.h +++ /dev/null @@ -1,77 +0,0 @@ -/* - * TLSv1 server - internal structures - * Copyright (c) 2006-2007, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#ifndef TLSV1_SERVER_I_H -#define TLSV1_SERVER_I_H - -struct tlsv1_server { - enum { - CLIENT_HELLO, SERVER_HELLO, SERVER_CERTIFICATE, - SERVER_KEY_EXCHANGE, SERVER_CERTIFICATE_REQUEST, - SERVER_HELLO_DONE, CLIENT_CERTIFICATE, CLIENT_KEY_EXCHANGE, - CERTIFICATE_VERIFY, CHANGE_CIPHER_SPEC, CLIENT_FINISHED, - SERVER_CHANGE_CIPHER_SPEC, SERVER_FINISHED, - ESTABLISHED, FAILED - } state; - - struct tlsv1_record_layer rl; - - u8 session_id[TLS_SESSION_ID_MAX_LEN]; - size_t session_id_len; - u8 client_random[TLS_RANDOM_LEN]; - u8 server_random[TLS_RANDOM_LEN]; - u8 master_secret[TLS_MASTER_SECRET_LEN]; - - u8 alert_level; - u8 alert_description; - - struct crypto_public_key *client_rsa_key; - - struct tls_verify_hash verify; - -#define MAX_CIPHER_COUNT 30 - u16 cipher_suites[MAX_CIPHER_COUNT]; - size_t num_cipher_suites; - - u16 cipher_suite; - - struct tlsv1_credentials *cred; - - int verify_peer; - u16 client_version; - - u8 *session_ticket; - size_t session_ticket_len; - - tlsv1_server_session_ticket_cb session_ticket_cb; - void *session_ticket_cb_ctx; - - int use_session_ticket; - - u8 *dh_secret; - size_t dh_secret_len; -}; - - -void tlsv1_server_alert(struct tlsv1_server *conn, u8 level, u8 description); -int tlsv1_server_derive_keys(struct tlsv1_server *conn, - const u8 *pre_master_secret, - size_t pre_master_secret_len); -u8 * tlsv1_server_handshake_write(struct tlsv1_server *conn, size_t *out_len); -u8 * tlsv1_server_send_alert(struct tlsv1_server *conn, u8 level, - u8 description, size_t *out_len); -int tlsv1_server_process_handshake(struct tlsv1_server *conn, u8 ct, - const u8 *buf, size_t *len); - -#endif /* TLSV1_SERVER_I_H */ diff --git a/hostapd-0.8/src/tls/tlsv1_server_read.c b/hostapd-0.8/src/tls/tlsv1_server_read.c deleted file mode 100644 index 49e811f..0000000 --- a/hostapd-0.8/src/tls/tlsv1_server_read.c +++ /dev/null @@ -1,1134 +0,0 @@ -/* - * TLSv1 server - read handshake message - * Copyright (c) 2006-2007, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#include "includes.h" - -#include "common.h" -#include "crypto/md5.h" -#include "crypto/sha1.h" -#include "crypto/tls.h" -#include "x509v3.h" -#include "tlsv1_common.h" -#include "tlsv1_record.h" -#include "tlsv1_server.h" -#include "tlsv1_server_i.h" - - -static int tls_process_client_key_exchange(struct tlsv1_server *conn, u8 ct, - const u8 *in_data, size_t *in_len); -static int tls_process_change_cipher_spec(struct tlsv1_server *conn, - u8 ct, const u8 *in_data, - size_t *in_len); - - -static int tls_process_client_hello(struct tlsv1_server *conn, u8 ct, - const u8 *in_data, size_t *in_len) -{ - const u8 *pos, *end, *c; - size_t left, len, i, j; - u16 cipher_suite; - u16 num_suites; - int compr_null_found; - u16 ext_type, ext_len; - - if (ct != TLS_CONTENT_TYPE_HANDSHAKE) { - wpa_printf(MSG_DEBUG, "TLSv1: Expected Handshake; " - "received content type 0x%x", ct); - tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, - TLS_ALERT_UNEXPECTED_MESSAGE); - return -1; - } - - pos = in_data; - left = *in_len; - - if (left < 4) - goto decode_error; - - /* HandshakeType msg_type */ - if (*pos != TLS_HANDSHAKE_TYPE_CLIENT_HELLO) { - wpa_printf(MSG_DEBUG, "TLSv1: Received unexpected handshake " - "message %d (expected ClientHello)", *pos); - tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, - TLS_ALERT_UNEXPECTED_MESSAGE); - return -1; - } - wpa_printf(MSG_DEBUG, "TLSv1: Received ClientHello"); - pos++; - /* uint24 length */ - len = WPA_GET_BE24(pos); - pos += 3; - left -= 4; - - if (len > left) - goto decode_error; - - /* body - ClientHello */ - - wpa_hexdump(MSG_MSGDUMP, "TLSv1: ClientHello", pos, len); - end = pos + len; - - /* ProtocolVersion client_version */ - if (end - pos < 2) - goto decode_error; - conn->client_version = WPA_GET_BE16(pos); - wpa_printf(MSG_DEBUG, "TLSv1: Client version %d.%d", - conn->client_version >> 8, conn->client_version & 0xff); - if (conn->client_version < TLS_VERSION) { - wpa_printf(MSG_DEBUG, "TLSv1: Unexpected protocol version in " - "ClientHello"); - tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, - TLS_ALERT_PROTOCOL_VERSION); - return -1; - } - pos += 2; - - /* Random random */ - if (end - pos < TLS_RANDOM_LEN) - goto decode_error; - - os_memcpy(conn->client_random, pos, TLS_RANDOM_LEN); - pos += TLS_RANDOM_LEN; - wpa_hexdump(MSG_MSGDUMP, "TLSv1: client_random", - conn->client_random, TLS_RANDOM_LEN); - - /* SessionID session_id */ - if (end - pos < 1) - goto decode_error; - if (end - pos < 1 + *pos || *pos > TLS_SESSION_ID_MAX_LEN) - goto decode_error; - wpa_hexdump(MSG_MSGDUMP, "TLSv1: client session_id", pos + 1, *pos); - pos += 1 + *pos; - /* TODO: add support for session resumption */ - - /* CipherSuite cipher_suites<2..2^16-1> */ - if (end - pos < 2) - goto decode_error; - num_suites = WPA_GET_BE16(pos); - pos += 2; - if (end - pos < num_suites) - goto decode_error; - wpa_hexdump(MSG_MSGDUMP, "TLSv1: client cipher suites", - pos, num_suites); - if (num_suites & 1) - goto decode_error; - num_suites /= 2; - - cipher_suite = 0; - for (i = 0; !cipher_suite && i < conn->num_cipher_suites; i++) { - c = pos; - for (j = 0; j < num_suites; j++) { - u16 tmp = WPA_GET_BE16(c); - c += 2; - if (!cipher_suite && tmp == conn->cipher_suites[i]) { - cipher_suite = tmp; - break; - } - } - } - pos += num_suites * 2; - if (!cipher_suite) { - wpa_printf(MSG_INFO, "TLSv1: No supported cipher suite " - "available"); - tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, - TLS_ALERT_ILLEGAL_PARAMETER); - return -1; - } - - if (tlsv1_record_set_cipher_suite(&conn->rl, cipher_suite) < 0) { - wpa_printf(MSG_DEBUG, "TLSv1: Failed to set CipherSuite for " - "record layer"); - tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, - TLS_ALERT_INTERNAL_ERROR); - return -1; - } - - conn->cipher_suite = cipher_suite; - - /* CompressionMethod compression_methods<1..2^8-1> */ - if (end - pos < 1) - goto decode_error; - num_suites = *pos++; - if (end - pos < num_suites) - goto decode_error; - wpa_hexdump(MSG_MSGDUMP, "TLSv1: client compression_methods", - pos, num_suites); - compr_null_found = 0; - for (i = 0; i < num_suites; i++) { - if (*pos++ == TLS_COMPRESSION_NULL) - compr_null_found = 1; - } - if (!compr_null_found) { - wpa_printf(MSG_INFO, "TLSv1: Client does not accept NULL " - "compression"); - tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, - TLS_ALERT_ILLEGAL_PARAMETER); - return -1; - } - - if (end - pos == 1) { - wpa_printf(MSG_DEBUG, "TLSv1: Unexpected extra octet in the " - "end of ClientHello: 0x%02x", *pos); - goto decode_error; - } - - if (end - pos >= 2) { - /* Extension client_hello_extension_list<0..2^16-1> */ - ext_len = WPA_GET_BE16(pos); - pos += 2; - - wpa_printf(MSG_DEBUG, "TLSv1: %u bytes of ClientHello " - "extensions", ext_len); - if (end - pos != ext_len) { - wpa_printf(MSG_DEBUG, "TLSv1: Invalid ClientHello " - "extension list length %u (expected %u)", - ext_len, (unsigned int) (end - pos)); - goto decode_error; - } - - /* - * struct { - * ExtensionType extension_type (0..65535) - * opaque extension_data<0..2^16-1> - * } Extension; - */ - - while (pos < end) { - if (end - pos < 2) { - wpa_printf(MSG_DEBUG, "TLSv1: Invalid " - "extension_type field"); - goto decode_error; - } - - ext_type = WPA_GET_BE16(pos); - pos += 2; - - if (end - pos < 2) { - wpa_printf(MSG_DEBUG, "TLSv1: Invalid " - "extension_data length field"); - goto decode_error; - } - - ext_len = WPA_GET_BE16(pos); - pos += 2; - - if (end - pos < ext_len) { - wpa_printf(MSG_DEBUG, "TLSv1: Invalid " - "extension_data field"); - goto decode_error; - } - - wpa_printf(MSG_DEBUG, "TLSv1: ClientHello Extension " - "type %u", ext_type); - wpa_hexdump(MSG_MSGDUMP, "TLSv1: ClientHello " - "Extension data", pos, ext_len); - - if (ext_type == TLS_EXT_SESSION_TICKET) { - os_free(conn->session_ticket); - conn->session_ticket = os_malloc(ext_len); - if (conn->session_ticket) { - os_memcpy(conn->session_ticket, pos, - ext_len); - conn->session_ticket_len = ext_len; - } - } - - pos += ext_len; - } - } - - *in_len = end - in_data; - - wpa_printf(MSG_DEBUG, "TLSv1: ClientHello OK - proceed to " - "ServerHello"); - conn->state = SERVER_HELLO; - - return 0; - -decode_error: - wpa_printf(MSG_DEBUG, "TLSv1: Failed to decode ClientHello"); - tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, - TLS_ALERT_DECODE_ERROR); - return -1; -} - - -static int tls_process_certificate(struct tlsv1_server *conn, u8 ct, - const u8 *in_data, size_t *in_len) -{ - const u8 *pos, *end; - size_t left, len, list_len, cert_len, idx; - u8 type; - struct x509_certificate *chain = NULL, *last = NULL, *cert; - int reason; - - if (ct != TLS_CONTENT_TYPE_HANDSHAKE) { - wpa_printf(MSG_DEBUG, "TLSv1: Expected Handshake; " - "received content type 0x%x", ct); - tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, - TLS_ALERT_UNEXPECTED_MESSAGE); - return -1; - } - - pos = in_data; - left = *in_len; - - if (left < 4) { - wpa_printf(MSG_DEBUG, "TLSv1: Too short Certificate message " - "(len=%lu)", (unsigned long) left); - tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, - TLS_ALERT_DECODE_ERROR); - return -1; - } - - type = *pos++; - len = WPA_GET_BE24(pos); - pos += 3; - left -= 4; - - if (len > left) { - wpa_printf(MSG_DEBUG, "TLSv1: Unexpected Certificate message " - "length (len=%lu != left=%lu)", - (unsigned long) len, (unsigned long) left); - tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, - TLS_ALERT_DECODE_ERROR); - return -1; - } - - if (type == TLS_HANDSHAKE_TYPE_CLIENT_KEY_EXCHANGE) { - if (conn->verify_peer) { - wpa_printf(MSG_DEBUG, "TLSv1: Client did not include " - "Certificate"); - tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, - TLS_ALERT_UNEXPECTED_MESSAGE); - return -1; - } - - return tls_process_client_key_exchange(conn, ct, in_data, - in_len); - } - if (type != TLS_HANDSHAKE_TYPE_CERTIFICATE) { - wpa_printf(MSG_DEBUG, "TLSv1: Received unexpected handshake " - "message %d (expected Certificate/" - "ClientKeyExchange)", type); - tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, - TLS_ALERT_UNEXPECTED_MESSAGE); - return -1; - } - - wpa_printf(MSG_DEBUG, - "TLSv1: Received Certificate (certificate_list len %lu)", - (unsigned long) len); - - /* - * opaque ASN.1Cert<2^24-1>; - * - * struct { - * ASN.1Cert certificate_list<1..2^24-1>; - * } Certificate; - */ - - end = pos + len; - - if (end - pos < 3) { - wpa_printf(MSG_DEBUG, "TLSv1: Too short Certificate " - "(left=%lu)", (unsigned long) left); - tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, - TLS_ALERT_DECODE_ERROR); - return -1; - } - - list_len = WPA_GET_BE24(pos); - pos += 3; - - if ((size_t) (end - pos) != list_len) { - wpa_printf(MSG_DEBUG, "TLSv1: Unexpected certificate_list " - "length (len=%lu left=%lu)", - (unsigned long) list_len, - (unsigned long) (end - pos)); - tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, - TLS_ALERT_DECODE_ERROR); - return -1; - } - - idx = 0; - while (pos < end) { - if (end - pos < 3) { - wpa_printf(MSG_DEBUG, "TLSv1: Failed to parse " - "certificate_list"); - tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, - TLS_ALERT_DECODE_ERROR); - x509_certificate_chain_free(chain); - return -1; - } - - cert_len = WPA_GET_BE24(pos); - pos += 3; - - if ((size_t) (end - pos) < cert_len) { - wpa_printf(MSG_DEBUG, "TLSv1: Unexpected certificate " - "length (len=%lu left=%lu)", - (unsigned long) cert_len, - (unsigned long) (end - pos)); - tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, - TLS_ALERT_DECODE_ERROR); - x509_certificate_chain_free(chain); - return -1; - } - - wpa_printf(MSG_DEBUG, "TLSv1: Certificate %lu (len %lu)", - (unsigned long) idx, (unsigned long) cert_len); - - if (idx == 0) { - crypto_public_key_free(conn->client_rsa_key); - if (tls_parse_cert(pos, cert_len, - &conn->client_rsa_key)) { - wpa_printf(MSG_DEBUG, "TLSv1: Failed to parse " - "the certificate"); - tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, - TLS_ALERT_BAD_CERTIFICATE); - x509_certificate_chain_free(chain); - return -1; - } - } - - cert = x509_certificate_parse(pos, cert_len); - if (cert == NULL) { - wpa_printf(MSG_DEBUG, "TLSv1: Failed to parse " - "the certificate"); - tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, - TLS_ALERT_BAD_CERTIFICATE); - x509_certificate_chain_free(chain); - return -1; - } - - if (last == NULL) - chain = cert; - else - last->next = cert; - last = cert; - - idx++; - pos += cert_len; - } - - if (x509_certificate_chain_validate(conn->cred->trusted_certs, chain, - &reason) < 0) { - int tls_reason; - wpa_printf(MSG_DEBUG, "TLSv1: Server certificate chain " - "validation failed (reason=%d)", reason); - switch (reason) { - case X509_VALIDATE_BAD_CERTIFICATE: - tls_reason = TLS_ALERT_BAD_CERTIFICATE; - break; - case X509_VALIDATE_UNSUPPORTED_CERTIFICATE: - tls_reason = TLS_ALERT_UNSUPPORTED_CERTIFICATE; - break; - case X509_VALIDATE_CERTIFICATE_REVOKED: - tls_reason = TLS_ALERT_CERTIFICATE_REVOKED; - break; - case X509_VALIDATE_CERTIFICATE_EXPIRED: - tls_reason = TLS_ALERT_CERTIFICATE_EXPIRED; - break; - case X509_VALIDATE_CERTIFICATE_UNKNOWN: - tls_reason = TLS_ALERT_CERTIFICATE_UNKNOWN; - break; - case X509_VALIDATE_UNKNOWN_CA: - tls_reason = TLS_ALERT_UNKNOWN_CA; - break; - default: - tls_reason = TLS_ALERT_BAD_CERTIFICATE; - break; - } - tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, tls_reason); - x509_certificate_chain_free(chain); - return -1; - } - - x509_certificate_chain_free(chain); - - *in_len = end - in_data; - - conn->state = CLIENT_KEY_EXCHANGE; - - return 0; -} - - -static int tls_process_client_key_exchange_rsa( - struct tlsv1_server *conn, const u8 *pos, const u8 *end) -{ - u8 *out; - size_t outlen, outbuflen; - u16 encr_len; - int res; - int use_random = 0; - - if (end - pos < 2) { - tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, - TLS_ALERT_DECODE_ERROR); - return -1; - } - - encr_len = WPA_GET_BE16(pos); - pos += 2; - - outbuflen = outlen = end - pos; - out = os_malloc(outlen >= TLS_PRE_MASTER_SECRET_LEN ? - outlen : TLS_PRE_MASTER_SECRET_LEN); - if (out == NULL) { - tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, - TLS_ALERT_INTERNAL_ERROR); - return -1; - } - - /* - * struct { - * ProtocolVersion client_version; - * opaque random[46]; - * } PreMasterSecret; - * - * struct { - * public-key-encrypted PreMasterSecret pre_master_secret; - * } EncryptedPreMasterSecret; - */ - - /* - * Note: To avoid Bleichenbacher attack, we do not report decryption or - * parsing errors from EncryptedPreMasterSecret processing to the - * client. Instead, a random pre-master secret is used to force the - * handshake to fail. - */ - - if (crypto_private_key_decrypt_pkcs1_v15(conn->cred->key, - pos, end - pos, - out, &outlen) < 0) { - wpa_printf(MSG_DEBUG, "TLSv1: Failed to decrypt " - "PreMasterSecret (encr_len=%d outlen=%lu)", - (int) (end - pos), (unsigned long) outlen); - use_random = 1; - } - - if (outlen != TLS_PRE_MASTER_SECRET_LEN) { - wpa_printf(MSG_DEBUG, "TLSv1: Unexpected PreMasterSecret " - "length %lu", (unsigned long) outlen); - use_random = 1; - } - - if (WPA_GET_BE16(out) != conn->client_version) { - wpa_printf(MSG_DEBUG, "TLSv1: Client version in " - "ClientKeyExchange does not match with version in " - "ClientHello"); - use_random = 1; - } - - if (use_random) { - wpa_printf(MSG_DEBUG, "TLSv1: Using random premaster secret " - "to avoid revealing information about private key"); - outlen = TLS_PRE_MASTER_SECRET_LEN; - if (os_get_random(out, outlen)) { - wpa_printf(MSG_DEBUG, "TLSv1: Failed to get random " - "data"); - tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, - TLS_ALERT_INTERNAL_ERROR); - os_free(out); - return -1; - } - } - - res = tlsv1_server_derive_keys(conn, out, outlen); - - /* Clear the pre-master secret since it is not needed anymore */ - os_memset(out, 0, outbuflen); - os_free(out); - - if (res) { - wpa_printf(MSG_DEBUG, "TLSv1: Failed to derive keys"); - tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, - TLS_ALERT_INTERNAL_ERROR); - return -1; - } - - return 0; -} - - -static int tls_process_client_key_exchange_dh_anon( - struct tlsv1_server *conn, const u8 *pos, const u8 *end) -{ - const u8 *dh_yc; - u16 dh_yc_len; - u8 *shared; - size_t shared_len; - int res; - - /* - * struct { - * select (PublicValueEncoding) { - * case implicit: struct { }; - * case explicit: opaque dh_Yc<1..2^16-1>; - * } dh_public; - * } ClientDiffieHellmanPublic; - */ - - wpa_hexdump(MSG_MSGDUMP, "TLSv1: ClientDiffieHellmanPublic", - pos, end - pos); - - if (end == pos) { - wpa_printf(MSG_DEBUG, "TLSv1: Implicit public value encoding " - "not supported"); - tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, - TLS_ALERT_INTERNAL_ERROR); - return -1; - } - - if (end - pos < 3) { - wpa_printf(MSG_DEBUG, "TLSv1: Invalid client public value " - "length"); - tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, - TLS_ALERT_DECODE_ERROR); - return -1; - } - - dh_yc_len = WPA_GET_BE16(pos); - dh_yc = pos + 2; - - if (dh_yc + dh_yc_len > end) { - wpa_printf(MSG_DEBUG, "TLSv1: Client public value overflow " - "(length %d)", dh_yc_len); - tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, - TLS_ALERT_DECODE_ERROR); - return -1; - } - - wpa_hexdump(MSG_DEBUG, "TLSv1: DH Yc (client's public value)", - dh_yc, dh_yc_len); - - if (conn->cred == NULL || conn->cred->dh_p == NULL || - conn->dh_secret == NULL) { - wpa_printf(MSG_DEBUG, "TLSv1: No DH parameters available"); - tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, - TLS_ALERT_INTERNAL_ERROR); - return -1; - } - - shared_len = conn->cred->dh_p_len; - shared = os_malloc(shared_len); - if (shared == NULL) { - wpa_printf(MSG_DEBUG, "TLSv1: Could not allocate memory for " - "DH"); - tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, - TLS_ALERT_INTERNAL_ERROR); - return -1; - } - - /* shared = Yc^secret mod p */ - if (crypto_mod_exp(dh_yc, dh_yc_len, conn->dh_secret, - conn->dh_secret_len, - conn->cred->dh_p, conn->cred->dh_p_len, - shared, &shared_len)) { - os_free(shared); - tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, - TLS_ALERT_INTERNAL_ERROR); - return -1; - } - wpa_hexdump_key(MSG_DEBUG, "TLSv1: Shared secret from DH key exchange", - shared, shared_len); - - os_memset(conn->dh_secret, 0, conn->dh_secret_len); - os_free(conn->dh_secret); - conn->dh_secret = NULL; - - res = tlsv1_server_derive_keys(conn, shared, shared_len); - - /* Clear the pre-master secret since it is not needed anymore */ - os_memset(shared, 0, shared_len); - os_free(shared); - - if (res) { - wpa_printf(MSG_DEBUG, "TLSv1: Failed to derive keys"); - tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, - TLS_ALERT_INTERNAL_ERROR); - return -1; - } - - return 0; -} - - -static int tls_process_client_key_exchange(struct tlsv1_server *conn, u8 ct, - const u8 *in_data, size_t *in_len) -{ - const u8 *pos, *end; - size_t left, len; - u8 type; - tls_key_exchange keyx; - const struct tls_cipher_suite *suite; - - if (ct != TLS_CONTENT_TYPE_HANDSHAKE) { - wpa_printf(MSG_DEBUG, "TLSv1: Expected Handshake; " - "received content type 0x%x", ct); - tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, - TLS_ALERT_UNEXPECTED_MESSAGE); - return -1; - } - - pos = in_data; - left = *in_len; - - if (left < 4) { - wpa_printf(MSG_DEBUG, "TLSv1: Too short ClientKeyExchange " - "(Left=%lu)", (unsigned long) left); - tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, - TLS_ALERT_DECODE_ERROR); - return -1; - } - - type = *pos++; - len = WPA_GET_BE24(pos); - pos += 3; - left -= 4; - - if (len > left) { - wpa_printf(MSG_DEBUG, "TLSv1: Mismatch in ClientKeyExchange " - "length (len=%lu != left=%lu)", - (unsigned long) len, (unsigned long) left); - tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, - TLS_ALERT_DECODE_ERROR); - return -1; - } - - end = pos + len; - - if (type != TLS_HANDSHAKE_TYPE_CLIENT_KEY_EXCHANGE) { - wpa_printf(MSG_DEBUG, "TLSv1: Received unexpected handshake " - "message %d (expected ClientKeyExchange)", type); - tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, - TLS_ALERT_UNEXPECTED_MESSAGE); - return -1; - } - - wpa_printf(MSG_DEBUG, "TLSv1: Received ClientKeyExchange"); - - wpa_hexdump(MSG_DEBUG, "TLSv1: ClientKeyExchange", pos, len); - - suite = tls_get_cipher_suite(conn->rl.cipher_suite); - if (suite == NULL) - keyx = TLS_KEY_X_NULL; - else - keyx = suite->key_exchange; - - if (keyx == TLS_KEY_X_DH_anon && - tls_process_client_key_exchange_dh_anon(conn, pos, end) < 0) - return -1; - - if (keyx != TLS_KEY_X_DH_anon && - tls_process_client_key_exchange_rsa(conn, pos, end) < 0) - return -1; - - *in_len = end - in_data; - - conn->state = CERTIFICATE_VERIFY; - - return 0; -} - - -static int tls_process_certificate_verify(struct tlsv1_server *conn, u8 ct, - const u8 *in_data, size_t *in_len) -{ - const u8 *pos, *end; - size_t left, len; - u8 type; - size_t hlen, buflen; - u8 hash[MD5_MAC_LEN + SHA1_MAC_LEN], *hpos, *buf; - enum { SIGN_ALG_RSA, SIGN_ALG_DSA } alg = SIGN_ALG_RSA; - u16 slen; - - if (ct == TLS_CONTENT_TYPE_CHANGE_CIPHER_SPEC) { - if (conn->verify_peer) { - wpa_printf(MSG_DEBUG, "TLSv1: Client did not include " - "CertificateVerify"); - tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, - TLS_ALERT_UNEXPECTED_MESSAGE); - return -1; - } - - return tls_process_change_cipher_spec(conn, ct, in_data, - in_len); - } - - if (ct != TLS_CONTENT_TYPE_HANDSHAKE) { - wpa_printf(MSG_DEBUG, "TLSv1: Expected Handshake; " - "received content type 0x%x", ct); - tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, - TLS_ALERT_UNEXPECTED_MESSAGE); - return -1; - } - - pos = in_data; - left = *in_len; - - if (left < 4) { - wpa_printf(MSG_DEBUG, "TLSv1: Too short CertificateVerify " - "message (len=%lu)", (unsigned long) left); - tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, - TLS_ALERT_DECODE_ERROR); - return -1; - } - - type = *pos++; - len = WPA_GET_BE24(pos); - pos += 3; - left -= 4; - - if (len > left) { - wpa_printf(MSG_DEBUG, "TLSv1: Unexpected CertificateVerify " - "message length (len=%lu != left=%lu)", - (unsigned long) len, (unsigned long) left); - tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, - TLS_ALERT_DECODE_ERROR); - return -1; - } - - end = pos + len; - - if (type != TLS_HANDSHAKE_TYPE_CERTIFICATE_VERIFY) { - wpa_printf(MSG_DEBUG, "TLSv1: Received unexpected handshake " - "message %d (expected CertificateVerify)", type); - tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, - TLS_ALERT_UNEXPECTED_MESSAGE); - return -1; - } - - wpa_printf(MSG_DEBUG, "TLSv1: Received CertificateVerify"); - - /* - * struct { - * Signature signature; - * } CertificateVerify; - */ - - hpos = hash; - - if (alg == SIGN_ALG_RSA) { - hlen = MD5_MAC_LEN; - if (conn->verify.md5_cert == NULL || - crypto_hash_finish(conn->verify.md5_cert, hpos, &hlen) < 0) - { - tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, - TLS_ALERT_INTERNAL_ERROR); - conn->verify.md5_cert = NULL; - crypto_hash_finish(conn->verify.sha1_cert, NULL, NULL); - conn->verify.sha1_cert = NULL; - return -1; - } - hpos += MD5_MAC_LEN; - } else - crypto_hash_finish(conn->verify.md5_cert, NULL, NULL); - - conn->verify.md5_cert = NULL; - hlen = SHA1_MAC_LEN; - if (conn->verify.sha1_cert == NULL || - crypto_hash_finish(conn->verify.sha1_cert, hpos, &hlen) < 0) { - conn->verify.sha1_cert = NULL; - tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, - TLS_ALERT_INTERNAL_ERROR); - return -1; - } - conn->verify.sha1_cert = NULL; - - if (alg == SIGN_ALG_RSA) - hlen += MD5_MAC_LEN; - - wpa_hexdump(MSG_MSGDUMP, "TLSv1: CertificateVerify hash", hash, hlen); - - if (end - pos < 2) { - tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, - TLS_ALERT_DECODE_ERROR); - return -1; - } - slen = WPA_GET_BE16(pos); - pos += 2; - if (end - pos < slen) { - tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, - TLS_ALERT_DECODE_ERROR); - return -1; - } - - wpa_hexdump(MSG_MSGDUMP, "TLSv1: Signature", pos, end - pos); - if (conn->client_rsa_key == NULL) { - wpa_printf(MSG_DEBUG, "TLSv1: No client public key to verify " - "signature"); - tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, - TLS_ALERT_INTERNAL_ERROR); - return -1; - } - - buflen = end - pos; - buf = os_malloc(end - pos); - if (crypto_public_key_decrypt_pkcs1(conn->client_rsa_key, - pos, end - pos, buf, &buflen) < 0) - { - wpa_printf(MSG_DEBUG, "TLSv1: Failed to decrypt signature"); - os_free(buf); - tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, - TLS_ALERT_DECRYPT_ERROR); - return -1; - } - - wpa_hexdump_key(MSG_MSGDUMP, "TLSv1: Decrypted Signature", - buf, buflen); - - if (buflen != hlen || os_memcmp(buf, hash, buflen) != 0) { - wpa_printf(MSG_DEBUG, "TLSv1: Invalid Signature in " - "CertificateVerify - did not match with calculated " - "hash"); - os_free(buf); - tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, - TLS_ALERT_DECRYPT_ERROR); - return -1; - } - - os_free(buf); - - *in_len = end - in_data; - - conn->state = CHANGE_CIPHER_SPEC; - - return 0; -} - - -static int tls_process_change_cipher_spec(struct tlsv1_server *conn, - u8 ct, const u8 *in_data, - size_t *in_len) -{ - const u8 *pos; - size_t left; - - if (ct != TLS_CONTENT_TYPE_CHANGE_CIPHER_SPEC) { - wpa_printf(MSG_DEBUG, "TLSv1: Expected ChangeCipherSpec; " - "received content type 0x%x", ct); - tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, - TLS_ALERT_UNEXPECTED_MESSAGE); - return -1; - } - - pos = in_data; - left = *in_len; - - if (left < 1) { - wpa_printf(MSG_DEBUG, "TLSv1: Too short ChangeCipherSpec"); - tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, - TLS_ALERT_DECODE_ERROR); - return -1; - } - - if (*pos != TLS_CHANGE_CIPHER_SPEC) { - wpa_printf(MSG_DEBUG, "TLSv1: Expected ChangeCipherSpec; " - "received data 0x%x", *pos); - tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, - TLS_ALERT_UNEXPECTED_MESSAGE); - return -1; - } - - wpa_printf(MSG_DEBUG, "TLSv1: Received ChangeCipherSpec"); - if (tlsv1_record_change_read_cipher(&conn->rl) < 0) { - wpa_printf(MSG_DEBUG, "TLSv1: Failed to change read cipher " - "for record layer"); - tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, - TLS_ALERT_INTERNAL_ERROR); - return -1; - } - - *in_len = pos + 1 - in_data; - - conn->state = CLIENT_FINISHED; - - return 0; -} - - -static int tls_process_client_finished(struct tlsv1_server *conn, u8 ct, - const u8 *in_data, size_t *in_len) -{ - const u8 *pos, *end; - size_t left, len, hlen; - u8 verify_data[TLS_VERIFY_DATA_LEN]; - u8 hash[MD5_MAC_LEN + SHA1_MAC_LEN]; - - if (ct != TLS_CONTENT_TYPE_HANDSHAKE) { - wpa_printf(MSG_DEBUG, "TLSv1: Expected Finished; " - "received content type 0x%x", ct); - tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, - TLS_ALERT_UNEXPECTED_MESSAGE); - return -1; - } - - pos = in_data; - left = *in_len; - - if (left < 4) { - wpa_printf(MSG_DEBUG, "TLSv1: Too short record (left=%lu) for " - "Finished", - (unsigned long) left); - tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, - TLS_ALERT_DECODE_ERROR); - return -1; - } - - if (pos[0] != TLS_HANDSHAKE_TYPE_FINISHED) { - wpa_printf(MSG_DEBUG, "TLSv1: Expected Finished; received " - "type 0x%x", pos[0]); - tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, - TLS_ALERT_UNEXPECTED_MESSAGE); - return -1; - } - - len = WPA_GET_BE24(pos + 1); - - pos += 4; - left -= 4; - - if (len > left) { - wpa_printf(MSG_DEBUG, "TLSv1: Too short buffer for Finished " - "(len=%lu > left=%lu)", - (unsigned long) len, (unsigned long) left); - tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, - TLS_ALERT_DECODE_ERROR); - return -1; - } - end = pos + len; - if (len != TLS_VERIFY_DATA_LEN) { - wpa_printf(MSG_DEBUG, "TLSv1: Unexpected verify_data length " - "in Finished: %lu (expected %d)", - (unsigned long) len, TLS_VERIFY_DATA_LEN); - tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, - TLS_ALERT_DECODE_ERROR); - return -1; - } - wpa_hexdump(MSG_MSGDUMP, "TLSv1: verify_data in Finished", - pos, TLS_VERIFY_DATA_LEN); - - hlen = MD5_MAC_LEN; - if (conn->verify.md5_client == NULL || - crypto_hash_finish(conn->verify.md5_client, hash, &hlen) < 0) { - tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, - TLS_ALERT_INTERNAL_ERROR); - conn->verify.md5_client = NULL; - crypto_hash_finish(conn->verify.sha1_client, NULL, NULL); - conn->verify.sha1_client = NULL; - return -1; - } - conn->verify.md5_client = NULL; - hlen = SHA1_MAC_LEN; - if (conn->verify.sha1_client == NULL || - crypto_hash_finish(conn->verify.sha1_client, hash + MD5_MAC_LEN, - &hlen) < 0) { - conn->verify.sha1_client = NULL; - tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, - TLS_ALERT_INTERNAL_ERROR); - return -1; - } - conn->verify.sha1_client = NULL; - - if (tls_prf(conn->master_secret, TLS_MASTER_SECRET_LEN, - "client finished", hash, MD5_MAC_LEN + SHA1_MAC_LEN, - verify_data, TLS_VERIFY_DATA_LEN)) { - wpa_printf(MSG_DEBUG, "TLSv1: Failed to derive verify_data"); - tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, - TLS_ALERT_DECRYPT_ERROR); - return -1; - } - wpa_hexdump_key(MSG_DEBUG, "TLSv1: verify_data (client)", - verify_data, TLS_VERIFY_DATA_LEN); - - if (os_memcmp(pos, verify_data, TLS_VERIFY_DATA_LEN) != 0) { - wpa_printf(MSG_INFO, "TLSv1: Mismatch in verify_data"); - return -1; - } - - wpa_printf(MSG_DEBUG, "TLSv1: Received Finished"); - - *in_len = end - in_data; - - if (conn->use_session_ticket) { - /* Abbreviated handshake using session ticket; RFC 4507 */ - wpa_printf(MSG_DEBUG, "TLSv1: Abbreviated handshake completed " - "successfully"); - conn->state = ESTABLISHED; - } else { - /* Full handshake */ - conn->state = SERVER_CHANGE_CIPHER_SPEC; - } - - return 0; -} - - -int tlsv1_server_process_handshake(struct tlsv1_server *conn, u8 ct, - const u8 *buf, size_t *len) -{ - if (ct == TLS_CONTENT_TYPE_ALERT) { - if (*len < 2) { - wpa_printf(MSG_DEBUG, "TLSv1: Alert underflow"); - tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, - TLS_ALERT_DECODE_ERROR); - return -1; - } - wpa_printf(MSG_DEBUG, "TLSv1: Received alert %d:%d", - buf[0], buf[1]); - *len = 2; - conn->state = FAILED; - return -1; - } - - switch (conn->state) { - case CLIENT_HELLO: - if (tls_process_client_hello(conn, ct, buf, len)) - return -1; - break; - case CLIENT_CERTIFICATE: - if (tls_process_certificate(conn, ct, buf, len)) - return -1; - break; - case CLIENT_KEY_EXCHANGE: - if (tls_process_client_key_exchange(conn, ct, buf, len)) - return -1; - break; - case CERTIFICATE_VERIFY: - if (tls_process_certificate_verify(conn, ct, buf, len)) - return -1; - break; - case CHANGE_CIPHER_SPEC: - if (tls_process_change_cipher_spec(conn, ct, buf, len)) - return -1; - break; - case CLIENT_FINISHED: - if (tls_process_client_finished(conn, ct, buf, len)) - return -1; - break; - default: - wpa_printf(MSG_DEBUG, "TLSv1: Unexpected state %d " - "while processing received message", - conn->state); - return -1; - } - - if (ct == TLS_CONTENT_TYPE_HANDSHAKE) - tls_verify_hash_add(&conn->verify, buf, *len); - - return 0; -} diff --git a/hostapd-0.8/src/tls/tlsv1_server_write.c b/hostapd-0.8/src/tls/tlsv1_server_write.c deleted file mode 100644 index e89e52e..0000000 --- a/hostapd-0.8/src/tls/tlsv1_server_write.c +++ /dev/null @@ -1,791 +0,0 @@ -/* - * TLSv1 server - write handshake message - * Copyright (c) 2006-2007, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#include "includes.h" - -#include "common.h" -#include "crypto/md5.h" -#include "crypto/sha1.h" -#include "crypto/tls.h" -#include "crypto/random.h" -#include "x509v3.h" -#include "tlsv1_common.h" -#include "tlsv1_record.h" -#include "tlsv1_server.h" -#include "tlsv1_server_i.h" - - -static size_t tls_server_cert_chain_der_len(struct tlsv1_server *conn) -{ - size_t len = 0; - struct x509_certificate *cert; - - cert = conn->cred->cert; - while (cert) { - len += 3 + cert->cert_len; - if (x509_certificate_self_signed(cert)) - break; - cert = x509_certificate_get_subject(conn->cred->trusted_certs, - &cert->issuer); - } - - return len; -} - - -static int tls_write_server_hello(struct tlsv1_server *conn, - u8 **msgpos, u8 *end) -{ - u8 *pos, *rhdr, *hs_start, *hs_length; - struct os_time now; - size_t rlen; - - pos = *msgpos; - - wpa_printf(MSG_DEBUG, "TLSv1: Send ServerHello"); - rhdr = pos; - pos += TLS_RECORD_HEADER_LEN; - - os_get_time(&now); - WPA_PUT_BE32(conn->server_random, now.sec); - if (random_get_bytes(conn->server_random + 4, TLS_RANDOM_LEN - 4)) { - wpa_printf(MSG_ERROR, "TLSv1: Could not generate " - "server_random"); - return -1; - } - wpa_hexdump(MSG_MSGDUMP, "TLSv1: server_random", - conn->server_random, TLS_RANDOM_LEN); - - conn->session_id_len = TLS_SESSION_ID_MAX_LEN; - if (random_get_bytes(conn->session_id, conn->session_id_len)) { - wpa_printf(MSG_ERROR, "TLSv1: Could not generate " - "session_id"); - return -1; - } - wpa_hexdump(MSG_MSGDUMP, "TLSv1: session_id", - conn->session_id, conn->session_id_len); - - /* opaque fragment[TLSPlaintext.length] */ - - /* Handshake */ - hs_start = pos; - /* HandshakeType msg_type */ - *pos++ = TLS_HANDSHAKE_TYPE_SERVER_HELLO; - /* uint24 length (to be filled) */ - hs_length = pos; - pos += 3; - /* body - ServerHello */ - /* ProtocolVersion server_version */ - WPA_PUT_BE16(pos, TLS_VERSION); - pos += 2; - /* Random random: uint32 gmt_unix_time, opaque random_bytes */ - os_memcpy(pos, conn->server_random, TLS_RANDOM_LEN); - pos += TLS_RANDOM_LEN; - /* SessionID session_id */ - *pos++ = conn->session_id_len; - os_memcpy(pos, conn->session_id, conn->session_id_len); - pos += conn->session_id_len; - /* CipherSuite cipher_suite */ - WPA_PUT_BE16(pos, conn->cipher_suite); - pos += 2; - /* CompressionMethod compression_method */ - *pos++ = TLS_COMPRESSION_NULL; - - if (conn->session_ticket && conn->session_ticket_cb) { - int res = conn->session_ticket_cb( - conn->session_ticket_cb_ctx, - conn->session_ticket, conn->session_ticket_len, - conn->client_random, conn->server_random, - conn->master_secret); - if (res < 0) { - wpa_printf(MSG_DEBUG, "TLSv1: SessionTicket callback " - "indicated failure"); - tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, - TLS_ALERT_HANDSHAKE_FAILURE); - return -1; - } - conn->use_session_ticket = res; - - if (conn->use_session_ticket) { - if (tlsv1_server_derive_keys(conn, NULL, 0) < 0) { - wpa_printf(MSG_DEBUG, "TLSv1: Failed to " - "derive keys"); - tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, - TLS_ALERT_INTERNAL_ERROR); - return -1; - } - } - - /* - * RFC 4507 specifies that server would include an empty - * SessionTicket extension in ServerHello and a - * NewSessionTicket message after the ServerHello. However, - * EAP-FAST (RFC 4851), i.e., the only user of SessionTicket - * extension at the moment, does not use such extensions. - * - * TODO: Add support for configuring RFC 4507 behavior and make - * EAP-FAST disable it. - */ - } - - WPA_PUT_BE24(hs_length, pos - hs_length - 3); - tls_verify_hash_add(&conn->verify, hs_start, pos - hs_start); - - if (tlsv1_record_send(&conn->rl, TLS_CONTENT_TYPE_HANDSHAKE, - rhdr, end - rhdr, pos - hs_start, &rlen) < 0) { - wpa_printf(MSG_DEBUG, "TLSv1: Failed to create TLS record"); - tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, - TLS_ALERT_INTERNAL_ERROR); - return -1; - } - pos = rhdr + rlen; - - *msgpos = pos; - - return 0; -} - - -static int tls_write_server_certificate(struct tlsv1_server *conn, - u8 **msgpos, u8 *end) -{ - u8 *pos, *rhdr, *hs_start, *hs_length, *cert_start; - size_t rlen; - struct x509_certificate *cert; - const struct tls_cipher_suite *suite; - - suite = tls_get_cipher_suite(conn->rl.cipher_suite); - if (suite && suite->key_exchange == TLS_KEY_X_DH_anon) { - wpa_printf(MSG_DEBUG, "TLSv1: Do not send Certificate when " - "using anonymous DH"); - return 0; - } - - pos = *msgpos; - - wpa_printf(MSG_DEBUG, "TLSv1: Send Certificate"); - rhdr = pos; - pos += TLS_RECORD_HEADER_LEN; - - /* opaque fragment[TLSPlaintext.length] */ - - /* Handshake */ - hs_start = pos; - /* HandshakeType msg_type */ - *pos++ = TLS_HANDSHAKE_TYPE_CERTIFICATE; - /* uint24 length (to be filled) */ - hs_length = pos; - pos += 3; - /* body - Certificate */ - /* uint24 length (to be filled) */ - cert_start = pos; - pos += 3; - cert = conn->cred->cert; - while (cert) { - if (pos + 3 + cert->cert_len > end) { - wpa_printf(MSG_DEBUG, "TLSv1: Not enough buffer space " - "for Certificate (cert_len=%lu left=%lu)", - (unsigned long) cert->cert_len, - (unsigned long) (end - pos)); - tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, - TLS_ALERT_INTERNAL_ERROR); - return -1; - } - WPA_PUT_BE24(pos, cert->cert_len); - pos += 3; - os_memcpy(pos, cert->cert_start, cert->cert_len); - pos += cert->cert_len; - - if (x509_certificate_self_signed(cert)) - break; - cert = x509_certificate_get_subject(conn->cred->trusted_certs, - &cert->issuer); - } - if (cert == conn->cred->cert || cert == NULL) { - /* - * Server was not configured with all the needed certificates - * to form a full certificate chain. The client may fail to - * validate the chain unless it is configured with all the - * missing CA certificates. - */ - wpa_printf(MSG_DEBUG, "TLSv1: Full server certificate chain " - "not configured - validation may fail"); - } - WPA_PUT_BE24(cert_start, pos - cert_start - 3); - - WPA_PUT_BE24(hs_length, pos - hs_length - 3); - - if (tlsv1_record_send(&conn->rl, TLS_CONTENT_TYPE_HANDSHAKE, - rhdr, end - rhdr, pos - hs_start, &rlen) < 0) { - wpa_printf(MSG_DEBUG, "TLSv1: Failed to generate a record"); - tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, - TLS_ALERT_INTERNAL_ERROR); - return -1; - } - pos = rhdr + rlen; - - tls_verify_hash_add(&conn->verify, hs_start, pos - hs_start); - - *msgpos = pos; - - return 0; -} - - -static int tls_write_server_key_exchange(struct tlsv1_server *conn, - u8 **msgpos, u8 *end) -{ - tls_key_exchange keyx; - const struct tls_cipher_suite *suite; - u8 *pos, *rhdr, *hs_start, *hs_length; - size_t rlen; - u8 *dh_ys; - size_t dh_ys_len; - - suite = tls_get_cipher_suite(conn->rl.cipher_suite); - if (suite == NULL) - keyx = TLS_KEY_X_NULL; - else - keyx = suite->key_exchange; - - if (!tls_server_key_exchange_allowed(conn->rl.cipher_suite)) { - wpa_printf(MSG_DEBUG, "TLSv1: No ServerKeyExchange needed"); - return 0; - } - - if (keyx != TLS_KEY_X_DH_anon) { - /* TODO? */ - wpa_printf(MSG_DEBUG, "TLSv1: ServerKeyExchange not yet " - "supported with key exchange type %d", keyx); - return -1; - } - - if (conn->cred == NULL || conn->cred->dh_p == NULL || - conn->cred->dh_g == NULL) { - wpa_printf(MSG_DEBUG, "TLSv1: No DH parameters available for " - "ServerKeyExhcange"); - return -1; - } - - os_free(conn->dh_secret); - conn->dh_secret_len = conn->cred->dh_p_len; - conn->dh_secret = os_malloc(conn->dh_secret_len); - if (conn->dh_secret == NULL) { - wpa_printf(MSG_DEBUG, "TLSv1: Failed to allocate " - "memory for secret (Diffie-Hellman)"); - tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, - TLS_ALERT_INTERNAL_ERROR); - return -1; - } - if (random_get_bytes(conn->dh_secret, conn->dh_secret_len)) { - wpa_printf(MSG_DEBUG, "TLSv1: Failed to get random " - "data for Diffie-Hellman"); - tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, - TLS_ALERT_INTERNAL_ERROR); - os_free(conn->dh_secret); - conn->dh_secret = NULL; - return -1; - } - - if (os_memcmp(conn->dh_secret, conn->cred->dh_p, conn->dh_secret_len) > - 0) - conn->dh_secret[0] = 0; /* make sure secret < p */ - - pos = conn->dh_secret; - while (pos + 1 < conn->dh_secret + conn->dh_secret_len && *pos == 0) - pos++; - if (pos != conn->dh_secret) { - os_memmove(conn->dh_secret, pos, - conn->dh_secret_len - (pos - conn->dh_secret)); - conn->dh_secret_len -= pos - conn->dh_secret; - } - wpa_hexdump_key(MSG_DEBUG, "TLSv1: DH server's secret value", - conn->dh_secret, conn->dh_secret_len); - - /* Ys = g^secret mod p */ - dh_ys_len = conn->cred->dh_p_len; - dh_ys = os_malloc(dh_ys_len); - if (dh_ys == NULL) { - wpa_printf(MSG_DEBUG, "TLSv1: Failed to allocate memory for " - "Diffie-Hellman"); - tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, - TLS_ALERT_INTERNAL_ERROR); - return -1; - } - if (crypto_mod_exp(conn->cred->dh_g, conn->cred->dh_g_len, - conn->dh_secret, conn->dh_secret_len, - conn->cred->dh_p, conn->cred->dh_p_len, - dh_ys, &dh_ys_len)) { - tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, - TLS_ALERT_INTERNAL_ERROR); - os_free(dh_ys); - return -1; - } - - wpa_hexdump(MSG_DEBUG, "TLSv1: DH Ys (server's public value)", - dh_ys, dh_ys_len); - - /* - * struct { - * select (KeyExchangeAlgorithm) { - * case diffie_hellman: - * ServerDHParams params; - * Signature signed_params; - * case rsa: - * ServerRSAParams params; - * Signature signed_params; - * }; - * } ServerKeyExchange; - * - * struct { - * opaque dh_p<1..2^16-1>; - * opaque dh_g<1..2^16-1>; - * opaque dh_Ys<1..2^16-1>; - * } ServerDHParams; - */ - - pos = *msgpos; - - wpa_printf(MSG_DEBUG, "TLSv1: Send ServerKeyExchange"); - rhdr = pos; - pos += TLS_RECORD_HEADER_LEN; - - /* opaque fragment[TLSPlaintext.length] */ - - /* Handshake */ - hs_start = pos; - /* HandshakeType msg_type */ - *pos++ = TLS_HANDSHAKE_TYPE_SERVER_KEY_EXCHANGE; - /* uint24 length (to be filled) */ - hs_length = pos; - pos += 3; - - /* body - ServerDHParams */ - /* dh_p */ - if (pos + 2 + conn->cred->dh_p_len > end) { - wpa_printf(MSG_DEBUG, "TLSv1: Not enough buffer space for " - "dh_p"); - tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, - TLS_ALERT_INTERNAL_ERROR); - os_free(dh_ys); - return -1; - } - WPA_PUT_BE16(pos, conn->cred->dh_p_len); - pos += 2; - os_memcpy(pos, conn->cred->dh_p, conn->cred->dh_p_len); - pos += conn->cred->dh_p_len; - - /* dh_g */ - if (pos + 2 + conn->cred->dh_g_len > end) { - wpa_printf(MSG_DEBUG, "TLSv1: Not enough buffer space for " - "dh_g"); - tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, - TLS_ALERT_INTERNAL_ERROR); - os_free(dh_ys); - return -1; - } - WPA_PUT_BE16(pos, conn->cred->dh_g_len); - pos += 2; - os_memcpy(pos, conn->cred->dh_g, conn->cred->dh_g_len); - pos += conn->cred->dh_g_len; - - /* dh_Ys */ - if (pos + 2 + dh_ys_len > end) { - wpa_printf(MSG_DEBUG, "TLSv1: Not enough buffer space for " - "dh_Ys"); - tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, - TLS_ALERT_INTERNAL_ERROR); - os_free(dh_ys); - return -1; - } - WPA_PUT_BE16(pos, dh_ys_len); - pos += 2; - os_memcpy(pos, dh_ys, dh_ys_len); - pos += dh_ys_len; - os_free(dh_ys); - - WPA_PUT_BE24(hs_length, pos - hs_length - 3); - - if (tlsv1_record_send(&conn->rl, TLS_CONTENT_TYPE_HANDSHAKE, - rhdr, end - rhdr, pos - hs_start, &rlen) < 0) { - wpa_printf(MSG_DEBUG, "TLSv1: Failed to generate a record"); - tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, - TLS_ALERT_INTERNAL_ERROR); - return -1; - } - pos = rhdr + rlen; - - tls_verify_hash_add(&conn->verify, hs_start, pos - hs_start); - - *msgpos = pos; - - return 0; -} - - -static int tls_write_server_certificate_request(struct tlsv1_server *conn, - u8 **msgpos, u8 *end) -{ - u8 *pos, *rhdr, *hs_start, *hs_length; - size_t rlen; - - if (!conn->verify_peer) { - wpa_printf(MSG_DEBUG, "TLSv1: No CertificateRequest needed"); - return 0; - } - - pos = *msgpos; - - wpa_printf(MSG_DEBUG, "TLSv1: Send CertificateRequest"); - rhdr = pos; - pos += TLS_RECORD_HEADER_LEN; - - /* opaque fragment[TLSPlaintext.length] */ - - /* Handshake */ - hs_start = pos; - /* HandshakeType msg_type */ - *pos++ = TLS_HANDSHAKE_TYPE_CERTIFICATE_REQUEST; - /* uint24 length (to be filled) */ - hs_length = pos; - pos += 3; - /* body - CertificateRequest */ - - /* - * enum { - * rsa_sign(1), dss_sign(2), rsa_fixed_dh(3), dss_fixed_dh(4), - * (255) - * } ClientCertificateType; - * ClientCertificateType certificate_types<1..2^8-1> - */ - *pos++ = 1; - *pos++ = 1; /* rsa_sign */ - - /* - * opaque DistinguishedName<1..2^16-1> - * DistinguishedName certificate_authorities<3..2^16-1> - */ - /* TODO: add support for listing DNs for trusted CAs */ - WPA_PUT_BE16(pos, 0); - pos += 2; - - WPA_PUT_BE24(hs_length, pos - hs_length - 3); - - if (tlsv1_record_send(&conn->rl, TLS_CONTENT_TYPE_HANDSHAKE, - rhdr, end - rhdr, pos - hs_start, &rlen) < 0) { - wpa_printf(MSG_DEBUG, "TLSv1: Failed to generate a record"); - tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, - TLS_ALERT_INTERNAL_ERROR); - return -1; - } - pos = rhdr + rlen; - - tls_verify_hash_add(&conn->verify, hs_start, pos - hs_start); - - *msgpos = pos; - - return 0; -} - - -static int tls_write_server_hello_done(struct tlsv1_server *conn, - u8 **msgpos, u8 *end) -{ - u8 *pos, *rhdr, *hs_start, *hs_length; - size_t rlen; - - pos = *msgpos; - - wpa_printf(MSG_DEBUG, "TLSv1: Send ServerHelloDone"); - rhdr = pos; - pos += TLS_RECORD_HEADER_LEN; - - /* opaque fragment[TLSPlaintext.length] */ - - /* Handshake */ - hs_start = pos; - /* HandshakeType msg_type */ - *pos++ = TLS_HANDSHAKE_TYPE_SERVER_HELLO_DONE; - /* uint24 length (to be filled) */ - hs_length = pos; - pos += 3; - /* body - ServerHelloDone (empty) */ - - WPA_PUT_BE24(hs_length, pos - hs_length - 3); - - if (tlsv1_record_send(&conn->rl, TLS_CONTENT_TYPE_HANDSHAKE, - rhdr, end - rhdr, pos - hs_start, &rlen) < 0) { - wpa_printf(MSG_DEBUG, "TLSv1: Failed to generate a record"); - tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, - TLS_ALERT_INTERNAL_ERROR); - return -1; - } - pos = rhdr + rlen; - - tls_verify_hash_add(&conn->verify, hs_start, pos - hs_start); - - *msgpos = pos; - - return 0; -} - - -static int tls_write_server_change_cipher_spec(struct tlsv1_server *conn, - u8 **msgpos, u8 *end) -{ - u8 *pos, *rhdr; - size_t rlen; - - pos = *msgpos; - - wpa_printf(MSG_DEBUG, "TLSv1: Send ChangeCipherSpec"); - rhdr = pos; - pos += TLS_RECORD_HEADER_LEN; - *pos = TLS_CHANGE_CIPHER_SPEC; - if (tlsv1_record_send(&conn->rl, TLS_CONTENT_TYPE_CHANGE_CIPHER_SPEC, - rhdr, end - rhdr, 1, &rlen) < 0) { - wpa_printf(MSG_DEBUG, "TLSv1: Failed to create a record"); - tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, - TLS_ALERT_INTERNAL_ERROR); - return -1; - } - - if (tlsv1_record_change_write_cipher(&conn->rl) < 0) { - wpa_printf(MSG_DEBUG, "TLSv1: Failed to set write cipher for " - "record layer"); - tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, - TLS_ALERT_INTERNAL_ERROR); - return -1; - } - - *msgpos = rhdr + rlen; - - return 0; -} - - -static int tls_write_server_finished(struct tlsv1_server *conn, - u8 **msgpos, u8 *end) -{ - u8 *pos, *rhdr, *hs_start, *hs_length; - size_t rlen, hlen; - u8 verify_data[TLS_VERIFY_DATA_LEN]; - u8 hash[MD5_MAC_LEN + SHA1_MAC_LEN]; - - pos = *msgpos; - - wpa_printf(MSG_DEBUG, "TLSv1: Send Finished"); - - /* Encrypted Handshake Message: Finished */ - - hlen = MD5_MAC_LEN; - if (conn->verify.md5_server == NULL || - crypto_hash_finish(conn->verify.md5_server, hash, &hlen) < 0) { - tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, - TLS_ALERT_INTERNAL_ERROR); - conn->verify.md5_server = NULL; - crypto_hash_finish(conn->verify.sha1_server, NULL, NULL); - conn->verify.sha1_server = NULL; - return -1; - } - conn->verify.md5_server = NULL; - hlen = SHA1_MAC_LEN; - if (conn->verify.sha1_server == NULL || - crypto_hash_finish(conn->verify.sha1_server, hash + MD5_MAC_LEN, - &hlen) < 0) { - conn->verify.sha1_server = NULL; - tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, - TLS_ALERT_INTERNAL_ERROR); - return -1; - } - conn->verify.sha1_server = NULL; - - if (tls_prf(conn->master_secret, TLS_MASTER_SECRET_LEN, - "server finished", hash, MD5_MAC_LEN + SHA1_MAC_LEN, - verify_data, TLS_VERIFY_DATA_LEN)) { - wpa_printf(MSG_DEBUG, "TLSv1: Failed to generate verify_data"); - tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, - TLS_ALERT_INTERNAL_ERROR); - return -1; - } - wpa_hexdump_key(MSG_DEBUG, "TLSv1: verify_data (server)", - verify_data, TLS_VERIFY_DATA_LEN); - - rhdr = pos; - pos += TLS_RECORD_HEADER_LEN; - /* Handshake */ - hs_start = pos; - /* HandshakeType msg_type */ - *pos++ = TLS_HANDSHAKE_TYPE_FINISHED; - /* uint24 length (to be filled) */ - hs_length = pos; - pos += 3; - os_memcpy(pos, verify_data, TLS_VERIFY_DATA_LEN); - pos += TLS_VERIFY_DATA_LEN; - WPA_PUT_BE24(hs_length, pos - hs_length - 3); - tls_verify_hash_add(&conn->verify, hs_start, pos - hs_start); - - if (tlsv1_record_send(&conn->rl, TLS_CONTENT_TYPE_HANDSHAKE, - rhdr, end - rhdr, pos - hs_start, &rlen) < 0) { - wpa_printf(MSG_DEBUG, "TLSv1: Failed to create a record"); - tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, - TLS_ALERT_INTERNAL_ERROR); - return -1; - } - - pos = rhdr + rlen; - - *msgpos = pos; - - return 0; -} - - -static u8 * tls_send_server_hello(struct tlsv1_server *conn, size_t *out_len) -{ - u8 *msg, *end, *pos; - size_t msglen; - - *out_len = 0; - - msglen = 1000 + tls_server_cert_chain_der_len(conn); - - msg = os_malloc(msglen); - if (msg == NULL) - return NULL; - - pos = msg; - end = msg + msglen; - - if (tls_write_server_hello(conn, &pos, end) < 0) { - os_free(msg); - return NULL; - } - - if (conn->use_session_ticket) { - /* Abbreviated handshake using session ticket; RFC 4507 */ - if (tls_write_server_change_cipher_spec(conn, &pos, end) < 0 || - tls_write_server_finished(conn, &pos, end) < 0) { - os_free(msg); - return NULL; - } - - *out_len = pos - msg; - - conn->state = CHANGE_CIPHER_SPEC; - - return msg; - } - - /* Full handshake */ - if (tls_write_server_certificate(conn, &pos, end) < 0 || - tls_write_server_key_exchange(conn, &pos, end) < 0 || - tls_write_server_certificate_request(conn, &pos, end) < 0 || - tls_write_server_hello_done(conn, &pos, end) < 0) { - os_free(msg); - return NULL; - } - - *out_len = pos - msg; - - conn->state = CLIENT_CERTIFICATE; - - return msg; -} - - -static u8 * tls_send_change_cipher_spec(struct tlsv1_server *conn, - size_t *out_len) -{ - u8 *msg, *end, *pos; - - *out_len = 0; - - msg = os_malloc(1000); - if (msg == NULL) - return NULL; - - pos = msg; - end = msg + 1000; - - if (tls_write_server_change_cipher_spec(conn, &pos, end) < 0 || - tls_write_server_finished(conn, &pos, end) < 0) { - os_free(msg); - return NULL; - } - - *out_len = pos - msg; - - wpa_printf(MSG_DEBUG, "TLSv1: Handshake completed successfully"); - conn->state = ESTABLISHED; - - return msg; -} - - -u8 * tlsv1_server_handshake_write(struct tlsv1_server *conn, size_t *out_len) -{ - switch (conn->state) { - case SERVER_HELLO: - return tls_send_server_hello(conn, out_len); - case SERVER_CHANGE_CIPHER_SPEC: - return tls_send_change_cipher_spec(conn, out_len); - default: - if (conn->state == ESTABLISHED && conn->use_session_ticket) { - /* Abbreviated handshake was already completed. */ - return NULL; - } - wpa_printf(MSG_DEBUG, "TLSv1: Unexpected state %d while " - "generating reply", conn->state); - return NULL; - } -} - - -u8 * tlsv1_server_send_alert(struct tlsv1_server *conn, u8 level, - u8 description, size_t *out_len) -{ - u8 *alert, *pos, *length; - - wpa_printf(MSG_DEBUG, "TLSv1: Send Alert(%d:%d)", level, description); - *out_len = 0; - - alert = os_malloc(10); - if (alert == NULL) - return NULL; - - pos = alert; - - /* TLSPlaintext */ - /* ContentType type */ - *pos++ = TLS_CONTENT_TYPE_ALERT; - /* ProtocolVersion version */ - WPA_PUT_BE16(pos, TLS_VERSION); - pos += 2; - /* uint16 length (to be filled) */ - length = pos; - pos += 2; - /* opaque fragment[TLSPlaintext.length] */ - - /* Alert */ - /* AlertLevel level */ - *pos++ = level; - /* AlertDescription description */ - *pos++ = description; - - WPA_PUT_BE16(length, pos - length - 2); - *out_len = pos - alert; - - return alert; -} diff --git a/hostapd-0.8/src/tls/x509v3.c b/hostapd-0.8/src/tls/x509v3.c deleted file mode 100644 index bc93df6..0000000 --- a/hostapd-0.8/src/tls/x509v3.c +++ /dev/null @@ -1,1985 +0,0 @@ -/* - * X.509v3 certificate parsing and processing (RFC 3280 profile) - * Copyright (c) 2006-2007, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#include "includes.h" - -#include "common.h" -#include "crypto/crypto.h" -#include "asn1.h" -#include "x509v3.h" - - -static void x509_free_name(struct x509_name *name) -{ - size_t i; - - for (i = 0; i < name->num_attr; i++) { - os_free(name->attr[i].value); - name->attr[i].value = NULL; - name->attr[i].type = X509_NAME_ATTR_NOT_USED; - } - name->num_attr = 0; - os_free(name->email); - name->email = NULL; - - os_free(name->alt_email); - os_free(name->dns); - os_free(name->uri); - os_free(name->ip); - name->alt_email = name->dns = name->uri = NULL; - name->ip = NULL; - name->ip_len = 0; - os_memset(&name->rid, 0, sizeof(name->rid)); -} - - -/** - * x509_certificate_free - Free an X.509 certificate - * @cert: Certificate to be freed - */ -void x509_certificate_free(struct x509_certificate *cert) -{ - if (cert == NULL) - return; - if (cert->next) { - wpa_printf(MSG_DEBUG, "X509: x509_certificate_free: cer=%p " - "was still on a list (next=%p)\n", - cert, cert->next); - } - x509_free_name(&cert->issuer); - x509_free_name(&cert->subject); - os_free(cert->public_key); - os_free(cert->sign_value); - os_free(cert); -} - - -/** - * x509_certificate_free - Free an X.509 certificate chain - * @cert: Pointer to the first certificate in the chain - */ -void x509_certificate_chain_free(struct x509_certificate *cert) -{ - struct x509_certificate *next; - - while (cert) { - next = cert->next; - cert->next = NULL; - x509_certificate_free(cert); - cert = next; - } -} - - -static int x509_whitespace(char c) -{ - return c == ' ' || c == '\t'; -} - - -static void x509_str_strip_whitespace(char *a) -{ - char *ipos, *opos; - int remove_whitespace = 1; - - ipos = opos = a; - - while (*ipos) { - if (remove_whitespace && x509_whitespace(*ipos)) - ipos++; - else { - remove_whitespace = x509_whitespace(*ipos); - *opos++ = *ipos++; - } - } - - *opos-- = '\0'; - if (opos > a && x509_whitespace(*opos)) - *opos = '\0'; -} - - -static int x509_str_compare(const char *a, const char *b) -{ - char *aa, *bb; - int ret; - - if (!a && b) - return -1; - if (a && !b) - return 1; - if (!a && !b) - return 0; - - aa = os_strdup(a); - bb = os_strdup(b); - - if (aa == NULL || bb == NULL) { - os_free(aa); - os_free(bb); - return os_strcasecmp(a, b); - } - - x509_str_strip_whitespace(aa); - x509_str_strip_whitespace(bb); - - ret = os_strcasecmp(aa, bb); - - os_free(aa); - os_free(bb); - - return ret; -} - - -/** - * x509_name_compare - Compare X.509 certificate names - * @a: Certificate name - * @b: Certificate name - * Returns: <0, 0, or >0 based on whether a is less than, equal to, or - * greater than b - */ -int x509_name_compare(struct x509_name *a, struct x509_name *b) -{ - int res; - size_t i; - - if (!a && b) - return -1; - if (a && !b) - return 1; - if (!a && !b) - return 0; - if (a->num_attr < b->num_attr) - return -1; - if (a->num_attr > b->num_attr) - return 1; - - for (i = 0; i < a->num_attr; i++) { - if (a->attr[i].type < b->attr[i].type) - return -1; - if (a->attr[i].type > b->attr[i].type) - return -1; - res = x509_str_compare(a->attr[i].value, b->attr[i].value); - if (res) - return res; - } - res = x509_str_compare(a->email, b->email); - if (res) - return res; - - return 0; -} - - -static int x509_parse_algorithm_identifier( - const u8 *buf, size_t len, - struct x509_algorithm_identifier *id, const u8 **next) -{ - struct asn1_hdr hdr; - const u8 *pos, *end; - - /* - * AlgorithmIdentifier ::= SEQUENCE { - * algorithm OBJECT IDENTIFIER, - * parameters ANY DEFINED BY algorithm OPTIONAL - * } - */ - - if (asn1_get_next(buf, len, &hdr) < 0 || - hdr.class != ASN1_CLASS_UNIVERSAL || - hdr.tag != ASN1_TAG_SEQUENCE) { - wpa_printf(MSG_DEBUG, "X509: Expected SEQUENCE " - "(AlgorithmIdentifier) - found class %d tag 0x%x", - hdr.class, hdr.tag); - return -1; - } - pos = hdr.payload; - end = pos + hdr.length; - - if (end > buf + len) - return -1; - - *next = end; - - if (asn1_get_oid(pos, end - pos, &id->oid, &pos)) - return -1; - - /* TODO: optional parameters */ - - return 0; -} - - -static int x509_parse_public_key(const u8 *buf, size_t len, - struct x509_certificate *cert, - const u8 **next) -{ - struct asn1_hdr hdr; - const u8 *pos, *end; - - /* - * SubjectPublicKeyInfo ::= SEQUENCE { - * algorithm AlgorithmIdentifier, - * subjectPublicKey BIT STRING - * } - */ - - pos = buf; - end = buf + len; - - if (asn1_get_next(pos, end - pos, &hdr) < 0 || - hdr.class != ASN1_CLASS_UNIVERSAL || - hdr.tag != ASN1_TAG_SEQUENCE) { - wpa_printf(MSG_DEBUG, "X509: Expected SEQUENCE " - "(SubjectPublicKeyInfo) - found class %d tag 0x%x", - hdr.class, hdr.tag); - return -1; - } - pos = hdr.payload; - - if (pos + hdr.length > end) - return -1; - end = pos + hdr.length; - *next = end; - - if (x509_parse_algorithm_identifier(pos, end - pos, - &cert->public_key_alg, &pos)) - return -1; - - if (asn1_get_next(pos, end - pos, &hdr) < 0 || - hdr.class != ASN1_CLASS_UNIVERSAL || - hdr.tag != ASN1_TAG_BITSTRING) { - wpa_printf(MSG_DEBUG, "X509: Expected BITSTRING " - "(subjectPublicKey) - found class %d tag 0x%x", - hdr.class, hdr.tag); - return -1; - } - if (hdr.length < 1) - return -1; - pos = hdr.payload; - if (*pos) { - wpa_printf(MSG_DEBUG, "X509: BITSTRING - %d unused bits", - *pos); - /* - * TODO: should this be rejected? X.509 certificates are - * unlikely to use such a construction. Now we would end up - * including the extra bits in the buffer which may also be - * ok. - */ - } - os_free(cert->public_key); - cert->public_key = os_malloc(hdr.length - 1); - if (cert->public_key == NULL) { - wpa_printf(MSG_DEBUG, "X509: Failed to allocate memory for " - "public key"); - return -1; - } - os_memcpy(cert->public_key, pos + 1, hdr.length - 1); - cert->public_key_len = hdr.length - 1; - wpa_hexdump(MSG_MSGDUMP, "X509: subjectPublicKey", - cert->public_key, cert->public_key_len); - - return 0; -} - - -static int x509_parse_name(const u8 *buf, size_t len, struct x509_name *name, - const u8 **next) -{ - struct asn1_hdr hdr; - const u8 *pos, *end, *set_pos, *set_end, *seq_pos, *seq_end; - struct asn1_oid oid; - char *val; - - /* - * Name ::= CHOICE { RDNSequence } - * RDNSequence ::= SEQUENCE OF RelativeDistinguishedName - * RelativeDistinguishedName ::= SET OF AttributeTypeAndValue - * AttributeTypeAndValue ::= SEQUENCE { - * type AttributeType, - * value AttributeValue - * } - * AttributeType ::= OBJECT IDENTIFIER - * AttributeValue ::= ANY DEFINED BY AttributeType - */ - - if (asn1_get_next(buf, len, &hdr) < 0 || - hdr.class != ASN1_CLASS_UNIVERSAL || - hdr.tag != ASN1_TAG_SEQUENCE) { - wpa_printf(MSG_DEBUG, "X509: Expected SEQUENCE " - "(Name / RDNSequencer) - found class %d tag 0x%x", - hdr.class, hdr.tag); - return -1; - } - pos = hdr.payload; - - if (pos + hdr.length > buf + len) - return -1; - - end = *next = pos + hdr.length; - - while (pos < end) { - enum x509_name_attr_type type; - - if (asn1_get_next(pos, end - pos, &hdr) < 0 || - hdr.class != ASN1_CLASS_UNIVERSAL || - hdr.tag != ASN1_TAG_SET) { - wpa_printf(MSG_DEBUG, "X509: Expected SET " - "(RelativeDistinguishedName) - found class " - "%d tag 0x%x", hdr.class, hdr.tag); - x509_free_name(name); - return -1; - } - - set_pos = hdr.payload; - pos = set_end = hdr.payload + hdr.length; - - if (asn1_get_next(set_pos, set_end - set_pos, &hdr) < 0 || - hdr.class != ASN1_CLASS_UNIVERSAL || - hdr.tag != ASN1_TAG_SEQUENCE) { - wpa_printf(MSG_DEBUG, "X509: Expected SEQUENCE " - "(AttributeTypeAndValue) - found class %d " - "tag 0x%x", hdr.class, hdr.tag); - x509_free_name(name); - return -1; - } - - seq_pos = hdr.payload; - seq_end = hdr.payload + hdr.length; - - if (asn1_get_oid(seq_pos, seq_end - seq_pos, &oid, &seq_pos)) { - x509_free_name(name); - return -1; - } - - if (asn1_get_next(seq_pos, seq_end - seq_pos, &hdr) < 0 || - hdr.class != ASN1_CLASS_UNIVERSAL) { - wpa_printf(MSG_DEBUG, "X509: Failed to parse " - "AttributeValue"); - x509_free_name(name); - return -1; - } - - /* RFC 3280: - * MUST: country, organization, organizational-unit, - * distinguished name qualifier, state or province name, - * common name, serial number. - * SHOULD: locality, title, surname, given name, initials, - * pseudonym, generation qualifier. - * MUST: domainComponent (RFC 2247). - */ - type = X509_NAME_ATTR_NOT_USED; - if (oid.len == 4 && - oid.oid[0] == 2 && oid.oid[1] == 5 && oid.oid[2] == 4) { - /* id-at ::= 2.5.4 */ - switch (oid.oid[3]) { - case 3: - /* commonName */ - type = X509_NAME_ATTR_CN; - break; - case 6: - /* countryName */ - type = X509_NAME_ATTR_C; - break; - case 7: - /* localityName */ - type = X509_NAME_ATTR_L; - break; - case 8: - /* stateOrProvinceName */ - type = X509_NAME_ATTR_ST; - break; - case 10: - /* organizationName */ - type = X509_NAME_ATTR_O; - break; - case 11: - /* organizationalUnitName */ - type = X509_NAME_ATTR_OU; - break; - } - } else if (oid.len == 7 && - oid.oid[0] == 1 && oid.oid[1] == 2 && - oid.oid[2] == 840 && oid.oid[3] == 113549 && - oid.oid[4] == 1 && oid.oid[5] == 9 && - oid.oid[6] == 1) { - /* 1.2.840.113549.1.9.1 - e-mailAddress */ - os_free(name->email); - name->email = os_malloc(hdr.length + 1); - if (name->email == NULL) { - x509_free_name(name); - return -1; - } - os_memcpy(name->email, hdr.payload, hdr.length); - name->email[hdr.length] = '\0'; - continue; - } else if (oid.len == 7 && - oid.oid[0] == 0 && oid.oid[1] == 9 && - oid.oid[2] == 2342 && oid.oid[3] == 19200300 && - oid.oid[4] == 100 && oid.oid[5] == 1 && - oid.oid[6] == 25) { - /* 0.9.2342.19200300.100.1.25 - domainComponent */ - type = X509_NAME_ATTR_DC; - } - - if (type == X509_NAME_ATTR_NOT_USED) { - wpa_hexdump(MSG_DEBUG, "X509: Unrecognized OID", - (u8 *) oid.oid, - oid.len * sizeof(oid.oid[0])); - wpa_hexdump_ascii(MSG_MSGDUMP, "X509: Attribute Data", - hdr.payload, hdr.length); - continue; - } - - if (name->num_attr == X509_MAX_NAME_ATTRIBUTES) { - wpa_printf(MSG_INFO, "X509: Too many Name attributes"); - x509_free_name(name); - return -1; - } - - val = os_malloc(hdr.length + 1); - if (val == NULL) { - x509_free_name(name); - return -1; - } - os_memcpy(val, hdr.payload, hdr.length); - val[hdr.length] = '\0'; - if (os_strlen(val) != hdr.length) { - wpa_printf(MSG_INFO, "X509: Reject certificate with " - "embedded NUL byte in a string (%s[NUL])", - val); - x509_free_name(name); - return -1; - } - - name->attr[name->num_attr].type = type; - name->attr[name->num_attr].value = val; - name->num_attr++; - } - - return 0; -} - - -static char * x509_name_attr_str(enum x509_name_attr_type type) -{ - switch (type) { - case X509_NAME_ATTR_NOT_USED: - return "[N/A]"; - case X509_NAME_ATTR_DC: - return "DC"; - case X509_NAME_ATTR_CN: - return "CN"; - case X509_NAME_ATTR_C: - return "C"; - case X509_NAME_ATTR_L: - return "L"; - case X509_NAME_ATTR_ST: - return "ST"; - case X509_NAME_ATTR_O: - return "O"; - case X509_NAME_ATTR_OU: - return "OU"; - } - return "?"; -} - - -/** - * x509_name_string - Convert an X.509 certificate name into a string - * @name: Name to convert - * @buf: Buffer for the string - * @len: Maximum buffer length - */ -void x509_name_string(struct x509_name *name, char *buf, size_t len) -{ - char *pos, *end; - int ret; - size_t i; - - if (len == 0) - return; - - pos = buf; - end = buf + len; - - for (i = 0; i < name->num_attr; i++) { - ret = os_snprintf(pos, end - pos, "%s=%s, ", - x509_name_attr_str(name->attr[i].type), - name->attr[i].value); - if (ret < 0 || ret >= end - pos) - goto done; - pos += ret; - } - - if (pos > buf + 1 && pos[-1] == ' ' && pos[-2] == ',') { - pos--; - *pos = '\0'; - pos--; - *pos = '\0'; - } - - if (name->email) { - ret = os_snprintf(pos, end - pos, "/emailAddress=%s", - name->email); - if (ret < 0 || ret >= end - pos) - goto done; - pos += ret; - } - -done: - end[-1] = '\0'; -} - - -static int x509_parse_time(const u8 *buf, size_t len, u8 asn1_tag, - os_time_t *val) -{ - const char *pos; - int year, month, day, hour, min, sec; - - /* - * Time ::= CHOICE { - * utcTime UTCTime, - * generalTime GeneralizedTime - * } - * - * UTCTime: YYMMDDHHMMSSZ - * GeneralizedTime: YYYYMMDDHHMMSSZ - */ - - pos = (const char *) buf; - - switch (asn1_tag) { - case ASN1_TAG_UTCTIME: - if (len != 13 || buf[12] != 'Z') { - wpa_hexdump_ascii(MSG_DEBUG, "X509: Unrecognized " - "UTCTime format", buf, len); - return -1; - } - if (sscanf(pos, "%02d", &year) != 1) { - wpa_hexdump_ascii(MSG_DEBUG, "X509: Failed to parse " - "UTCTime year", buf, len); - return -1; - } - if (year < 50) - year += 2000; - else - year += 1900; - pos += 2; - break; - case ASN1_TAG_GENERALIZEDTIME: - if (len != 15 || buf[14] != 'Z') { - wpa_hexdump_ascii(MSG_DEBUG, "X509: Unrecognized " - "GeneralizedTime format", buf, len); - return -1; - } - if (sscanf(pos, "%04d", &year) != 1) { - wpa_hexdump_ascii(MSG_DEBUG, "X509: Failed to parse " - "GeneralizedTime year", buf, len); - return -1; - } - pos += 4; - break; - default: - wpa_printf(MSG_DEBUG, "X509: Expected UTCTime or " - "GeneralizedTime - found tag 0x%x", asn1_tag); - return -1; - } - - if (sscanf(pos, "%02d", &month) != 1) { - wpa_hexdump_ascii(MSG_DEBUG, "X509: Failed to parse Time " - "(month)", buf, len); - return -1; - } - pos += 2; - - if (sscanf(pos, "%02d", &day) != 1) { - wpa_hexdump_ascii(MSG_DEBUG, "X509: Failed to parse Time " - "(day)", buf, len); - return -1; - } - pos += 2; - - if (sscanf(pos, "%02d", &hour) != 1) { - wpa_hexdump_ascii(MSG_DEBUG, "X509: Failed to parse Time " - "(hour)", buf, len); - return -1; - } - pos += 2; - - if (sscanf(pos, "%02d", &min) != 1) { - wpa_hexdump_ascii(MSG_DEBUG, "X509: Failed to parse Time " - "(min)", buf, len); - return -1; - } - pos += 2; - - if (sscanf(pos, "%02d", &sec) != 1) { - wpa_hexdump_ascii(MSG_DEBUG, "X509: Failed to parse Time " - "(sec)", buf, len); - return -1; - } - - if (os_mktime(year, month, day, hour, min, sec, val) < 0) { - wpa_hexdump_ascii(MSG_DEBUG, "X509: Failed to convert Time", - buf, len); - if (year < 1970) { - /* - * At least some test certificates have been configured - * to use dates prior to 1970. Set the date to - * beginning of 1970 to handle these case. - */ - wpa_printf(MSG_DEBUG, "X509: Year=%d before epoch - " - "assume epoch as the time", year); - *val = 0; - return 0; - } - return -1; - } - - return 0; -} - - -static int x509_parse_validity(const u8 *buf, size_t len, - struct x509_certificate *cert, const u8 **next) -{ - struct asn1_hdr hdr; - const u8 *pos; - size_t plen; - - /* - * Validity ::= SEQUENCE { - * notBefore Time, - * notAfter Time - * } - * - * RFC 3280, 4.1.2.5: - * CAs conforming to this profile MUST always encode certificate - * validity dates through the year 2049 as UTCTime; certificate - * validity dates in 2050 or later MUST be encoded as GeneralizedTime. - */ - - if (asn1_get_next(buf, len, &hdr) < 0 || - hdr.class != ASN1_CLASS_UNIVERSAL || - hdr.tag != ASN1_TAG_SEQUENCE) { - wpa_printf(MSG_DEBUG, "X509: Expected SEQUENCE " - "(Validity) - found class %d tag 0x%x", - hdr.class, hdr.tag); - return -1; - } - pos = hdr.payload; - plen = hdr.length; - - if (pos + plen > buf + len) - return -1; - - *next = pos + plen; - - if (asn1_get_next(pos, plen, &hdr) < 0 || - hdr.class != ASN1_CLASS_UNIVERSAL || - x509_parse_time(hdr.payload, hdr.length, hdr.tag, - &cert->not_before) < 0) { - wpa_hexdump_ascii(MSG_DEBUG, "X509: Failed to parse notBefore " - "Time", hdr.payload, hdr.length); - return -1; - } - - pos = hdr.payload + hdr.length; - plen = *next - pos; - - if (asn1_get_next(pos, plen, &hdr) < 0 || - hdr.class != ASN1_CLASS_UNIVERSAL || - x509_parse_time(hdr.payload, hdr.length, hdr.tag, - &cert->not_after) < 0) { - wpa_hexdump_ascii(MSG_DEBUG, "X509: Failed to parse notAfter " - "Time", hdr.payload, hdr.length); - return -1; - } - - wpa_printf(MSG_MSGDUMP, "X509: Validity: notBefore: %lu notAfter: %lu", - (unsigned long) cert->not_before, - (unsigned long) cert->not_after); - - return 0; -} - - -static int x509_id_ce_oid(struct asn1_oid *oid) -{ - /* id-ce arc from X.509 for standard X.509v3 extensions */ - return oid->len >= 4 && - oid->oid[0] == 2 /* joint-iso-ccitt */ && - oid->oid[1] == 5 /* ds */ && - oid->oid[2] == 29 /* id-ce */; -} - - -static int x509_parse_ext_key_usage(struct x509_certificate *cert, - const u8 *pos, size_t len) -{ - struct asn1_hdr hdr; - - /* - * KeyUsage ::= BIT STRING { - * digitalSignature (0), - * nonRepudiation (1), - * keyEncipherment (2), - * dataEncipherment (3), - * keyAgreement (4), - * keyCertSign (5), - * cRLSign (6), - * encipherOnly (7), - * decipherOnly (8) } - */ - - if (asn1_get_next(pos, len, &hdr) < 0 || - hdr.class != ASN1_CLASS_UNIVERSAL || - hdr.tag != ASN1_TAG_BITSTRING || - hdr.length < 1) { - wpa_printf(MSG_DEBUG, "X509: Expected BIT STRING in " - "KeyUsage; found %d tag 0x%x len %d", - hdr.class, hdr.tag, hdr.length); - return -1; - } - - cert->extensions_present |= X509_EXT_KEY_USAGE; - cert->key_usage = asn1_bit_string_to_long(hdr.payload, hdr.length); - - wpa_printf(MSG_DEBUG, "X509: KeyUsage 0x%lx", cert->key_usage); - - return 0; -} - - -static int x509_parse_ext_basic_constraints(struct x509_certificate *cert, - const u8 *pos, size_t len) -{ - struct asn1_hdr hdr; - unsigned long value; - size_t left; - - /* - * BasicConstraints ::= SEQUENCE { - * cA BOOLEAN DEFAULT FALSE, - * pathLenConstraint INTEGER (0..MAX) OPTIONAL } - */ - - if (asn1_get_next(pos, len, &hdr) < 0 || - hdr.class != ASN1_CLASS_UNIVERSAL || - hdr.tag != ASN1_TAG_SEQUENCE) { - wpa_printf(MSG_DEBUG, "X509: Expected SEQUENCE in " - "BasicConstraints; found %d tag 0x%x", - hdr.class, hdr.tag); - return -1; - } - - cert->extensions_present |= X509_EXT_BASIC_CONSTRAINTS; - - if (hdr.length == 0) - return 0; - - if (asn1_get_next(hdr.payload, hdr.length, &hdr) < 0 || - hdr.class != ASN1_CLASS_UNIVERSAL) { - wpa_printf(MSG_DEBUG, "X509: Failed to parse " - "BasicConstraints"); - return -1; - } - - if (hdr.tag == ASN1_TAG_BOOLEAN) { - if (hdr.length != 1) { - wpa_printf(MSG_DEBUG, "X509: Unexpected " - "Boolean length (%u) in BasicConstraints", - hdr.length); - return -1; - } - cert->ca = hdr.payload[0]; - - if (hdr.payload + hdr.length == pos + len) { - wpa_printf(MSG_DEBUG, "X509: BasicConstraints - cA=%d", - cert->ca); - return 0; - } - - if (asn1_get_next(hdr.payload + hdr.length, len - hdr.length, - &hdr) < 0 || - hdr.class != ASN1_CLASS_UNIVERSAL) { - wpa_printf(MSG_DEBUG, "X509: Failed to parse " - "BasicConstraints"); - return -1; - } - } - - if (hdr.tag != ASN1_TAG_INTEGER) { - wpa_printf(MSG_DEBUG, "X509: Expected INTEGER in " - "BasicConstraints; found class %d tag 0x%x", - hdr.class, hdr.tag); - return -1; - } - - pos = hdr.payload; - left = hdr.length; - value = 0; - while (left) { - value <<= 8; - value |= *pos++; - left--; - } - - cert->path_len_constraint = value; - cert->extensions_present |= X509_EXT_PATH_LEN_CONSTRAINT; - - wpa_printf(MSG_DEBUG, "X509: BasicConstraints - cA=%d " - "pathLenConstraint=%lu", - cert->ca, cert->path_len_constraint); - - return 0; -} - - -static int x509_parse_alt_name_rfc8222(struct x509_name *name, - const u8 *pos, size_t len) -{ - /* rfc822Name IA5String */ - wpa_hexdump_ascii(MSG_MSGDUMP, "X509: altName - rfc822Name", pos, len); - os_free(name->alt_email); - name->alt_email = os_zalloc(len + 1); - if (name->alt_email == NULL) - return -1; - os_memcpy(name->alt_email, pos, len); - if (os_strlen(name->alt_email) != len) { - wpa_printf(MSG_INFO, "X509: Reject certificate with " - "embedded NUL byte in rfc822Name (%s[NUL])", - name->alt_email); - os_free(name->alt_email); - name->alt_email = NULL; - return -1; - } - return 0; -} - - -static int x509_parse_alt_name_dns(struct x509_name *name, - const u8 *pos, size_t len) -{ - /* dNSName IA5String */ - wpa_hexdump_ascii(MSG_MSGDUMP, "X509: altName - dNSName", pos, len); - os_free(name->dns); - name->dns = os_zalloc(len + 1); - if (name->dns == NULL) - return -1; - os_memcpy(name->dns, pos, len); - if (os_strlen(name->dns) != len) { - wpa_printf(MSG_INFO, "X509: Reject certificate with " - "embedded NUL byte in dNSName (%s[NUL])", - name->dns); - os_free(name->dns); - name->dns = NULL; - return -1; - } - return 0; -} - - -static int x509_parse_alt_name_uri(struct x509_name *name, - const u8 *pos, size_t len) -{ - /* uniformResourceIdentifier IA5String */ - wpa_hexdump_ascii(MSG_MSGDUMP, - "X509: altName - uniformResourceIdentifier", - pos, len); - os_free(name->uri); - name->uri = os_zalloc(len + 1); - if (name->uri == NULL) - return -1; - os_memcpy(name->uri, pos, len); - if (os_strlen(name->uri) != len) { - wpa_printf(MSG_INFO, "X509: Reject certificate with " - "embedded NUL byte in uniformResourceIdentifier " - "(%s[NUL])", name->uri); - os_free(name->uri); - name->uri = NULL; - return -1; - } - return 0; -} - - -static int x509_parse_alt_name_ip(struct x509_name *name, - const u8 *pos, size_t len) -{ - /* iPAddress OCTET STRING */ - wpa_hexdump(MSG_MSGDUMP, "X509: altName - iPAddress", pos, len); - os_free(name->ip); - name->ip = os_malloc(len); - if (name->ip == NULL) - return -1; - os_memcpy(name->ip, pos, len); - name->ip_len = len; - return 0; -} - - -static int x509_parse_alt_name_rid(struct x509_name *name, - const u8 *pos, size_t len) -{ - char buf[80]; - - /* registeredID OBJECT IDENTIFIER */ - if (asn1_parse_oid(pos, len, &name->rid) < 0) - return -1; - - asn1_oid_to_str(&name->rid, buf, sizeof(buf)); - wpa_printf(MSG_MSGDUMP, "X509: altName - registeredID: %s", buf); - - return 0; -} - - -static int x509_parse_ext_alt_name(struct x509_name *name, - const u8 *pos, size_t len) -{ - struct asn1_hdr hdr; - const u8 *p, *end; - - /* - * GeneralNames ::= SEQUENCE SIZE (1..MAX) OF GeneralName - * - * GeneralName ::= CHOICE { - * otherName [0] OtherName, - * rfc822Name [1] IA5String, - * dNSName [2] IA5String, - * x400Address [3] ORAddress, - * directoryName [4] Name, - * ediPartyName [5] EDIPartyName, - * uniformResourceIdentifier [6] IA5String, - * iPAddress [7] OCTET STRING, - * registeredID [8] OBJECT IDENTIFIER } - * - * OtherName ::= SEQUENCE { - * type-id OBJECT IDENTIFIER, - * value [0] EXPLICIT ANY DEFINED BY type-id } - * - * EDIPartyName ::= SEQUENCE { - * nameAssigner [0] DirectoryString OPTIONAL, - * partyName [1] DirectoryString } - */ - - for (p = pos, end = pos + len; p < end; p = hdr.payload + hdr.length) { - int res; - - if (asn1_get_next(p, end - p, &hdr) < 0) { - wpa_printf(MSG_DEBUG, "X509: Failed to parse " - "SubjectAltName item"); - return -1; - } - - if (hdr.class != ASN1_CLASS_CONTEXT_SPECIFIC) - continue; - - switch (hdr.tag) { - case 1: - res = x509_parse_alt_name_rfc8222(name, hdr.payload, - hdr.length); - break; - case 2: - res = x509_parse_alt_name_dns(name, hdr.payload, - hdr.length); - break; - case 6: - res = x509_parse_alt_name_uri(name, hdr.payload, - hdr.length); - break; - case 7: - res = x509_parse_alt_name_ip(name, hdr.payload, - hdr.length); - break; - case 8: - res = x509_parse_alt_name_rid(name, hdr.payload, - hdr.length); - break; - case 0: /* TODO: otherName */ - case 3: /* TODO: x500Address */ - case 4: /* TODO: directoryName */ - case 5: /* TODO: ediPartyName */ - default: - res = 0; - break; - } - if (res < 0) - return res; - } - - return 0; -} - - -static int x509_parse_ext_subject_alt_name(struct x509_certificate *cert, - const u8 *pos, size_t len) -{ - struct asn1_hdr hdr; - - /* SubjectAltName ::= GeneralNames */ - - if (asn1_get_next(pos, len, &hdr) < 0 || - hdr.class != ASN1_CLASS_UNIVERSAL || - hdr.tag != ASN1_TAG_SEQUENCE) { - wpa_printf(MSG_DEBUG, "X509: Expected SEQUENCE in " - "SubjectAltName; found %d tag 0x%x", - hdr.class, hdr.tag); - return -1; - } - - wpa_printf(MSG_DEBUG, "X509: SubjectAltName"); - cert->extensions_present |= X509_EXT_SUBJECT_ALT_NAME; - - if (hdr.length == 0) - return 0; - - return x509_parse_ext_alt_name(&cert->subject, hdr.payload, - hdr.length); -} - - -static int x509_parse_ext_issuer_alt_name(struct x509_certificate *cert, - const u8 *pos, size_t len) -{ - struct asn1_hdr hdr; - - /* IssuerAltName ::= GeneralNames */ - - if (asn1_get_next(pos, len, &hdr) < 0 || - hdr.class != ASN1_CLASS_UNIVERSAL || - hdr.tag != ASN1_TAG_SEQUENCE) { - wpa_printf(MSG_DEBUG, "X509: Expected SEQUENCE in " - "IssuerAltName; found %d tag 0x%x", - hdr.class, hdr.tag); - return -1; - } - - wpa_printf(MSG_DEBUG, "X509: IssuerAltName"); - cert->extensions_present |= X509_EXT_ISSUER_ALT_NAME; - - if (hdr.length == 0) - return 0; - - return x509_parse_ext_alt_name(&cert->issuer, hdr.payload, - hdr.length); -} - - -static int x509_parse_extension_data(struct x509_certificate *cert, - struct asn1_oid *oid, - const u8 *pos, size_t len) -{ - if (!x509_id_ce_oid(oid)) - return 1; - - /* TODO: add other extensions required by RFC 3280, Ch 4.2: - * certificate policies (section 4.2.1.5) - * name constraints (section 4.2.1.11) - * policy constraints (section 4.2.1.12) - * extended key usage (section 4.2.1.13) - * inhibit any-policy (section 4.2.1.15) - */ - switch (oid->oid[3]) { - case 15: /* id-ce-keyUsage */ - return x509_parse_ext_key_usage(cert, pos, len); - case 17: /* id-ce-subjectAltName */ - return x509_parse_ext_subject_alt_name(cert, pos, len); - case 18: /* id-ce-issuerAltName */ - return x509_parse_ext_issuer_alt_name(cert, pos, len); - case 19: /* id-ce-basicConstraints */ - return x509_parse_ext_basic_constraints(cert, pos, len); - default: - return 1; - } -} - - -static int x509_parse_extension(struct x509_certificate *cert, - const u8 *pos, size_t len, const u8 **next) -{ - const u8 *end; - struct asn1_hdr hdr; - struct asn1_oid oid; - int critical_ext = 0, res; - char buf[80]; - - /* - * Extension ::= SEQUENCE { - * extnID OBJECT IDENTIFIER, - * critical BOOLEAN DEFAULT FALSE, - * extnValue OCTET STRING - * } - */ - - if (asn1_get_next(pos, len, &hdr) < 0 || - hdr.class != ASN1_CLASS_UNIVERSAL || - hdr.tag != ASN1_TAG_SEQUENCE) { - wpa_printf(MSG_DEBUG, "X509: Unexpected ASN.1 header in " - "Extensions: class %d tag 0x%x; expected SEQUENCE", - hdr.class, hdr.tag); - return -1; - } - pos = hdr.payload; - *next = end = pos + hdr.length; - - if (asn1_get_oid(pos, end - pos, &oid, &pos) < 0) { - wpa_printf(MSG_DEBUG, "X509: Unexpected ASN.1 data for " - "Extension (expected OID)"); - return -1; - } - - if (asn1_get_next(pos, end - pos, &hdr) < 0 || - hdr.class != ASN1_CLASS_UNIVERSAL || - (hdr.tag != ASN1_TAG_BOOLEAN && - hdr.tag != ASN1_TAG_OCTETSTRING)) { - wpa_printf(MSG_DEBUG, "X509: Unexpected ASN.1 header in " - "Extensions: class %d tag 0x%x; expected BOOLEAN " - "or OCTET STRING", hdr.class, hdr.tag); - return -1; - } - - if (hdr.tag == ASN1_TAG_BOOLEAN) { - if (hdr.length != 1) { - wpa_printf(MSG_DEBUG, "X509: Unexpected " - "Boolean length (%u)", hdr.length); - return -1; - } - critical_ext = hdr.payload[0]; - pos = hdr.payload; - if (asn1_get_next(pos, end - pos, &hdr) < 0 || - (hdr.class != ASN1_CLASS_UNIVERSAL && - hdr.class != ASN1_CLASS_PRIVATE) || - hdr.tag != ASN1_TAG_OCTETSTRING) { - wpa_printf(MSG_DEBUG, "X509: Unexpected ASN.1 header " - "in Extensions: class %d tag 0x%x; " - "expected OCTET STRING", - hdr.class, hdr.tag); - return -1; - } - } - - asn1_oid_to_str(&oid, buf, sizeof(buf)); - wpa_printf(MSG_DEBUG, "X509: Extension: extnID=%s critical=%d", - buf, critical_ext); - wpa_hexdump(MSG_MSGDUMP, "X509: extnValue", hdr.payload, hdr.length); - - res = x509_parse_extension_data(cert, &oid, hdr.payload, hdr.length); - if (res < 0) - return res; - if (res == 1 && critical_ext) { - wpa_printf(MSG_INFO, "X509: Unknown critical extension %s", - buf); - return -1; - } - - return 0; -} - - -static int x509_parse_extensions(struct x509_certificate *cert, - const u8 *pos, size_t len) -{ - const u8 *end; - struct asn1_hdr hdr; - - /* Extensions ::= SEQUENCE SIZE (1..MAX) OF Extension */ - - if (asn1_get_next(pos, len, &hdr) < 0 || - hdr.class != ASN1_CLASS_UNIVERSAL || - hdr.tag != ASN1_TAG_SEQUENCE) { - wpa_printf(MSG_DEBUG, "X509: Unexpected ASN.1 data " - "for Extensions: class %d tag 0x%x; " - "expected SEQUENCE", hdr.class, hdr.tag); - return -1; - } - - pos = hdr.payload; - end = pos + hdr.length; - - while (pos < end) { - if (x509_parse_extension(cert, pos, end - pos, &pos) - < 0) - return -1; - } - - return 0; -} - - -static int x509_parse_tbs_certificate(const u8 *buf, size_t len, - struct x509_certificate *cert, - const u8 **next) -{ - struct asn1_hdr hdr; - const u8 *pos, *end; - size_t left; - char sbuf[128]; - unsigned long value; - - /* tbsCertificate TBSCertificate ::= SEQUENCE */ - if (asn1_get_next(buf, len, &hdr) < 0 || - hdr.class != ASN1_CLASS_UNIVERSAL || - hdr.tag != ASN1_TAG_SEQUENCE) { - wpa_printf(MSG_DEBUG, "X509: tbsCertificate did not start " - "with a valid SEQUENCE - found class %d tag 0x%x", - hdr.class, hdr.tag); - return -1; - } - pos = hdr.payload; - end = *next = pos + hdr.length; - - /* - * version [0] EXPLICIT Version DEFAULT v1 - * Version ::= INTEGER { v1(0), v2(1), v3(2) } - */ - if (asn1_get_next(pos, end - pos, &hdr) < 0) - return -1; - pos = hdr.payload; - - if (hdr.class == ASN1_CLASS_CONTEXT_SPECIFIC) { - if (asn1_get_next(pos, end - pos, &hdr) < 0) - return -1; - - if (hdr.class != ASN1_CLASS_UNIVERSAL || - hdr.tag != ASN1_TAG_INTEGER) { - wpa_printf(MSG_DEBUG, "X509: No INTEGER tag found for " - "version field - found class %d tag 0x%x", - hdr.class, hdr.tag); - return -1; - } - if (hdr.length != 1) { - wpa_printf(MSG_DEBUG, "X509: Unexpected version field " - "length %u (expected 1)", hdr.length); - return -1; - } - pos = hdr.payload; - left = hdr.length; - value = 0; - while (left) { - value <<= 8; - value |= *pos++; - left--; - } - - cert->version = value; - if (cert->version != X509_CERT_V1 && - cert->version != X509_CERT_V2 && - cert->version != X509_CERT_V3) { - wpa_printf(MSG_DEBUG, "X509: Unsupported version %d", - cert->version + 1); - return -1; - } - - if (asn1_get_next(pos, end - pos, &hdr) < 0) - return -1; - } else - cert->version = X509_CERT_V1; - wpa_printf(MSG_MSGDUMP, "X509: Version X.509v%d", cert->version + 1); - - /* serialNumber CertificateSerialNumber ::= INTEGER */ - if (hdr.class != ASN1_CLASS_UNIVERSAL || - hdr.tag != ASN1_TAG_INTEGER) { - wpa_printf(MSG_DEBUG, "X509: No INTEGER tag found for " - "serialNumber; class=%d tag=0x%x", - hdr.class, hdr.tag); - return -1; - } - - pos = hdr.payload; - left = hdr.length; - while (left) { - cert->serial_number <<= 8; - cert->serial_number |= *pos++; - left--; - } - wpa_printf(MSG_MSGDUMP, "X509: serialNumber %lu", cert->serial_number); - - /* signature AlgorithmIdentifier */ - if (x509_parse_algorithm_identifier(pos, end - pos, &cert->signature, - &pos)) - return -1; - - /* issuer Name */ - if (x509_parse_name(pos, end - pos, &cert->issuer, &pos)) - return -1; - x509_name_string(&cert->issuer, sbuf, sizeof(sbuf)); - wpa_printf(MSG_MSGDUMP, "X509: issuer %s", sbuf); - - /* validity Validity */ - if (x509_parse_validity(pos, end - pos, cert, &pos)) - return -1; - - /* subject Name */ - if (x509_parse_name(pos, end - pos, &cert->subject, &pos)) - return -1; - x509_name_string(&cert->subject, sbuf, sizeof(sbuf)); - wpa_printf(MSG_MSGDUMP, "X509: subject %s", sbuf); - - /* subjectPublicKeyInfo SubjectPublicKeyInfo */ - if (x509_parse_public_key(pos, end - pos, cert, &pos)) - return -1; - - if (pos == end) - return 0; - - if (cert->version == X509_CERT_V1) - return 0; - - if (asn1_get_next(pos, end - pos, &hdr) < 0 || - hdr.class != ASN1_CLASS_CONTEXT_SPECIFIC) { - wpa_printf(MSG_DEBUG, "X509: Expected Context-Specific" - " tag to parse optional tbsCertificate " - "field(s); parsed class %d tag 0x%x", - hdr.class, hdr.tag); - return -1; - } - - if (hdr.tag == 1) { - /* issuerUniqueID [1] IMPLICIT UniqueIdentifier OPTIONAL */ - wpa_printf(MSG_DEBUG, "X509: issuerUniqueID"); - /* TODO: parse UniqueIdentifier ::= BIT STRING */ - - if (hdr.payload + hdr.length == end) - return 0; - - if (asn1_get_next(pos, end - pos, &hdr) < 0 || - hdr.class != ASN1_CLASS_CONTEXT_SPECIFIC) { - wpa_printf(MSG_DEBUG, "X509: Expected Context-Specific" - " tag to parse optional tbsCertificate " - "field(s); parsed class %d tag 0x%x", - hdr.class, hdr.tag); - return -1; - } - } - - if (hdr.tag == 2) { - /* subjectUniqueID [2] IMPLICIT UniqueIdentifier OPTIONAL */ - wpa_printf(MSG_DEBUG, "X509: subjectUniqueID"); - /* TODO: parse UniqueIdentifier ::= BIT STRING */ - - if (hdr.payload + hdr.length == end) - return 0; - - if (asn1_get_next(pos, end - pos, &hdr) < 0 || - hdr.class != ASN1_CLASS_CONTEXT_SPECIFIC) { - wpa_printf(MSG_DEBUG, "X509: Expected Context-Specific" - " tag to parse optional tbsCertificate " - "field(s); parsed class %d tag 0x%x", - hdr.class, hdr.tag); - return -1; - } - } - - if (hdr.tag != 3) { - wpa_printf(MSG_DEBUG, "X509: Ignored unexpected " - "Context-Specific tag %d in optional " - "tbsCertificate fields", hdr.tag); - return 0; - } - - /* extensions [3] EXPLICIT Extensions OPTIONAL */ - - if (cert->version != X509_CERT_V3) { - wpa_printf(MSG_DEBUG, "X509: X.509%d certificate and " - "Extensions data which are only allowed for " - "version 3", cert->version + 1); - return -1; - } - - if (x509_parse_extensions(cert, hdr.payload, hdr.length) < 0) - return -1; - - pos = hdr.payload + hdr.length; - if (pos < end) { - wpa_hexdump(MSG_DEBUG, - "X509: Ignored extra tbsCertificate data", - pos, end - pos); - } - - return 0; -} - - -static int x509_rsadsi_oid(struct asn1_oid *oid) -{ - return oid->len >= 4 && - oid->oid[0] == 1 /* iso */ && - oid->oid[1] == 2 /* member-body */ && - oid->oid[2] == 840 /* us */ && - oid->oid[3] == 113549 /* rsadsi */; -} - - -static int x509_pkcs_oid(struct asn1_oid *oid) -{ - return oid->len >= 5 && - x509_rsadsi_oid(oid) && - oid->oid[4] == 1 /* pkcs */; -} - - -static int x509_digest_oid(struct asn1_oid *oid) -{ - return oid->len >= 5 && - x509_rsadsi_oid(oid) && - oid->oid[4] == 2 /* digestAlgorithm */; -} - - -static int x509_sha1_oid(struct asn1_oid *oid) -{ - return oid->len == 6 && - oid->oid[0] == 1 /* iso */ && - oid->oid[1] == 3 /* identified-organization */ && - oid->oid[2] == 14 /* oiw */ && - oid->oid[3] == 3 /* secsig */ && - oid->oid[4] == 2 /* algorithms */ && - oid->oid[5] == 26 /* id-sha1 */; -} - - -static int x509_sha256_oid(struct asn1_oid *oid) -{ - return oid->len == 9 && - oid->oid[0] == 2 /* joint-iso-itu-t */ && - oid->oid[1] == 16 /* country */ && - oid->oid[2] == 840 /* us */ && - oid->oid[3] == 1 /* organization */ && - oid->oid[4] == 101 /* gov */ && - oid->oid[5] == 3 /* csor */ && - oid->oid[6] == 4 /* nistAlgorithm */ && - oid->oid[7] == 2 /* hashAlgs */ && - oid->oid[8] == 1 /* sha256 */; -} - - -/** - * x509_certificate_parse - Parse a X.509 certificate in DER format - * @buf: Pointer to the X.509 certificate in DER format - * @len: Buffer length - * Returns: Pointer to the parsed certificate or %NULL on failure - * - * Caller is responsible for freeing the returned certificate by calling - * x509_certificate_free(). - */ -struct x509_certificate * x509_certificate_parse(const u8 *buf, size_t len) -{ - struct asn1_hdr hdr; - const u8 *pos, *end, *hash_start; - struct x509_certificate *cert; - - cert = os_zalloc(sizeof(*cert) + len); - if (cert == NULL) - return NULL; - os_memcpy(cert + 1, buf, len); - cert->cert_start = (u8 *) (cert + 1); - cert->cert_len = len; - - pos = buf; - end = buf + len; - - /* RFC 3280 - X.509 v3 certificate / ASN.1 DER */ - - /* Certificate ::= SEQUENCE */ - if (asn1_get_next(pos, len, &hdr) < 0 || - hdr.class != ASN1_CLASS_UNIVERSAL || - hdr.tag != ASN1_TAG_SEQUENCE) { - wpa_printf(MSG_DEBUG, "X509: Certificate did not start with " - "a valid SEQUENCE - found class %d tag 0x%x", - hdr.class, hdr.tag); - x509_certificate_free(cert); - return NULL; - } - pos = hdr.payload; - - if (pos + hdr.length > end) { - x509_certificate_free(cert); - return NULL; - } - - if (pos + hdr.length < end) { - wpa_hexdump(MSG_MSGDUMP, "X509: Ignoring extra data after DER " - "encoded certificate", - pos + hdr.length, end - pos + hdr.length); - end = pos + hdr.length; - } - - hash_start = pos; - cert->tbs_cert_start = cert->cert_start + (hash_start - buf); - if (x509_parse_tbs_certificate(pos, end - pos, cert, &pos)) { - x509_certificate_free(cert); - return NULL; - } - cert->tbs_cert_len = pos - hash_start; - - /* signatureAlgorithm AlgorithmIdentifier */ - if (x509_parse_algorithm_identifier(pos, end - pos, - &cert->signature_alg, &pos)) { - x509_certificate_free(cert); - return NULL; - } - - /* signatureValue BIT STRING */ - if (asn1_get_next(pos, end - pos, &hdr) < 0 || - hdr.class != ASN1_CLASS_UNIVERSAL || - hdr.tag != ASN1_TAG_BITSTRING) { - wpa_printf(MSG_DEBUG, "X509: Expected BITSTRING " - "(signatureValue) - found class %d tag 0x%x", - hdr.class, hdr.tag); - x509_certificate_free(cert); - return NULL; - } - if (hdr.length < 1) { - x509_certificate_free(cert); - return NULL; - } - pos = hdr.payload; - if (*pos) { - wpa_printf(MSG_DEBUG, "X509: BITSTRING - %d unused bits", - *pos); - /* PKCS #1 v1.5 10.2.1: - * It is an error if the length in bits of the signature S is - * not a multiple of eight. - */ - x509_certificate_free(cert); - return NULL; - } - os_free(cert->sign_value); - cert->sign_value = os_malloc(hdr.length - 1); - if (cert->sign_value == NULL) { - wpa_printf(MSG_DEBUG, "X509: Failed to allocate memory for " - "signatureValue"); - x509_certificate_free(cert); - return NULL; - } - os_memcpy(cert->sign_value, pos + 1, hdr.length - 1); - cert->sign_value_len = hdr.length - 1; - wpa_hexdump(MSG_MSGDUMP, "X509: signature", - cert->sign_value, cert->sign_value_len); - - return cert; -} - - -/** - * x509_certificate_check_signature - Verify certificate signature - * @issuer: Issuer certificate - * @cert: Certificate to be verified - * Returns: 0 if cert has a valid signature that was signed by the issuer, - * -1 if not - */ -int x509_certificate_check_signature(struct x509_certificate *issuer, - struct x509_certificate *cert) -{ - struct crypto_public_key *pk; - u8 *data; - const u8 *pos, *end, *next, *da_end; - size_t data_len; - struct asn1_hdr hdr; - struct asn1_oid oid; - u8 hash[32]; - size_t hash_len; - - if (!x509_pkcs_oid(&cert->signature.oid) || - cert->signature.oid.len != 7 || - cert->signature.oid.oid[5] != 1 /* pkcs-1 */) { - wpa_printf(MSG_DEBUG, "X509: Unrecognized signature " - "algorithm"); - return -1; - } - - pk = crypto_public_key_import(issuer->public_key, - issuer->public_key_len); - if (pk == NULL) - return -1; - - data_len = cert->sign_value_len; - data = os_malloc(data_len); - if (data == NULL) { - crypto_public_key_free(pk); - return -1; - } - - if (crypto_public_key_decrypt_pkcs1(pk, cert->sign_value, - cert->sign_value_len, data, - &data_len) < 0) { - wpa_printf(MSG_DEBUG, "X509: Failed to decrypt signature"); - crypto_public_key_free(pk); - os_free(data); - return -1; - } - crypto_public_key_free(pk); - - wpa_hexdump(MSG_MSGDUMP, "X509: Signature data D", data, data_len); - - /* - * PKCS #1 v1.5, 10.1.2: - * - * DigestInfo ::= SEQUENCE { - * digestAlgorithm DigestAlgorithmIdentifier, - * digest Digest - * } - * - * DigestAlgorithmIdentifier ::= AlgorithmIdentifier - * - * Digest ::= OCTET STRING - * - */ - if (asn1_get_next(data, data_len, &hdr) < 0 || - hdr.class != ASN1_CLASS_UNIVERSAL || - hdr.tag != ASN1_TAG_SEQUENCE) { - wpa_printf(MSG_DEBUG, "X509: Expected SEQUENCE " - "(DigestInfo) - found class %d tag 0x%x", - hdr.class, hdr.tag); - os_free(data); - return -1; - } - - pos = hdr.payload; - end = pos + hdr.length; - - /* - * X.509: - * AlgorithmIdentifier ::= SEQUENCE { - * algorithm OBJECT IDENTIFIER, - * parameters ANY DEFINED BY algorithm OPTIONAL - * } - */ - - if (asn1_get_next(pos, end - pos, &hdr) < 0 || - hdr.class != ASN1_CLASS_UNIVERSAL || - hdr.tag != ASN1_TAG_SEQUENCE) { - wpa_printf(MSG_DEBUG, "X509: Expected SEQUENCE " - "(AlgorithmIdentifier) - found class %d tag 0x%x", - hdr.class, hdr.tag); - os_free(data); - return -1; - } - da_end = hdr.payload + hdr.length; - - if (asn1_get_oid(hdr.payload, hdr.length, &oid, &next)) { - wpa_printf(MSG_DEBUG, "X509: Failed to parse digestAlgorithm"); - os_free(data); - return -1; - } - - if (x509_sha1_oid(&oid)) { - if (cert->signature.oid.oid[6] != - 5 /* sha-1WithRSAEncryption */) { - wpa_printf(MSG_DEBUG, "X509: digestAlgorithm SHA1 " - "does not match with certificate " - "signatureAlgorithm (%lu)", - cert->signature.oid.oid[6]); - os_free(data); - return -1; - } - goto skip_digest_oid; - } - - if (x509_sha256_oid(&oid)) { - if (cert->signature.oid.oid[6] != - 11 /* sha2561WithRSAEncryption */) { - wpa_printf(MSG_DEBUG, "X509: digestAlgorithm SHA256 " - "does not match with certificate " - "signatureAlgorithm (%lu)", - cert->signature.oid.oid[6]); - os_free(data); - return -1; - } - goto skip_digest_oid; - } - - if (!x509_digest_oid(&oid)) { - wpa_printf(MSG_DEBUG, "X509: Unrecognized digestAlgorithm"); - os_free(data); - return -1; - } - switch (oid.oid[5]) { - case 5: /* md5 */ - if (cert->signature.oid.oid[6] != 4 /* md5WithRSAEncryption */) - { - wpa_printf(MSG_DEBUG, "X509: digestAlgorithm MD5 does " - "not match with certificate " - "signatureAlgorithm (%lu)", - cert->signature.oid.oid[6]); - os_free(data); - return -1; - } - break; - case 2: /* md2 */ - case 4: /* md4 */ - default: - wpa_printf(MSG_DEBUG, "X509: Unsupported digestAlgorithm " - "(%lu)", oid.oid[5]); - os_free(data); - return -1; - } - -skip_digest_oid: - /* Digest ::= OCTET STRING */ - pos = da_end; - end = data + data_len; - - if (asn1_get_next(pos, end - pos, &hdr) < 0 || - hdr.class != ASN1_CLASS_UNIVERSAL || - hdr.tag != ASN1_TAG_OCTETSTRING) { - wpa_printf(MSG_DEBUG, "X509: Expected OCTETSTRING " - "(Digest) - found class %d tag 0x%x", - hdr.class, hdr.tag); - os_free(data); - return -1; - } - wpa_hexdump(MSG_MSGDUMP, "X509: Decrypted Digest", - hdr.payload, hdr.length); - - switch (cert->signature.oid.oid[6]) { - case 4: /* md5WithRSAEncryption */ - md5_vector(1, &cert->tbs_cert_start, &cert->tbs_cert_len, - hash); - hash_len = 16; - wpa_hexdump(MSG_MSGDUMP, "X509: Certificate hash (MD5)", - hash, hash_len); - break; - case 5: /* sha-1WithRSAEncryption */ - sha1_vector(1, &cert->tbs_cert_start, &cert->tbs_cert_len, - hash); - hash_len = 20; - wpa_hexdump(MSG_MSGDUMP, "X509: Certificate hash (SHA1)", - hash, hash_len); - break; - case 11: /* sha256WithRSAEncryption */ - sha256_vector(1, &cert->tbs_cert_start, &cert->tbs_cert_len, - hash); - hash_len = 32; - wpa_hexdump(MSG_MSGDUMP, "X509: Certificate hash (SHA256)", - hash, hash_len); - break; - case 2: /* md2WithRSAEncryption */ - case 12: /* sha384WithRSAEncryption */ - case 13: /* sha512WithRSAEncryption */ - default: - wpa_printf(MSG_INFO, "X509: Unsupported certificate signature " - "algorithm (%lu)", cert->signature.oid.oid[6]); - os_free(data); - return -1; - } - - if (hdr.length != hash_len || - os_memcmp(hdr.payload, hash, hdr.length) != 0) { - wpa_printf(MSG_INFO, "X509: Certificate Digest does not match " - "with calculated tbsCertificate hash"); - os_free(data); - return -1; - } - - os_free(data); - - wpa_printf(MSG_DEBUG, "X509: Certificate Digest matches with " - "calculated tbsCertificate hash"); - - return 0; -} - - -static int x509_valid_issuer(const struct x509_certificate *cert) -{ - if ((cert->extensions_present & X509_EXT_BASIC_CONSTRAINTS) && - !cert->ca) { - wpa_printf(MSG_DEBUG, "X509: Non-CA certificate used as an " - "issuer"); - return -1; - } - - if (cert->version == X509_CERT_V3 && - !(cert->extensions_present & X509_EXT_BASIC_CONSTRAINTS)) { - wpa_printf(MSG_DEBUG, "X509: v3 CA certificate did not " - "include BasicConstraints extension"); - return -1; - } - - if ((cert->extensions_present & X509_EXT_KEY_USAGE) && - !(cert->key_usage & X509_KEY_USAGE_KEY_CERT_SIGN)) { - wpa_printf(MSG_DEBUG, "X509: Issuer certificate did not have " - "keyCertSign bit in Key Usage"); - return -1; - } - - return 0; -} - - -/** - * x509_certificate_chain_validate - Validate X.509 certificate chain - * @trusted: List of trusted certificates - * @chain: Certificate chain to be validated (first chain must be issued by - * signed by the second certificate in the chain and so on) - * @reason: Buffer for returning failure reason (X509_VALIDATE_*) - * Returns: 0 if chain is valid, -1 if not - */ -int x509_certificate_chain_validate(struct x509_certificate *trusted, - struct x509_certificate *chain, - int *reason) -{ - long unsigned idx; - int chain_trusted = 0; - struct x509_certificate *cert, *trust; - char buf[128]; - struct os_time now; - - *reason = X509_VALIDATE_OK; - - wpa_printf(MSG_DEBUG, "X509: Validate certificate chain"); - os_get_time(&now); - - for (cert = chain, idx = 0; cert; cert = cert->next, idx++) { - x509_name_string(&cert->subject, buf, sizeof(buf)); - wpa_printf(MSG_DEBUG, "X509: %lu: %s", idx, buf); - - if (chain_trusted) - continue; - - if ((unsigned long) now.sec < - (unsigned long) cert->not_before || - (unsigned long) now.sec > - (unsigned long) cert->not_after) { - wpa_printf(MSG_INFO, "X509: Certificate not valid " - "(now=%lu not_before=%lu not_after=%lu)", - now.sec, cert->not_before, cert->not_after); - *reason = X509_VALIDATE_CERTIFICATE_EXPIRED; - return -1; - } - - if (cert->next) { - if (x509_name_compare(&cert->issuer, - &cert->next->subject) != 0) { - wpa_printf(MSG_DEBUG, "X509: Certificate " - "chain issuer name mismatch"); - x509_name_string(&cert->issuer, buf, - sizeof(buf)); - wpa_printf(MSG_DEBUG, "X509: cert issuer: %s", - buf); - x509_name_string(&cert->next->subject, buf, - sizeof(buf)); - wpa_printf(MSG_DEBUG, "X509: next cert " - "subject: %s", buf); - *reason = X509_VALIDATE_CERTIFICATE_UNKNOWN; - return -1; - } - - if (x509_valid_issuer(cert->next) < 0) { - *reason = X509_VALIDATE_BAD_CERTIFICATE; - return -1; - } - - if ((cert->next->extensions_present & - X509_EXT_PATH_LEN_CONSTRAINT) && - idx > cert->next->path_len_constraint) { - wpa_printf(MSG_DEBUG, "X509: pathLenConstraint" - " not met (idx=%lu issuer " - "pathLenConstraint=%lu)", idx, - cert->next->path_len_constraint); - *reason = X509_VALIDATE_BAD_CERTIFICATE; - return -1; - } - - if (x509_certificate_check_signature(cert->next, cert) - < 0) { - wpa_printf(MSG_DEBUG, "X509: Invalid " - "certificate signature within " - "chain"); - *reason = X509_VALIDATE_BAD_CERTIFICATE; - return -1; - } - } - - for (trust = trusted; trust; trust = trust->next) { - if (x509_name_compare(&cert->issuer, &trust->subject) - == 0) - break; - } - - if (trust) { - wpa_printf(MSG_DEBUG, "X509: Found issuer from the " - "list of trusted certificates"); - if (x509_valid_issuer(trust) < 0) { - *reason = X509_VALIDATE_BAD_CERTIFICATE; - return -1; - } - - if (x509_certificate_check_signature(trust, cert) < 0) - { - wpa_printf(MSG_DEBUG, "X509: Invalid " - "certificate signature"); - *reason = X509_VALIDATE_BAD_CERTIFICATE; - return -1; - } - - wpa_printf(MSG_DEBUG, "X509: Trusted certificate " - "found to complete the chain"); - chain_trusted = 1; - } - } - - if (!chain_trusted) { - wpa_printf(MSG_DEBUG, "X509: Did not find any of the issuers " - "from the list of trusted certificates"); - if (trusted) { - *reason = X509_VALIDATE_UNKNOWN_CA; - return -1; - } - wpa_printf(MSG_DEBUG, "X509: Certificate chain validation " - "disabled - ignore unknown CA issue"); - } - - wpa_printf(MSG_DEBUG, "X509: Certificate chain valid"); - - return 0; -} - - -/** - * x509_certificate_get_subject - Get a certificate based on Subject name - * @chain: Certificate chain to search through - * @name: Subject name to search for - * Returns: Pointer to the certificate with the given Subject name or - * %NULL on failure - */ -struct x509_certificate * -x509_certificate_get_subject(struct x509_certificate *chain, - struct x509_name *name) -{ - struct x509_certificate *cert; - - for (cert = chain; cert; cert = cert->next) { - if (x509_name_compare(&cert->subject, name) == 0) - return cert; - } - return NULL; -} - - -/** - * x509_certificate_self_signed - Is the certificate self-signed? - * @cert: Certificate - * Returns: 1 if certificate is self-signed, 0 if not - */ -int x509_certificate_self_signed(struct x509_certificate *cert) -{ - return x509_name_compare(&cert->issuer, &cert->subject) == 0; -} diff --git a/hostapd-0.8/src/tls/x509v3.h b/hostapd-0.8/src/tls/x509v3.h deleted file mode 100644 index 37292d7..0000000 --- a/hostapd-0.8/src/tls/x509v3.h +++ /dev/null @@ -1,129 +0,0 @@ -/* - * X.509v3 certificate parsing and processing - * Copyright (c) 2006, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#ifndef X509V3_H -#define X509V3_H - -#include "asn1.h" - -struct x509_algorithm_identifier { - struct asn1_oid oid; -}; - -struct x509_name_attr { - enum x509_name_attr_type { - X509_NAME_ATTR_NOT_USED, - X509_NAME_ATTR_DC, - X509_NAME_ATTR_CN, - X509_NAME_ATTR_C, - X509_NAME_ATTR_L, - X509_NAME_ATTR_ST, - X509_NAME_ATTR_O, - X509_NAME_ATTR_OU - } type; - char *value; -}; - -#define X509_MAX_NAME_ATTRIBUTES 20 - -struct x509_name { - struct x509_name_attr attr[X509_MAX_NAME_ATTRIBUTES]; - size_t num_attr; - char *email; /* emailAddress */ - - /* from alternative name extension */ - char *alt_email; /* rfc822Name */ - char *dns; /* dNSName */ - char *uri; /* uniformResourceIdentifier */ - u8 *ip; /* iPAddress */ - size_t ip_len; /* IPv4: 4, IPv6: 16 */ - struct asn1_oid rid; /* registeredID */ -}; - -struct x509_certificate { - struct x509_certificate *next; - enum { X509_CERT_V1 = 0, X509_CERT_V2 = 1, X509_CERT_V3 = 2 } version; - unsigned long serial_number; - struct x509_algorithm_identifier signature; - struct x509_name issuer; - struct x509_name subject; - os_time_t not_before; - os_time_t not_after; - struct x509_algorithm_identifier public_key_alg; - u8 *public_key; - size_t public_key_len; - struct x509_algorithm_identifier signature_alg; - u8 *sign_value; - size_t sign_value_len; - - /* Extensions */ - unsigned int extensions_present; -#define X509_EXT_BASIC_CONSTRAINTS (1 << 0) -#define X509_EXT_PATH_LEN_CONSTRAINT (1 << 1) -#define X509_EXT_KEY_USAGE (1 << 2) -#define X509_EXT_SUBJECT_ALT_NAME (1 << 3) -#define X509_EXT_ISSUER_ALT_NAME (1 << 4) - - /* BasicConstraints */ - int ca; /* cA */ - unsigned long path_len_constraint; /* pathLenConstraint */ - - /* KeyUsage */ - unsigned long key_usage; -#define X509_KEY_USAGE_DIGITAL_SIGNATURE (1 << 0) -#define X509_KEY_USAGE_NON_REPUDIATION (1 << 1) -#define X509_KEY_USAGE_KEY_ENCIPHERMENT (1 << 2) -#define X509_KEY_USAGE_DATA_ENCIPHERMENT (1 << 3) -#define X509_KEY_USAGE_KEY_AGREEMENT (1 << 4) -#define X509_KEY_USAGE_KEY_CERT_SIGN (1 << 5) -#define X509_KEY_USAGE_CRL_SIGN (1 << 6) -#define X509_KEY_USAGE_ENCIPHER_ONLY (1 << 7) -#define X509_KEY_USAGE_DECIPHER_ONLY (1 << 8) - - /* - * The DER format certificate follows struct x509_certificate. These - * pointers point to that buffer. - */ - const u8 *cert_start; - size_t cert_len; - const u8 *tbs_cert_start; - size_t tbs_cert_len; -}; - -enum { - X509_VALIDATE_OK, - X509_VALIDATE_BAD_CERTIFICATE, - X509_VALIDATE_UNSUPPORTED_CERTIFICATE, - X509_VALIDATE_CERTIFICATE_REVOKED, - X509_VALIDATE_CERTIFICATE_EXPIRED, - X509_VALIDATE_CERTIFICATE_UNKNOWN, - X509_VALIDATE_UNKNOWN_CA -}; - -void x509_certificate_free(struct x509_certificate *cert); -struct x509_certificate * x509_certificate_parse(const u8 *buf, size_t len); -void x509_name_string(struct x509_name *name, char *buf, size_t len); -int x509_name_compare(struct x509_name *a, struct x509_name *b); -void x509_certificate_chain_free(struct x509_certificate *cert); -int x509_certificate_check_signature(struct x509_certificate *issuer, - struct x509_certificate *cert); -int x509_certificate_chain_validate(struct x509_certificate *trusted, - struct x509_certificate *chain, - int *reason); -struct x509_certificate * -x509_certificate_get_subject(struct x509_certificate *chain, - struct x509_name *name); -int x509_certificate_self_signed(struct x509_certificate *cert); - -#endif /* X509V3_H */ diff --git a/hostapd-0.8/src/utils/.gitignore b/hostapd-0.8/src/utils/.gitignore deleted file mode 100644 index 833734f..0000000 --- a/hostapd-0.8/src/utils/.gitignore +++ /dev/null @@ -1 +0,0 @@ -libutils.a diff --git a/hostapd-0.8/src/utils/Makefile b/hostapd-0.8/src/utils/Makefile deleted file mode 100644 index 0f1f191..0000000 --- a/hostapd-0.8/src/utils/Makefile +++ /dev/null @@ -1,39 +0,0 @@ -all: libutils.a - -clean: - rm -f *~ *.o *.d libutils.a - -install: - @echo Nothing to be made. - - -include ../lib.rules - -#CFLAGS += -DWPA_TRACE -CFLAGS += -DCONFIG_IPV6 - -LIB_OBJS= \ - base64.o \ - common.o \ - ip_addr.o \ - radiotap.o \ - trace.o \ - uuid.o \ - wpa_debug.o \ - wpabuf.o - -# Pick correct OS wrapper implementation -LIB_OBJS += os_unix.o - -# Pick correct event loop implementation -LIB_OBJS += eloop.o - -# Pick correct edit implementation -LIB_OBJS += edit.o - -#LIB_OBJS += pcsc_funcs.o - -libutils.a: $(LIB_OBJS) - $(AR) crT $@ $? - --include $(OBJS:%.o=%.d) diff --git a/hostapd-0.8/src/utils/base64.c b/hostapd-0.8/src/utils/base64.c deleted file mode 100644 index 155bfce..0000000 --- a/hostapd-0.8/src/utils/base64.c +++ /dev/null @@ -1,154 +0,0 @@ -/* - * Base64 encoding/decoding (RFC1341) - * Copyright (c) 2005, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#include "includes.h" - -#include "os.h" -#include "base64.h" - -static const unsigned char base64_table[65] = - "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; - -/** - * base64_encode - Base64 encode - * @src: Data to be encoded - * @len: Length of the data to be encoded - * @out_len: Pointer to output length variable, or %NULL if not used - * Returns: Allocated buffer of out_len bytes of encoded data, - * or %NULL on failure - * - * Caller is responsible for freeing the returned buffer. Returned buffer is - * nul terminated to make it easier to use as a C string. The nul terminator is - * not included in out_len. - */ -unsigned char * base64_encode(const unsigned char *src, size_t len, - size_t *out_len) -{ - unsigned char *out, *pos; - const unsigned char *end, *in; - size_t olen; - int line_len; - - olen = len * 4 / 3 + 4; /* 3-byte blocks to 4-byte */ - olen += olen / 72; /* line feeds */ - olen++; /* nul termination */ - if (olen < len) - return NULL; /* integer overflow */ - out = os_malloc(olen); - if (out == NULL) - return NULL; - - end = src + len; - in = src; - pos = out; - line_len = 0; - while (end - in >= 3) { - *pos++ = base64_table[in[0] >> 2]; - *pos++ = base64_table[((in[0] & 0x03) << 4) | (in[1] >> 4)]; - *pos++ = base64_table[((in[1] & 0x0f) << 2) | (in[2] >> 6)]; - *pos++ = base64_table[in[2] & 0x3f]; - in += 3; - line_len += 4; - if (line_len >= 72) { - *pos++ = '\n'; - line_len = 0; - } - } - - if (end - in) { - *pos++ = base64_table[in[0] >> 2]; - if (end - in == 1) { - *pos++ = base64_table[(in[0] & 0x03) << 4]; - *pos++ = '='; - } else { - *pos++ = base64_table[((in[0] & 0x03) << 4) | - (in[1] >> 4)]; - *pos++ = base64_table[(in[1] & 0x0f) << 2]; - } - *pos++ = '='; - line_len += 4; - } - - if (line_len) - *pos++ = '\n'; - - *pos = '\0'; - if (out_len) - *out_len = pos - out; - return out; -} - - -/** - * base64_decode - Base64 decode - * @src: Data to be decoded - * @len: Length of the data to be decoded - * @out_len: Pointer to output length variable - * Returns: Allocated buffer of out_len bytes of decoded data, - * or %NULL on failure - * - * Caller is responsible for freeing the returned buffer. - */ -unsigned char * base64_decode(const unsigned char *src, size_t len, - size_t *out_len) -{ - unsigned char dtable[256], *out, *pos, in[4], block[4], tmp; - size_t i, count, olen; - - os_memset(dtable, 0x80, 256); - for (i = 0; i < sizeof(base64_table) - 1; i++) - dtable[base64_table[i]] = (unsigned char) i; - dtable['='] = 0; - - count = 0; - for (i = 0; i < len; i++) { - if (dtable[src[i]] != 0x80) - count++; - } - - if (count == 0 || count % 4) - return NULL; - - olen = count / 4 * 3; - pos = out = os_malloc(olen); - if (out == NULL) - return NULL; - - count = 0; - for (i = 0; i < len; i++) { - tmp = dtable[src[i]]; - if (tmp == 0x80) - continue; - - in[count] = src[i]; - block[count] = tmp; - count++; - if (count == 4) { - *pos++ = (block[0] << 2) | (block[1] >> 4); - *pos++ = (block[1] << 4) | (block[2] >> 2); - *pos++ = (block[2] << 6) | block[3]; - count = 0; - } - } - - if (pos > out) { - if (in[2] == '=') - pos -= 2; - else if (in[3] == '=') - pos--; - } - - *out_len = pos - out; - return out; -} diff --git a/hostapd-0.8/src/utils/base64.h b/hostapd-0.8/src/utils/base64.h deleted file mode 100644 index b87a168..0000000 --- a/hostapd-0.8/src/utils/base64.h +++ /dev/null @@ -1,23 +0,0 @@ -/* - * Base64 encoding/decoding (RFC1341) - * Copyright (c) 2005, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#ifndef BASE64_H -#define BASE64_H - -unsigned char * base64_encode(const unsigned char *src, size_t len, - size_t *out_len); -unsigned char * base64_decode(const unsigned char *src, size_t len, - size_t *out_len); - -#endif /* BASE64_H */ diff --git a/hostapd-0.8/src/utils/build_config.h b/hostapd-0.8/src/utils/build_config.h deleted file mode 100644 index 3666778..0000000 --- a/hostapd-0.8/src/utils/build_config.h +++ /dev/null @@ -1,105 +0,0 @@ -/* - * wpa_supplicant/hostapd - Build time configuration defines - * Copyright (c) 2005-2006, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - * - * This header file can be used to define configuration defines that were - * originally defined in Makefile. This is mainly meant for IDE use or for - * systems that do not have suitable 'make' tool. In these cases, it may be - * easier to have a single place for defining all the needed C pre-processor - * defines. - */ - -#ifndef BUILD_CONFIG_H -#define BUILD_CONFIG_H - -/* Insert configuration defines, e.g., #define EAP_MD5, here, if needed. */ - -#ifdef CONFIG_WIN32_DEFAULTS -#define CONFIG_NATIVE_WINDOWS -#define CONFIG_ANSI_C_EXTRA -#define CONFIG_WINPCAP -#define IEEE8021X_EAPOL -#define PKCS12_FUNCS -#define PCSC_FUNCS -#define CONFIG_CTRL_IFACE -#define CONFIG_CTRL_IFACE_NAMED_PIPE -#define CONFIG_DRIVER_NDIS -#define CONFIG_NDIS_EVENTS_INTEGRATED -#define CONFIG_DEBUG_FILE -#define EAP_MD5 -#define EAP_TLS -#define EAP_MSCHAPv2 -#define EAP_PEAP -#define EAP_TTLS -#define EAP_GTC -#define EAP_OTP -#define EAP_LEAP -#define EAP_TNC -#define _CRT_SECURE_NO_DEPRECATE - -#ifdef USE_INTERNAL_CRYPTO -#define CONFIG_TLS_INTERNAL_CLIENT -#define CONFIG_INTERNAL_LIBTOMMATH -#define CONFIG_CRYPTO_INTERNAL -#endif /* USE_INTERNAL_CRYPTO */ -#endif /* CONFIG_WIN32_DEFAULTS */ - -#ifdef __SYMBIAN32__ -#define OS_NO_C_LIB_DEFINES -#define CONFIG_ANSI_C_EXTRA -#define CONFIG_NO_WPA_MSG -#define CONFIG_NO_HOSTAPD_LOGGER -#define CONFIG_NO_STDOUT_DEBUG -#define CONFIG_BACKEND_FILE -#define CONFIG_INTERNAL_LIBTOMMATH -#define CONFIG_CRYPTO_INTERNAL -#define IEEE8021X_EAPOL -#define PKCS12_FUNCS -#define EAP_MD5 -#define EAP_TLS -#define EAP_MSCHAPv2 -#define EAP_PEAP -#define EAP_TTLS -#define EAP_GTC -#define EAP_OTP -#define EAP_LEAP -#define EAP_FAST -#endif /* __SYMBIAN32__ */ - -#ifdef CONFIG_XCODE_DEFAULTS -#define CONFIG_DRIVER_OSX -#define CONFIG_BACKEND_FILE -#define IEEE8021X_EAPOL -#define PKCS12_FUNCS -#define CONFIG_CTRL_IFACE -#define CONFIG_CTRL_IFACE_UNIX -#define CONFIG_DEBUG_FILE -#define EAP_MD5 -#define EAP_TLS -#define EAP_MSCHAPv2 -#define EAP_PEAP -#define EAP_TTLS -#define EAP_GTC -#define EAP_OTP -#define EAP_LEAP -#define EAP_TNC -#define CONFIG_WPS -#define EAP_WSC - -#ifdef USE_INTERNAL_CRYPTO -#define CONFIG_TLS_INTERNAL_CLIENT -#define CONFIG_INTERNAL_LIBTOMMATH -#define CONFIG_CRYPTO_INTERNAL -#endif /* USE_INTERNAL_CRYPTO */ -#endif /* CONFIG_XCODE_DEFAULTS */ - -#endif /* BUILD_CONFIG_H */ diff --git a/hostapd-0.8/src/utils/common.c b/hostapd-0.8/src/utils/common.c deleted file mode 100644 index 89eca1c..0000000 --- a/hostapd-0.8/src/utils/common.c +++ /dev/null @@ -1,387 +0,0 @@ -/* - * wpa_supplicant/hostapd / common helper functions, etc. - * Copyright (c) 2002-2007, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#include "includes.h" - -#include "common.h" - - -static int hex2num(char c) -{ - if (c >= '0' && c <= '9') - return c - '0'; - if (c >= 'a' && c <= 'f') - return c - 'a' + 10; - if (c >= 'A' && c <= 'F') - return c - 'A' + 10; - return -1; -} - - -int hex2byte(const char *hex) -{ - int a, b; - a = hex2num(*hex++); - if (a < 0) - return -1; - b = hex2num(*hex++); - if (b < 0) - return -1; - return (a << 4) | b; -} - - -/** - * hwaddr_aton - Convert ASCII string to MAC address (colon-delimited format) - * @txt: MAC address as a string (e.g., "00:11:22:33:44:55") - * @addr: Buffer for the MAC address (ETH_ALEN = 6 bytes) - * Returns: 0 on success, -1 on failure (e.g., string not a MAC address) - */ -int hwaddr_aton(const char *txt, u8 *addr) -{ - int i; - - for (i = 0; i < 6; i++) { - int a, b; - - a = hex2num(*txt++); - if (a < 0) - return -1; - b = hex2num(*txt++); - if (b < 0) - return -1; - *addr++ = (a << 4) | b; - if (i < 5 && *txt++ != ':') - return -1; - } - - return 0; -} - -/** - * hwaddr_compact_aton - Convert ASCII string to MAC address (no colon delimitors format) - * @txt: MAC address as a string (e.g., "001122334455") - * @addr: Buffer for the MAC address (ETH_ALEN = 6 bytes) - * Returns: 0 on success, -1 on failure (e.g., string not a MAC address) - */ -int hwaddr_compact_aton(const char *txt, u8 *addr) -{ - int i; - - for (i = 0; i < 6; i++) { - int a, b; - - a = hex2num(*txt++); - if (a < 0) - return -1; - b = hex2num(*txt++); - if (b < 0) - return -1; - *addr++ = (a << 4) | b; - } - - return 0; -} - -/** - * hwaddr_aton2 - Convert ASCII string to MAC address (in any known format) - * @txt: MAC address as a string (e.g., 00:11:22:33:44:55 or 0011.2233.4455) - * @addr: Buffer for the MAC address (ETH_ALEN = 6 bytes) - * Returns: Characters used (> 0) on success, -1 on failure - */ -int hwaddr_aton2(const char *txt, u8 *addr) -{ - int i; - const char *pos = txt; - - for (i = 0; i < 6; i++) { - int a, b; - - while (*pos == ':' || *pos == '.' || *pos == '-') - pos++; - - a = hex2num(*pos++); - if (a < 0) - return -1; - b = hex2num(*pos++); - if (b < 0) - return -1; - *addr++ = (a << 4) | b; - } - - return pos - txt; -} - - -/** - * hexstr2bin - Convert ASCII hex string into binary data - * @hex: ASCII hex string (e.g., "01ab") - * @buf: Buffer for the binary data - * @len: Length of the text to convert in bytes (of buf); hex will be double - * this size - * Returns: 0 on success, -1 on failure (invalid hex string) - */ -int hexstr2bin(const char *hex, u8 *buf, size_t len) -{ - size_t i; - int a; - const char *ipos = hex; - u8 *opos = buf; - - for (i = 0; i < len; i++) { - a = hex2byte(ipos); - if (a < 0) - return -1; - *opos++ = a; - ipos += 2; - } - return 0; -} - - -/** - * inc_byte_array - Increment arbitrary length byte array by one - * @counter: Pointer to byte array - * @len: Length of the counter in bytes - * - * This function increments the last byte of the counter by one and continues - * rolling over to more significant bytes if the byte was incremented from - * 0xff to 0x00. - */ -void inc_byte_array(u8 *counter, size_t len) -{ - int pos = len - 1; - while (pos >= 0) { - counter[pos]++; - if (counter[pos] != 0) - break; - pos--; - } -} - - -void wpa_get_ntp_timestamp(u8 *buf) -{ - struct os_time now; - u32 sec, usec; - be32 tmp; - - /* 64-bit NTP timestamp (time from 1900-01-01 00:00:00) */ - os_get_time(&now); - sec = now.sec + 2208988800U; /* Epoch to 1900 */ - /* Estimate 2^32/10^6 = 4295 - 1/32 - 1/512 */ - usec = now.usec; - usec = 4295 * usec - (usec >> 5) - (usec >> 9); - tmp = host_to_be32(sec); - os_memcpy(buf, (u8 *) &tmp, 4); - tmp = host_to_be32(usec); - os_memcpy(buf + 4, (u8 *) &tmp, 4); -} - - -static inline int _wpa_snprintf_hex(char *buf, size_t buf_size, const u8 *data, - size_t len, int uppercase) -{ - size_t i; - char *pos = buf, *end = buf + buf_size; - int ret; - if (buf_size == 0) - return 0; - for (i = 0; i < len; i++) { - ret = os_snprintf(pos, end - pos, uppercase ? "%02X" : "%02x", - data[i]); - if (ret < 0 || ret >= end - pos) { - end[-1] = '\0'; - return pos - buf; - } - pos += ret; - } - end[-1] = '\0'; - return pos - buf; -} - -/** - * wpa_snprintf_hex - Print data as a hex string into a buffer - * @buf: Memory area to use as the output buffer - * @buf_size: Maximum buffer size in bytes (should be at least 2 * len + 1) - * @data: Data to be printed - * @len: Length of data in bytes - * Returns: Number of bytes written - */ -int wpa_snprintf_hex(char *buf, size_t buf_size, const u8 *data, size_t len) -{ - return _wpa_snprintf_hex(buf, buf_size, data, len, 0); -} - - -/** - * wpa_snprintf_hex_uppercase - Print data as a upper case hex string into buf - * @buf: Memory area to use as the output buffer - * @buf_size: Maximum buffer size in bytes (should be at least 2 * len + 1) - * @data: Data to be printed - * @len: Length of data in bytes - * Returns: Number of bytes written - */ -int wpa_snprintf_hex_uppercase(char *buf, size_t buf_size, const u8 *data, - size_t len) -{ - return _wpa_snprintf_hex(buf, buf_size, data, len, 1); -} - - -#ifdef CONFIG_ANSI_C_EXTRA - -#ifdef _WIN32_WCE -void perror(const char *s) -{ - wpa_printf(MSG_ERROR, "%s: GetLastError: %d", - s, (int) GetLastError()); -} -#endif /* _WIN32_WCE */ - - -int optind = 1; -int optopt; -char *optarg; - -int getopt(int argc, char *const argv[], const char *optstring) -{ - static int optchr = 1; - char *cp; - - if (optchr == 1) { - if (optind >= argc) { - /* all arguments processed */ - return EOF; - } - - if (argv[optind][0] != '-' || argv[optind][1] == '\0') { - /* no option characters */ - return EOF; - } - } - - if (os_strcmp(argv[optind], "--") == 0) { - /* no more options */ - optind++; - return EOF; - } - - optopt = argv[optind][optchr]; - cp = os_strchr(optstring, optopt); - if (cp == NULL || optopt == ':') { - if (argv[optind][++optchr] == '\0') { - optchr = 1; - optind++; - } - return '?'; - } - - if (cp[1] == ':') { - /* Argument required */ - optchr = 1; - if (argv[optind][optchr + 1]) { - /* No space between option and argument */ - optarg = &argv[optind++][optchr + 1]; - } else if (++optind >= argc) { - /* option requires an argument */ - return '?'; - } else { - /* Argument in the next argv */ - optarg = argv[optind++]; - } - } else { - /* No argument */ - if (argv[optind][++optchr] == '\0') { - optchr = 1; - optind++; - } - optarg = NULL; - } - return *cp; -} -#endif /* CONFIG_ANSI_C_EXTRA */ - - -#ifdef CONFIG_NATIVE_WINDOWS -/** - * wpa_unicode2ascii_inplace - Convert unicode string into ASCII - * @str: Pointer to string to convert - * - * This function converts a unicode string to ASCII using the same - * buffer for output. If UNICODE is not set, the buffer is not - * modified. - */ -void wpa_unicode2ascii_inplace(TCHAR *str) -{ -#ifdef UNICODE - char *dst = (char *) str; - while (*str) - *dst++ = (char) *str++; - *dst = '\0'; -#endif /* UNICODE */ -} - - -TCHAR * wpa_strdup_tchar(const char *str) -{ -#ifdef UNICODE - TCHAR *buf; - buf = os_malloc((strlen(str) + 1) * sizeof(TCHAR)); - if (buf == NULL) - return NULL; - wsprintf(buf, L"%S", str); - return buf; -#else /* UNICODE */ - return os_strdup(str); -#endif /* UNICODE */ -} -#endif /* CONFIG_NATIVE_WINDOWS */ - - -/** - * wpa_ssid_txt - Convert SSID to a printable string - * @ssid: SSID (32-octet string) - * @ssid_len: Length of ssid in octets - * Returns: Pointer to a printable string - * - * This function can be used to convert SSIDs into printable form. In most - * cases, SSIDs do not use unprintable characters, but IEEE 802.11 standard - * does not limit the used character set, so anything could be used in an SSID. - * - * This function uses a static buffer, so only one call can be used at the - * time, i.e., this is not re-entrant and the returned buffer must be used - * before calling this again. - */ -const char * wpa_ssid_txt(const u8 *ssid, size_t ssid_len) -{ - static char ssid_txt[33]; - char *pos; - - if (ssid_len > 32) - ssid_len = 32; - os_memcpy(ssid_txt, ssid, ssid_len); - ssid_txt[ssid_len] = '\0'; - for (pos = ssid_txt; *pos != '\0'; pos++) { - if ((u8) *pos < 32 || (u8) *pos >= 127) - *pos = '_'; - } - return ssid_txt; -} - - -void * __hide_aliasing_typecast(void *foo) -{ - return foo; -} diff --git a/hostapd-0.8/src/utils/common.h b/hostapd-0.8/src/utils/common.h deleted file mode 100644 index 14ab297..0000000 --- a/hostapd-0.8/src/utils/common.h +++ /dev/null @@ -1,502 +0,0 @@ -/* - * wpa_supplicant/hostapd / common helper functions, etc. - * Copyright (c) 2002-2007, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#ifndef COMMON_H -#define COMMON_H - -#include "os.h" - -#if defined(__linux__) || defined(__GLIBC__) -#include -#include -#endif /* __linux__ */ - -#if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__DragonFly__) || \ - defined(__OpenBSD__) -#include -#include -#define __BYTE_ORDER _BYTE_ORDER -#define __LITTLE_ENDIAN _LITTLE_ENDIAN -#define __BIG_ENDIAN _BIG_ENDIAN -#ifdef __OpenBSD__ -#define bswap_16 swap16 -#define bswap_32 swap32 -#define bswap_64 swap64 -#else /* __OpenBSD__ */ -#define bswap_16 bswap16 -#define bswap_32 bswap32 -#define bswap_64 bswap64 -#endif /* __OpenBSD__ */ -#endif /* defined(__FreeBSD__) || defined(__NetBSD__) || - * defined(__DragonFly__) || defined(__OpenBSD__) */ - -#ifdef __APPLE__ -#include -#include -#define __BYTE_ORDER _BYTE_ORDER -#define __LITTLE_ENDIAN _LITTLE_ENDIAN -#define __BIG_ENDIAN _BIG_ENDIAN -static inline unsigned short bswap_16(unsigned short v) -{ - return ((v & 0xff) << 8) | (v >> 8); -} - -static inline unsigned int bswap_32(unsigned int v) -{ - return ((v & 0xff) << 24) | ((v & 0xff00) << 8) | - ((v & 0xff0000) >> 8) | (v >> 24); -} -#endif /* __APPLE__ */ - -#ifdef CONFIG_TI_COMPILER -#define __BIG_ENDIAN 4321 -#define __LITTLE_ENDIAN 1234 -#ifdef __big_endian__ -#define __BYTE_ORDER __BIG_ENDIAN -#else -#define __BYTE_ORDER __LITTLE_ENDIAN -#endif -#endif /* CONFIG_TI_COMPILER */ - -#ifdef __SYMBIAN32__ -#define __BIG_ENDIAN 4321 -#define __LITTLE_ENDIAN 1234 -#define __BYTE_ORDER __LITTLE_ENDIAN -#endif /* __SYMBIAN32__ */ - -#ifdef CONFIG_NATIVE_WINDOWS -#include - -typedef int socklen_t; - -#ifndef MSG_DONTWAIT -#define MSG_DONTWAIT 0 /* not supported */ -#endif - -#endif /* CONFIG_NATIVE_WINDOWS */ - -#ifdef _MSC_VER -#define inline __inline - -#undef vsnprintf -#define vsnprintf _vsnprintf -#undef close -#define close closesocket -#endif /* _MSC_VER */ - - -/* Define platform specific integer types */ - -#ifdef _MSC_VER -typedef UINT64 u64; -typedef UINT32 u32; -typedef UINT16 u16; -typedef UINT8 u8; -typedef INT64 s64; -typedef INT32 s32; -typedef INT16 s16; -typedef INT8 s8; -#define WPA_TYPES_DEFINED -#endif /* _MSC_VER */ - -#ifdef __vxworks -typedef unsigned long long u64; -typedef UINT32 u32; -typedef UINT16 u16; -typedef UINT8 u8; -typedef long long s64; -typedef INT32 s32; -typedef INT16 s16; -typedef INT8 s8; -#define WPA_TYPES_DEFINED -#endif /* __vxworks */ - -#ifdef CONFIG_TI_COMPILER -#ifdef _LLONG_AVAILABLE -typedef unsigned long long u64; -#else -/* - * TODO: 64-bit variable not available. Using long as a workaround to test the - * build, but this will likely not work for all operations. - */ -typedef unsigned long u64; -#endif -typedef unsigned int u32; -typedef unsigned short u16; -typedef unsigned char u8; -#define WPA_TYPES_DEFINED -#endif /* CONFIG_TI_COMPILER */ - -#ifdef __SYMBIAN32__ -#define __REMOVE_PLATSEC_DIAGNOSTICS__ -#include -typedef TUint64 u64; -typedef TUint32 u32; -typedef TUint16 u16; -typedef TUint8 u8; -#define WPA_TYPES_DEFINED -#endif /* __SYMBIAN32__ */ - -#ifndef WPA_TYPES_DEFINED -#ifdef CONFIG_USE_INTTYPES_H -#include -#else -#include -#endif -typedef uint64_t u64; -typedef uint32_t u32; -typedef uint16_t u16; -typedef uint8_t u8; -typedef int64_t s64; -typedef int32_t s32; -typedef int16_t s16; -typedef int8_t s8; -#define WPA_TYPES_DEFINED -#endif /* !WPA_TYPES_DEFINED */ - - -/* Define platform specific byte swapping macros */ - -#if defined(__CYGWIN__) || defined(CONFIG_NATIVE_WINDOWS) - -static inline unsigned short wpa_swap_16(unsigned short v) -{ - return ((v & 0xff) << 8) | (v >> 8); -} - -static inline unsigned int wpa_swap_32(unsigned int v) -{ - return ((v & 0xff) << 24) | ((v & 0xff00) << 8) | - ((v & 0xff0000) >> 8) | (v >> 24); -} - -#define le_to_host16(n) (n) -#define host_to_le16(n) (n) -#define be_to_host16(n) wpa_swap_16(n) -#define host_to_be16(n) wpa_swap_16(n) -#define le_to_host32(n) (n) -#define be_to_host32(n) wpa_swap_32(n) -#define host_to_be32(n) wpa_swap_32(n) - -#define WPA_BYTE_SWAP_DEFINED - -#endif /* __CYGWIN__ || CONFIG_NATIVE_WINDOWS */ - - -#ifndef WPA_BYTE_SWAP_DEFINED - -#ifndef __BYTE_ORDER -#ifndef __LITTLE_ENDIAN -#ifndef __BIG_ENDIAN -#define __LITTLE_ENDIAN 1234 -#define __BIG_ENDIAN 4321 -#if defined(sparc) -#define __BYTE_ORDER __BIG_ENDIAN -#endif -#endif /* __BIG_ENDIAN */ -#endif /* __LITTLE_ENDIAN */ -#endif /* __BYTE_ORDER */ - -#if __BYTE_ORDER == __LITTLE_ENDIAN -#define le_to_host16(n) ((__force u16) (le16) (n)) -#define host_to_le16(n) ((__force le16) (u16) (n)) -#define be_to_host16(n) bswap_16((__force u16) (be16) (n)) -#define host_to_be16(n) ((__force be16) bswap_16((n))) -#define le_to_host32(n) ((__force u32) (le32) (n)) -#define host_to_le32(n) ((__force le32) (u32) (n)) -#define be_to_host32(n) bswap_32((__force u32) (be32) (n)) -#define host_to_be32(n) ((__force be32) bswap_32((n))) -#define le_to_host64(n) ((__force u64) (le64) (n)) -#define host_to_le64(n) ((__force le64) (u64) (n)) -#define be_to_host64(n) bswap_64((__force u64) (be64) (n)) -#define host_to_be64(n) ((__force be64) bswap_64((n))) -#elif __BYTE_ORDER == __BIG_ENDIAN -#define le_to_host16(n) bswap_16(n) -#define host_to_le16(n) bswap_16(n) -#define be_to_host16(n) (n) -#define host_to_be16(n) (n) -#define le_to_host32(n) bswap_32(n) -#define be_to_host32(n) (n) -#define host_to_be32(n) (n) -#define le_to_host64(n) bswap_64(n) -#define host_to_le64(n) bswap_64(n) -#define be_to_host64(n) (n) -#define host_to_be64(n) (n) -#ifndef WORDS_BIGENDIAN -#define WORDS_BIGENDIAN -#endif -#else -#error Could not determine CPU byte order -#endif - -#define WPA_BYTE_SWAP_DEFINED -#endif /* !WPA_BYTE_SWAP_DEFINED */ - - -/* Macros for handling unaligned memory accesses */ - -#define WPA_GET_BE16(a) ((u16) (((a)[0] << 8) | (a)[1])) -#define WPA_PUT_BE16(a, val) \ - do { \ - (a)[0] = ((u16) (val)) >> 8; \ - (a)[1] = ((u16) (val)) & 0xff; \ - } while (0) - -#define WPA_GET_LE16(a) ((u16) (((a)[1] << 8) | (a)[0])) -#define WPA_PUT_LE16(a, val) \ - do { \ - (a)[1] = ((u16) (val)) >> 8; \ - (a)[0] = ((u16) (val)) & 0xff; \ - } while (0) - -#define WPA_GET_BE24(a) ((((u32) (a)[0]) << 16) | (((u32) (a)[1]) << 8) | \ - ((u32) (a)[2])) -#define WPA_PUT_BE24(a, val) \ - do { \ - (a)[0] = (u8) ((((u32) (val)) >> 16) & 0xff); \ - (a)[1] = (u8) ((((u32) (val)) >> 8) & 0xff); \ - (a)[2] = (u8) (((u32) (val)) & 0xff); \ - } while (0) - -#define WPA_GET_BE32(a) ((((u32) (a)[0]) << 24) | (((u32) (a)[1]) << 16) | \ - (((u32) (a)[2]) << 8) | ((u32) (a)[3])) -#define WPA_PUT_BE32(a, val) \ - do { \ - (a)[0] = (u8) ((((u32) (val)) >> 24) & 0xff); \ - (a)[1] = (u8) ((((u32) (val)) >> 16) & 0xff); \ - (a)[2] = (u8) ((((u32) (val)) >> 8) & 0xff); \ - (a)[3] = (u8) (((u32) (val)) & 0xff); \ - } while (0) - -#define WPA_GET_LE32(a) ((((u32) (a)[3]) << 24) | (((u32) (a)[2]) << 16) | \ - (((u32) (a)[1]) << 8) | ((u32) (a)[0])) -#define WPA_PUT_LE32(a, val) \ - do { \ - (a)[3] = (u8) ((((u32) (val)) >> 24) & 0xff); \ - (a)[2] = (u8) ((((u32) (val)) >> 16) & 0xff); \ - (a)[1] = (u8) ((((u32) (val)) >> 8) & 0xff); \ - (a)[0] = (u8) (((u32) (val)) & 0xff); \ - } while (0) - -#define WPA_GET_BE64(a) ((((u64) (a)[0]) << 56) | (((u64) (a)[1]) << 48) | \ - (((u64) (a)[2]) << 40) | (((u64) (a)[3]) << 32) | \ - (((u64) (a)[4]) << 24) | (((u64) (a)[5]) << 16) | \ - (((u64) (a)[6]) << 8) | ((u64) (a)[7])) -#define WPA_PUT_BE64(a, val) \ - do { \ - (a)[0] = (u8) (((u64) (val)) >> 56); \ - (a)[1] = (u8) (((u64) (val)) >> 48); \ - (a)[2] = (u8) (((u64) (val)) >> 40); \ - (a)[3] = (u8) (((u64) (val)) >> 32); \ - (a)[4] = (u8) (((u64) (val)) >> 24); \ - (a)[5] = (u8) (((u64) (val)) >> 16); \ - (a)[6] = (u8) (((u64) (val)) >> 8); \ - (a)[7] = (u8) (((u64) (val)) & 0xff); \ - } while (0) - -#define WPA_GET_LE64(a) ((((u64) (a)[7]) << 56) | (((u64) (a)[6]) << 48) | \ - (((u64) (a)[5]) << 40) | (((u64) (a)[4]) << 32) | \ - (((u64) (a)[3]) << 24) | (((u64) (a)[2]) << 16) | \ - (((u64) (a)[1]) << 8) | ((u64) (a)[0])) - - -#ifndef ETH_ALEN -#define ETH_ALEN 6 -#endif -#ifndef IFNAMSIZ -#define IFNAMSIZ 16 -#endif -#ifndef ETH_P_ALL -#define ETH_P_ALL 0x0003 -#endif -#ifndef ETH_P_80211_ENCAP -#define ETH_P_80211_ENCAP 0x890d /* TDLS comes under this category */ -#endif -#ifndef ETH_P_PAE -#define ETH_P_PAE 0x888E /* Port Access Entity (IEEE 802.1X) */ -#endif /* ETH_P_PAE */ -#ifndef ETH_P_EAPOL -#define ETH_P_EAPOL ETH_P_PAE -#endif /* ETH_P_EAPOL */ -#ifndef ETH_P_RSN_PREAUTH -#define ETH_P_RSN_PREAUTH 0x88c7 -#endif /* ETH_P_RSN_PREAUTH */ -#ifndef ETH_P_RRB -#define ETH_P_RRB 0x890D -#endif /* ETH_P_RRB */ - - -#ifdef __GNUC__ -#define PRINTF_FORMAT(a,b) __attribute__ ((format (printf, (a), (b)))) -#define STRUCT_PACKED __attribute__ ((packed)) -#else -#define PRINTF_FORMAT(a,b) -#define STRUCT_PACKED -#endif - - -#ifdef CONFIG_ANSI_C_EXTRA - -#if !defined(_MSC_VER) || _MSC_VER < 1400 -/* snprintf - used in number of places; sprintf() is _not_ a good replacement - * due to possible buffer overflow; see, e.g., - * http://www.ijs.si/software/snprintf/ for portable implementation of - * snprintf. */ -int snprintf(char *str, size_t size, const char *format, ...); - -/* vsnprintf - only used for wpa_msg() in wpa_supplicant.c */ -int vsnprintf(char *str, size_t size, const char *format, va_list ap); -#endif /* !defined(_MSC_VER) || _MSC_VER < 1400 */ - -/* getopt - only used in main.c */ -int getopt(int argc, char *const argv[], const char *optstring); -extern char *optarg; -extern int optind; - -#ifndef CONFIG_NO_SOCKLEN_T_TYPEDEF -#ifndef __socklen_t_defined -typedef int socklen_t; -#endif -#endif - -/* inline - define as __inline or just define it to be empty, if needed */ -#ifdef CONFIG_NO_INLINE -#define inline -#else -#define inline __inline -#endif - -#ifndef __func__ -#define __func__ "__func__ not defined" -#endif - -#ifndef bswap_16 -#define bswap_16(a) ((((u16) (a) << 8) & 0xff00) | (((u16) (a) >> 8) & 0xff)) -#endif - -#ifndef bswap_32 -#define bswap_32(a) ((((u32) (a) << 24) & 0xff000000) | \ - (((u32) (a) << 8) & 0xff0000) | \ - (((u32) (a) >> 8) & 0xff00) | \ - (((u32) (a) >> 24) & 0xff)) -#endif - -#ifndef MSG_DONTWAIT -#define MSG_DONTWAIT 0 -#endif - -#ifdef _WIN32_WCE -void perror(const char *s); -#endif /* _WIN32_WCE */ - -#endif /* CONFIG_ANSI_C_EXTRA */ - -#ifndef MAC2STR -#define MAC2STR(a) (a)[0], (a)[1], (a)[2], (a)[3], (a)[4], (a)[5] -#define MACSTR "%02x:%02x:%02x:%02x:%02x:%02x" - -/* - * Compact form for string representation of MAC address - * To be used, e.g., for constructing dbus paths for P2P Devices - */ -#define COMPACT_MACSTR "%02x%02x%02x%02x%02x%02x" -#endif - -#ifndef BIT -#define BIT(x) (1 << (x)) -#endif - -/* - * Definitions for sparse validation - * (http://kernel.org/pub/linux/kernel/people/josh/sparse/) - */ -#ifdef __CHECKER__ -#define __force __attribute__((force)) -#define __bitwise __attribute__((bitwise)) -#else -#define __force -#define __bitwise -#endif - -typedef u16 __bitwise be16; -typedef u16 __bitwise le16; -typedef u32 __bitwise be32; -typedef u32 __bitwise le32; -typedef u64 __bitwise be64; -typedef u64 __bitwise le64; - -#ifndef __must_check -#if __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) -#define __must_check __attribute__((__warn_unused_result__)) -#else -#define __must_check -#endif /* __GNUC__ */ -#endif /* __must_check */ - -int hwaddr_aton(const char *txt, u8 *addr); -int hwaddr_compact_aton(const char *txt, u8 *addr); -int hwaddr_aton2(const char *txt, u8 *addr); -int hex2byte(const char *hex); -int hexstr2bin(const char *hex, u8 *buf, size_t len); -void inc_byte_array(u8 *counter, size_t len); -void wpa_get_ntp_timestamp(u8 *buf); -int wpa_snprintf_hex(char *buf, size_t buf_size, const u8 *data, size_t len); -int wpa_snprintf_hex_uppercase(char *buf, size_t buf_size, const u8 *data, - size_t len); - -#ifdef CONFIG_NATIVE_WINDOWS -void wpa_unicode2ascii_inplace(TCHAR *str); -TCHAR * wpa_strdup_tchar(const char *str); -#else /* CONFIG_NATIVE_WINDOWS */ -#define wpa_unicode2ascii_inplace(s) do { } while (0) -#define wpa_strdup_tchar(s) strdup((s)) -#endif /* CONFIG_NATIVE_WINDOWS */ - -const char * wpa_ssid_txt(const u8 *ssid, size_t ssid_len); - -static inline int is_zero_ether_addr(const u8 *a) -{ - return !(a[0] | a[1] | a[2] | a[3] | a[4] | a[5]); -} - -static inline int is_broadcast_ether_addr(const u8 *a) -{ - return (a[0] & a[1] & a[2] & a[3] & a[4] & a[5]) == 0xff; -} - -#define broadcast_ether_addr (const u8 *) "\xff\xff\xff\xff\xff\xff" - -#include "wpa_debug.h" - - -/* - * gcc 4.4 ends up generating strict-aliasing warnings about some very common - * networking socket uses that do not really result in a real problem and - * cannot be easily avoided with union-based type-punning due to struct - * definitions including another struct in system header files. To avoid having - * to fully disable strict-aliasing warnings, provide a mechanism to hide the - * typecast from aliasing for now. A cleaner solution will hopefully be found - * in the future to handle these cases. - */ -void * __hide_aliasing_typecast(void *foo); -#define aliasing_hide_typecast(a,t) (t *) __hide_aliasing_typecast((a)) - -#ifdef CONFIG_VALGRIND -#include -#define WPA_MEM_DEFINED(ptr, len) VALGRIND_MAKE_MEM_DEFINED((ptr), (len)) -#else /* CONFIG_VALGRIND */ -#define WPA_MEM_DEFINED(ptr, len) do { } while (0) -#endif /* CONFIG_VALGRIND */ - -#endif /* COMMON_H */ diff --git a/hostapd-0.8/src/utils/edit.c b/hostapd-0.8/src/utils/edit.c deleted file mode 100644 index 8f9e4ed..0000000 --- a/hostapd-0.8/src/utils/edit.c +++ /dev/null @@ -1,1161 +0,0 @@ -/* - * Command line editing and history - * Copyright (c) 2010, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#include "includes.h" -#include - -#include "common.h" -#include "eloop.h" -#include "list.h" -#include "edit.h" - -#define CMD_BUF_LEN 256 -static char cmdbuf[CMD_BUF_LEN]; -static int cmdbuf_pos = 0; -static int cmdbuf_len = 0; - -#define HISTORY_MAX 100 - -struct edit_history { - struct dl_list list; - char str[1]; -}; - -static struct dl_list history_list; -static struct edit_history *history_curr; - -static void *edit_cb_ctx; -static void (*edit_cmd_cb)(void *ctx, char *cmd); -static void (*edit_eof_cb)(void *ctx); -static char ** (*edit_completion_cb)(void *ctx, const char *cmd, int pos) = - NULL; - -static struct termios prevt, newt; - - -#define CLEAR_END_LINE "\e[K" - - -void edit_clear_line(void) -{ - int i; - putchar('\r'); - for (i = 0; i < cmdbuf_len + 2; i++) - putchar(' '); -} - - -static void move_start(void) -{ - cmdbuf_pos = 0; - edit_redraw(); -} - - -static void move_end(void) -{ - cmdbuf_pos = cmdbuf_len; - edit_redraw(); -} - - -static void move_left(void) -{ - if (cmdbuf_pos > 0) { - cmdbuf_pos--; - edit_redraw(); - } -} - - -static void move_right(void) -{ - if (cmdbuf_pos < cmdbuf_len) { - cmdbuf_pos++; - edit_redraw(); - } -} - - -static void move_word_left(void) -{ - while (cmdbuf_pos > 0 && cmdbuf[cmdbuf_pos - 1] == ' ') - cmdbuf_pos--; - while (cmdbuf_pos > 0 && cmdbuf[cmdbuf_pos - 1] != ' ') - cmdbuf_pos--; - edit_redraw(); -} - - -static void move_word_right(void) -{ - while (cmdbuf_pos < cmdbuf_len && cmdbuf[cmdbuf_pos] == ' ') - cmdbuf_pos++; - while (cmdbuf_pos < cmdbuf_len && cmdbuf[cmdbuf_pos] != ' ') - cmdbuf_pos++; - edit_redraw(); -} - - -static void delete_left(void) -{ - if (cmdbuf_pos == 0) - return; - - edit_clear_line(); - os_memmove(cmdbuf + cmdbuf_pos - 1, cmdbuf + cmdbuf_pos, - cmdbuf_len - cmdbuf_pos); - cmdbuf_pos--; - cmdbuf_len--; - edit_redraw(); -} - - -static void delete_current(void) -{ - if (cmdbuf_pos == cmdbuf_len) - return; - - edit_clear_line(); - os_memmove(cmdbuf + cmdbuf_pos, cmdbuf + cmdbuf_pos + 1, - cmdbuf_len - cmdbuf_pos); - cmdbuf_len--; - edit_redraw(); -} - - -static void delete_word(void) -{ - int pos; - - edit_clear_line(); - pos = cmdbuf_pos; - while (pos > 0 && cmdbuf[pos - 1] == ' ') - pos--; - while (pos > 0 && cmdbuf[pos - 1] != ' ') - pos--; - os_memmove(cmdbuf + pos, cmdbuf + cmdbuf_pos, cmdbuf_len - cmdbuf_pos); - cmdbuf_len -= cmdbuf_pos - pos; - cmdbuf_pos = pos; - edit_redraw(); -} - - -static void clear_left(void) -{ - if (cmdbuf_pos == 0) - return; - - edit_clear_line(); - os_memmove(cmdbuf, cmdbuf + cmdbuf_pos, cmdbuf_len - cmdbuf_pos); - cmdbuf_len -= cmdbuf_pos; - cmdbuf_pos = 0; - edit_redraw(); -} - - -static void clear_right(void) -{ - if (cmdbuf_pos == cmdbuf_len) - return; - - edit_clear_line(); - cmdbuf_len = cmdbuf_pos; - edit_redraw(); -} - - -static void history_add(const char *str) -{ - struct edit_history *h, *match = NULL, *last = NULL; - size_t len, count = 0; - - if (str[0] == '\0') - return; - - dl_list_for_each(h, &history_list, struct edit_history, list) { - if (os_strcmp(str, h->str) == 0) { - match = h; - break; - } - last = h; - count++; - } - - if (match) { - dl_list_del(&h->list); - dl_list_add(&history_list, &h->list); - history_curr = h; - return; - } - - if (count >= HISTORY_MAX && last) { - dl_list_del(&last->list); - os_free(last); - } - - len = os_strlen(str); - h = os_zalloc(sizeof(*h) + len); - if (h == NULL) - return; - dl_list_add(&history_list, &h->list); - os_strlcpy(h->str, str, len + 1); - history_curr = h; -} - - -static void history_use(void) -{ - edit_clear_line(); - cmdbuf_len = cmdbuf_pos = os_strlen(history_curr->str); - os_memcpy(cmdbuf, history_curr->str, cmdbuf_len); - edit_redraw(); -} - - -static void history_prev(void) -{ - if (history_curr == NULL) - return; - - if (history_curr == - dl_list_first(&history_list, struct edit_history, list)) { - cmdbuf[cmdbuf_len] = '\0'; - history_add(cmdbuf); - } - - history_use(); - - if (history_curr == - dl_list_last(&history_list, struct edit_history, list)) - return; - - history_curr = dl_list_entry(history_curr->list.next, - struct edit_history, list); -} - - -static void history_next(void) -{ - if (history_curr == NULL || - history_curr == - dl_list_first(&history_list, struct edit_history, list)) - return; - - history_curr = dl_list_entry(history_curr->list.prev, - struct edit_history, list); - history_use(); -} - - -static void history_read(const char *fname) -{ - FILE *f; - char buf[CMD_BUF_LEN], *pos; - - f = fopen(fname, "r"); - if (f == NULL) - return; - - while (fgets(buf, CMD_BUF_LEN, f)) { - for (pos = buf; *pos; pos++) { - if (*pos == '\r' || *pos == '\n') { - *pos = '\0'; - break; - } - } - history_add(buf); - } - - fclose(f); -} - - -static void history_write(const char *fname, - int (*filter_cb)(void *ctx, const char *cmd)) -{ - FILE *f; - struct edit_history *h; - - f = fopen(fname, "w"); - if (f == NULL) - return; - - dl_list_for_each_reverse(h, &history_list, struct edit_history, list) { - if (filter_cb && filter_cb(edit_cb_ctx, h->str)) - continue; - fprintf(f, "%s\n", h->str); - } - - fclose(f); -} - - -static void history_debug_dump(void) -{ - struct edit_history *h; - edit_clear_line(); - printf("\r"); - dl_list_for_each_reverse(h, &history_list, struct edit_history, list) - printf("%s%s\n", h == history_curr ? "[C]" : "", h->str); - edit_redraw(); -} - - -static void insert_char(int c) -{ - if (cmdbuf_len >= (int) sizeof(cmdbuf) - 1) - return; - if (cmdbuf_len == cmdbuf_pos) { - cmdbuf[cmdbuf_pos++] = c; - cmdbuf_len++; - putchar(c); - fflush(stdout); - } else { - os_memmove(cmdbuf + cmdbuf_pos + 1, cmdbuf + cmdbuf_pos, - cmdbuf_len - cmdbuf_pos); - cmdbuf[cmdbuf_pos++] = c; - cmdbuf_len++; - edit_redraw(); - } -} - - -static void process_cmd(void) -{ - - if (cmdbuf_len == 0) { - printf("\n> "); - fflush(stdout); - return; - } - printf("\n"); - cmdbuf[cmdbuf_len] = '\0'; - history_add(cmdbuf); - cmdbuf_pos = 0; - cmdbuf_len = 0; - edit_cmd_cb(edit_cb_ctx, cmdbuf); - printf("> "); - fflush(stdout); -} - - -static void free_completions(char **c) -{ - int i; - if (c == NULL) - return; - for (i = 0; c[i]; i++) - os_free(c[i]); - os_free(c); -} - - -static int filter_strings(char **c, char *str, size_t len) -{ - int i, j; - - for (i = 0, j = 0; c[j]; j++) { - if (os_strncasecmp(c[j], str, len) == 0) { - if (i != j) { - c[i] = c[j]; - c[j] = NULL; - } - i++; - } else { - os_free(c[j]); - c[j] = NULL; - } - } - c[i] = NULL; - return i; -} - - -static int common_len(const char *a, const char *b) -{ - int len = 0; - while (a[len] && a[len] == b[len]) - len++; - return len; -} - - -static int max_common_length(char **c) -{ - int len, i; - - len = os_strlen(c[0]); - for (i = 1; c[i]; i++) { - int same = common_len(c[0], c[i]); - if (same < len) - len = same; - } - - return len; -} - - -static int cmp_str(const void *a, const void *b) -{ - return os_strcmp(* (const char **) a, * (const char **) b); -} - -static void complete(int list) -{ - char **c; - int i, len, count; - int start, end; - int room, plen, add_space; - - if (edit_completion_cb == NULL) - return; - - cmdbuf[cmdbuf_len] = '\0'; - c = edit_completion_cb(edit_cb_ctx, cmdbuf, cmdbuf_pos); - if (c == NULL) - return; - - end = cmdbuf_pos; - start = end; - while (start > 0 && cmdbuf[start - 1] != ' ') - start--; - plen = end - start; - - count = filter_strings(c, &cmdbuf[start], plen); - if (count == 0) { - free_completions(c); - return; - } - - len = max_common_length(c); - if (len <= plen && count > 1) { - if (list) { - qsort(c, count, sizeof(char *), cmp_str); - edit_clear_line(); - printf("\r"); - for (i = 0; c[i]; i++) - printf("%s%s", i > 0 ? " " : "", c[i]); - printf("\n"); - edit_redraw(); - } - free_completions(c); - return; - } - len -= plen; - - room = sizeof(cmdbuf) - 1 - cmdbuf_len; - if (room < len) - len = room; - add_space = count == 1 && len < room; - - os_memmove(cmdbuf + cmdbuf_pos + len + add_space, cmdbuf + cmdbuf_pos, - cmdbuf_len - cmdbuf_pos); - os_memcpy(&cmdbuf[cmdbuf_pos - plen], c[0], plen + len); - if (add_space) - cmdbuf[cmdbuf_pos + len] = ' '; - - cmdbuf_pos += len + add_space; - cmdbuf_len += len + add_space; - - edit_redraw(); - - free_completions(c); -} - - -enum edit_key_code { - EDIT_KEY_NONE = 256, - EDIT_KEY_TAB, - EDIT_KEY_UP, - EDIT_KEY_DOWN, - EDIT_KEY_RIGHT, - EDIT_KEY_LEFT, - EDIT_KEY_ENTER, - EDIT_KEY_BACKSPACE, - EDIT_KEY_INSERT, - EDIT_KEY_DELETE, - EDIT_KEY_HOME, - EDIT_KEY_END, - EDIT_KEY_PAGE_UP, - EDIT_KEY_PAGE_DOWN, - EDIT_KEY_F1, - EDIT_KEY_F2, - EDIT_KEY_F3, - EDIT_KEY_F4, - EDIT_KEY_F5, - EDIT_KEY_F6, - EDIT_KEY_F7, - EDIT_KEY_F8, - EDIT_KEY_F9, - EDIT_KEY_F10, - EDIT_KEY_F11, - EDIT_KEY_F12, - EDIT_KEY_CTRL_UP, - EDIT_KEY_CTRL_DOWN, - EDIT_KEY_CTRL_RIGHT, - EDIT_KEY_CTRL_LEFT, - EDIT_KEY_CTRL_A, - EDIT_KEY_CTRL_B, - EDIT_KEY_CTRL_D, - EDIT_KEY_CTRL_E, - EDIT_KEY_CTRL_F, - EDIT_KEY_CTRL_G, - EDIT_KEY_CTRL_H, - EDIT_KEY_CTRL_J, - EDIT_KEY_CTRL_K, - EDIT_KEY_CTRL_L, - EDIT_KEY_CTRL_N, - EDIT_KEY_CTRL_O, - EDIT_KEY_CTRL_P, - EDIT_KEY_CTRL_R, - EDIT_KEY_CTRL_T, - EDIT_KEY_CTRL_U, - EDIT_KEY_CTRL_V, - EDIT_KEY_CTRL_W, - EDIT_KEY_ALT_UP, - EDIT_KEY_ALT_DOWN, - EDIT_KEY_ALT_RIGHT, - EDIT_KEY_ALT_LEFT, - EDIT_KEY_SHIFT_UP, - EDIT_KEY_SHIFT_DOWN, - EDIT_KEY_SHIFT_RIGHT, - EDIT_KEY_SHIFT_LEFT, - EDIT_KEY_ALT_SHIFT_UP, - EDIT_KEY_ALT_SHIFT_DOWN, - EDIT_KEY_ALT_SHIFT_RIGHT, - EDIT_KEY_ALT_SHIFT_LEFT, - EDIT_KEY_EOF -}; - -static void show_esc_buf(const char *esc_buf, char c, int i) -{ - edit_clear_line(); - printf("\rESC buffer '%s' c='%c' [%d]\n", esc_buf, c, i); - edit_redraw(); -} - - -static enum edit_key_code esc_seq_to_key1_no(char last) -{ - switch (last) { - case 'A': - return EDIT_KEY_UP; - case 'B': - return EDIT_KEY_DOWN; - case 'C': - return EDIT_KEY_RIGHT; - case 'D': - return EDIT_KEY_LEFT; - default: - return EDIT_KEY_NONE; - } -} - - -static enum edit_key_code esc_seq_to_key1_shift(char last) -{ - switch (last) { - case 'A': - return EDIT_KEY_SHIFT_UP; - case 'B': - return EDIT_KEY_SHIFT_DOWN; - case 'C': - return EDIT_KEY_SHIFT_RIGHT; - case 'D': - return EDIT_KEY_SHIFT_LEFT; - default: - return EDIT_KEY_NONE; - } -} - - -static enum edit_key_code esc_seq_to_key1_alt(char last) -{ - switch (last) { - case 'A': - return EDIT_KEY_ALT_UP; - case 'B': - return EDIT_KEY_ALT_DOWN; - case 'C': - return EDIT_KEY_ALT_RIGHT; - case 'D': - return EDIT_KEY_ALT_LEFT; - default: - return EDIT_KEY_NONE; - } -} - - -static enum edit_key_code esc_seq_to_key1_alt_shift(char last) -{ - switch (last) { - case 'A': - return EDIT_KEY_ALT_SHIFT_UP; - case 'B': - return EDIT_KEY_ALT_SHIFT_DOWN; - case 'C': - return EDIT_KEY_ALT_SHIFT_RIGHT; - case 'D': - return EDIT_KEY_ALT_SHIFT_LEFT; - default: - return EDIT_KEY_NONE; - } -} - - -static enum edit_key_code esc_seq_to_key1_ctrl(char last) -{ - switch (last) { - case 'A': - return EDIT_KEY_CTRL_UP; - case 'B': - return EDIT_KEY_CTRL_DOWN; - case 'C': - return EDIT_KEY_CTRL_RIGHT; - case 'D': - return EDIT_KEY_CTRL_LEFT; - default: - return EDIT_KEY_NONE; - } -} - - -static enum edit_key_code esc_seq_to_key1(int param1, int param2, char last) -{ - /* ESC-[; */ - - if (param1 < 0 && param2 < 0) - return esc_seq_to_key1_no(last); - - if (param1 == 1 && param2 == 2) - return esc_seq_to_key1_shift(last); - - if (param1 == 1 && param2 == 3) - return esc_seq_to_key1_alt(last); - - if (param1 == 1 && param2 == 4) - return esc_seq_to_key1_alt_shift(last); - - if (param1 == 1 && param2 == 5) - return esc_seq_to_key1_ctrl(last); - - if (param2 < 0) { - if (last != '~') - return EDIT_KEY_NONE; - switch (param1) { - case 2: - return EDIT_KEY_INSERT; - case 3: - return EDIT_KEY_DELETE; - case 5: - return EDIT_KEY_PAGE_UP; - case 6: - return EDIT_KEY_PAGE_DOWN; - case 15: - return EDIT_KEY_F5; - case 17: - return EDIT_KEY_F6; - case 18: - return EDIT_KEY_F7; - case 19: - return EDIT_KEY_F8; - case 20: - return EDIT_KEY_F9; - case 21: - return EDIT_KEY_F10; - case 23: - return EDIT_KEY_F11; - case 24: - return EDIT_KEY_F12; - } - } - - return EDIT_KEY_NONE; -} - - -static enum edit_key_code esc_seq_to_key2(int param1, int param2, char last) -{ - /* ESC-O; */ - - if (param1 >= 0 || param2 >= 0) - return EDIT_KEY_NONE; - - switch (last) { - case 'F': - return EDIT_KEY_END; - case 'H': - return EDIT_KEY_HOME; - case 'P': - return EDIT_KEY_F1; - case 'Q': - return EDIT_KEY_F2; - case 'R': - return EDIT_KEY_F3; - case 'S': - return EDIT_KEY_F4; - default: - return EDIT_KEY_NONE; - } -} - - -static enum edit_key_code esc_seq_to_key(char *seq) -{ - char last, *pos; - int param1 = -1, param2 = -1; - enum edit_key_code ret = EDIT_KEY_NONE; - - last = '\0'; - for (pos = seq; *pos; pos++) - last = *pos; - - if (seq[1] >= '0' && seq[1] <= '9') { - param1 = atoi(&seq[1]); - pos = os_strchr(seq, ';'); - if (pos) - param2 = atoi(pos + 1); - } - - if (seq[0] == '[') - ret = esc_seq_to_key1(param1, param2, last); - else if (seq[0] == 'O') - ret = esc_seq_to_key2(param1, param2, last); - - if (ret != EDIT_KEY_NONE) - return ret; - - edit_clear_line(); - printf("\rUnknown escape sequence '%s'\n", seq); - edit_redraw(); - return EDIT_KEY_NONE; -} - - -static enum edit_key_code edit_read_key(int sock) -{ - int c; - unsigned char buf[1]; - int res; - static int esc = -1; - static char esc_buf[7]; - - res = read(sock, buf, 1); - if (res < 0) - perror("read"); - if (res <= 0) - return EDIT_KEY_EOF; - - c = buf[0]; - - if (esc >= 0) { - if (c == 27 /* ESC */) { - esc = 0; - return EDIT_KEY_NONE; - } - - if (esc == 6) { - show_esc_buf(esc_buf, c, 0); - esc = -1; - } else { - esc_buf[esc++] = c; - esc_buf[esc] = '\0'; - } - } - - if (esc == 1) { - if (esc_buf[0] != '[' && esc_buf[0] != 'O') { - show_esc_buf(esc_buf, c, 1); - esc = -1; - return EDIT_KEY_NONE; - } else - return EDIT_KEY_NONE; /* Escape sequence continues */ - } - - if (esc > 1) { - if ((c >= '0' && c <= '9') || c == ';') - return EDIT_KEY_NONE; /* Escape sequence continues */ - - if (c == '~' || (c >= 'A' && c <= 'Z')) { - esc = -1; - return esc_seq_to_key(esc_buf); - } - - show_esc_buf(esc_buf, c, 2); - esc = -1; - return EDIT_KEY_NONE; - } - - switch (c) { - case 1: - return EDIT_KEY_CTRL_A; - case 2: - return EDIT_KEY_CTRL_B; - case 4: - return EDIT_KEY_CTRL_D; - case 5: - return EDIT_KEY_CTRL_E; - case 6: - return EDIT_KEY_CTRL_F; - case 7: - return EDIT_KEY_CTRL_G; - case 8: - return EDIT_KEY_CTRL_H; - case 9: - return EDIT_KEY_TAB; - case 10: - return EDIT_KEY_CTRL_J; - case 13: /* CR */ - return EDIT_KEY_ENTER; - case 11: - return EDIT_KEY_CTRL_K; - case 12: - return EDIT_KEY_CTRL_L; - case 14: - return EDIT_KEY_CTRL_N; - case 15: - return EDIT_KEY_CTRL_O; - case 16: - return EDIT_KEY_CTRL_P; - case 18: - return EDIT_KEY_CTRL_R; - case 20: - return EDIT_KEY_CTRL_T; - case 21: - return EDIT_KEY_CTRL_U; - case 22: - return EDIT_KEY_CTRL_V; - case 23: - return EDIT_KEY_CTRL_W; - case 27: /* ESC */ - esc = 0; - return EDIT_KEY_NONE; - case 127: - return EDIT_KEY_BACKSPACE; - default: - return c; - } -} - - -static char search_buf[21]; -static int search_skip; - -static char * search_find(void) -{ - struct edit_history *h; - size_t len = os_strlen(search_buf); - int skip = search_skip; - - if (len == 0) - return NULL; - - dl_list_for_each(h, &history_list, struct edit_history, list) { - if (os_strstr(h->str, search_buf)) { - if (skip == 0) - return h->str; - skip--; - } - } - - search_skip = 0; - return NULL; -} - - -static void search_redraw(void) -{ - char *match = search_find(); - printf("\rsearch '%s': %s" CLEAR_END_LINE, - search_buf, match ? match : ""); - printf("\rsearch '%s", search_buf); - fflush(stdout); -} - - -static void search_start(void) -{ - edit_clear_line(); - search_buf[0] = '\0'; - search_skip = 0; - search_redraw(); -} - - -static void search_clear(void) -{ - search_redraw(); - printf("\r" CLEAR_END_LINE); -} - - -static void search_stop(void) -{ - char *match = search_find(); - search_buf[0] = '\0'; - search_clear(); - if (match) { - os_strlcpy(cmdbuf, match, CMD_BUF_LEN); - cmdbuf_len = os_strlen(cmdbuf); - cmdbuf_pos = cmdbuf_len; - } - edit_redraw(); -} - - -static void search_cancel(void) -{ - search_buf[0] = '\0'; - search_clear(); - edit_redraw(); -} - - -static void search_backspace(void) -{ - size_t len; - len = os_strlen(search_buf); - if (len == 0) - return; - search_buf[len - 1] = '\0'; - search_skip = 0; - search_redraw(); -} - - -static void search_next(void) -{ - search_skip++; - search_find(); - search_redraw(); -} - - -static void search_char(char c) -{ - size_t len; - len = os_strlen(search_buf); - if (len == sizeof(search_buf) - 1) - return; - search_buf[len] = c; - search_buf[len + 1] = '\0'; - search_skip = 0; - search_redraw(); -} - - -static enum edit_key_code search_key(enum edit_key_code c) -{ - switch (c) { - case EDIT_KEY_ENTER: - case EDIT_KEY_CTRL_J: - case EDIT_KEY_LEFT: - case EDIT_KEY_RIGHT: - case EDIT_KEY_HOME: - case EDIT_KEY_END: - case EDIT_KEY_CTRL_A: - case EDIT_KEY_CTRL_E: - search_stop(); - return c; - case EDIT_KEY_DOWN: - case EDIT_KEY_UP: - search_cancel(); - return EDIT_KEY_EOF; - case EDIT_KEY_CTRL_H: - case EDIT_KEY_BACKSPACE: - search_backspace(); - break; - case EDIT_KEY_CTRL_R: - search_next(); - break; - default: - if (c >= 32 && c <= 255) - search_char(c); - break; - } - - return EDIT_KEY_NONE; -} - - -static void edit_read_char(int sock, void *eloop_ctx, void *sock_ctx) -{ - static int last_tab = 0; - static int search = 0; - enum edit_key_code c; - - c = edit_read_key(sock); - - if (search) { - c = search_key(c); - if (c == EDIT_KEY_NONE) - return; - search = 0; - if (c == EDIT_KEY_EOF) - return; - } - - if (c != EDIT_KEY_TAB && c != EDIT_KEY_NONE) - last_tab = 0; - - switch (c) { - case EDIT_KEY_NONE: - break; - case EDIT_KEY_EOF: - edit_eof_cb(edit_cb_ctx); - break; - case EDIT_KEY_TAB: - complete(last_tab); - last_tab = 1; - break; - case EDIT_KEY_UP: - case EDIT_KEY_CTRL_P: - history_prev(); - break; - case EDIT_KEY_DOWN: - case EDIT_KEY_CTRL_N: - history_next(); - break; - case EDIT_KEY_RIGHT: - case EDIT_KEY_CTRL_F: - move_right(); - break; - case EDIT_KEY_LEFT: - case EDIT_KEY_CTRL_B: - move_left(); - break; - case EDIT_KEY_CTRL_RIGHT: - move_word_right(); - break; - case EDIT_KEY_CTRL_LEFT: - move_word_left(); - break; - case EDIT_KEY_DELETE: - delete_current(); - break; - case EDIT_KEY_END: - move_end(); - break; - case EDIT_KEY_HOME: - case EDIT_KEY_CTRL_A: - move_start(); - break; - case EDIT_KEY_F2: - history_debug_dump(); - break; - case EDIT_KEY_CTRL_D: - if (cmdbuf_len > 0) { - delete_current(); - return; - } - printf("\n"); - edit_eof_cb(edit_cb_ctx); - break; - case EDIT_KEY_CTRL_E: - move_end(); - break; - case EDIT_KEY_CTRL_H: - case EDIT_KEY_BACKSPACE: - delete_left(); - break; - case EDIT_KEY_ENTER: - case EDIT_KEY_CTRL_J: - process_cmd(); - break; - case EDIT_KEY_CTRL_K: - clear_right(); - break; - case EDIT_KEY_CTRL_L: - edit_clear_line(); - edit_redraw(); - break; - case EDIT_KEY_CTRL_R: - search = 1; - search_start(); - break; - case EDIT_KEY_CTRL_U: - clear_left(); - break; - case EDIT_KEY_CTRL_W: - delete_word(); - break; - default: - if (c >= 32 && c <= 255) - insert_char(c); - break; - } -} - - -int edit_init(void (*cmd_cb)(void *ctx, char *cmd), - void (*eof_cb)(void *ctx), - char ** (*completion_cb)(void *ctx, const char *cmd, int pos), - void *ctx, const char *history_file) -{ - dl_list_init(&history_list); - history_curr = NULL; - if (history_file) - history_read(history_file); - - edit_cb_ctx = ctx; - edit_cmd_cb = cmd_cb; - edit_eof_cb = eof_cb; - edit_completion_cb = completion_cb; - - tcgetattr(STDIN_FILENO, &prevt); - newt = prevt; - newt.c_lflag &= ~(ICANON | ECHO); - tcsetattr(STDIN_FILENO, TCSANOW, &newt); - - eloop_register_read_sock(STDIN_FILENO, edit_read_char, NULL, NULL); - - printf("> "); - fflush(stdout); - - return 0; -} - - -void edit_deinit(const char *history_file, - int (*filter_cb)(void *ctx, const char *cmd)) -{ - struct edit_history *h; - if (history_file) - history_write(history_file, filter_cb); - while ((h = dl_list_first(&history_list, struct edit_history, list))) { - dl_list_del(&h->list); - os_free(h); - } - edit_clear_line(); - putchar('\r'); - fflush(stdout); - eloop_unregister_read_sock(STDIN_FILENO); - tcsetattr(STDIN_FILENO, TCSANOW, &prevt); -} - - -void edit_redraw(void) -{ - char tmp; - cmdbuf[cmdbuf_len] = '\0'; - printf("\r> %s", cmdbuf); - if (cmdbuf_pos != cmdbuf_len) { - tmp = cmdbuf[cmdbuf_pos]; - cmdbuf[cmdbuf_pos] = '\0'; - printf("\r> %s", cmdbuf); - cmdbuf[cmdbuf_pos] = tmp; - } - fflush(stdout); -} diff --git a/hostapd-0.8/src/utils/edit.h b/hostapd-0.8/src/utils/edit.h deleted file mode 100644 index fc4474b..0000000 --- a/hostapd-0.8/src/utils/edit.h +++ /dev/null @@ -1,27 +0,0 @@ -/* - * Command line editing and history - * Copyright (c) 2010, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#ifndef EDIT_H -#define EDIT_H - -int edit_init(void (*cmd_cb)(void *ctx, char *cmd), - void (*eof_cb)(void *ctx), - char ** (*completion_cb)(void *ctx, const char *cmd, int pos), - void *ctx, const char *history_file); -void edit_deinit(const char *history_file, - int (*filter_cb)(void *ctx, const char *cmd)); -void edit_clear_line(void); -void edit_redraw(void); - -#endif /* EDIT_H */ diff --git a/hostapd-0.8/src/utils/edit_readline.c b/hostapd-0.8/src/utils/edit_readline.c deleted file mode 100644 index 1fef7b9..0000000 --- a/hostapd-0.8/src/utils/edit_readline.c +++ /dev/null @@ -1,184 +0,0 @@ -/* - * Command line editing and history wrapper for readline - * Copyright (c) 2010, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#include "includes.h" -#include -#include - -#include "common.h" -#include "eloop.h" -#include "edit.h" - - -static void *edit_cb_ctx; -static void (*edit_cmd_cb)(void *ctx, char *cmd); -static void (*edit_eof_cb)(void *ctx); -static char ** (*edit_completion_cb)(void *ctx, const char *cmd, int pos) = - NULL; - -static char **pending_completions = NULL; - - -static void readline_free_completions(void) -{ - int i; - if (pending_completions == NULL) - return; - for (i = 0; pending_completions[i]; i++) - os_free(pending_completions[i]); - os_free(pending_completions); - pending_completions = NULL; -} - - -static char * readline_completion_func(const char *text, int state) -{ - static int pos = 0; - static size_t len = 0; - - if (pending_completions == NULL) { - rl_attempted_completion_over = 1; - return NULL; - } - - if (state == 0) { - pos = 0; - len = os_strlen(text); - } - for (; pending_completions[pos]; pos++) { - if (strncmp(pending_completions[pos], text, len) == 0) - return strdup(pending_completions[pos++]); - } - - rl_attempted_completion_over = 1; - return NULL; -} - - -static char ** readline_completion(const char *text, int start, int end) -{ - readline_free_completions(); - if (edit_completion_cb) - pending_completions = edit_completion_cb(edit_cb_ctx, - rl_line_buffer, end); - return rl_completion_matches(text, readline_completion_func); -} - - -static void edit_read_char(int sock, void *eloop_ctx, void *sock_ctx) -{ - rl_callback_read_char(); -} - - -static void trunc_nl(char *str) -{ - char *pos = str; - while (*pos != '\0') { - if (*pos == '\n') { - *pos = '\0'; - break; - } - pos++; - } -} - - -static void readline_cmd_handler(char *cmd) -{ - if (cmd && *cmd) { - HIST_ENTRY *h; - while (next_history()) - ; - h = previous_history(); - if (h == NULL || os_strcmp(cmd, h->line) != 0) - add_history(cmd); - next_history(); - } - if (cmd == NULL) { - edit_eof_cb(edit_cb_ctx); - return; - } - trunc_nl(cmd); - edit_cmd_cb(edit_cb_ctx, cmd); -} - - -int edit_init(void (*cmd_cb)(void *ctx, char *cmd), - void (*eof_cb)(void *ctx), - char ** (*completion_cb)(void *ctx, const char *cmd, int pos), - void *ctx, const char *history_file) -{ - edit_cb_ctx = ctx; - edit_cmd_cb = cmd_cb; - edit_eof_cb = eof_cb; - edit_completion_cb = completion_cb; - - rl_attempted_completion_function = readline_completion; - if (history_file) { - read_history(history_file); - stifle_history(100); - } - - eloop_register_read_sock(STDIN_FILENO, edit_read_char, NULL, NULL); - - rl_callback_handler_install("> ", readline_cmd_handler); - - return 0; -} - - -void edit_deinit(const char *history_file, - int (*filter_cb)(void *ctx, const char *cmd)) -{ - rl_callback_handler_remove(); - readline_free_completions(); - - eloop_unregister_read_sock(STDIN_FILENO); - - if (history_file) { - /* Save command history, excluding lines that may contain - * passwords. */ - HIST_ENTRY *h; - history_set_pos(0); - while ((h = current_history())) { - char *p = h->line; - while (*p == ' ' || *p == '\t') - p++; - if (filter_cb && filter_cb(edit_cb_ctx, p)) { - h = remove_history(where_history()); - if (h) { - os_free(h->line); - free(h->data); - os_free(h); - } else - next_history(); - } else - next_history(); - } - write_history(history_file); - } -} - - -void edit_clear_line(void) -{ -} - - -void edit_redraw(void) -{ - rl_on_new_line(); - rl_redisplay(); -} diff --git a/hostapd-0.8/src/utils/edit_simple.c b/hostapd-0.8/src/utils/edit_simple.c deleted file mode 100644 index 61fb24e..0000000 --- a/hostapd-0.8/src/utils/edit_simple.c +++ /dev/null @@ -1,96 +0,0 @@ -/* - * Minimal command line editing - * Copyright (c) 2010, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#include "includes.h" - -#include "common.h" -#include "eloop.h" -#include "edit.h" - - -#define CMD_BUF_LEN 256 -static char cmdbuf[CMD_BUF_LEN]; -static int cmdbuf_pos = 0; - -static void *edit_cb_ctx; -static void (*edit_cmd_cb)(void *ctx, char *cmd); -static void (*edit_eof_cb)(void *ctx); - - -static void edit_read_char(int sock, void *eloop_ctx, void *sock_ctx) -{ - int c; - unsigned char buf[1]; - int res; - - res = read(sock, buf, 1); - if (res < 0) - perror("read"); - if (res <= 0) { - edit_eof_cb(edit_cb_ctx); - return; - } - c = buf[0]; - - if (c == '\r' || c == '\n') { - cmdbuf[cmdbuf_pos] = '\0'; - cmdbuf_pos = 0; - edit_cmd_cb(edit_cb_ctx, cmdbuf); - printf("> "); - fflush(stdout); - return; - } - - if (c >= 32 && c <= 255) { - if (cmdbuf_pos < (int) sizeof(cmdbuf) - 1) { - cmdbuf[cmdbuf_pos++] = c; - } - } -} - - -int edit_init(void (*cmd_cb)(void *ctx, char *cmd), - void (*eof_cb)(void *ctx), - char ** (*completion_cb)(void *ctx, const char *cmd, int pos), - void *ctx, const char *history_file) -{ - edit_cb_ctx = ctx; - edit_cmd_cb = cmd_cb; - edit_eof_cb = eof_cb; - eloop_register_read_sock(STDIN_FILENO, edit_read_char, NULL, NULL); - - printf("> "); - fflush(stdout); - - return 0; -} - - -void edit_deinit(const char *history_file, - int (*filter_cb)(void *ctx, const char *cmd)) -{ - eloop_unregister_read_sock(STDIN_FILENO); -} - - -void edit_clear_line(void) -{ -} - - -void edit_redraw(void) -{ - cmdbuf[cmdbuf_pos] = '\0'; - printf("\r> %s", cmdbuf); -} diff --git a/hostapd-0.8/src/utils/eloop.c b/hostapd-0.8/src/utils/eloop.c deleted file mode 100644 index b550c63..0000000 --- a/hostapd-0.8/src/utils/eloop.c +++ /dev/null @@ -1,627 +0,0 @@ -/* - * Event loop based on select() loop - * Copyright (c) 2002-2009, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#include "includes.h" - -#include "common.h" -#include "trace.h" -#include "list.h" -#include "eloop.h" - - -struct eloop_sock { - int sock; - void *eloop_data; - void *user_data; - eloop_sock_handler handler; - WPA_TRACE_REF(eloop); - WPA_TRACE_REF(user); - WPA_TRACE_INFO -}; - -struct eloop_timeout { - struct dl_list list; - struct os_time time; - void *eloop_data; - void *user_data; - eloop_timeout_handler handler; - WPA_TRACE_REF(eloop); - WPA_TRACE_REF(user); - WPA_TRACE_INFO -}; - -struct eloop_signal { - int sig; - void *user_data; - eloop_signal_handler handler; - int signaled; -}; - -struct eloop_sock_table { - int count; - struct eloop_sock *table; - int changed; -}; - -struct eloop_data { - int max_sock; - - struct eloop_sock_table readers; - struct eloop_sock_table writers; - struct eloop_sock_table exceptions; - - struct dl_list timeout; - - int signal_count; - struct eloop_signal *signals; - int signaled; - int pending_terminate; - - int terminate; - int reader_table_changed; -}; - -static struct eloop_data eloop; - - -#ifdef WPA_TRACE - -static void eloop_sigsegv_handler(int sig) -{ - wpa_trace_show("eloop SIGSEGV"); - abort(); -} - -static void eloop_trace_sock_add_ref(struct eloop_sock_table *table) -{ - int i; - if (table == NULL || table->table == NULL) - return; - for (i = 0; i < table->count; i++) { - wpa_trace_add_ref(&table->table[i], eloop, - table->table[i].eloop_data); - wpa_trace_add_ref(&table->table[i], user, - table->table[i].user_data); - } -} - - -static void eloop_trace_sock_remove_ref(struct eloop_sock_table *table) -{ - int i; - if (table == NULL || table->table == NULL) - return; - for (i = 0; i < table->count; i++) { - wpa_trace_remove_ref(&table->table[i], eloop, - table->table[i].eloop_data); - wpa_trace_remove_ref(&table->table[i], user, - table->table[i].user_data); - } -} - -#else /* WPA_TRACE */ - -#define eloop_trace_sock_add_ref(table) do { } while (0) -#define eloop_trace_sock_remove_ref(table) do { } while (0) - -#endif /* WPA_TRACE */ - - -int eloop_init(void) -{ - os_memset(&eloop, 0, sizeof(eloop)); - dl_list_init(&eloop.timeout); -#ifdef WPA_TRACE - signal(SIGSEGV, eloop_sigsegv_handler); -#endif /* WPA_TRACE */ - return 0; -} - - -static int eloop_sock_table_add_sock(struct eloop_sock_table *table, - int sock, eloop_sock_handler handler, - void *eloop_data, void *user_data) -{ - struct eloop_sock *tmp; - - if (table == NULL) - return -1; - - eloop_trace_sock_remove_ref(table); - tmp = (struct eloop_sock *) - os_realloc(table->table, - (table->count + 1) * sizeof(struct eloop_sock)); - if (tmp == NULL) - return -1; - - tmp[table->count].sock = sock; - tmp[table->count].eloop_data = eloop_data; - tmp[table->count].user_data = user_data; - tmp[table->count].handler = handler; - wpa_trace_record(&tmp[table->count]); - table->count++; - table->table = tmp; - if (sock > eloop.max_sock) - eloop.max_sock = sock; - table->changed = 1; - eloop_trace_sock_add_ref(table); - - return 0; -} - - -static void eloop_sock_table_remove_sock(struct eloop_sock_table *table, - int sock) -{ - int i; - - if (table == NULL || table->table == NULL || table->count == 0) - return; - - for (i = 0; i < table->count; i++) { - if (table->table[i].sock == sock) - break; - } - if (i == table->count) - return; - eloop_trace_sock_remove_ref(table); - if (i != table->count - 1) { - os_memmove(&table->table[i], &table->table[i + 1], - (table->count - i - 1) * - sizeof(struct eloop_sock)); - } - table->count--; - table->changed = 1; - eloop_trace_sock_add_ref(table); -} - - -static void eloop_sock_table_set_fds(struct eloop_sock_table *table, - fd_set *fds) -{ - int i; - - FD_ZERO(fds); - - if (table->table == NULL) - return; - - for (i = 0; i < table->count; i++) - FD_SET(table->table[i].sock, fds); -} - - -static void eloop_sock_table_dispatch(struct eloop_sock_table *table, - fd_set *fds) -{ - int i; - - if (table == NULL || table->table == NULL) - return; - - table->changed = 0; - for (i = 0; i < table->count; i++) { - if (FD_ISSET(table->table[i].sock, fds)) { - table->table[i].handler(table->table[i].sock, - table->table[i].eloop_data, - table->table[i].user_data); - if (table->changed) - break; - } - } -} - - -static void eloop_sock_table_destroy(struct eloop_sock_table *table) -{ - if (table) { - int i; - for (i = 0; i < table->count && table->table; i++) { - wpa_printf(MSG_INFO, "ELOOP: remaining socket: " - "sock=%d eloop_data=%p user_data=%p " - "handler=%p", - table->table[i].sock, - table->table[i].eloop_data, - table->table[i].user_data, - table->table[i].handler); - wpa_trace_dump_funcname("eloop unregistered socket " - "handler", - table->table[i].handler); - wpa_trace_dump("eloop sock", &table->table[i]); - } - os_free(table->table); - } -} - - -int eloop_register_read_sock(int sock, eloop_sock_handler handler, - void *eloop_data, void *user_data) -{ - return eloop_register_sock(sock, EVENT_TYPE_READ, handler, - eloop_data, user_data); -} - - -void eloop_unregister_read_sock(int sock) -{ - eloop_unregister_sock(sock, EVENT_TYPE_READ); -} - - -static struct eloop_sock_table *eloop_get_sock_table(eloop_event_type type) -{ - switch (type) { - case EVENT_TYPE_READ: - return &eloop.readers; - case EVENT_TYPE_WRITE: - return &eloop.writers; - case EVENT_TYPE_EXCEPTION: - return &eloop.exceptions; - } - - return NULL; -} - - -int eloop_register_sock(int sock, eloop_event_type type, - eloop_sock_handler handler, - void *eloop_data, void *user_data) -{ - struct eloop_sock_table *table; - - table = eloop_get_sock_table(type); - return eloop_sock_table_add_sock(table, sock, handler, - eloop_data, user_data); -} - - -void eloop_unregister_sock(int sock, eloop_event_type type) -{ - struct eloop_sock_table *table; - - table = eloop_get_sock_table(type); - eloop_sock_table_remove_sock(table, sock); -} - - -int eloop_register_timeout(unsigned int secs, unsigned int usecs, - eloop_timeout_handler handler, - void *eloop_data, void *user_data) -{ - struct eloop_timeout *timeout, *tmp; - os_time_t now_sec; - - timeout = os_zalloc(sizeof(*timeout)); - if (timeout == NULL) - return -1; - if (os_get_time(&timeout->time) < 0) { - os_free(timeout); - return -1; - } - now_sec = timeout->time.sec; - timeout->time.sec += secs; - if (timeout->time.sec < now_sec) { - /* - * Integer overflow - assume long enough timeout to be assumed - * to be infinite, i.e., the timeout would never happen. - */ - wpa_printf(MSG_DEBUG, "ELOOP: Too long timeout (secs=%u) to " - "ever happen - ignore it", secs); - os_free(timeout); - return 0; - } - timeout->time.usec += usecs; - while (timeout->time.usec >= 1000000) { - timeout->time.sec++; - timeout->time.usec -= 1000000; - } - timeout->eloop_data = eloop_data; - timeout->user_data = user_data; - timeout->handler = handler; - wpa_trace_add_ref(timeout, eloop, eloop_data); - wpa_trace_add_ref(timeout, user, user_data); - wpa_trace_record(timeout); - - /* Maintain timeouts in order of increasing time */ - dl_list_for_each(tmp, &eloop.timeout, struct eloop_timeout, list) { - if (os_time_before(&timeout->time, &tmp->time)) { - dl_list_add(tmp->list.prev, &timeout->list); - return 0; - } - } - dl_list_add_tail(&eloop.timeout, &timeout->list); - - return 0; -} - - -static void eloop_remove_timeout(struct eloop_timeout *timeout) -{ - dl_list_del(&timeout->list); - wpa_trace_remove_ref(timeout, eloop, timeout->eloop_data); - wpa_trace_remove_ref(timeout, user, timeout->user_data); - os_free(timeout); -} - - -int eloop_cancel_timeout(eloop_timeout_handler handler, - void *eloop_data, void *user_data) -{ - struct eloop_timeout *timeout, *prev; - int removed = 0; - - dl_list_for_each_safe(timeout, prev, &eloop.timeout, - struct eloop_timeout, list) { - if (timeout->handler == handler && - (timeout->eloop_data == eloop_data || - eloop_data == ELOOP_ALL_CTX) && - (timeout->user_data == user_data || - user_data == ELOOP_ALL_CTX)) { - eloop_remove_timeout(timeout); - removed++; - } - } - - return removed; -} - - -int eloop_is_timeout_registered(eloop_timeout_handler handler, - void *eloop_data, void *user_data) -{ - struct eloop_timeout *tmp; - - dl_list_for_each(tmp, &eloop.timeout, struct eloop_timeout, list) { - if (tmp->handler == handler && - tmp->eloop_data == eloop_data && - tmp->user_data == user_data) - return 1; - } - - return 0; -} - - -#ifndef CONFIG_NATIVE_WINDOWS -static void eloop_handle_alarm(int sig) -{ - wpa_printf(MSG_ERROR, "eloop: could not process SIGINT or SIGTERM in " - "two seconds. Looks like there\n" - "is a bug that ends up in a busy loop that " - "prevents clean shutdown.\n" - "Killing program forcefully.\n"); - exit(1); -} -#endif /* CONFIG_NATIVE_WINDOWS */ - - -static void eloop_handle_signal(int sig) -{ - int i; - -#ifndef CONFIG_NATIVE_WINDOWS - if ((sig == SIGINT || sig == SIGTERM) && !eloop.pending_terminate) { - /* Use SIGALRM to break out from potential busy loops that - * would not allow the program to be killed. */ - eloop.pending_terminate = 1; - signal(SIGALRM, eloop_handle_alarm); - alarm(2); - } -#endif /* CONFIG_NATIVE_WINDOWS */ - - eloop.signaled++; - for (i = 0; i < eloop.signal_count; i++) { - if (eloop.signals[i].sig == sig) { - eloop.signals[i].signaled++; - break; - } - } -} - - -static void eloop_process_pending_signals(void) -{ - int i; - - if (eloop.signaled == 0) - return; - eloop.signaled = 0; - - if (eloop.pending_terminate) { -#ifndef CONFIG_NATIVE_WINDOWS - alarm(0); -#endif /* CONFIG_NATIVE_WINDOWS */ - eloop.pending_terminate = 0; - } - - for (i = 0; i < eloop.signal_count; i++) { - if (eloop.signals[i].signaled) { - eloop.signals[i].signaled = 0; - eloop.signals[i].handler(eloop.signals[i].sig, - eloop.signals[i].user_data); - } - } -} - - -int eloop_register_signal(int sig, eloop_signal_handler handler, - void *user_data) -{ - struct eloop_signal *tmp; - - tmp = (struct eloop_signal *) - os_realloc(eloop.signals, - (eloop.signal_count + 1) * - sizeof(struct eloop_signal)); - if (tmp == NULL) - return -1; - - tmp[eloop.signal_count].sig = sig; - tmp[eloop.signal_count].user_data = user_data; - tmp[eloop.signal_count].handler = handler; - tmp[eloop.signal_count].signaled = 0; - eloop.signal_count++; - eloop.signals = tmp; - signal(sig, eloop_handle_signal); - - return 0; -} - - -int eloop_register_signal_terminate(eloop_signal_handler handler, - void *user_data) -{ - int ret = eloop_register_signal(SIGINT, handler, user_data); - if (ret == 0) - ret = eloop_register_signal(SIGTERM, handler, user_data); - return ret; -} - - -int eloop_register_signal_reconfig(eloop_signal_handler handler, - void *user_data) -{ -#ifdef CONFIG_NATIVE_WINDOWS - return 0; -#else /* CONFIG_NATIVE_WINDOWS */ - return eloop_register_signal(SIGHUP, handler, user_data); -#endif /* CONFIG_NATIVE_WINDOWS */ -} - - -void eloop_run(void) -{ - fd_set *rfds, *wfds, *efds; - int res; - struct timeval _tv; - struct os_time tv, now; - - rfds = os_malloc(sizeof(*rfds)); - wfds = os_malloc(sizeof(*wfds)); - efds = os_malloc(sizeof(*efds)); - if (rfds == NULL || wfds == NULL || efds == NULL) - goto out; - - while (!eloop.terminate && - (!dl_list_empty(&eloop.timeout) || eloop.readers.count > 0 || - eloop.writers.count > 0 || eloop.exceptions.count > 0)) { - struct eloop_timeout *timeout; - timeout = dl_list_first(&eloop.timeout, struct eloop_timeout, - list); - if (timeout) { - os_get_time(&now); - if (os_time_before(&now, &timeout->time)) - os_time_sub(&timeout->time, &now, &tv); - else - tv.sec = tv.usec = 0; - _tv.tv_sec = tv.sec; - _tv.tv_usec = tv.usec; - } - - eloop_sock_table_set_fds(&eloop.readers, rfds); - eloop_sock_table_set_fds(&eloop.writers, wfds); - eloop_sock_table_set_fds(&eloop.exceptions, efds); - res = select(eloop.max_sock + 1, rfds, wfds, efds, - timeout ? &_tv : NULL); - if (res < 0 && errno != EINTR && errno != 0) { - perror("select"); - goto out; - } - eloop_process_pending_signals(); - - /* check if some registered timeouts have occurred */ - timeout = dl_list_first(&eloop.timeout, struct eloop_timeout, - list); - if (timeout) { - os_get_time(&now); - if (!os_time_before(&now, &timeout->time)) { - void *eloop_data = timeout->eloop_data; - void *user_data = timeout->user_data; - eloop_timeout_handler handler = - timeout->handler; - eloop_remove_timeout(timeout); - handler(eloop_data, user_data); - } - - } - - if (res <= 0) - continue; - - eloop_sock_table_dispatch(&eloop.readers, rfds); - eloop_sock_table_dispatch(&eloop.writers, wfds); - eloop_sock_table_dispatch(&eloop.exceptions, efds); - } - -out: - os_free(rfds); - os_free(wfds); - os_free(efds); -} - - -void eloop_terminate(void) -{ - eloop.terminate = 1; -} - - -void eloop_destroy(void) -{ - struct eloop_timeout *timeout, *prev; - struct os_time now; - - os_get_time(&now); - dl_list_for_each_safe(timeout, prev, &eloop.timeout, - struct eloop_timeout, list) { - int sec, usec; - sec = timeout->time.sec - now.sec; - usec = timeout->time.usec - now.usec; - if (timeout->time.usec < now.usec) { - sec--; - usec += 1000000; - } - wpa_printf(MSG_INFO, "ELOOP: remaining timeout: %d.%06d " - "eloop_data=%p user_data=%p handler=%p", - sec, usec, timeout->eloop_data, timeout->user_data, - timeout->handler); - wpa_trace_dump_funcname("eloop unregistered timeout handler", - timeout->handler); - wpa_trace_dump("eloop timeout", timeout); - eloop_remove_timeout(timeout); - } - eloop_sock_table_destroy(&eloop.readers); - eloop_sock_table_destroy(&eloop.writers); - eloop_sock_table_destroy(&eloop.exceptions); - os_free(eloop.signals); -} - - -int eloop_terminated(void) -{ - return eloop.terminate; -} - - -void eloop_wait_for_read_sock(int sock) -{ - fd_set rfds; - - if (sock < 0) - return; - - FD_ZERO(&rfds); - FD_SET(sock, &rfds); - select(sock + 1, &rfds, NULL, NULL, NULL); -} diff --git a/hostapd-0.8/src/utils/eloop.h b/hostapd-0.8/src/utils/eloop.h deleted file mode 100644 index 1228f24..0000000 --- a/hostapd-0.8/src/utils/eloop.h +++ /dev/null @@ -1,316 +0,0 @@ -/* - * Event loop - * Copyright (c) 2002-2006, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - * - * This file defines an event loop interface that supports processing events - * from registered timeouts (i.e., do something after N seconds), sockets - * (e.g., a new packet available for reading), and signals. eloop.c is an - * implementation of this interface using select() and sockets. This is - * suitable for most UNIX/POSIX systems. When porting to other operating - * systems, it may be necessary to replace that implementation with OS specific - * mechanisms. - */ - -#ifndef ELOOP_H -#define ELOOP_H - -/** - * ELOOP_ALL_CTX - eloop_cancel_timeout() magic number to match all timeouts - */ -#define ELOOP_ALL_CTX (void *) -1 - -/** - * eloop_event_type - eloop socket event type for eloop_register_sock() - * @EVENT_TYPE_READ: Socket has data available for reading - * @EVENT_TYPE_WRITE: Socket has room for new data to be written - * @EVENT_TYPE_EXCEPTION: An exception has been reported - */ -typedef enum { - EVENT_TYPE_READ = 0, - EVENT_TYPE_WRITE, - EVENT_TYPE_EXCEPTION -} eloop_event_type; - -/** - * eloop_sock_handler - eloop socket event callback type - * @sock: File descriptor number for the socket - * @eloop_ctx: Registered callback context data (eloop_data) - * @sock_ctx: Registered callback context data (user_data) - */ -typedef void (*eloop_sock_handler)(int sock, void *eloop_ctx, void *sock_ctx); - -/** - * eloop_event_handler - eloop generic event callback type - * @eloop_ctx: Registered callback context data (eloop_data) - * @sock_ctx: Registered callback context data (user_data) - */ -typedef void (*eloop_event_handler)(void *eloop_data, void *user_ctx); - -/** - * eloop_timeout_handler - eloop timeout event callback type - * @eloop_ctx: Registered callback context data (eloop_data) - * @sock_ctx: Registered callback context data (user_data) - */ -typedef void (*eloop_timeout_handler)(void *eloop_data, void *user_ctx); - -/** - * eloop_signal_handler - eloop signal event callback type - * @sig: Signal number - * @signal_ctx: Registered callback context data (user_data from - * eloop_register_signal(), eloop_register_signal_terminate(), or - * eloop_register_signal_reconfig() call) - */ -typedef void (*eloop_signal_handler)(int sig, void *signal_ctx); - -/** - * eloop_init() - Initialize global event loop data - * Returns: 0 on success, -1 on failure - * - * This function must be called before any other eloop_* function. - */ -int eloop_init(void); - -/** - * eloop_register_read_sock - Register handler for read events - * @sock: File descriptor number for the socket - * @handler: Callback function to be called when data is available for reading - * @eloop_data: Callback context data (eloop_ctx) - * @user_data: Callback context data (sock_ctx) - * Returns: 0 on success, -1 on failure - * - * Register a read socket notifier for the given file descriptor. The handler - * function will be called whenever data is available for reading from the - * socket. The handler function is responsible for clearing the event after - * having processed it in order to avoid eloop from calling the handler again - * for the same event. - */ -int eloop_register_read_sock(int sock, eloop_sock_handler handler, - void *eloop_data, void *user_data); - -/** - * eloop_unregister_read_sock - Unregister handler for read events - * @sock: File descriptor number for the socket - * - * Unregister a read socket notifier that was previously registered with - * eloop_register_read_sock(). - */ -void eloop_unregister_read_sock(int sock); - -/** - * eloop_register_sock - Register handler for socket events - * @sock: File descriptor number for the socket - * @type: Type of event to wait for - * @handler: Callback function to be called when the event is triggered - * @eloop_data: Callback context data (eloop_ctx) - * @user_data: Callback context data (sock_ctx) - * Returns: 0 on success, -1 on failure - * - * Register an event notifier for the given socket's file descriptor. The - * handler function will be called whenever the that event is triggered for the - * socket. The handler function is responsible for clearing the event after - * having processed it in order to avoid eloop from calling the handler again - * for the same event. - */ -int eloop_register_sock(int sock, eloop_event_type type, - eloop_sock_handler handler, - void *eloop_data, void *user_data); - -/** - * eloop_unregister_sock - Unregister handler for socket events - * @sock: File descriptor number for the socket - * @type: Type of event for which sock was registered - * - * Unregister a socket event notifier that was previously registered with - * eloop_register_sock(). - */ -void eloop_unregister_sock(int sock, eloop_event_type type); - -/** - * eloop_register_event - Register handler for generic events - * @event: Event to wait (eloop implementation specific) - * @event_size: Size of event data - * @handler: Callback function to be called when event is triggered - * @eloop_data: Callback context data (eloop_data) - * @user_data: Callback context data (user_data) - * Returns: 0 on success, -1 on failure - * - * Register an event handler for the given event. This function is used to - * register eloop implementation specific events which are mainly targetted for - * operating system specific code (driver interface and l2_packet) since the - * portable code will not be able to use such an OS-specific call. The handler - * function will be called whenever the event is triggered. The handler - * function is responsible for clearing the event after having processed it in - * order to avoid eloop from calling the handler again for the same event. - * - * In case of Windows implementation (eloop_win.c), event pointer is of HANDLE - * type, i.e., void*. The callers are likely to have 'HANDLE h' type variable, - * and they would call this function with eloop_register_event(h, sizeof(h), - * ...). - */ -int eloop_register_event(void *event, size_t event_size, - eloop_event_handler handler, - void *eloop_data, void *user_data); - -/** - * eloop_unregister_event - Unregister handler for a generic event - * @event: Event to cancel (eloop implementation specific) - * @event_size: Size of event data - * - * Unregister a generic event notifier that was previously registered with - * eloop_register_event(). - */ -void eloop_unregister_event(void *event, size_t event_size); - -/** - * eloop_register_timeout - Register timeout - * @secs: Number of seconds to the timeout - * @usecs: Number of microseconds to the timeout - * @handler: Callback function to be called when timeout occurs - * @eloop_data: Callback context data (eloop_ctx) - * @user_data: Callback context data (sock_ctx) - * Returns: 0 on success, -1 on failure - * - * Register a timeout that will cause the handler function to be called after - * given time. - */ -int eloop_register_timeout(unsigned int secs, unsigned int usecs, - eloop_timeout_handler handler, - void *eloop_data, void *user_data); - -/** - * eloop_cancel_timeout - Cancel timeouts - * @handler: Matching callback function - * @eloop_data: Matching eloop_data or %ELOOP_ALL_CTX to match all - * @user_data: Matching user_data or %ELOOP_ALL_CTX to match all - * Returns: Number of cancelled timeouts - * - * Cancel matching timeouts registered with - * eloop_register_timeout(). ELOOP_ALL_CTX can be used as a wildcard for - * cancelling all timeouts regardless of eloop_data/user_data. - */ -int eloop_cancel_timeout(eloop_timeout_handler handler, - void *eloop_data, void *user_data); - -/** - * eloop_is_timeout_registered - Check if a timeout is already registered - * @handler: Matching callback function - * @eloop_data: Matching eloop_data - * @user_data: Matching user_data - * Returns: 1 if the timeout is registered, 0 if the timeout is not registered - * - * Determine if a matching timeout is registered - * with eloop_register_timeout(). - */ -int eloop_is_timeout_registered(eloop_timeout_handler handler, - void *eloop_data, void *user_data); - -/** - * eloop_register_signal - Register handler for signals - * @sig: Signal number (e.g., SIGHUP) - * @handler: Callback function to be called when the signal is received - * @user_data: Callback context data (signal_ctx) - * Returns: 0 on success, -1 on failure - * - * Register a callback function that will be called when a signal is received. - * The callback function is actually called only after the system signal - * handler has returned. This means that the normal limits for sighandlers - * (i.e., only "safe functions" allowed) do not apply for the registered - * callback. - */ -int eloop_register_signal(int sig, eloop_signal_handler handler, - void *user_data); - -/** - * eloop_register_signal_terminate - Register handler for terminate signals - * @handler: Callback function to be called when the signal is received - * @user_data: Callback context data (signal_ctx) - * Returns: 0 on success, -1 on failure - * - * Register a callback function that will be called when a process termination - * signal is received. The callback function is actually called only after the - * system signal handler has returned. This means that the normal limits for - * sighandlers (i.e., only "safe functions" allowed) do not apply for the - * registered callback. - * - * This function is a more portable version of eloop_register_signal() since - * the knowledge of exact details of the signals is hidden in eloop - * implementation. In case of operating systems using signal(), this function - * registers handlers for SIGINT and SIGTERM. - */ -int eloop_register_signal_terminate(eloop_signal_handler handler, - void *user_data); - -/** - * eloop_register_signal_reconfig - Register handler for reconfig signals - * @handler: Callback function to be called when the signal is received - * @user_data: Callback context data (signal_ctx) - * Returns: 0 on success, -1 on failure - * - * Register a callback function that will be called when a reconfiguration / - * hangup signal is received. The callback function is actually called only - * after the system signal handler has returned. This means that the normal - * limits for sighandlers (i.e., only "safe functions" allowed) do not apply - * for the registered callback. - * - * This function is a more portable version of eloop_register_signal() since - * the knowledge of exact details of the signals is hidden in eloop - * implementation. In case of operating systems using signal(), this function - * registers a handler for SIGHUP. - */ -int eloop_register_signal_reconfig(eloop_signal_handler handler, - void *user_data); - -/** - * eloop_run - Start the event loop - * - * Start the event loop and continue running as long as there are any - * registered event handlers. This function is run after event loop has been - * initialized with event_init() and one or more events have been registered. - */ -void eloop_run(void); - -/** - * eloop_terminate - Terminate event loop - * - * Terminate event loop even if there are registered events. This can be used - * to request the program to be terminated cleanly. - */ -void eloop_terminate(void); - -/** - * eloop_destroy - Free any resources allocated for the event loop - * - * After calling eloop_destroy(), other eloop_* functions must not be called - * before re-running eloop_init(). - */ -void eloop_destroy(void); - -/** - * eloop_terminated - Check whether event loop has been terminated - * Returns: 1 = event loop terminate, 0 = event loop still running - * - * This function can be used to check whether eloop_terminate() has been called - * to request termination of the event loop. This is normally used to abort - * operations that may still be queued to be run when eloop_terminate() was - * called. - */ -int eloop_terminated(void); - -/** - * eloop_wait_for_read_sock - Wait for a single reader - * @sock: File descriptor number for the socket - * - * Do a blocking wait for a single read socket. - */ -void eloop_wait_for_read_sock(int sock); - -#endif /* ELOOP_H */ diff --git a/hostapd-0.8/src/utils/eloop_none.c b/hostapd-0.8/src/utils/eloop_none.c deleted file mode 100644 index 18eae4e..0000000 --- a/hostapd-0.8/src/utils/eloop_none.c +++ /dev/null @@ -1,401 +0,0 @@ -/* - * Event loop - empty template (basic structure, but no OS specific operations) - * Copyright (c) 2002-2005, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#include "includes.h" - -#include "common.h" -#include "eloop.h" - - -struct eloop_sock { - int sock; - void *eloop_data; - void *user_data; - void (*handler)(int sock, void *eloop_ctx, void *sock_ctx); -}; - -struct eloop_timeout { - struct os_time time; - void *eloop_data; - void *user_data; - void (*handler)(void *eloop_ctx, void *sock_ctx); - struct eloop_timeout *next; -}; - -struct eloop_signal { - int sig; - void *user_data; - void (*handler)(int sig, void *eloop_ctx, void *signal_ctx); - int signaled; -}; - -struct eloop_data { - int max_sock, reader_count; - struct eloop_sock *readers; - - struct eloop_timeout *timeout; - - int signal_count; - struct eloop_signal *signals; - int signaled; - int pending_terminate; - - int terminate; - int reader_table_changed; -}; - -static struct eloop_data eloop; - - -int eloop_init(void) -{ - memset(&eloop, 0, sizeof(eloop)); - return 0; -} - - -int eloop_register_read_sock(int sock, - void (*handler)(int sock, void *eloop_ctx, - void *sock_ctx), - void *eloop_data, void *user_data) -{ - struct eloop_sock *tmp; - - tmp = (struct eloop_sock *) - realloc(eloop.readers, - (eloop.reader_count + 1) * sizeof(struct eloop_sock)); - if (tmp == NULL) - return -1; - - tmp[eloop.reader_count].sock = sock; - tmp[eloop.reader_count].eloop_data = eloop_data; - tmp[eloop.reader_count].user_data = user_data; - tmp[eloop.reader_count].handler = handler; - eloop.reader_count++; - eloop.readers = tmp; - if (sock > eloop.max_sock) - eloop.max_sock = sock; - eloop.reader_table_changed = 1; - - return 0; -} - - -void eloop_unregister_read_sock(int sock) -{ - int i; - - if (eloop.readers == NULL || eloop.reader_count == 0) - return; - - for (i = 0; i < eloop.reader_count; i++) { - if (eloop.readers[i].sock == sock) - break; - } - if (i == eloop.reader_count) - return; - if (i != eloop.reader_count - 1) { - memmove(&eloop.readers[i], &eloop.readers[i + 1], - (eloop.reader_count - i - 1) * - sizeof(struct eloop_sock)); - } - eloop.reader_count--; - eloop.reader_table_changed = 1; -} - - -int eloop_register_timeout(unsigned int secs, unsigned int usecs, - void (*handler)(void *eloop_ctx, void *timeout_ctx), - void *eloop_data, void *user_data) -{ - struct eloop_timeout *timeout, *tmp, *prev; - - timeout = (struct eloop_timeout *) malloc(sizeof(*timeout)); - if (timeout == NULL) - return -1; - os_get_time(&timeout->time); - timeout->time.sec += secs; - timeout->time.usec += usecs; - while (timeout->time.usec >= 1000000) { - timeout->time.sec++; - timeout->time.usec -= 1000000; - } - timeout->eloop_data = eloop_data; - timeout->user_data = user_data; - timeout->handler = handler; - timeout->next = NULL; - - if (eloop.timeout == NULL) { - eloop.timeout = timeout; - return 0; - } - - prev = NULL; - tmp = eloop.timeout; - while (tmp != NULL) { - if (os_time_before(&timeout->time, &tmp->time)) - break; - prev = tmp; - tmp = tmp->next; - } - - if (prev == NULL) { - timeout->next = eloop.timeout; - eloop.timeout = timeout; - } else { - timeout->next = prev->next; - prev->next = timeout; - } - - return 0; -} - - -int eloop_cancel_timeout(void (*handler)(void *eloop_ctx, void *sock_ctx), - void *eloop_data, void *user_data) -{ - struct eloop_timeout *timeout, *prev, *next; - int removed = 0; - - prev = NULL; - timeout = eloop.timeout; - while (timeout != NULL) { - next = timeout->next; - - if (timeout->handler == handler && - (timeout->eloop_data == eloop_data || - eloop_data == ELOOP_ALL_CTX) && - (timeout->user_data == user_data || - user_data == ELOOP_ALL_CTX)) { - if (prev == NULL) - eloop.timeout = next; - else - prev->next = next; - free(timeout); - removed++; - } else - prev = timeout; - - timeout = next; - } - - return removed; -} - - -int eloop_is_timeout_registered(void (*handler)(void *eloop_ctx, - void *timeout_ctx), - void *eloop_data, void *user_data) -{ - struct eloop_timeout *tmp; - - tmp = eloop.timeout; - while (tmp != NULL) { - if (tmp->handler == handler && - tmp->eloop_data == eloop_data && - tmp->user_data == user_data) - return 1; - - tmp = tmp->next; - } - - return 0; -} - - -/* TODO: replace with suitable signal handler */ -#if 0 -static void eloop_handle_signal(int sig) -{ - int i; - - eloop.signaled++; - for (i = 0; i < eloop.signal_count; i++) { - if (eloop.signals[i].sig == sig) { - eloop.signals[i].signaled++; - break; - } - } -} -#endif - - -static void eloop_process_pending_signals(void) -{ - int i; - - if (eloop.signaled == 0) - return; - eloop.signaled = 0; - - if (eloop.pending_terminate) { - eloop.pending_terminate = 0; - } - - for (i = 0; i < eloop.signal_count; i++) { - if (eloop.signals[i].signaled) { - eloop.signals[i].signaled = 0; - eloop.signals[i].handler(eloop.signals[i].sig, - eloop.user_data, - eloop.signals[i].user_data); - } - } -} - - -int eloop_register_signal(int sig, - void (*handler)(int sig, void *eloop_ctx, - void *signal_ctx), - void *user_data) -{ - struct eloop_signal *tmp; - - tmp = (struct eloop_signal *) - realloc(eloop.signals, - (eloop.signal_count + 1) * - sizeof(struct eloop_signal)); - if (tmp == NULL) - return -1; - - tmp[eloop.signal_count].sig = sig; - tmp[eloop.signal_count].user_data = user_data; - tmp[eloop.signal_count].handler = handler; - tmp[eloop.signal_count].signaled = 0; - eloop.signal_count++; - eloop.signals = tmp; - - /* TODO: register signal handler */ - - return 0; -} - - -int eloop_register_signal_terminate(void (*handler)(int sig, void *eloop_ctx, - void *signal_ctx), - void *user_data) -{ -#if 0 - /* TODO: for example */ - int ret = eloop_register_signal(SIGINT, handler, user_data); - if (ret == 0) - ret = eloop_register_signal(SIGTERM, handler, user_data); - return ret; -#endif - return 0; -} - - -int eloop_register_signal_reconfig(void (*handler)(int sig, void *eloop_ctx, - void *signal_ctx), - void *user_data) -{ -#if 0 - /* TODO: for example */ - return eloop_register_signal(SIGHUP, handler, user_data); -#endif - return 0; -} - - -void eloop_run(void) -{ - int i; - struct os_time tv, now; - - while (!eloop.terminate && - (eloop.timeout || eloop.reader_count > 0)) { - if (eloop.timeout) { - os_get_time(&now); - if (os_time_before(&now, &eloop.timeout->time)) - os_time_sub(&eloop.timeout->time, &now, &tv); - else - tv.sec = tv.usec = 0; - } - - /* - * TODO: wait for any event (read socket ready, timeout (tv), - * signal - */ - os_sleep(1, 0); /* just a dummy wait for testing */ - - eloop_process_pending_signals(); - - /* check if some registered timeouts have occurred */ - if (eloop.timeout) { - struct eloop_timeout *tmp; - - os_get_time(&now); - if (!os_time_before(&now, &eloop.timeout->time)) { - tmp = eloop.timeout; - eloop.timeout = eloop.timeout->next; - tmp->handler(tmp->eloop_data, - tmp->user_data); - free(tmp); - } - - } - - eloop.reader_table_changed = 0; - for (i = 0; i < eloop.reader_count; i++) { - /* - * TODO: call each handler that has pending data to - * read - */ - if (0 /* TODO: eloop.readers[i].sock ready */) { - eloop.readers[i].handler( - eloop.readers[i].sock, - eloop.readers[i].eloop_data, - eloop.readers[i].user_data); - if (eloop.reader_table_changed) - break; - } - } - } -} - - -void eloop_terminate(void) -{ - eloop.terminate = 1; -} - - -void eloop_destroy(void) -{ - struct eloop_timeout *timeout, *prev; - - timeout = eloop.timeout; - while (timeout != NULL) { - prev = timeout; - timeout = timeout->next; - free(prev); - } - free(eloop.readers); - free(eloop.signals); -} - - -int eloop_terminated(void) -{ - return eloop.terminate; -} - - -void eloop_wait_for_read_sock(int sock) -{ - /* - * TODO: wait for the file descriptor to have something available for - * reading - */ -} diff --git a/hostapd-0.8/src/utils/eloop_win.c b/hostapd-0.8/src/utils/eloop_win.c deleted file mode 100644 index c726ece..0000000 --- a/hostapd-0.8/src/utils/eloop_win.c +++ /dev/null @@ -1,623 +0,0 @@ -/* - * Event loop based on Windows events and WaitForMultipleObjects - * Copyright (c) 2002-2006, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#include "includes.h" -#include - -#include "common.h" -#include "eloop.h" - - -struct eloop_sock { - int sock; - void *eloop_data; - void *user_data; - eloop_sock_handler handler; - WSAEVENT event; -}; - -struct eloop_event { - void *eloop_data; - void *user_data; - eloop_event_handler handler; - HANDLE event; -}; - -struct eloop_timeout { - struct os_time time; - void *eloop_data; - void *user_data; - eloop_timeout_handler handler; - struct eloop_timeout *next; -}; - -struct eloop_signal { - int sig; - void *user_data; - eloop_signal_handler handler; - int signaled; -}; - -struct eloop_data { - int max_sock; - size_t reader_count; - struct eloop_sock *readers; - - size_t event_count; - struct eloop_event *events; - - struct eloop_timeout *timeout; - - int signal_count; - struct eloop_signal *signals; - int signaled; - int pending_terminate; - - int terminate; - int reader_table_changed; - - struct eloop_signal term_signal; - HANDLE term_event; - - HANDLE *handles; - size_t num_handles; -}; - -static struct eloop_data eloop; - - -int eloop_init(void) -{ - os_memset(&eloop, 0, sizeof(eloop)); - eloop.num_handles = 1; - eloop.handles = os_malloc(eloop.num_handles * - sizeof(eloop.handles[0])); - if (eloop.handles == NULL) - return -1; - - eloop.term_event = CreateEvent(NULL, FALSE, FALSE, NULL); - if (eloop.term_event == NULL) { - printf("CreateEvent() failed: %d\n", - (int) GetLastError()); - os_free(eloop.handles); - return -1; - } - - return 0; -} - - -static int eloop_prepare_handles(void) -{ - HANDLE *n; - - if (eloop.num_handles > eloop.reader_count + eloop.event_count + 8) - return 0; - n = os_realloc(eloop.handles, - eloop.num_handles * 2 * sizeof(eloop.handles[0])); - if (n == NULL) - return -1; - eloop.handles = n; - eloop.num_handles *= 2; - return 0; -} - - -int eloop_register_read_sock(int sock, eloop_sock_handler handler, - void *eloop_data, void *user_data) -{ - WSAEVENT event; - struct eloop_sock *tmp; - - if (eloop_prepare_handles()) - return -1; - - event = WSACreateEvent(); - if (event == WSA_INVALID_EVENT) { - printf("WSACreateEvent() failed: %d\n", WSAGetLastError()); - return -1; - } - - if (WSAEventSelect(sock, event, FD_READ)) { - printf("WSAEventSelect() failed: %d\n", WSAGetLastError()); - WSACloseEvent(event); - return -1; - } - tmp = os_realloc(eloop.readers, - (eloop.reader_count + 1) * sizeof(struct eloop_sock)); - if (tmp == NULL) { - WSAEventSelect(sock, event, 0); - WSACloseEvent(event); - return -1; - } - - tmp[eloop.reader_count].sock = sock; - tmp[eloop.reader_count].eloop_data = eloop_data; - tmp[eloop.reader_count].user_data = user_data; - tmp[eloop.reader_count].handler = handler; - tmp[eloop.reader_count].event = event; - eloop.reader_count++; - eloop.readers = tmp; - if (sock > eloop.max_sock) - eloop.max_sock = sock; - eloop.reader_table_changed = 1; - - return 0; -} - - -void eloop_unregister_read_sock(int sock) -{ - size_t i; - - if (eloop.readers == NULL || eloop.reader_count == 0) - return; - - for (i = 0; i < eloop.reader_count; i++) { - if (eloop.readers[i].sock == sock) - break; - } - if (i == eloop.reader_count) - return; - - WSAEventSelect(eloop.readers[i].sock, eloop.readers[i].event, 0); - WSACloseEvent(eloop.readers[i].event); - - if (i != eloop.reader_count - 1) { - os_memmove(&eloop.readers[i], &eloop.readers[i + 1], - (eloop.reader_count - i - 1) * - sizeof(struct eloop_sock)); - } - eloop.reader_count--; - eloop.reader_table_changed = 1; -} - - -int eloop_register_event(void *event, size_t event_size, - eloop_event_handler handler, - void *eloop_data, void *user_data) -{ - struct eloop_event *tmp; - HANDLE h = event; - - if (event_size != sizeof(HANDLE) || h == INVALID_HANDLE_VALUE) - return -1; - - if (eloop_prepare_handles()) - return -1; - - tmp = os_realloc(eloop.events, - (eloop.event_count + 1) * sizeof(struct eloop_event)); - if (tmp == NULL) - return -1; - - tmp[eloop.event_count].eloop_data = eloop_data; - tmp[eloop.event_count].user_data = user_data; - tmp[eloop.event_count].handler = handler; - tmp[eloop.event_count].event = h; - eloop.event_count++; - eloop.events = tmp; - - return 0; -} - - -void eloop_unregister_event(void *event, size_t event_size) -{ - size_t i; - HANDLE h = event; - - if (eloop.events == NULL || eloop.event_count == 0 || - event_size != sizeof(HANDLE)) - return; - - for (i = 0; i < eloop.event_count; i++) { - if (eloop.events[i].event == h) - break; - } - if (i == eloop.event_count) - return; - - if (i != eloop.event_count - 1) { - os_memmove(&eloop.events[i], &eloop.events[i + 1], - (eloop.event_count - i - 1) * - sizeof(struct eloop_event)); - } - eloop.event_count--; -} - - -int eloop_register_timeout(unsigned int secs, unsigned int usecs, - eloop_timeout_handler handler, - void *eloop_data, void *user_data) -{ - struct eloop_timeout *timeout, *tmp, *prev; - os_time_t now_sec; - - timeout = os_malloc(sizeof(*timeout)); - if (timeout == NULL) - return -1; - os_get_time(&timeout->time); - now_sec = timeout->time.sec; - timeout->time.sec += secs; - if (timeout->time.sec < now_sec) { - /* - * Integer overflow - assume long enough timeout to be assumed - * to be infinite, i.e., the timeout would never happen. - */ - wpa_printf(MSG_DEBUG, "ELOOP: Too long timeout (secs=%u) to " - "ever happen - ignore it", secs); - os_free(timeout); - return 0; - } - timeout->time.usec += usecs; - while (timeout->time.usec >= 1000000) { - timeout->time.sec++; - timeout->time.usec -= 1000000; - } - timeout->eloop_data = eloop_data; - timeout->user_data = user_data; - timeout->handler = handler; - timeout->next = NULL; - - if (eloop.timeout == NULL) { - eloop.timeout = timeout; - return 0; - } - - prev = NULL; - tmp = eloop.timeout; - while (tmp != NULL) { - if (os_time_before(&timeout->time, &tmp->time)) - break; - prev = tmp; - tmp = tmp->next; - } - - if (prev == NULL) { - timeout->next = eloop.timeout; - eloop.timeout = timeout; - } else { - timeout->next = prev->next; - prev->next = timeout; - } - - return 0; -} - - -int eloop_cancel_timeout(eloop_timeout_handler handler, - void *eloop_data, void *user_data) -{ - struct eloop_timeout *timeout, *prev, *next; - int removed = 0; - - prev = NULL; - timeout = eloop.timeout; - while (timeout != NULL) { - next = timeout->next; - - if (timeout->handler == handler && - (timeout->eloop_data == eloop_data || - eloop_data == ELOOP_ALL_CTX) && - (timeout->user_data == user_data || - user_data == ELOOP_ALL_CTX)) { - if (prev == NULL) - eloop.timeout = next; - else - prev->next = next; - os_free(timeout); - removed++; - } else - prev = timeout; - - timeout = next; - } - - return removed; -} - - -int eloop_is_timeout_registered(eloop_timeout_handler handler, - void *eloop_data, void *user_data) -{ - struct eloop_timeout *tmp; - - tmp = eloop.timeout; - while (tmp != NULL) { - if (tmp->handler == handler && - tmp->eloop_data == eloop_data && - tmp->user_data == user_data) - return 1; - - tmp = tmp->next; - } - - return 0; -} - - -/* TODO: replace with suitable signal handler */ -#if 0 -static void eloop_handle_signal(int sig) -{ - int i; - - eloop.signaled++; - for (i = 0; i < eloop.signal_count; i++) { - if (eloop.signals[i].sig == sig) { - eloop.signals[i].signaled++; - break; - } - } -} -#endif - - -static void eloop_process_pending_signals(void) -{ - int i; - - if (eloop.signaled == 0) - return; - eloop.signaled = 0; - - if (eloop.pending_terminate) { - eloop.pending_terminate = 0; - } - - for (i = 0; i < eloop.signal_count; i++) { - if (eloop.signals[i].signaled) { - eloop.signals[i].signaled = 0; - eloop.signals[i].handler(eloop.signals[i].sig, - eloop.signals[i].user_data); - } - } - - if (eloop.term_signal.signaled) { - eloop.term_signal.signaled = 0; - eloop.term_signal.handler(eloop.term_signal.sig, - eloop.term_signal.user_data); - } -} - - -int eloop_register_signal(int sig, eloop_signal_handler handler, - void *user_data) -{ - struct eloop_signal *tmp; - - tmp = os_realloc(eloop.signals, - (eloop.signal_count + 1) * - sizeof(struct eloop_signal)); - if (tmp == NULL) - return -1; - - tmp[eloop.signal_count].sig = sig; - tmp[eloop.signal_count].user_data = user_data; - tmp[eloop.signal_count].handler = handler; - tmp[eloop.signal_count].signaled = 0; - eloop.signal_count++; - eloop.signals = tmp; - - /* TODO: register signal handler */ - - return 0; -} - - -#ifndef _WIN32_WCE -static BOOL eloop_handle_console_ctrl(DWORD type) -{ - switch (type) { - case CTRL_C_EVENT: - case CTRL_BREAK_EVENT: - eloop.signaled++; - eloop.term_signal.signaled++; - SetEvent(eloop.term_event); - return TRUE; - default: - return FALSE; - } -} -#endif /* _WIN32_WCE */ - - -int eloop_register_signal_terminate(eloop_signal_handler handler, - void *user_data) -{ -#ifndef _WIN32_WCE - if (SetConsoleCtrlHandler((PHANDLER_ROUTINE) eloop_handle_console_ctrl, - TRUE) == 0) { - printf("SetConsoleCtrlHandler() failed: %d\n", - (int) GetLastError()); - return -1; - } -#endif /* _WIN32_WCE */ - - eloop.term_signal.handler = handler; - eloop.term_signal.user_data = user_data; - - return 0; -} - - -int eloop_register_signal_reconfig(eloop_signal_handler handler, - void *user_data) -{ - /* TODO */ - return 0; -} - - -void eloop_run(void) -{ - struct os_time tv, now; - DWORD count, ret, timeout, err; - size_t i; - - while (!eloop.terminate && - (eloop.timeout || eloop.reader_count > 0 || - eloop.event_count > 0)) { - tv.sec = tv.usec = 0; - if (eloop.timeout) { - os_get_time(&now); - if (os_time_before(&now, &eloop.timeout->time)) - os_time_sub(&eloop.timeout->time, &now, &tv); - } - - count = 0; - for (i = 0; i < eloop.event_count; i++) - eloop.handles[count++] = eloop.events[i].event; - - for (i = 0; i < eloop.reader_count; i++) - eloop.handles[count++] = eloop.readers[i].event; - - if (eloop.term_event) - eloop.handles[count++] = eloop.term_event; - - if (eloop.timeout) - timeout = tv.sec * 1000 + tv.usec / 1000; - else - timeout = INFINITE; - - if (count > MAXIMUM_WAIT_OBJECTS) { - printf("WaitForMultipleObjects: Too many events: " - "%d > %d (ignoring extra events)\n", - (int) count, MAXIMUM_WAIT_OBJECTS); - count = MAXIMUM_WAIT_OBJECTS; - } -#ifdef _WIN32_WCE - ret = WaitForMultipleObjects(count, eloop.handles, FALSE, - timeout); -#else /* _WIN32_WCE */ - ret = WaitForMultipleObjectsEx(count, eloop.handles, FALSE, - timeout, TRUE); -#endif /* _WIN32_WCE */ - err = GetLastError(); - - eloop_process_pending_signals(); - - /* check if some registered timeouts have occurred */ - if (eloop.timeout) { - struct eloop_timeout *tmp; - - os_get_time(&now); - if (!os_time_before(&now, &eloop.timeout->time)) { - tmp = eloop.timeout; - eloop.timeout = eloop.timeout->next; - tmp->handler(tmp->eloop_data, - tmp->user_data); - os_free(tmp); - } - - } - - if (ret == WAIT_FAILED) { - printf("WaitForMultipleObjects(count=%d) failed: %d\n", - (int) count, (int) err); - os_sleep(1, 0); - continue; - } - -#ifndef _WIN32_WCE - if (ret == WAIT_IO_COMPLETION) - continue; -#endif /* _WIN32_WCE */ - - if (ret == WAIT_TIMEOUT) - continue; - - while (ret >= WAIT_OBJECT_0 && - ret < WAIT_OBJECT_0 + eloop.event_count) { - eloop.events[ret].handler( - eloop.events[ret].eloop_data, - eloop.events[ret].user_data); - ret = WaitForMultipleObjects(eloop.event_count, - eloop.handles, FALSE, 0); - } - - eloop.reader_table_changed = 0; - for (i = 0; i < eloop.reader_count; i++) { - WSANETWORKEVENTS events; - if (WSAEnumNetworkEvents(eloop.readers[i].sock, - eloop.readers[i].event, - &events) == 0 && - (events.lNetworkEvents & FD_READ)) { - eloop.readers[i].handler( - eloop.readers[i].sock, - eloop.readers[i].eloop_data, - eloop.readers[i].user_data); - if (eloop.reader_table_changed) - break; - } - } - } -} - - -void eloop_terminate(void) -{ - eloop.terminate = 1; - SetEvent(eloop.term_event); -} - - -void eloop_destroy(void) -{ - struct eloop_timeout *timeout, *prev; - - timeout = eloop.timeout; - while (timeout != NULL) { - prev = timeout; - timeout = timeout->next; - os_free(prev); - } - os_free(eloop.readers); - os_free(eloop.signals); - if (eloop.term_event) - CloseHandle(eloop.term_event); - os_free(eloop.handles); - eloop.handles = NULL; - os_free(eloop.events); - eloop.events = NULL; -} - - -int eloop_terminated(void) -{ - return eloop.terminate; -} - - -void eloop_wait_for_read_sock(int sock) -{ - WSAEVENT event; - - event = WSACreateEvent(); - if (event == WSA_INVALID_EVENT) { - printf("WSACreateEvent() failed: %d\n", WSAGetLastError()); - return; - } - - if (WSAEventSelect(sock, event, FD_READ)) { - printf("WSAEventSelect() failed: %d\n", WSAGetLastError()); - WSACloseEvent(event); - return ; - } - - WaitForSingleObject(event, INFINITE); - WSAEventSelect(sock, event, 0); - WSACloseEvent(event); -} diff --git a/hostapd-0.8/src/utils/includes.h b/hostapd-0.8/src/utils/includes.h deleted file mode 100644 index 63b5c23..0000000 --- a/hostapd-0.8/src/utils/includes.h +++ /dev/null @@ -1,59 +0,0 @@ -/* - * wpa_supplicant/hostapd - Default include files - * Copyright (c) 2005-2006, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - * - * This header file is included into all C files so that commonly used header - * files can be selected with OS specific ifdef blocks in one place instead of - * having to have OS/C library specific selection in many files. - */ - -#ifndef INCLUDES_H -#define INCLUDES_H - -/* Include possible build time configuration before including anything else */ -#include "build_config.h" - -#include -#include -#include -#include -#ifndef _WIN32_WCE -#ifndef CONFIG_TI_COMPILER -#include -#include -#endif /* CONFIG_TI_COMPILER */ -#include -#endif /* _WIN32_WCE */ -#include -#include - -#ifndef CONFIG_TI_COMPILER -#ifndef _MSC_VER -#include -#endif /* _MSC_VER */ -#endif /* CONFIG_TI_COMPILER */ - -#ifndef CONFIG_NATIVE_WINDOWS -#ifndef CONFIG_TI_COMPILER -#include -#include -#include -#ifndef __vxworks -#ifndef __SYMBIAN32__ -#include -#endif /* __SYMBIAN32__ */ -#include -#endif /* __vxworks */ -#endif /* CONFIG_TI_COMPILER */ -#endif /* CONFIG_NATIVE_WINDOWS */ - -#endif /* INCLUDES_H */ diff --git a/hostapd-0.8/src/utils/ip_addr.c b/hostapd-0.8/src/utils/ip_addr.c deleted file mode 100644 index 158fd57..0000000 --- a/hostapd-0.8/src/utils/ip_addr.c +++ /dev/null @@ -1,83 +0,0 @@ -/* - * IP address processing - * Copyright (c) 2003-2006, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#include "includes.h" - -#include "common.h" -#include "ip_addr.h" - -const char * hostapd_ip_txt(const struct hostapd_ip_addr *addr, char *buf, - size_t buflen) -{ - if (buflen == 0 || addr == NULL) - return NULL; - - if (addr->af == AF_INET) { - os_strlcpy(buf, inet_ntoa(addr->u.v4), buflen); - } else { - buf[0] = '\0'; - } -#ifdef CONFIG_IPV6 - if (addr->af == AF_INET6) { - if (inet_ntop(AF_INET6, &addr->u.v6, buf, buflen) == NULL) - buf[0] = '\0'; - } -#endif /* CONFIG_IPV6 */ - - return buf; -} - - -int hostapd_ip_diff(struct hostapd_ip_addr *a, struct hostapd_ip_addr *b) -{ - if (a == NULL && b == NULL) - return 0; - if (a == NULL || b == NULL) - return 1; - - switch (a->af) { - case AF_INET: - if (a->u.v4.s_addr != b->u.v4.s_addr) - return 1; - break; -#ifdef CONFIG_IPV6 - case AF_INET6: - if (os_memcmp(&a->u.v6, &b->u.v6, sizeof(a->u.v6)) != 0) - return 1; - break; -#endif /* CONFIG_IPV6 */ - } - - return 0; -} - - -int hostapd_parse_ip_addr(const char *txt, struct hostapd_ip_addr *addr) -{ -#ifndef CONFIG_NATIVE_WINDOWS - if (inet_aton(txt, &addr->u.v4)) { - addr->af = AF_INET; - return 0; - } - -#ifdef CONFIG_IPV6 - if (inet_pton(AF_INET6, txt, &addr->u.v6) > 0) { - addr->af = AF_INET6; - return 0; - } -#endif /* CONFIG_IPV6 */ -#endif /* CONFIG_NATIVE_WINDOWS */ - - return -1; -} diff --git a/hostapd-0.8/src/utils/ip_addr.h b/hostapd-0.8/src/utils/ip_addr.h deleted file mode 100644 index 28ccaef..0000000 --- a/hostapd-0.8/src/utils/ip_addr.h +++ /dev/null @@ -1,34 +0,0 @@ -/* - * IP address processing - * Copyright (c) 2003-2006, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#ifndef IP_ADDR_H -#define IP_ADDR_H - -struct hostapd_ip_addr { - int af; /* AF_INET / AF_INET6 */ - union { - struct in_addr v4; -#ifdef CONFIG_IPV6 - struct in6_addr v6; -#endif /* CONFIG_IPV6 */ - u8 max_len[16]; - } u; -}; - -const char * hostapd_ip_txt(const struct hostapd_ip_addr *addr, char *buf, - size_t buflen); -int hostapd_ip_diff(struct hostapd_ip_addr *a, struct hostapd_ip_addr *b); -int hostapd_parse_ip_addr(const char *txt, struct hostapd_ip_addr *addr); - -#endif /* IP_ADDR_H */ diff --git a/hostapd-0.8/src/utils/list.h b/hostapd-0.8/src/utils/list.h deleted file mode 100644 index ded7846..0000000 --- a/hostapd-0.8/src/utils/list.h +++ /dev/null @@ -1,98 +0,0 @@ -/* - * Doubly-linked list - * Copyright (c) 2009, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#ifndef LIST_H -#define LIST_H - -/** - * struct dl_list - Doubly-linked list - */ -struct dl_list { - struct dl_list *next; - struct dl_list *prev; -}; - -static inline void dl_list_init(struct dl_list *list) -{ - list->next = list; - list->prev = list; -} - -static inline void dl_list_add(struct dl_list *list, struct dl_list *item) -{ - item->next = list->next; - item->prev = list; - list->next->prev = item; - list->next = item; -} - -static inline void dl_list_add_tail(struct dl_list *list, struct dl_list *item) -{ - dl_list_add(list->prev, item); -} - -static inline void dl_list_del(struct dl_list *item) -{ - item->next->prev = item->prev; - item->prev->next = item->next; - item->next = NULL; - item->prev = NULL; -} - -static inline int dl_list_empty(struct dl_list *list) -{ - return list->next == list; -} - -static inline unsigned int dl_list_len(struct dl_list *list) -{ - struct dl_list *item; - int count = 0; - for (item = list->next; item != list; item = item->next) - count++; - return count; -} - -#ifndef offsetof -#define offsetof(type, member) ((long) &((type *) 0)->member) -#endif - -#define dl_list_entry(item, type, member) \ - ((type *) ((char *) item - offsetof(type, member))) - -#define dl_list_first(list, type, member) \ - (dl_list_empty((list)) ? NULL : \ - dl_list_entry((list)->next, type, member)) - -#define dl_list_last(list, type, member) \ - (dl_list_empty((list)) ? NULL : \ - dl_list_entry((list)->prev, type, member)) - -#define dl_list_for_each(item, list, type, member) \ - for (item = dl_list_entry((list)->next, type, member); \ - &item->member != (list); \ - item = dl_list_entry(item->member.next, type, member)) - -#define dl_list_for_each_safe(item, n, list, type, member) \ - for (item = dl_list_entry((list)->next, type, member), \ - n = dl_list_entry(item->member.next, type, member); \ - &item->member != (list); \ - item = n, n = dl_list_entry(n->member.next, type, member)) - -#define dl_list_for_each_reverse(item, list, type, member) \ - for (item = dl_list_entry((list)->prev, type, member); \ - &item->member != (list); \ - item = dl_list_entry(item->member.prev, type, member)) - -#endif /* LIST_H */ diff --git a/hostapd-0.8/src/utils/os.h b/hostapd-0.8/src/utils/os.h deleted file mode 100644 index f4723d8..0000000 --- a/hostapd-0.8/src/utils/os.h +++ /dev/null @@ -1,508 +0,0 @@ -/* - * OS specific functions - * Copyright (c) 2005-2009, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#ifndef OS_H -#define OS_H - -typedef long os_time_t; - -/** - * os_sleep - Sleep (sec, usec) - * @sec: Number of seconds to sleep - * @usec: Number of microseconds to sleep - */ -void os_sleep(os_time_t sec, os_time_t usec); - -struct os_time { - os_time_t sec; - os_time_t usec; -}; - -/** - * os_get_time - Get current time (sec, usec) - * @t: Pointer to buffer for the time - * Returns: 0 on success, -1 on failure - */ -int os_get_time(struct os_time *t); - - -/* Helper macros for handling struct os_time */ - -#define os_time_before(a, b) \ - ((a)->sec < (b)->sec || \ - ((a)->sec == (b)->sec && (a)->usec < (b)->usec)) - -#define os_time_sub(a, b, res) do { \ - (res)->sec = (a)->sec - (b)->sec; \ - (res)->usec = (a)->usec - (b)->usec; \ - if ((res)->usec < 0) { \ - (res)->sec--; \ - (res)->usec += 1000000; \ - } \ -} while (0) - -/** - * os_mktime - Convert broken-down time into seconds since 1970-01-01 - * @year: Four digit year - * @month: Month (1 .. 12) - * @day: Day of month (1 .. 31) - * @hour: Hour (0 .. 23) - * @min: Minute (0 .. 59) - * @sec: Second (0 .. 60) - * @t: Buffer for returning calendar time representation (seconds since - * 1970-01-01 00:00:00) - * Returns: 0 on success, -1 on failure - * - * Note: The result is in seconds from Epoch, i.e., in UTC, not in local time - * which is used by POSIX mktime(). - */ -int os_mktime(int year, int month, int day, int hour, int min, int sec, - os_time_t *t); - - -/** - * os_daemonize - Run in the background (detach from the controlling terminal) - * @pid_file: File name to write the process ID to or %NULL to skip this - * Returns: 0 on success, -1 on failure - */ -int os_daemonize(const char *pid_file); - -/** - * os_daemonize_terminate - Stop running in the background (remove pid file) - * @pid_file: File name to write the process ID to or %NULL to skip this - */ -void os_daemonize_terminate(const char *pid_file); - -/** - * os_get_random - Get cryptographically strong pseudo random data - * @buf: Buffer for pseudo random data - * @len: Length of the buffer - * Returns: 0 on success, -1 on failure - */ -int os_get_random(unsigned char *buf, size_t len); - -/** - * os_random - Get pseudo random value (not necessarily very strong) - * Returns: Pseudo random value - */ -unsigned long os_random(void); - -/** - * os_rel2abs_path - Get an absolute path for a file - * @rel_path: Relative path to a file - * Returns: Absolute path for the file or %NULL on failure - * - * This function tries to convert a relative path of a file to an absolute path - * in order for the file to be found even if current working directory has - * changed. The returned value is allocated and caller is responsible for - * freeing it. It is acceptable to just return the same path in an allocated - * buffer, e.g., return strdup(rel_path). This function is only used to find - * configuration files when os_daemonize() may have changed the current working - * directory and relative path would be pointing to a different location. - */ -char * os_rel2abs_path(const char *rel_path); - -/** - * os_program_init - Program initialization (called at start) - * Returns: 0 on success, -1 on failure - * - * This function is called when a programs starts. If there are any OS specific - * processing that is needed, it can be placed here. It is also acceptable to - * just return 0 if not special processing is needed. - */ -int os_program_init(void); - -/** - * os_program_deinit - Program deinitialization (called just before exit) - * - * This function is called just before a program exists. If there are any OS - * specific processing, e.g., freeing resourced allocated in os_program_init(), - * it should be done here. It is also acceptable for this function to do - * nothing. - */ -void os_program_deinit(void); - -/** - * os_setenv - Set environment variable - * @name: Name of the variable - * @value: Value to set to the variable - * @overwrite: Whether existing variable should be overwritten - * Returns: 0 on success, -1 on error - * - * This function is only used for wpa_cli action scripts. OS wrapper does not - * need to implement this if such functionality is not needed. - */ -int os_setenv(const char *name, const char *value, int overwrite); - -/** - * os_unsetenv - Delete environent variable - * @name: Name of the variable - * Returns: 0 on success, -1 on error - * - * This function is only used for wpa_cli action scripts. OS wrapper does not - * need to implement this if such functionality is not needed. - */ -int os_unsetenv(const char *name); - -/** - * os_readfile - Read a file to an allocated memory buffer - * @name: Name of the file to read - * @len: For returning the length of the allocated buffer - * Returns: Pointer to the allocated buffer or %NULL on failure - * - * This function allocates memory and reads the given file to this buffer. Both - * binary and text files can be read with this function. The caller is - * responsible for freeing the returned buffer with os_free(). - */ -char * os_readfile(const char *name, size_t *len); - -/** - * os_zalloc - Allocate and zero memory - * @size: Number of bytes to allocate - * Returns: Pointer to allocated and zeroed memory or %NULL on failure - * - * Caller is responsible for freeing the returned buffer with os_free(). - */ -void * os_zalloc(size_t size); - - -/* - * The following functions are wrapper for standard ANSI C or POSIX functions. - * By default, they are just defined to use the standard function name and no - * os_*.c implementation is needed for them. This avoids extra function calls - * by allowing the C pre-processor take care of the function name mapping. - * - * If the target system uses a C library that does not provide these functions, - * build_config.h can be used to define the wrappers to use a different - * function name. This can be done on function-by-function basis since the - * defines here are only used if build_config.h does not define the os_* name. - * If needed, os_*.c file can be used to implement the functions that are not - * included in the C library on the target system. Alternatively, - * OS_NO_C_LIB_DEFINES can be defined to skip all defines here in which case - * these functions need to be implemented in os_*.c file for the target system. - */ - -#ifdef OS_NO_C_LIB_DEFINES - -/** - * os_malloc - Allocate dynamic memory - * @size: Size of the buffer to allocate - * Returns: Allocated buffer or %NULL on failure - * - * Caller is responsible for freeing the returned buffer with os_free(). - */ -void * os_malloc(size_t size); - -/** - * os_realloc - Re-allocate dynamic memory - * @ptr: Old buffer from os_malloc() or os_realloc() - * @size: Size of the new buffer - * Returns: Allocated buffer or %NULL on failure - * - * Caller is responsible for freeing the returned buffer with os_free(). - * If re-allocation fails, %NULL is returned and the original buffer (ptr) is - * not freed and caller is still responsible for freeing it. - */ -void * os_realloc(void *ptr, size_t size); - -/** - * os_free - Free dynamic memory - * @ptr: Old buffer from os_malloc() or os_realloc(); can be %NULL - */ -void os_free(void *ptr); - -/** - * os_memcpy - Copy memory area - * @dest: Destination - * @src: Source - * @n: Number of bytes to copy - * Returns: dest - * - * The memory areas src and dst must not overlap. os_memmove() can be used with - * overlapping memory. - */ -void * os_memcpy(void *dest, const void *src, size_t n); - -/** - * os_memmove - Copy memory area - * @dest: Destination - * @src: Source - * @n: Number of bytes to copy - * Returns: dest - * - * The memory areas src and dst may overlap. - */ -void * os_memmove(void *dest, const void *src, size_t n); - -/** - * os_memset - Fill memory with a constant byte - * @s: Memory area to be filled - * @c: Constant byte - * @n: Number of bytes started from s to fill with c - * Returns: s - */ -void * os_memset(void *s, int c, size_t n); - -/** - * os_memcmp - Compare memory areas - * @s1: First buffer - * @s2: Second buffer - * @n: Maximum numbers of octets to compare - * Returns: An integer less than, equal to, or greater than zero if s1 is - * found to be less than, to match, or be greater than s2. Only first n - * characters will be compared. - */ -int os_memcmp(const void *s1, const void *s2, size_t n); - -/** - * os_strdup - Duplicate a string - * @s: Source string - * Returns: Allocated buffer with the string copied into it or %NULL on failure - * - * Caller is responsible for freeing the returned buffer with os_free(). - */ -char * os_strdup(const char *s); - -/** - * os_strlen - Calculate the length of a string - * @s: '\0' terminated string - * Returns: Number of characters in s (not counting the '\0' terminator) - */ -size_t os_strlen(const char *s); - -/** - * os_strcasecmp - Compare two strings ignoring case - * @s1: First string - * @s2: Second string - * Returns: An integer less than, equal to, or greater than zero if s1 is - * found to be less than, to match, or be greatred than s2 - */ -int os_strcasecmp(const char *s1, const char *s2); - -/** - * os_strncasecmp - Compare two strings ignoring case - * @s1: First string - * @s2: Second string - * @n: Maximum numbers of characters to compare - * Returns: An integer less than, equal to, or greater than zero if s1 is - * found to be less than, to match, or be greater than s2. Only first n - * characters will be compared. - */ -int os_strncasecmp(const char *s1, const char *s2, size_t n); - -/** - * os_strchr - Locate the first occurrence of a character in string - * @s: String - * @c: Character to search for - * Returns: Pointer to the matched character or %NULL if not found - */ -char * os_strchr(const char *s, int c); - -/** - * os_strrchr - Locate the last occurrence of a character in string - * @s: String - * @c: Character to search for - * Returns: Pointer to the matched character or %NULL if not found - */ -char * os_strrchr(const char *s, int c); - -/** - * os_strcmp - Compare two strings - * @s1: First string - * @s2: Second string - * Returns: An integer less than, equal to, or greater than zero if s1 is - * found to be less than, to match, or be greatred than s2 - */ -int os_strcmp(const char *s1, const char *s2); - -/** - * os_strncmp - Compare two strings - * @s1: First string - * @s2: Second string - * @n: Maximum numbers of characters to compare - * Returns: An integer less than, equal to, or greater than zero if s1 is - * found to be less than, to match, or be greater than s2. Only first n - * characters will be compared. - */ -int os_strncmp(const char *s1, const char *s2, size_t n); - -/** - * os_strncpy - Copy a string - * @dest: Destination - * @src: Source - * @n: Maximum number of characters to copy - * Returns: dest - */ -char * os_strncpy(char *dest, const char *src, size_t n); - -/** - * os_strstr - Locate a substring - * @haystack: String (haystack) to search from - * @needle: Needle to search from haystack - * Returns: Pointer to the beginning of the substring or %NULL if not found - */ -char * os_strstr(const char *haystack, const char *needle); - -/** - * os_snprintf - Print to a memory buffer - * @str: Memory buffer to print into - * @size: Maximum length of the str buffer - * @format: printf format - * Returns: Number of characters printed (not including trailing '\0'). - * - * If the output buffer is truncated, number of characters which would have - * been written is returned. Since some C libraries return -1 in such a case, - * the caller must be prepared on that value, too, to indicate truncation. - * - * Note: Some C library implementations of snprintf() may not guarantee null - * termination in case the output is truncated. The OS wrapper function of - * os_snprintf() should provide this guarantee, i.e., to null terminate the - * output buffer if a C library version of the function is used and if that - * function does not guarantee null termination. - * - * If the target system does not include snprintf(), see, e.g., - * http://www.ijs.si/software/snprintf/ for an example of a portable - * implementation of snprintf. - */ -int os_snprintf(char *str, size_t size, const char *format, ...); - -#else /* OS_NO_C_LIB_DEFINES */ - -#ifdef WPA_TRACE -void * os_malloc(size_t size); -void * os_realloc(void *ptr, size_t size); -void os_free(void *ptr); -char * os_strdup(const char *s); -#else /* WPA_TRACE */ -#ifndef os_malloc -#define os_malloc(s) malloc((s)) -#endif -#ifndef os_realloc -#define os_realloc(p, s) realloc((p), (s)) -#endif -#ifndef os_free -#define os_free(p) free((p)) -#endif -#ifndef os_strdup -#ifdef _MSC_VER -#define os_strdup(s) _strdup(s) -#else -#define os_strdup(s) strdup(s) -#endif -#endif -#endif /* WPA_TRACE */ - -#ifndef os_memcpy -#define os_memcpy(d, s, n) memcpy((d), (s), (n)) -#endif -#ifndef os_memmove -#define os_memmove(d, s, n) memmove((d), (s), (n)) -#endif -#ifndef os_memset -#define os_memset(s, c, n) memset(s, c, n) -#endif -#ifndef os_memcmp -#define os_memcmp(s1, s2, n) memcmp((s1), (s2), (n)) -#endif - -#ifndef os_strlen -#define os_strlen(s) strlen(s) -#endif -#ifndef os_strcasecmp -#ifdef _MSC_VER -#define os_strcasecmp(s1, s2) _stricmp((s1), (s2)) -#else -#define os_strcasecmp(s1, s2) strcasecmp((s1), (s2)) -#endif -#endif -#ifndef os_strncasecmp -#ifdef _MSC_VER -#define os_strncasecmp(s1, s2, n) _strnicmp((s1), (s2), (n)) -#else -#define os_strncasecmp(s1, s2, n) strncasecmp((s1), (s2), (n)) -#endif -#endif -#ifndef os_strchr -#define os_strchr(s, c) strchr((s), (c)) -#endif -#ifndef os_strcmp -#define os_strcmp(s1, s2) strcmp((s1), (s2)) -#endif -#ifndef os_strncmp -#define os_strncmp(s1, s2, n) strncmp((s1), (s2), (n)) -#endif -#ifndef os_strncpy -#define os_strncpy(d, s, n) strncpy((d), (s), (n)) -#endif -#ifndef os_strrchr -#define os_strrchr(s, c) strrchr((s), (c)) -#endif -#ifndef os_strstr -#define os_strstr(h, n) strstr((h), (n)) -#endif - -#ifndef os_snprintf -#ifdef _MSC_VER -#define os_snprintf _snprintf -#else -#define os_snprintf snprintf -#endif -#endif - -#endif /* OS_NO_C_LIB_DEFINES */ - - -/** - * os_strlcpy - Copy a string with size bound and NUL-termination - * @dest: Destination - * @src: Source - * @siz: Size of the target buffer - * Returns: Total length of the target string (length of src) (not including - * NUL-termination) - * - * This function matches in behavior with the strlcpy(3) function in OpenBSD. - */ -size_t os_strlcpy(char *dest, const char *src, size_t siz); - - -#ifdef OS_REJECT_C_LIB_FUNCTIONS -#define malloc OS_DO_NOT_USE_malloc -#define realloc OS_DO_NOT_USE_realloc -#define free OS_DO_NOT_USE_free -#define memcpy OS_DO_NOT_USE_memcpy -#define memmove OS_DO_NOT_USE_memmove -#define memset OS_DO_NOT_USE_memset -#define memcmp OS_DO_NOT_USE_memcmp -#undef strdup -#define strdup OS_DO_NOT_USE_strdup -#define strlen OS_DO_NOT_USE_strlen -#define strcasecmp OS_DO_NOT_USE_strcasecmp -#define strncasecmp OS_DO_NOT_USE_strncasecmp -#undef strchr -#define strchr OS_DO_NOT_USE_strchr -#undef strcmp -#define strcmp OS_DO_NOT_USE_strcmp -#undef strncmp -#define strncmp OS_DO_NOT_USE_strncmp -#undef strncpy -#define strncpy OS_DO_NOT_USE_strncpy -#define strrchr OS_DO_NOT_USE_strrchr -#define strstr OS_DO_NOT_USE_strstr -#undef snprintf -#define snprintf OS_DO_NOT_USE_snprintf - -#define strcpy OS_DO_NOT_USE_strcpy -#endif /* OS_REJECT_C_LIB_FUNCTIONS */ - -#endif /* OS_H */ diff --git a/hostapd-0.8/src/utils/os_internal.c b/hostapd-0.8/src/utils/os_internal.c deleted file mode 100644 index 5260e23..0000000 --- a/hostapd-0.8/src/utils/os_internal.c +++ /dev/null @@ -1,471 +0,0 @@ -/* - * wpa_supplicant/hostapd / Internal implementation of OS specific functions - * Copyright (c) 2005-2006, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - * - * This file is an example of operating system specific wrapper functions. - * This version implements many of the functions internally, so it can be used - * to fill in missing functions from the target system C libraries. - * - * Some of the functions are using standard C library calls in order to keep - * this file in working condition to allow the functions to be tested on a - * Linux target. Please note that OS_NO_C_LIB_DEFINES needs to be defined for - * this file to work correctly. Note that these implementations are only - * examples and are not optimized for speed. - */ - -#include "includes.h" - -#undef OS_REJECT_C_LIB_FUNCTIONS -#include "os.h" - -void os_sleep(os_time_t sec, os_time_t usec) -{ - if (sec) - sleep(sec); - if (usec) - usleep(usec); -} - - -int os_get_time(struct os_time *t) -{ - int res; - struct timeval tv; - res = gettimeofday(&tv, NULL); - t->sec = tv.tv_sec; - t->usec = tv.tv_usec; - return res; -} - - -int os_mktime(int year, int month, int day, int hour, int min, int sec, - os_time_t *t) -{ - struct tm tm; - - if (year < 1970 || month < 1 || month > 12 || day < 1 || day > 31 || - hour < 0 || hour > 23 || min < 0 || min > 59 || sec < 0 || - sec > 60) - return -1; - - os_memset(&tm, 0, sizeof(tm)); - tm.tm_year = year - 1900; - tm.tm_mon = month - 1; - tm.tm_mday = day; - tm.tm_hour = hour; - tm.tm_min = min; - tm.tm_sec = sec; - - *t = (os_time_t) mktime(&tm); - return 0; -} - - -int os_daemonize(const char *pid_file) -{ - if (daemon(0, 0)) { - perror("daemon"); - return -1; - } - - if (pid_file) { - FILE *f = fopen(pid_file, "w"); - if (f) { - fprintf(f, "%u\n", getpid()); - fclose(f); - } - } - - return -0; -} - - -void os_daemonize_terminate(const char *pid_file) -{ - if (pid_file) - unlink(pid_file); -} - - -int os_get_random(unsigned char *buf, size_t len) -{ - FILE *f; - size_t rc; - - f = fopen("/dev/urandom", "rb"); - if (f == NULL) { - printf("Could not open /dev/urandom.\n"); - return -1; - } - - rc = fread(buf, 1, len, f); - fclose(f); - - return rc != len ? -1 : 0; -} - - -unsigned long os_random(void) -{ - return random(); -} - - -char * os_rel2abs_path(const char *rel_path) -{ - char *buf = NULL, *cwd, *ret; - size_t len = 128, cwd_len, rel_len, ret_len; - - if (rel_path[0] == '/') - return os_strdup(rel_path); - - for (;;) { - buf = os_malloc(len); - if (buf == NULL) - return NULL; - cwd = getcwd(buf, len); - if (cwd == NULL) { - os_free(buf); - if (errno != ERANGE) { - return NULL; - } - len *= 2; - } else { - break; - } - } - - cwd_len = strlen(cwd); - rel_len = strlen(rel_path); - ret_len = cwd_len + 1 + rel_len + 1; - ret = os_malloc(ret_len); - if (ret) { - os_memcpy(ret, cwd, cwd_len); - ret[cwd_len] = '/'; - os_memcpy(ret + cwd_len + 1, rel_path, rel_len); - ret[ret_len - 1] = '\0'; - } - os_free(buf); - return ret; -} - - -int os_program_init(void) -{ - return 0; -} - - -void os_program_deinit(void) -{ -} - - -int os_setenv(const char *name, const char *value, int overwrite) -{ - return setenv(name, value, overwrite); -} - - -int os_unsetenv(const char *name) -{ -#if defined(__FreeBSD__) || defined(__NetBSD__) - unsetenv(name); - return 0; -#else - return unsetenv(name); -#endif -} - - -char * os_readfile(const char *name, size_t *len) -{ - FILE *f; - char *buf; - - f = fopen(name, "rb"); - if (f == NULL) - return NULL; - - fseek(f, 0, SEEK_END); - *len = ftell(f); - fseek(f, 0, SEEK_SET); - - buf = os_malloc(*len); - if (buf == NULL) { - fclose(f); - return NULL; - } - - if (fread(buf, 1, *len, f) != *len) { - fclose(f); - os_free(buf); - return NULL; - } - - fclose(f); - - return buf; -} - - -void * os_zalloc(size_t size) -{ - void *n = os_malloc(size); - if (n) - os_memset(n, 0, size); - return n; -} - - -void * os_malloc(size_t size) -{ - return malloc(size); -} - - -void * os_realloc(void *ptr, size_t size) -{ - return realloc(ptr, size); -} - - -void os_free(void *ptr) -{ - free(ptr); -} - - -void * os_memcpy(void *dest, const void *src, size_t n) -{ - char *d = dest; - const char *s = src; - while (n--) - *d++ = *s++; - return dest; -} - - -void * os_memmove(void *dest, const void *src, size_t n) -{ - if (dest < src) - os_memcpy(dest, src, n); - else { - /* overlapping areas */ - char *d = (char *) dest + n; - const char *s = (const char *) src + n; - while (n--) - *--d = *--s; - } - return dest; -} - - -void * os_memset(void *s, int c, size_t n) -{ - char *p = s; - while (n--) - *p++ = c; - return s; -} - - -int os_memcmp(const void *s1, const void *s2, size_t n) -{ - const unsigned char *p1 = s1, *p2 = s2; - - if (n == 0) - return 0; - - while (*p1 == *p2) { - p1++; - p2++; - n--; - if (n == 0) - return 0; - } - - return *p1 - *p2; -} - - -char * os_strdup(const char *s) -{ - char *res; - size_t len; - if (s == NULL) - return NULL; - len = os_strlen(s); - res = os_malloc(len + 1); - if (res) - os_memcpy(res, s, len + 1); - return res; -} - - -size_t os_strlen(const char *s) -{ - const char *p = s; - while (*p) - p++; - return p - s; -} - - -int os_strcasecmp(const char *s1, const char *s2) -{ - /* - * Ignoring case is not required for main functionality, so just use - * the case sensitive version of the function. - */ - return os_strcmp(s1, s2); -} - - -int os_strncasecmp(const char *s1, const char *s2, size_t n) -{ - /* - * Ignoring case is not required for main functionality, so just use - * the case sensitive version of the function. - */ - return os_strncmp(s1, s2, n); -} - - -char * os_strchr(const char *s, int c) -{ - while (*s) { - if (*s == c) - return (char *) s; - s++; - } - return NULL; -} - - -char * os_strrchr(const char *s, int c) -{ - const char *p = s; - while (*p) - p++; - p--; - while (p >= s) { - if (*p == c) - return (char *) p; - p--; - } - return NULL; -} - - -int os_strcmp(const char *s1, const char *s2) -{ - while (*s1 == *s2) { - if (*s1 == '\0') - break; - s1++; - s2++; - } - - return *s1 - *s2; -} - - -int os_strncmp(const char *s1, const char *s2, size_t n) -{ - if (n == 0) - return 0; - - while (*s1 == *s2) { - if (*s1 == '\0') - break; - s1++; - s2++; - n--; - if (n == 0) - return 0; - } - - return *s1 - *s2; -} - - -char * os_strncpy(char *dest, const char *src, size_t n) -{ - char *d = dest; - - while (n--) { - *d = *src; - if (*src == '\0') - break; - d++; - src++; - } - - return dest; -} - - -size_t os_strlcpy(char *dest, const char *src, size_t siz) -{ - const char *s = src; - size_t left = siz; - - if (left) { - /* Copy string up to the maximum size of the dest buffer */ - while (--left != 0) { - if ((*dest++ = *s++) == '\0') - break; - } - } - - if (left == 0) { - /* Not enough room for the string; force NUL-termination */ - if (siz != 0) - *dest = '\0'; - while (*s++) - ; /* determine total src string length */ - } - - return s - src - 1; -} - - -char * os_strstr(const char *haystack, const char *needle) -{ - size_t len = os_strlen(needle); - while (*haystack) { - if (os_strncmp(haystack, needle, len) == 0) - return (char *) haystack; - haystack++; - } - - return NULL; -} - - -int os_snprintf(char *str, size_t size, const char *format, ...) -{ - va_list ap; - int ret; - - /* See http://www.ijs.si/software/snprintf/ for portable - * implementation of snprintf. - */ - - va_start(ap, format); - ret = vsnprintf(str, size, format, ap); - va_end(ap); - if (size > 0) - str[size - 1] = '\0'; - return ret; -} diff --git a/hostapd-0.8/src/utils/os_none.c b/hostapd-0.8/src/utils/os_none.c deleted file mode 100644 index bab8f17..0000000 --- a/hostapd-0.8/src/utils/os_none.c +++ /dev/null @@ -1,226 +0,0 @@ -/* - * wpa_supplicant/hostapd / Empty OS specific functions - * Copyright (c) 2005-2006, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - * - * This file can be used as a starting point when adding a new OS target. The - * functions here do not really work as-is since they are just empty or only - * return an error value. os_internal.c can be used as another starting point - * or reference since it has example implementation of many of these functions. - */ - -#include "includes.h" - -#include "os.h" - -void os_sleep(os_time_t sec, os_time_t usec) -{ -} - - -int os_get_time(struct os_time *t) -{ - return -1; -} - - -int os_mktime(int year, int month, int day, int hour, int min, int sec, - os_time_t *t) -{ - return -1; -} - - -int os_daemonize(const char *pid_file) -{ - return -1; -} - - -void os_daemonize_terminate(const char *pid_file) -{ -} - - -int os_get_random(unsigned char *buf, size_t len) -{ - return -1; -} - - -unsigned long os_random(void) -{ - return 0; -} - - -char * os_rel2abs_path(const char *rel_path) -{ - return NULL; /* strdup(rel_path) can be used here */ -} - - -int os_program_init(void) -{ - return 0; -} - - -void os_program_deinit(void) -{ -} - - -int os_setenv(const char *name, const char *value, int overwrite) -{ - return -1; -} - - -int os_unsetenv(const char *name) -{ - return -1; -} - - -char * os_readfile(const char *name, size_t *len) -{ - return NULL; -} - - -void * os_zalloc(size_t size) -{ - return NULL; -} - - -#ifdef OS_NO_C_LIB_DEFINES -void * os_malloc(size_t size) -{ - return NULL; -} - - -void * os_realloc(void *ptr, size_t size) -{ - return NULL; -} - - -void os_free(void *ptr) -{ -} - - -void * os_memcpy(void *dest, const void *src, size_t n) -{ - return dest; -} - - -void * os_memmove(void *dest, const void *src, size_t n) -{ - return dest; -} - - -void * os_memset(void *s, int c, size_t n) -{ - return s; -} - - -int os_memcmp(const void *s1, const void *s2, size_t n) -{ - return 0; -} - - -char * os_strdup(const char *s) -{ - return NULL; -} - - -size_t os_strlen(const char *s) -{ - return 0; -} - - -int os_strcasecmp(const char *s1, const char *s2) -{ - /* - * Ignoring case is not required for main functionality, so just use - * the case sensitive version of the function. - */ - return os_strcmp(s1, s2); -} - - -int os_strncasecmp(const char *s1, const char *s2, size_t n) -{ - /* - * Ignoring case is not required for main functionality, so just use - * the case sensitive version of the function. - */ - return os_strncmp(s1, s2, n); -} - - -char * os_strchr(const char *s, int c) -{ - return NULL; -} - - -char * os_strrchr(const char *s, int c) -{ - return NULL; -} - - -int os_strcmp(const char *s1, const char *s2) -{ - return 0; -} - - -int os_strncmp(const char *s1, const char *s2, size_t n) -{ - return 0; -} - - -char * os_strncpy(char *dest, const char *src, size_t n) -{ - return dest; -} - - -size_t os_strlcpy(char *dest, const char *src, size_t size) -{ - return 0; -} - - -char * os_strstr(const char *haystack, const char *needle) -{ - return NULL; -} - - -int os_snprintf(char *str, size_t size, const char *format, ...) -{ - return 0; -} -#endif /* OS_NO_C_LIB_DEFINES */ diff --git a/hostapd-0.8/src/utils/os_unix.c b/hostapd-0.8/src/utils/os_unix.c deleted file mode 100644 index 4e11758..0000000 --- a/hostapd-0.8/src/utils/os_unix.c +++ /dev/null @@ -1,474 +0,0 @@ -/* - * OS specific functions for UNIX/POSIX systems - * Copyright (c) 2005-2009, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#include "includes.h" - -#ifdef ANDROID -#include -#include -#include -#endif /* ANDROID */ - -#include "os.h" - -#ifdef WPA_TRACE - -#include "common.h" -#include "list.h" -#include "wpa_debug.h" -#include "trace.h" - -static struct dl_list alloc_list; - -#define ALLOC_MAGIC 0xa84ef1b2 -#define FREED_MAGIC 0x67fd487a - -struct os_alloc_trace { - unsigned int magic; - struct dl_list list; - size_t len; - WPA_TRACE_INFO -}; - -#endif /* WPA_TRACE */ - - -void os_sleep(os_time_t sec, os_time_t usec) -{ - if (sec) - sleep(sec); - if (usec) - usleep(usec); -} - - -int os_get_time(struct os_time *t) -{ - int res; - struct timeval tv; - res = gettimeofday(&tv, NULL); - t->sec = tv.tv_sec; - t->usec = tv.tv_usec; - return res; -} - - -int os_mktime(int year, int month, int day, int hour, int min, int sec, - os_time_t *t) -{ - struct tm tm, *tm1; - time_t t_local, t1, t2; - os_time_t tz_offset; - - if (year < 1970 || month < 1 || month > 12 || day < 1 || day > 31 || - hour < 0 || hour > 23 || min < 0 || min > 59 || sec < 0 || - sec > 60) - return -1; - - memset(&tm, 0, sizeof(tm)); - tm.tm_year = year - 1900; - tm.tm_mon = month - 1; - tm.tm_mday = day; - tm.tm_hour = hour; - tm.tm_min = min; - tm.tm_sec = sec; - - t_local = mktime(&tm); - - /* figure out offset to UTC */ - tm1 = localtime(&t_local); - if (tm1) { - t1 = mktime(tm1); - tm1 = gmtime(&t_local); - if (tm1) { - t2 = mktime(tm1); - tz_offset = t2 - t1; - } else - tz_offset = 0; - } else - tz_offset = 0; - - *t = (os_time_t) t_local - tz_offset; - return 0; -} - - -#ifdef __APPLE__ -#include -static int os_daemon(int nochdir, int noclose) -{ - int devnull; - - if (chdir("/") < 0) - return -1; - - devnull = open("/dev/null", O_RDWR); - if (devnull < 0) - return -1; - - if (dup2(devnull, STDIN_FILENO) < 0) { - close(devnull); - return -1; - } - - if (dup2(devnull, STDOUT_FILENO) < 0) { - close(devnull); - return -1; - } - - if (dup2(devnull, STDERR_FILENO) < 0) { - close(devnull); - return -1; - } - - return 0; -} -#else /* __APPLE__ */ -#define os_daemon daemon -#endif /* __APPLE__ */ - - -int os_daemonize(const char *pid_file) -{ -#if defined(__uClinux__) || defined(__sun__) - return -1; -#else /* defined(__uClinux__) || defined(__sun__) */ - if (os_daemon(0, 0)) { - perror("daemon"); - return -1; - } - - if (pid_file) { - FILE *f = fopen(pid_file, "w"); - if (f) { - fprintf(f, "%u\n", getpid()); - fclose(f); - } - } - - return -0; -#endif /* defined(__uClinux__) || defined(__sun__) */ -} - - -void os_daemonize_terminate(const char *pid_file) -{ - if (pid_file) - unlink(pid_file); -} - - -int os_get_random(unsigned char *buf, size_t len) -{ - FILE *f; - size_t rc; - - f = fopen("/dev/urandom", "rb"); - if (f == NULL) { - printf("Could not open /dev/urandom.\n"); - return -1; - } - - rc = fread(buf, 1, len, f); - fclose(f); - - return rc != len ? -1 : 0; -} - - -unsigned long os_random(void) -{ - return random(); -} - - -char * os_rel2abs_path(const char *rel_path) -{ - char *buf = NULL, *cwd, *ret; - size_t len = 128, cwd_len, rel_len, ret_len; - int last_errno; - - if (rel_path[0] == '/') - return os_strdup(rel_path); - - for (;;) { - buf = os_malloc(len); - if (buf == NULL) - return NULL; - cwd = getcwd(buf, len); - if (cwd == NULL) { - last_errno = errno; - os_free(buf); - if (last_errno != ERANGE) - return NULL; - len *= 2; - if (len > 2000) - return NULL; - } else { - buf[len - 1] = '\0'; - break; - } - } - - cwd_len = os_strlen(cwd); - rel_len = os_strlen(rel_path); - ret_len = cwd_len + 1 + rel_len + 1; - ret = os_malloc(ret_len); - if (ret) { - os_memcpy(ret, cwd, cwd_len); - ret[cwd_len] = '/'; - os_memcpy(ret + cwd_len + 1, rel_path, rel_len); - ret[ret_len - 1] = '\0'; - } - os_free(buf); - return ret; -} - - -int os_program_init(void) -{ -#ifdef ANDROID - /* - * We ignore errors here since errors are normal if we - * are already running as non-root. - */ - gid_t groups[] = { AID_INET, AID_WIFI, AID_KEYSTORE }; - struct __user_cap_header_struct header; - struct __user_cap_data_struct cap; - - setgroups(sizeof(groups)/sizeof(groups[0]), groups); - - prctl(PR_SET_KEEPCAPS, 1, 0, 0, 0); - - setgid(AID_WIFI); - setuid(AID_WIFI); - - header.version = _LINUX_CAPABILITY_VERSION; - header.pid = 0; - cap.effective = cap.permitted = - (1 << CAP_NET_ADMIN) | (1 << CAP_NET_RAW); - cap.inheritable = 0; - capset(&header, &cap); -#endif /* ANDROID */ - -#ifdef WPA_TRACE - dl_list_init(&alloc_list); -#endif /* WPA_TRACE */ - return 0; -} - - -void os_program_deinit(void) -{ -#ifdef WPA_TRACE - struct os_alloc_trace *a; - unsigned long total = 0; - dl_list_for_each(a, &alloc_list, struct os_alloc_trace, list) { - total += a->len; - if (a->magic != ALLOC_MAGIC) { - wpa_printf(MSG_INFO, "MEMLEAK[%p]: invalid magic 0x%x " - "len %lu", - a, a->magic, (unsigned long) a->len); - continue; - } - wpa_printf(MSG_INFO, "MEMLEAK[%p]: len %lu", - a, (unsigned long) a->len); - wpa_trace_dump("memleak", a); - } - if (total) - wpa_printf(MSG_INFO, "MEMLEAK: total %lu bytes", - (unsigned long) total); -#endif /* WPA_TRACE */ -} - - -int os_setenv(const char *name, const char *value, int overwrite) -{ - return setenv(name, value, overwrite); -} - - -int os_unsetenv(const char *name) -{ -#if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__APPLE__) || \ - defined(__OpenBSD__) - unsetenv(name); - return 0; -#else - return unsetenv(name); -#endif -} - - -char * os_readfile(const char *name, size_t *len) -{ - FILE *f; - char *buf; - long pos; - - f = fopen(name, "rb"); - if (f == NULL) - return NULL; - - if (fseek(f, 0, SEEK_END) < 0 || (pos = ftell(f)) < 0) { - fclose(f); - return NULL; - } - *len = pos; - if (fseek(f, 0, SEEK_SET) < 0) { - fclose(f); - return NULL; - } - - buf = os_malloc(*len); - if (buf == NULL) { - fclose(f); - return NULL; - } - - if (fread(buf, 1, *len, f) != *len) { - fclose(f); - os_free(buf); - return NULL; - } - - fclose(f); - - return buf; -} - - -#ifndef WPA_TRACE -void * os_zalloc(size_t size) -{ - return calloc(1, size); -} -#endif /* WPA_TRACE */ - - -size_t os_strlcpy(char *dest, const char *src, size_t siz) -{ - const char *s = src; - size_t left = siz; - - if (left) { - /* Copy string up to the maximum size of the dest buffer */ - while (--left != 0) { - if ((*dest++ = *s++) == '\0') - break; - } - } - - if (left == 0) { - /* Not enough room for the string; force NUL-termination */ - if (siz != 0) - *dest = '\0'; - while (*s++) - ; /* determine total src string length */ - } - - return s - src - 1; -} - - -#ifdef WPA_TRACE - -void * os_malloc(size_t size) -{ - struct os_alloc_trace *a; - a = malloc(sizeof(*a) + size); - if (a == NULL) - return NULL; - a->magic = ALLOC_MAGIC; - dl_list_add(&alloc_list, &a->list); - a->len = size; - wpa_trace_record(a); - return a + 1; -} - - -void * os_realloc(void *ptr, size_t size) -{ - struct os_alloc_trace *a; - size_t copy_len; - void *n; - - if (ptr == NULL) - return os_malloc(size); - - a = (struct os_alloc_trace *) ptr - 1; - if (a->magic != ALLOC_MAGIC) { - wpa_printf(MSG_INFO, "REALLOC[%p]: invalid magic 0x%x%s", - a, a->magic, - a->magic == FREED_MAGIC ? " (already freed)" : ""); - wpa_trace_show("Invalid os_realloc() call"); - abort(); - } - n = os_malloc(size); - if (n == NULL) - return NULL; - copy_len = a->len; - if (copy_len > size) - copy_len = size; - os_memcpy(n, a + 1, copy_len); - os_free(ptr); - return n; -} - - -void os_free(void *ptr) -{ - struct os_alloc_trace *a; - - if (ptr == NULL) - return; - a = (struct os_alloc_trace *) ptr - 1; - if (a->magic != ALLOC_MAGIC) { - wpa_printf(MSG_INFO, "FREE[%p]: invalid magic 0x%x%s", - a, a->magic, - a->magic == FREED_MAGIC ? " (already freed)" : ""); - wpa_trace_show("Invalid os_free() call"); - abort(); - } - dl_list_del(&a->list); - a->magic = FREED_MAGIC; - - wpa_trace_check_ref(ptr); - free(a); -} - - -void * os_zalloc(size_t size) -{ - void *ptr = os_malloc(size); - if (ptr) - os_memset(ptr, 0, size); - return ptr; -} - - -char * os_strdup(const char *s) -{ - size_t len; - char *d; - len = os_strlen(s); - d = os_malloc(len + 1); - if (d == NULL) - return NULL; - os_memcpy(d, s, len); - d[len] = '\0'; - return d; -} - -#endif /* WPA_TRACE */ diff --git a/hostapd-0.8/src/utils/os_win32.c b/hostapd-0.8/src/utils/os_win32.c deleted file mode 100644 index 0740964..0000000 --- a/hostapd-0.8/src/utils/os_win32.c +++ /dev/null @@ -1,222 +0,0 @@ -/* - * wpa_supplicant/hostapd / OS specific functions for Win32 systems - * Copyright (c) 2005-2006, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#include "includes.h" -#include -#include - -#include "os.h" - -void os_sleep(os_time_t sec, os_time_t usec) -{ - if (sec) - Sleep(sec * 1000); - if (usec) - Sleep(usec / 1000); -} - - -int os_get_time(struct os_time *t) -{ -#define EPOCHFILETIME (116444736000000000ULL) - FILETIME ft; - LARGE_INTEGER li; - ULONGLONG tt; - -#ifdef _WIN32_WCE - SYSTEMTIME st; - - GetSystemTime(&st); - SystemTimeToFileTime(&st, &ft); -#else /* _WIN32_WCE */ - GetSystemTimeAsFileTime(&ft); -#endif /* _WIN32_WCE */ - li.LowPart = ft.dwLowDateTime; - li.HighPart = ft.dwHighDateTime; - tt = (li.QuadPart - EPOCHFILETIME) / 10; - t->sec = (os_time_t) (tt / 1000000); - t->usec = (os_time_t) (tt % 1000000); - - return 0; -} - - -int os_mktime(int year, int month, int day, int hour, int min, int sec, - os_time_t *t) -{ - struct tm tm, *tm1; - time_t t_local, t1, t2; - os_time_t tz_offset; - - if (year < 1970 || month < 1 || month > 12 || day < 1 || day > 31 || - hour < 0 || hour > 23 || min < 0 || min > 59 || sec < 0 || - sec > 60) - return -1; - - memset(&tm, 0, sizeof(tm)); - tm.tm_year = year - 1900; - tm.tm_mon = month - 1; - tm.tm_mday = day; - tm.tm_hour = hour; - tm.tm_min = min; - tm.tm_sec = sec; - - t_local = mktime(&tm); - - /* figure out offset to UTC */ - tm1 = localtime(&t_local); - if (tm1) { - t1 = mktime(tm1); - tm1 = gmtime(&t_local); - if (tm1) { - t2 = mktime(tm1); - tz_offset = t2 - t1; - } else - tz_offset = 0; - } else - tz_offset = 0; - - *t = (os_time_t) t_local - tz_offset; - return 0; -} - - -int os_daemonize(const char *pid_file) -{ - /* TODO */ - return -1; -} - - -void os_daemonize_terminate(const char *pid_file) -{ -} - - -int os_get_random(unsigned char *buf, size_t len) -{ - HCRYPTPROV prov; - BOOL ret; - - if (!CryptAcquireContext(&prov, NULL, NULL, PROV_RSA_FULL, - CRYPT_VERIFYCONTEXT)) - return -1; - - ret = CryptGenRandom(prov, len, buf); - CryptReleaseContext(prov, 0); - - return ret ? 0 : -1; -} - - -unsigned long os_random(void) -{ - return rand(); -} - - -char * os_rel2abs_path(const char *rel_path) -{ - return _strdup(rel_path); -} - - -int os_program_init(void) -{ -#ifdef CONFIG_NATIVE_WINDOWS - WSADATA wsaData; - if (WSAStartup(MAKEWORD(2, 0), &wsaData)) { - printf("Could not find a usable WinSock.dll\n"); - return -1; - } -#endif /* CONFIG_NATIVE_WINDOWS */ - return 0; -} - - -void os_program_deinit(void) -{ -#ifdef CONFIG_NATIVE_WINDOWS - WSACleanup(); -#endif /* CONFIG_NATIVE_WINDOWS */ -} - - -int os_setenv(const char *name, const char *value, int overwrite) -{ - return -1; -} - - -int os_unsetenv(const char *name) -{ - return -1; -} - - -char * os_readfile(const char *name, size_t *len) -{ - FILE *f; - char *buf; - - f = fopen(name, "rb"); - if (f == NULL) - return NULL; - - fseek(f, 0, SEEK_END); - *len = ftell(f); - fseek(f, 0, SEEK_SET); - - buf = malloc(*len); - if (buf == NULL) { - fclose(f); - return NULL; - } - - fread(buf, 1, *len, f); - fclose(f); - - return buf; -} - - -void * os_zalloc(size_t size) -{ - return calloc(1, size); -} - - -size_t os_strlcpy(char *dest, const char *src, size_t siz) -{ - const char *s = src; - size_t left = siz; - - if (left) { - /* Copy string up to the maximum size of the dest buffer */ - while (--left != 0) { - if ((*dest++ = *s++) == '\0') - break; - } - } - - if (left == 0) { - /* Not enough room for the string; force NUL-termination */ - if (siz != 0) - *dest = '\0'; - while (*s++) - ; /* determine total src string length */ - } - - return s - src - 1; -} diff --git a/hostapd-0.8/src/utils/pcsc_funcs.c b/hostapd-0.8/src/utils/pcsc_funcs.c deleted file mode 100644 index bf9f04a..0000000 --- a/hostapd-0.8/src/utils/pcsc_funcs.c +++ /dev/null @@ -1,1238 +0,0 @@ -/* - * WPA Supplicant / PC/SC smartcard interface for USIM, GSM SIM - * Copyright (c) 2004-2007, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - * - * This file implements wrapper functions for accessing GSM SIM and 3GPP USIM - * cards through PC/SC smartcard library. These functions are used to implement - * authentication routines for EAP-SIM and EAP-AKA. - */ - -#include "includes.h" -#include - -#include "common.h" -#include "pcsc_funcs.h" - - -/* See ETSI GSM 11.11 and ETSI TS 102 221 for details. - * SIM commands: - * Command APDU: CLA INS P1 P2 P3 Data - * CLA (class of instruction): A0 for GSM, 00 for USIM - * INS (instruction) - * P1 P2 P3 (parameters, P3 = length of Data) - * Response APDU: Data SW1 SW2 - * SW1 SW2 (Status words) - * Commands (INS P1 P2 P3): - * SELECT: A4 00 00 02 - * GET RESPONSE: C0 00 00 - * RUN GSM ALG: 88 00 00 00 - * RUN UMTS ALG: 88 00 81 data: 0x10 | RAND | 0x10 | AUTN - * P1 = ID of alg in card - * P2 = ID of secret key - * READ BINARY: B0 - * READ RECORD: B2 - * P2 (mode) = '02' (next record), '03' (previous record), - * '04' (absolute mode) - * VERIFY CHV: 20 00 08 - * CHANGE CHV: 24 00 10 - * DISABLE CHV: 26 00 01 08 - * ENABLE CHV: 28 00 01 08 - * UNBLOCK CHV: 2C 00 <00=CHV1, 02=CHV2> 10 - * SLEEP: FA 00 00 00 - */ - -/* GSM SIM commands */ -#define SIM_CMD_SELECT 0xa0, 0xa4, 0x00, 0x00, 0x02 -#define SIM_CMD_RUN_GSM_ALG 0xa0, 0x88, 0x00, 0x00, 0x10 -#define SIM_CMD_GET_RESPONSE 0xa0, 0xc0, 0x00, 0x00 -#define SIM_CMD_READ_BIN 0xa0, 0xb0, 0x00, 0x00 -#define SIM_CMD_READ_RECORD 0xa0, 0xb2, 0x00, 0x00 -#define SIM_CMD_VERIFY_CHV1 0xa0, 0x20, 0x00, 0x01, 0x08 - -/* USIM commands */ -#define USIM_CLA 0x00 -#define USIM_CMD_RUN_UMTS_ALG 0x00, 0x88, 0x00, 0x81, 0x22 -#define USIM_CMD_GET_RESPONSE 0x00, 0xc0, 0x00, 0x00 - -#define SIM_RECORD_MODE_ABSOLUTE 0x04 - -#define USIM_FSP_TEMPL_TAG 0x62 - -#define USIM_TLV_FILE_DESC 0x82 -#define USIM_TLV_FILE_ID 0x83 -#define USIM_TLV_DF_NAME 0x84 -#define USIM_TLV_PROPR_INFO 0xA5 -#define USIM_TLV_LIFE_CYCLE_STATUS 0x8A -#define USIM_TLV_FILE_SIZE 0x80 -#define USIM_TLV_TOTAL_FILE_SIZE 0x81 -#define USIM_TLV_PIN_STATUS_TEMPLATE 0xC6 -#define USIM_TLV_SHORT_FILE_ID 0x88 - -#define USIM_PS_DO_TAG 0x90 - -#define AKA_RAND_LEN 16 -#define AKA_AUTN_LEN 16 -#define AKA_AUTS_LEN 14 -#define RES_MAX_LEN 16 -#define IK_LEN 16 -#define CK_LEN 16 - - -typedef enum { SCARD_GSM_SIM, SCARD_USIM } sim_types; - -struct scard_data { - SCARDCONTEXT ctx; - SCARDHANDLE card; - DWORD protocol; - sim_types sim_type; - int pin1_required; -}; - -#ifdef __MINGW32_VERSION -/* MinGW does not yet support WinScard, so load the needed functions - * dynamically from winscard.dll for now. */ - -static HINSTANCE dll = NULL; /* winscard.dll */ - -static const SCARD_IO_REQUEST *dll_g_rgSCardT0Pci, *dll_g_rgSCardT1Pci; -#undef SCARD_PCI_T0 -#define SCARD_PCI_T0 (dll_g_rgSCardT0Pci) -#undef SCARD_PCI_T1 -#define SCARD_PCI_T1 (dll_g_rgSCardT1Pci) - - -static WINSCARDAPI LONG WINAPI -(*dll_SCardEstablishContext)(IN DWORD dwScope, - IN LPCVOID pvReserved1, - IN LPCVOID pvReserved2, - OUT LPSCARDCONTEXT phContext); -#define SCardEstablishContext dll_SCardEstablishContext - -static long (*dll_SCardReleaseContext)(long hContext); -#define SCardReleaseContext dll_SCardReleaseContext - -static WINSCARDAPI LONG WINAPI -(*dll_SCardListReadersA)(IN SCARDCONTEXT hContext, - IN LPCSTR mszGroups, - OUT LPSTR mszReaders, - IN OUT LPDWORD pcchReaders); -#undef SCardListReaders -#define SCardListReaders dll_SCardListReadersA - -static WINSCARDAPI LONG WINAPI -(*dll_SCardConnectA)(IN SCARDCONTEXT hContext, - IN LPCSTR szReader, - IN DWORD dwShareMode, - IN DWORD dwPreferredProtocols, - OUT LPSCARDHANDLE phCard, - OUT LPDWORD pdwActiveProtocol); -#undef SCardConnect -#define SCardConnect dll_SCardConnectA - -static WINSCARDAPI LONG WINAPI -(*dll_SCardDisconnect)(IN SCARDHANDLE hCard, - IN DWORD dwDisposition); -#define SCardDisconnect dll_SCardDisconnect - -static WINSCARDAPI LONG WINAPI -(*dll_SCardTransmit)(IN SCARDHANDLE hCard, - IN LPCSCARD_IO_REQUEST pioSendPci, - IN LPCBYTE pbSendBuffer, - IN DWORD cbSendLength, - IN OUT LPSCARD_IO_REQUEST pioRecvPci, - OUT LPBYTE pbRecvBuffer, - IN OUT LPDWORD pcbRecvLength); -#define SCardTransmit dll_SCardTransmit - -static WINSCARDAPI LONG WINAPI -(*dll_SCardBeginTransaction)(IN SCARDHANDLE hCard); -#define SCardBeginTransaction dll_SCardBeginTransaction - -static WINSCARDAPI LONG WINAPI -(*dll_SCardEndTransaction)(IN SCARDHANDLE hCard, IN DWORD dwDisposition); -#define SCardEndTransaction dll_SCardEndTransaction - - -static int mingw_load_symbols(void) -{ - char *sym; - - if (dll) - return 0; - - dll = LoadLibrary("winscard"); - if (dll == NULL) { - wpa_printf(MSG_DEBUG, "WinSCard: Could not load winscard.dll " - "library"); - return -1; - } - -#define LOADSYM(s) \ - sym = #s; \ - dll_ ## s = (void *) GetProcAddress(dll, sym); \ - if (dll_ ## s == NULL) \ - goto fail; - - LOADSYM(SCardEstablishContext); - LOADSYM(SCardReleaseContext); - LOADSYM(SCardListReadersA); - LOADSYM(SCardConnectA); - LOADSYM(SCardDisconnect); - LOADSYM(SCardTransmit); - LOADSYM(SCardBeginTransaction); - LOADSYM(SCardEndTransaction); - LOADSYM(g_rgSCardT0Pci); - LOADSYM(g_rgSCardT1Pci); - -#undef LOADSYM - - return 0; - -fail: - wpa_printf(MSG_DEBUG, "WinSCard: Could not get address for %s from " - "winscard.dll", sym); - FreeLibrary(dll); - dll = NULL; - return -1; -} - - -static void mingw_unload_symbols(void) -{ - if (dll == NULL) - return; - - FreeLibrary(dll); - dll = NULL; -} - -#else /* __MINGW32_VERSION */ - -#define mingw_load_symbols() 0 -#define mingw_unload_symbols() do { } while (0) - -#endif /* __MINGW32_VERSION */ - - -static int _scard_select_file(struct scard_data *scard, unsigned short file_id, - unsigned char *buf, size_t *buf_len, - sim_types sim_type, unsigned char *aid, - size_t aidlen); -static int scard_select_file(struct scard_data *scard, unsigned short file_id, - unsigned char *buf, size_t *buf_len); -static int scard_verify_pin(struct scard_data *scard, const char *pin); -static int scard_get_record_len(struct scard_data *scard, - unsigned char recnum, unsigned char mode); -static int scard_read_record(struct scard_data *scard, - unsigned char *data, size_t len, - unsigned char recnum, unsigned char mode); - - -static int scard_parse_fsp_templ(unsigned char *buf, size_t buf_len, - int *ps_do, int *file_len) -{ - unsigned char *pos, *end; - - if (ps_do) - *ps_do = -1; - if (file_len) - *file_len = -1; - - pos = buf; - end = pos + buf_len; - if (*pos != USIM_FSP_TEMPL_TAG) { - wpa_printf(MSG_DEBUG, "SCARD: file header did not " - "start with FSP template tag"); - return -1; - } - pos++; - if (pos >= end) - return -1; - if ((pos + pos[0]) < end) - end = pos + 1 + pos[0]; - pos++; - wpa_hexdump(MSG_DEBUG, "SCARD: file header FSP template", - pos, end - pos); - - while (pos + 1 < end) { - wpa_printf(MSG_MSGDUMP, "SCARD: file header TLV " - "0x%02x len=%d", pos[0], pos[1]); - if (pos + 2 + pos[1] > end) - break; - - if (pos[0] == USIM_TLV_FILE_SIZE && - (pos[1] == 1 || pos[1] == 2) && file_len) { - if (pos[1] == 1) - *file_len = (int) pos[2]; - else - *file_len = ((int) pos[2] << 8) | - (int) pos[3]; - wpa_printf(MSG_DEBUG, "SCARD: file_size=%d", - *file_len); - } - - if (pos[0] == USIM_TLV_PIN_STATUS_TEMPLATE && - pos[1] >= 2 && pos[2] == USIM_PS_DO_TAG && - pos[3] >= 1 && ps_do) { - wpa_printf(MSG_DEBUG, "SCARD: PS_DO=0x%02x", - pos[4]); - *ps_do = (int) pos[4]; - } - - pos += 2 + pos[1]; - - if (pos == end) - return 0; - } - return -1; -} - - -static int scard_pin_needed(struct scard_data *scard, - unsigned char *hdr, size_t hlen) -{ - if (scard->sim_type == SCARD_GSM_SIM) { - if (hlen > SCARD_CHV1_OFFSET && - !(hdr[SCARD_CHV1_OFFSET] & SCARD_CHV1_FLAG)) - return 1; - return 0; - } - - if (scard->sim_type == SCARD_USIM) { - int ps_do; - if (scard_parse_fsp_templ(hdr, hlen, &ps_do, NULL)) - return -1; - /* TODO: there could be more than one PS_DO entry because of - * multiple PINs in key reference.. */ - if (ps_do > 0 && (ps_do & 0x80)) - return 1; - return 0; - } - - return -1; -} - - -static int scard_get_aid(struct scard_data *scard, unsigned char *aid, - size_t maxlen) -{ - int rlen, rec; - struct efdir { - unsigned char appl_template_tag; /* 0x61 */ - unsigned char appl_template_len; - unsigned char appl_id_tag; /* 0x4f */ - unsigned char aid_len; - unsigned char rid[5]; - unsigned char appl_code[2]; /* 0x1002 for 3G USIM */ - } *efdir; - unsigned char buf[100]; - size_t blen; - - efdir = (struct efdir *) buf; - blen = sizeof(buf); - if (scard_select_file(scard, SCARD_FILE_EF_DIR, buf, &blen)) { - wpa_printf(MSG_DEBUG, "SCARD: Failed to read EF_DIR"); - return -1; - } - wpa_hexdump(MSG_DEBUG, "SCARD: EF_DIR select", buf, blen); - - for (rec = 1; rec < 10; rec++) { - rlen = scard_get_record_len(scard, rec, - SIM_RECORD_MODE_ABSOLUTE); - if (rlen < 0) { - wpa_printf(MSG_DEBUG, "SCARD: Failed to get EF_DIR " - "record length"); - return -1; - } - blen = sizeof(buf); - if (rlen > (int) blen) { - wpa_printf(MSG_DEBUG, "SCARD: Too long EF_DIR record"); - return -1; - } - if (scard_read_record(scard, buf, rlen, rec, - SIM_RECORD_MODE_ABSOLUTE) < 0) { - wpa_printf(MSG_DEBUG, "SCARD: Failed to read " - "EF_DIR record %d", rec); - return -1; - } - wpa_hexdump(MSG_DEBUG, "SCARD: EF_DIR record", buf, rlen); - - if (efdir->appl_template_tag != 0x61) { - wpa_printf(MSG_DEBUG, "SCARD: Unexpected application " - "template tag 0x%x", - efdir->appl_template_tag); - continue; - } - - if (efdir->appl_template_len > rlen - 2) { - wpa_printf(MSG_DEBUG, "SCARD: Too long application " - "template (len=%d rlen=%d)", - efdir->appl_template_len, rlen); - continue; - } - - if (efdir->appl_id_tag != 0x4f) { - wpa_printf(MSG_DEBUG, "SCARD: Unexpected application " - "identifier tag 0x%x", efdir->appl_id_tag); - continue; - } - - if (efdir->aid_len < 1 || efdir->aid_len > 16) { - wpa_printf(MSG_DEBUG, "SCARD: Invalid AID length %d", - efdir->aid_len); - continue; - } - - wpa_hexdump(MSG_DEBUG, "SCARD: AID from EF_DIR record", - efdir->rid, efdir->aid_len); - - if (efdir->appl_code[0] == 0x10 && - efdir->appl_code[1] == 0x02) { - wpa_printf(MSG_DEBUG, "SCARD: 3G USIM app found from " - "EF_DIR record %d", rec); - break; - } - } - - if (rec >= 10) { - wpa_printf(MSG_DEBUG, "SCARD: 3G USIM app not found " - "from EF_DIR records"); - return -1; - } - - if (efdir->aid_len > maxlen) { - wpa_printf(MSG_DEBUG, "SCARD: Too long AID"); - return -1; - } - - os_memcpy(aid, efdir->rid, efdir->aid_len); - - return efdir->aid_len; -} - - -/** - * scard_init - Initialize SIM/USIM connection using PC/SC - * @sim_type: Allowed SIM types (SIM, USIM, or both) - * Returns: Pointer to private data structure, or %NULL on failure - * - * This function is used to initialize SIM/USIM connection. PC/SC is used to - * open connection to the SIM/USIM card and the card is verified to support the - * selected sim_type. In addition, local flag is set if a PIN is needed to - * access some of the card functions. Once the connection is not needed - * anymore, scard_deinit() can be used to close it. - */ -struct scard_data * scard_init(scard_sim_type sim_type) -{ - long ret; - unsigned long len; - struct scard_data *scard; -#ifdef CONFIG_NATIVE_WINDOWS - TCHAR *readers = NULL; -#else /* CONFIG_NATIVE_WINDOWS */ - char *readers = NULL; -#endif /* CONFIG_NATIVE_WINDOWS */ - unsigned char buf[100]; - size_t blen; - int transaction = 0; - int pin_needed; - - wpa_printf(MSG_DEBUG, "SCARD: initializing smart card interface"); - if (mingw_load_symbols()) - return NULL; - scard = os_zalloc(sizeof(*scard)); - if (scard == NULL) - return NULL; - - ret = SCardEstablishContext(SCARD_SCOPE_SYSTEM, NULL, NULL, - &scard->ctx); - if (ret != SCARD_S_SUCCESS) { - wpa_printf(MSG_DEBUG, "SCARD: Could not establish smart card " - "context (err=%ld)", ret); - goto failed; - } - - ret = SCardListReaders(scard->ctx, NULL, NULL, &len); - if (ret != SCARD_S_SUCCESS) { - wpa_printf(MSG_DEBUG, "SCARD: SCardListReaders failed " - "(err=%ld)", ret); - goto failed; - } - -#ifdef UNICODE - len *= 2; -#endif /* UNICODE */ - readers = os_malloc(len); - if (readers == NULL) { - wpa_printf(MSG_INFO, "SCARD: malloc failed\n"); - goto failed; - } - - ret = SCardListReaders(scard->ctx, NULL, readers, &len); - if (ret != SCARD_S_SUCCESS) { - wpa_printf(MSG_DEBUG, "SCARD: SCardListReaders failed(2) " - "(err=%ld)", ret); - goto failed; - } - if (len < 3) { - wpa_printf(MSG_WARNING, "SCARD: No smart card readers " - "available."); - goto failed; - } - /* readers is a list of available reader. Last entry is terminated with - * double NUL. - * TODO: add support for selecting the reader; now just use the first - * one.. */ -#ifdef UNICODE - wpa_printf(MSG_DEBUG, "SCARD: Selected reader='%S'", readers); -#else /* UNICODE */ - wpa_printf(MSG_DEBUG, "SCARD: Selected reader='%s'", readers); -#endif /* UNICODE */ - - ret = SCardConnect(scard->ctx, readers, SCARD_SHARE_SHARED, - SCARD_PROTOCOL_T0, &scard->card, &scard->protocol); - if (ret != SCARD_S_SUCCESS) { - if (ret == (long) SCARD_E_NO_SMARTCARD) - wpa_printf(MSG_INFO, "No smart card inserted."); - else - wpa_printf(MSG_WARNING, "SCardConnect err=%lx", ret); - goto failed; - } - - os_free(readers); - readers = NULL; - - wpa_printf(MSG_DEBUG, "SCARD: card=0x%x active_protocol=%lu (%s)", - (unsigned int) scard->card, scard->protocol, - scard->protocol == SCARD_PROTOCOL_T0 ? "T0" : "T1"); - - ret = SCardBeginTransaction(scard->card); - if (ret != SCARD_S_SUCCESS) { - wpa_printf(MSG_DEBUG, "SCARD: Could not begin transaction: " - "0x%x", (unsigned int) ret); - goto failed; - } - transaction = 1; - - blen = sizeof(buf); - - scard->sim_type = SCARD_GSM_SIM; - if (sim_type == SCARD_USIM_ONLY || sim_type == SCARD_TRY_BOTH) { - wpa_printf(MSG_DEBUG, "SCARD: verifying USIM support"); - if (_scard_select_file(scard, SCARD_FILE_MF, buf, &blen, - SCARD_USIM, NULL, 0)) { - wpa_printf(MSG_DEBUG, "SCARD: USIM is not supported"); - if (sim_type == SCARD_USIM_ONLY) - goto failed; - wpa_printf(MSG_DEBUG, "SCARD: Trying to use GSM SIM"); - scard->sim_type = SCARD_GSM_SIM; - } else { - wpa_printf(MSG_DEBUG, "SCARD: USIM is supported"); - scard->sim_type = SCARD_USIM; - } - } - - if (scard->sim_type == SCARD_GSM_SIM) { - blen = sizeof(buf); - if (scard_select_file(scard, SCARD_FILE_MF, buf, &blen)) { - wpa_printf(MSG_DEBUG, "SCARD: Failed to read MF"); - goto failed; - } - - blen = sizeof(buf); - if (scard_select_file(scard, SCARD_FILE_GSM_DF, buf, &blen)) { - wpa_printf(MSG_DEBUG, "SCARD: Failed to read GSM DF"); - goto failed; - } - } else { - unsigned char aid[32]; - int aid_len; - - aid_len = scard_get_aid(scard, aid, sizeof(aid)); - if (aid_len < 0) { - wpa_printf(MSG_DEBUG, "SCARD: Failed to find AID for " - "3G USIM app - try to use standard 3G RID"); - os_memcpy(aid, "\xa0\x00\x00\x00\x87", 5); - aid_len = 5; - } - wpa_hexdump(MSG_DEBUG, "SCARD: 3G USIM AID", aid, aid_len); - - /* Select based on AID = 3G RID from EF_DIR. This is usually - * starting with A0 00 00 00 87. */ - blen = sizeof(buf); - if (_scard_select_file(scard, 0, buf, &blen, scard->sim_type, - aid, aid_len)) { - wpa_printf(MSG_INFO, "SCARD: Failed to read 3G USIM " - "app"); - wpa_hexdump(MSG_INFO, "SCARD: 3G USIM AID", - aid, aid_len); - goto failed; - } - } - - /* Verify whether CHV1 (PIN1) is needed to access the card. */ - pin_needed = scard_pin_needed(scard, buf, blen); - if (pin_needed < 0) { - wpa_printf(MSG_DEBUG, "SCARD: Failed to determine whether PIN " - "is needed"); - goto failed; - } - if (pin_needed) { - scard->pin1_required = 1; - wpa_printf(MSG_DEBUG, "PIN1 needed for SIM access"); - } - - ret = SCardEndTransaction(scard->card, SCARD_LEAVE_CARD); - if (ret != SCARD_S_SUCCESS) { - wpa_printf(MSG_DEBUG, "SCARD: Could not end transaction: " - "0x%x", (unsigned int) ret); - } - - return scard; - -failed: - if (transaction) - SCardEndTransaction(scard->card, SCARD_LEAVE_CARD); - os_free(readers); - scard_deinit(scard); - return NULL; -} - - -/** - * scard_set_pin - Set PIN (CHV1/PIN1) code for accessing SIM/USIM commands - * @scard: Pointer to private data from scard_init() - * @pin: PIN code as an ASCII string (e.g., "1234") - * Returns: 0 on success, -1 on failure - */ -int scard_set_pin(struct scard_data *scard, const char *pin) -{ - if (scard == NULL) - return -1; - - /* Verify whether CHV1 (PIN1) is needed to access the card. */ - if (scard->pin1_required) { - if (pin == NULL) { - wpa_printf(MSG_DEBUG, "No PIN configured for SIM " - "access"); - return -1; - } - if (scard_verify_pin(scard, pin)) { - wpa_printf(MSG_INFO, "PIN verification failed for " - "SIM access"); - return -1; - } - } - - return 0; -} - - -/** - * scard_deinit - Deinitialize SIM/USIM connection - * @scard: Pointer to private data from scard_init() - * - * This function closes the SIM/USIM connect opened with scard_init(). - */ -void scard_deinit(struct scard_data *scard) -{ - long ret; - - if (scard == NULL) - return; - - wpa_printf(MSG_DEBUG, "SCARD: deinitializing smart card interface"); - if (scard->card) { - ret = SCardDisconnect(scard->card, SCARD_UNPOWER_CARD); - if (ret != SCARD_S_SUCCESS) { - wpa_printf(MSG_DEBUG, "SCARD: Failed to disconnect " - "smart card (err=%ld)", ret); - } - } - - if (scard->ctx) { - ret = SCardReleaseContext(scard->ctx); - if (ret != SCARD_S_SUCCESS) { - wpa_printf(MSG_DEBUG, "Failed to release smart card " - "context (err=%ld)", ret); - } - } - os_free(scard); - mingw_unload_symbols(); -} - - -static long scard_transmit(struct scard_data *scard, - unsigned char *_send, size_t send_len, - unsigned char *_recv, size_t *recv_len) -{ - long ret; - unsigned long rlen; - - wpa_hexdump_key(MSG_DEBUG, "SCARD: scard_transmit: send", - _send, send_len); - rlen = *recv_len; - ret = SCardTransmit(scard->card, - scard->protocol == SCARD_PROTOCOL_T1 ? - SCARD_PCI_T1 : SCARD_PCI_T0, - _send, (unsigned long) send_len, - NULL, _recv, &rlen); - *recv_len = rlen; - if (ret == SCARD_S_SUCCESS) { - wpa_hexdump(MSG_DEBUG, "SCARD: scard_transmit: recv", - _recv, rlen); - } else { - wpa_printf(MSG_WARNING, "SCARD: SCardTransmit failed " - "(err=0x%lx)", ret); - } - return ret; -} - - -static int _scard_select_file(struct scard_data *scard, unsigned short file_id, - unsigned char *buf, size_t *buf_len, - sim_types sim_type, unsigned char *aid, - size_t aidlen) -{ - long ret; - unsigned char resp[3]; - unsigned char cmd[50] = { SIM_CMD_SELECT }; - int cmdlen; - unsigned char get_resp[5] = { SIM_CMD_GET_RESPONSE }; - size_t len, rlen; - - if (sim_type == SCARD_USIM) { - cmd[0] = USIM_CLA; - cmd[3] = 0x04; - get_resp[0] = USIM_CLA; - } - - wpa_printf(MSG_DEBUG, "SCARD: select file %04x", file_id); - if (aid) { - wpa_hexdump(MSG_DEBUG, "SCARD: select file by AID", - aid, aidlen); - if (5 + aidlen > sizeof(cmd)) - return -1; - cmd[2] = 0x04; /* Select by AID */ - cmd[4] = aidlen; /* len */ - os_memcpy(cmd + 5, aid, aidlen); - cmdlen = 5 + aidlen; - } else { - cmd[5] = file_id >> 8; - cmd[6] = file_id & 0xff; - cmdlen = 7; - } - len = sizeof(resp); - ret = scard_transmit(scard, cmd, cmdlen, resp, &len); - if (ret != SCARD_S_SUCCESS) { - wpa_printf(MSG_WARNING, "SCARD: SCardTransmit failed " - "(err=0x%lx)", ret); - return -1; - } - - if (len != 2) { - wpa_printf(MSG_WARNING, "SCARD: unexpected resp len " - "%d (expected 2)", (int) len); - return -1; - } - - if (resp[0] == 0x98 && resp[1] == 0x04) { - /* Security status not satisfied (PIN_WLAN) */ - wpa_printf(MSG_WARNING, "SCARD: Security status not satisfied " - "(PIN_WLAN)"); - return -1; - } - - if (resp[0] == 0x6e) { - wpa_printf(MSG_DEBUG, "SCARD: used CLA not supported"); - return -1; - } - - if (resp[0] != 0x6c && resp[0] != 0x9f && resp[0] != 0x61) { - wpa_printf(MSG_WARNING, "SCARD: unexpected response 0x%02x " - "(expected 0x61, 0x6c, or 0x9f)", resp[0]); - return -1; - } - /* Normal ending of command; resp[1] bytes available */ - get_resp[4] = resp[1]; - wpa_printf(MSG_DEBUG, "SCARD: trying to get response (%d bytes)", - resp[1]); - - rlen = *buf_len; - ret = scard_transmit(scard, get_resp, sizeof(get_resp), buf, &rlen); - if (ret == SCARD_S_SUCCESS) { - *buf_len = resp[1] < rlen ? resp[1] : rlen; - return 0; - } - - wpa_printf(MSG_WARNING, "SCARD: SCardTransmit err=0x%lx\n", ret); - return -1; -} - - -static int scard_select_file(struct scard_data *scard, unsigned short file_id, - unsigned char *buf, size_t *buf_len) -{ - return _scard_select_file(scard, file_id, buf, buf_len, - scard->sim_type, NULL, 0); -} - - -static int scard_get_record_len(struct scard_data *scard, unsigned char recnum, - unsigned char mode) -{ - unsigned char buf[255]; - unsigned char cmd[5] = { SIM_CMD_READ_RECORD /* , len */ }; - size_t blen; - long ret; - - if (scard->sim_type == SCARD_USIM) - cmd[0] = USIM_CLA; - cmd[2] = recnum; - cmd[3] = mode; - cmd[4] = sizeof(buf); - - blen = sizeof(buf); - ret = scard_transmit(scard, cmd, sizeof(cmd), buf, &blen); - if (ret != SCARD_S_SUCCESS) { - wpa_printf(MSG_DEBUG, "SCARD: failed to determine file " - "length for record %d", recnum); - return -1; - } - - wpa_hexdump(MSG_DEBUG, "SCARD: file length determination response", - buf, blen); - - if (blen < 2 || buf[0] != 0x6c) { - wpa_printf(MSG_DEBUG, "SCARD: unexpected response to file " - "length determination"); - return -1; - } - - return buf[1]; -} - - -static int scard_read_record(struct scard_data *scard, - unsigned char *data, size_t len, - unsigned char recnum, unsigned char mode) -{ - unsigned char cmd[5] = { SIM_CMD_READ_RECORD /* , len */ }; - size_t blen = len + 3; - unsigned char *buf; - long ret; - - if (scard->sim_type == SCARD_USIM) - cmd[0] = USIM_CLA; - cmd[2] = recnum; - cmd[3] = mode; - cmd[4] = len; - - buf = os_malloc(blen); - if (buf == NULL) - return -1; - - ret = scard_transmit(scard, cmd, sizeof(cmd), buf, &blen); - if (ret != SCARD_S_SUCCESS) { - os_free(buf); - return -2; - } - if (blen != len + 2) { - wpa_printf(MSG_DEBUG, "SCARD: record read returned unexpected " - "length %ld (expected %ld)", - (long) blen, (long) len + 2); - os_free(buf); - return -3; - } - - if (buf[len] != 0x90 || buf[len + 1] != 0x00) { - wpa_printf(MSG_DEBUG, "SCARD: record read returned unexpected " - "status %02x %02x (expected 90 00)", - buf[len], buf[len + 1]); - os_free(buf); - return -4; - } - - os_memcpy(data, buf, len); - os_free(buf); - - return 0; -} - - -static int scard_read_file(struct scard_data *scard, - unsigned char *data, size_t len) -{ - unsigned char cmd[5] = { SIM_CMD_READ_BIN /* , len */ }; - size_t blen = len + 3; - unsigned char *buf; - long ret; - - cmd[4] = len; - - buf = os_malloc(blen); - if (buf == NULL) - return -1; - - if (scard->sim_type == SCARD_USIM) - cmd[0] = USIM_CLA; - ret = scard_transmit(scard, cmd, sizeof(cmd), buf, &blen); - if (ret != SCARD_S_SUCCESS) { - os_free(buf); - return -2; - } - if (blen != len + 2) { - wpa_printf(MSG_DEBUG, "SCARD: file read returned unexpected " - "length %ld (expected %ld)", - (long) blen, (long) len + 2); - os_free(buf); - return -3; - } - - if (buf[len] != 0x90 || buf[len + 1] != 0x00) { - wpa_printf(MSG_DEBUG, "SCARD: file read returned unexpected " - "status %02x %02x (expected 90 00)", - buf[len], buf[len + 1]); - os_free(buf); - return -4; - } - - os_memcpy(data, buf, len); - os_free(buf); - - return 0; -} - - -static int scard_verify_pin(struct scard_data *scard, const char *pin) -{ - long ret; - unsigned char resp[3]; - unsigned char cmd[5 + 8] = { SIM_CMD_VERIFY_CHV1 }; - size_t len; - - wpa_printf(MSG_DEBUG, "SCARD: verifying PIN"); - - if (pin == NULL || os_strlen(pin) > 8) - return -1; - - if (scard->sim_type == SCARD_USIM) - cmd[0] = USIM_CLA; - os_memcpy(cmd + 5, pin, os_strlen(pin)); - os_memset(cmd + 5 + os_strlen(pin), 0xff, 8 - os_strlen(pin)); - - len = sizeof(resp); - ret = scard_transmit(scard, cmd, sizeof(cmd), resp, &len); - if (ret != SCARD_S_SUCCESS) - return -2; - - if (len != 2 || resp[0] != 0x90 || resp[1] != 0x00) { - wpa_printf(MSG_WARNING, "SCARD: PIN verification failed"); - return -1; - } - - wpa_printf(MSG_DEBUG, "SCARD: PIN verified successfully"); - return 0; -} - - -/** - * scard_get_imsi - Read IMSI from SIM/USIM card - * @scard: Pointer to private data from scard_init() - * @imsi: Buffer for IMSI - * @len: Length of imsi buffer; set to IMSI length on success - * Returns: 0 on success, -1 if IMSI file cannot be selected, -2 if IMSI file - * selection returns invalid result code, -3 if parsing FSP template file fails - * (USIM only), -4 if IMSI does not fit in the provided imsi buffer (len is set - * to needed length), -5 if reading IMSI file fails. - * - * This function can be used to read IMSI from the SIM/USIM card. If the IMSI - * file is PIN protected, scard_set_pin() must have been used to set the - * correct PIN code before calling scard_get_imsi(). - */ -int scard_get_imsi(struct scard_data *scard, char *imsi, size_t *len) -{ - unsigned char buf[100]; - size_t blen, imsilen, i; - char *pos; - - wpa_printf(MSG_DEBUG, "SCARD: reading IMSI from (GSM) EF-IMSI"); - blen = sizeof(buf); - if (scard_select_file(scard, SCARD_FILE_GSM_EF_IMSI, buf, &blen)) - return -1; - if (blen < 4) { - wpa_printf(MSG_WARNING, "SCARD: too short (GSM) EF-IMSI " - "header (len=%ld)", (long) blen); - return -2; - } - - if (scard->sim_type == SCARD_GSM_SIM) { - blen = (buf[2] << 8) | buf[3]; - } else { - int file_size; - if (scard_parse_fsp_templ(buf, blen, NULL, &file_size)) - return -3; - blen = file_size; - } - if (blen < 2 || blen > sizeof(buf)) { - wpa_printf(MSG_DEBUG, "SCARD: invalid IMSI file length=%ld", - (long) blen); - return -3; - } - - imsilen = (blen - 2) * 2 + 1; - wpa_printf(MSG_DEBUG, "SCARD: IMSI file length=%ld imsilen=%ld", - (long) blen, (long) imsilen); - if (blen < 2 || imsilen > *len) { - *len = imsilen; - return -4; - } - - if (scard_read_file(scard, buf, blen)) - return -5; - - pos = imsi; - *pos++ = '0' + (buf[1] >> 4 & 0x0f); - for (i = 2; i < blen; i++) { - unsigned char digit; - - digit = buf[i] & 0x0f; - if (digit < 10) - *pos++ = '0' + digit; - else - imsilen--; - - digit = buf[i] >> 4 & 0x0f; - if (digit < 10) - *pos++ = '0' + digit; - else - imsilen--; - } - *len = imsilen; - - return 0; -} - - -/** - * scard_gsm_auth - Run GSM authentication command on SIM card - * @scard: Pointer to private data from scard_init() - * @_rand: 16-byte RAND value from HLR/AuC - * @sres: 4-byte buffer for SRES - * @kc: 8-byte buffer for Kc - * Returns: 0 on success, -1 if SIM/USIM connection has not been initialized, - * -2 if authentication command execution fails, -3 if unknown response code - * for authentication command is received, -4 if reading of response fails, - * -5 if if response data is of unexpected length - * - * This function performs GSM authentication using SIM/USIM card and the - * provided RAND value from HLR/AuC. If authentication command can be completed - * successfully, SRES and Kc values will be written into sres and kc buffers. - */ -int scard_gsm_auth(struct scard_data *scard, const unsigned char *_rand, - unsigned char *sres, unsigned char *kc) -{ - unsigned char cmd[5 + 1 + 16] = { SIM_CMD_RUN_GSM_ALG }; - int cmdlen; - unsigned char get_resp[5] = { SIM_CMD_GET_RESPONSE }; - unsigned char resp[3], buf[12 + 3 + 2]; - size_t len; - long ret; - - if (scard == NULL) - return -1; - - wpa_hexdump(MSG_DEBUG, "SCARD: GSM auth - RAND", _rand, 16); - if (scard->sim_type == SCARD_GSM_SIM) { - cmdlen = 5 + 16; - os_memcpy(cmd + 5, _rand, 16); - } else { - cmdlen = 5 + 1 + 16; - cmd[0] = USIM_CLA; - cmd[3] = 0x80; - cmd[4] = 17; - cmd[5] = 16; - os_memcpy(cmd + 6, _rand, 16); - } - len = sizeof(resp); - ret = scard_transmit(scard, cmd, cmdlen, resp, &len); - if (ret != SCARD_S_SUCCESS) - return -2; - - if ((scard->sim_type == SCARD_GSM_SIM && - (len != 2 || resp[0] != 0x9f || resp[1] != 0x0c)) || - (scard->sim_type == SCARD_USIM && - (len != 2 || resp[0] != 0x61 || resp[1] != 0x0e))) { - wpa_printf(MSG_WARNING, "SCARD: unexpected response for GSM " - "auth request (len=%ld resp=%02x %02x)", - (long) len, resp[0], resp[1]); - return -3; - } - get_resp[4] = resp[1]; - - len = sizeof(buf); - ret = scard_transmit(scard, get_resp, sizeof(get_resp), buf, &len); - if (ret != SCARD_S_SUCCESS) - return -4; - - if (scard->sim_type == SCARD_GSM_SIM) { - if (len != 4 + 8 + 2) { - wpa_printf(MSG_WARNING, "SCARD: unexpected data " - "length for GSM auth (len=%ld, expected 14)", - (long) len); - return -5; - } - os_memcpy(sres, buf, 4); - os_memcpy(kc, buf + 4, 8); - } else { - if (len != 1 + 4 + 1 + 8 + 2) { - wpa_printf(MSG_WARNING, "SCARD: unexpected data " - "length for USIM auth (len=%ld, " - "expected 16)", (long) len); - return -5; - } - if (buf[0] != 4 || buf[5] != 8) { - wpa_printf(MSG_WARNING, "SCARD: unexpected SREC/Kc " - "length (%d %d, expected 4 8)", - buf[0], buf[5]); - } - os_memcpy(sres, buf + 1, 4); - os_memcpy(kc, buf + 6, 8); - } - - wpa_hexdump(MSG_DEBUG, "SCARD: GSM auth - SRES", sres, 4); - wpa_hexdump(MSG_DEBUG, "SCARD: GSM auth - Kc", kc, 8); - - return 0; -} - - -/** - * scard_umts_auth - Run UMTS authentication command on USIM card - * @scard: Pointer to private data from scard_init() - * @_rand: 16-byte RAND value from HLR/AuC - * @autn: 16-byte AUTN value from HLR/AuC - * @res: 16-byte buffer for RES - * @res_len: Variable that will be set to RES length - * @ik: 16-byte buffer for IK - * @ck: 16-byte buffer for CK - * @auts: 14-byte buffer for AUTS - * Returns: 0 on success, -1 on failure, or -2 if USIM reports synchronization - * failure - * - * This function performs AKA authentication using USIM card and the provided - * RAND and AUTN values from HLR/AuC. If authentication command can be - * completed successfully, RES, IK, and CK values will be written into provided - * buffers and res_len is set to length of received RES value. If USIM reports - * synchronization failure, the received AUTS value will be written into auts - * buffer. In this case, RES, IK, and CK are not valid. - */ -int scard_umts_auth(struct scard_data *scard, const unsigned char *_rand, - const unsigned char *autn, - unsigned char *res, size_t *res_len, - unsigned char *ik, unsigned char *ck, unsigned char *auts) -{ - unsigned char cmd[5 + 1 + AKA_RAND_LEN + 1 + AKA_AUTN_LEN] = - { USIM_CMD_RUN_UMTS_ALG }; - unsigned char get_resp[5] = { USIM_CMD_GET_RESPONSE }; - unsigned char resp[3], buf[64], *pos, *end; - size_t len; - long ret; - - if (scard == NULL) - return -1; - - if (scard->sim_type == SCARD_GSM_SIM) { - wpa_printf(MSG_ERROR, "SCARD: Non-USIM card - cannot do UMTS " - "auth"); - return -1; - } - - wpa_hexdump(MSG_DEBUG, "SCARD: UMTS auth - RAND", _rand, AKA_RAND_LEN); - wpa_hexdump(MSG_DEBUG, "SCARD: UMTS auth - AUTN", autn, AKA_AUTN_LEN); - cmd[5] = AKA_RAND_LEN; - os_memcpy(cmd + 6, _rand, AKA_RAND_LEN); - cmd[6 + AKA_RAND_LEN] = AKA_AUTN_LEN; - os_memcpy(cmd + 6 + AKA_RAND_LEN + 1, autn, AKA_AUTN_LEN); - - len = sizeof(resp); - ret = scard_transmit(scard, cmd, sizeof(cmd), resp, &len); - if (ret != SCARD_S_SUCCESS) - return -1; - - if (len <= sizeof(resp)) - wpa_hexdump(MSG_DEBUG, "SCARD: UMTS alg response", resp, len); - - if (len == 2 && resp[0] == 0x98 && resp[1] == 0x62) { - wpa_printf(MSG_WARNING, "SCARD: UMTS auth failed - " - "MAC != XMAC"); - return -1; - } else if (len != 2 || resp[0] != 0x61) { - wpa_printf(MSG_WARNING, "SCARD: unexpected response for UMTS " - "auth request (len=%ld resp=%02x %02x)", - (long) len, resp[0], resp[1]); - return -1; - } - get_resp[4] = resp[1]; - - len = sizeof(buf); - ret = scard_transmit(scard, get_resp, sizeof(get_resp), buf, &len); - if (ret != SCARD_S_SUCCESS || len > sizeof(buf)) - return -1; - - wpa_hexdump(MSG_DEBUG, "SCARD: UMTS get response result", buf, len); - if (len >= 2 + AKA_AUTS_LEN && buf[0] == 0xdc && - buf[1] == AKA_AUTS_LEN) { - wpa_printf(MSG_DEBUG, "SCARD: UMTS Synchronization-Failure"); - os_memcpy(auts, buf + 2, AKA_AUTS_LEN); - wpa_hexdump(MSG_DEBUG, "SCARD: AUTS", auts, AKA_AUTS_LEN); - return -2; - } else if (len >= 6 + IK_LEN + CK_LEN && buf[0] == 0xdb) { - pos = buf + 1; - end = buf + len; - - /* RES */ - if (pos[0] > RES_MAX_LEN || pos + pos[0] > end) { - wpa_printf(MSG_DEBUG, "SCARD: Invalid RES"); - return -1; - } - *res_len = *pos++; - os_memcpy(res, pos, *res_len); - pos += *res_len; - wpa_hexdump(MSG_DEBUG, "SCARD: RES", res, *res_len); - - /* CK */ - if (pos[0] != CK_LEN || pos + CK_LEN > end) { - wpa_printf(MSG_DEBUG, "SCARD: Invalid CK"); - return -1; - } - pos++; - os_memcpy(ck, pos, CK_LEN); - pos += CK_LEN; - wpa_hexdump(MSG_DEBUG, "SCARD: CK", ck, CK_LEN); - - /* IK */ - if (pos[0] != IK_LEN || pos + IK_LEN > end) { - wpa_printf(MSG_DEBUG, "SCARD: Invalid IK"); - return -1; - } - pos++; - os_memcpy(ik, pos, IK_LEN); - pos += IK_LEN; - wpa_hexdump(MSG_DEBUG, "SCARD: IK", ik, IK_LEN); - - return 0; - } - - wpa_printf(MSG_DEBUG, "SCARD: Unrecognized response"); - return -1; -} diff --git a/hostapd-0.8/src/utils/pcsc_funcs.h b/hostapd-0.8/src/utils/pcsc_funcs.h deleted file mode 100644 index 543f7c5..0000000 --- a/hostapd-0.8/src/utils/pcsc_funcs.h +++ /dev/null @@ -1,68 +0,0 @@ -/* - * WPA Supplicant / PC/SC smartcard interface for USIM, GSM SIM - * Copyright (c) 2004-2006, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#ifndef PCSC_FUNCS_H -#define PCSC_FUNCS_H - -/* GSM files - * File type in first octet: - * 3F = Master File - * 7F = Dedicated File - * 2F = Elementary File under the Master File - * 6F = Elementary File under a Dedicated File - */ -#define SCARD_FILE_MF 0x3F00 -#define SCARD_FILE_GSM_DF 0x7F20 -#define SCARD_FILE_UMTS_DF 0x7F50 -#define SCARD_FILE_GSM_EF_IMSI 0x6F07 -#define SCARD_FILE_EF_DIR 0x2F00 -#define SCARD_FILE_EF_ICCID 0x2FE2 -#define SCARD_FILE_EF_CK 0x6FE1 -#define SCARD_FILE_EF_IK 0x6FE2 - -#define SCARD_CHV1_OFFSET 13 -#define SCARD_CHV1_FLAG 0x80 - -typedef enum { - SCARD_GSM_SIM_ONLY, - SCARD_USIM_ONLY, - SCARD_TRY_BOTH -} scard_sim_type; - - -#ifdef PCSC_FUNCS -struct scard_data * scard_init(scard_sim_type sim_type); -void scard_deinit(struct scard_data *scard); - -int scard_set_pin(struct scard_data *scard, const char *pin); -int scard_get_imsi(struct scard_data *scard, char *imsi, size_t *len); -int scard_gsm_auth(struct scard_data *scard, const unsigned char *_rand, - unsigned char *sres, unsigned char *kc); -int scard_umts_auth(struct scard_data *scard, const unsigned char *_rand, - const unsigned char *autn, - unsigned char *res, size_t *res_len, - unsigned char *ik, unsigned char *ck, unsigned char *auts); - -#else /* PCSC_FUNCS */ - -#define scard_init(s) NULL -#define scard_deinit(s) do { } while (0) -#define scard_set_pin(s, p) -1 -#define scard_get_imsi(s, i, l) -1 -#define scard_gsm_auth(s, r, s2, k) -1 -#define scard_umts_auth(s, r, a, r2, rl, i, c, a2) -1 - -#endif /* PCSC_FUNCS */ - -#endif /* PCSC_FUNCS_H */ diff --git a/hostapd-0.8/src/utils/radiotap.c b/hostapd-0.8/src/utils/radiotap.c deleted file mode 100644 index 804473f..0000000 --- a/hostapd-0.8/src/utils/radiotap.c +++ /dev/null @@ -1,287 +0,0 @@ -/* - * Radiotap parser - * - * Copyright 2007 Andy Green - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - * - * - * Modified for userspace by Johannes Berg - * I only modified some things on top to ease syncing should bugs be found. - */ - -#include "includes.h" - -#include "common.h" -#include "radiotap_iter.h" - -#define le16_to_cpu le_to_host16 -#define le32_to_cpu le_to_host32 -#define __le32 uint32_t -#define ulong unsigned long -#define unlikely(cond) (cond) -#define get_unaligned(p) \ -({ \ - struct packed_dummy_struct { \ - typeof(*(p)) __val; \ - } __attribute__((packed)) *__ptr = (void *) (p); \ - \ - __ptr->__val; \ -}) - -/* function prototypes and related defs are in radiotap_iter.h */ - -/** - * ieee80211_radiotap_iterator_init - radiotap parser iterator initialization - * @iterator: radiotap_iterator to initialize - * @radiotap_header: radiotap header to parse - * @max_length: total length we can parse into (eg, whole packet length) - * - * Returns: 0 or a negative error code if there is a problem. - * - * This function initializes an opaque iterator struct which can then - * be passed to ieee80211_radiotap_iterator_next() to visit every radiotap - * argument which is present in the header. It knows about extended - * present headers and handles them. - * - * How to use: - * call __ieee80211_radiotap_iterator_init() to init a semi-opaque iterator - * struct ieee80211_radiotap_iterator (no need to init the struct beforehand) - * checking for a good 0 return code. Then loop calling - * __ieee80211_radiotap_iterator_next()... it returns either 0, - * -ENOENT if there are no more args to parse, or -EINVAL if there is a problem. - * The iterator's @this_arg member points to the start of the argument - * associated with the current argument index that is present, which can be - * found in the iterator's @this_arg_index member. This arg index corresponds - * to the IEEE80211_RADIOTAP_... defines. - * - * Radiotap header length: - * You can find the CPU-endian total radiotap header length in - * iterator->max_length after executing ieee80211_radiotap_iterator_init() - * successfully. - * - * Alignment Gotcha: - * You must take care when dereferencing iterator.this_arg - * for multibyte types... the pointer is not aligned. Use - * get_unaligned((type *)iterator.this_arg) to dereference - * iterator.this_arg for type "type" safely on all arches. - * - * Example code: - * See Documentation/networking/radiotap-headers.txt - */ - -int ieee80211_radiotap_iterator_init( - struct ieee80211_radiotap_iterator *iterator, - struct ieee80211_radiotap_header *radiotap_header, - int max_length) -{ - /* Linux only supports version 0 radiotap format */ - if (radiotap_header->it_version) - return -EINVAL; - - /* sanity check for allowed length and radiotap length field */ - if (max_length < le16_to_cpu(get_unaligned(&radiotap_header->it_len))) - return -EINVAL; - - iterator->rtheader = radiotap_header; - iterator->max_length = le16_to_cpu(get_unaligned( - &radiotap_header->it_len)); - iterator->arg_index = 0; - iterator->bitmap_shifter = le32_to_cpu(get_unaligned( - &radiotap_header->it_present)); - iterator->arg = (u8 *)radiotap_header + sizeof(*radiotap_header); - iterator->this_arg = NULL; - - /* find payload start allowing for extended bitmap(s) */ - - if (unlikely(iterator->bitmap_shifter & (1<arg)) & - (1<arg += sizeof(u32); - - /* - * check for insanity where the present bitmaps - * keep claiming to extend up to or even beyond the - * stated radiotap header length - */ - - if (((ulong)iterator->arg - (ulong)iterator->rtheader) - > (ulong)iterator->max_length) - return -EINVAL; - } - - iterator->arg += sizeof(u32); - - /* - * no need to check again for blowing past stated radiotap - * header length, because ieee80211_radiotap_iterator_next - * checks it before it is dereferenced - */ - } - - /* we are all initialized happily */ - - return 0; -} - - -/** - * ieee80211_radiotap_iterator_next - return next radiotap parser iterator arg - * @iterator: radiotap_iterator to move to next arg (if any) - * - * Returns: 0 if there is an argument to handle, - * -ENOENT if there are no more args or -EINVAL - * if there is something else wrong. - * - * This function provides the next radiotap arg index (IEEE80211_RADIOTAP_*) - * in @this_arg_index and sets @this_arg to point to the - * payload for the field. It takes care of alignment handling and extended - * present fields. @this_arg can be changed by the caller (eg, - * incremented to move inside a compound argument like - * IEEE80211_RADIOTAP_CHANNEL). The args pointed to are in - * little-endian format whatever the endianess of your CPU. - * - * Alignment Gotcha: - * You must take care when dereferencing iterator.this_arg - * for multibyte types... the pointer is not aligned. Use - * get_unaligned((type *)iterator.this_arg) to dereference - * iterator.this_arg for type "type" safely on all arches. - */ - -int ieee80211_radiotap_iterator_next( - struct ieee80211_radiotap_iterator *iterator) -{ - - /* - * small length lookup table for all radiotap types we heard of - * starting from b0 in the bitmap, so we can walk the payload - * area of the radiotap header - * - * There is a requirement to pad args, so that args - * of a given length must begin at a boundary of that length - * -- but note that compound args are allowed (eg, 2 x u16 - * for IEEE80211_RADIOTAP_CHANNEL) so total arg length is not - * a reliable indicator of alignment requirement. - * - * upper nybble: content alignment for arg - * lower nybble: content length for arg - */ - - static const u8 rt_sizes[] = { - [IEEE80211_RADIOTAP_TSFT] = 0x88, - [IEEE80211_RADIOTAP_FLAGS] = 0x11, - [IEEE80211_RADIOTAP_RATE] = 0x11, - [IEEE80211_RADIOTAP_CHANNEL] = 0x24, - [IEEE80211_RADIOTAP_FHSS] = 0x22, - [IEEE80211_RADIOTAP_DBM_ANTSIGNAL] = 0x11, - [IEEE80211_RADIOTAP_DBM_ANTNOISE] = 0x11, - [IEEE80211_RADIOTAP_LOCK_QUALITY] = 0x22, - [IEEE80211_RADIOTAP_TX_ATTENUATION] = 0x22, - [IEEE80211_RADIOTAP_DB_TX_ATTENUATION] = 0x22, - [IEEE80211_RADIOTAP_DBM_TX_POWER] = 0x11, - [IEEE80211_RADIOTAP_ANTENNA] = 0x11, - [IEEE80211_RADIOTAP_DB_ANTSIGNAL] = 0x11, - [IEEE80211_RADIOTAP_DB_ANTNOISE] = 0x11, - [IEEE80211_RADIOTAP_RX_FLAGS] = 0x22, - [IEEE80211_RADIOTAP_TX_FLAGS] = 0x22, - [IEEE80211_RADIOTAP_RTS_RETRIES] = 0x11, - [IEEE80211_RADIOTAP_DATA_RETRIES] = 0x11, - /* - * add more here as they are defined in - * include/net/ieee80211_radiotap.h - */ - }; - - /* - * for every radiotap entry we can at - * least skip (by knowing the length)... - */ - - while (iterator->arg_index < (int) sizeof(rt_sizes)) { - int hit = 0; - int pad; - - if (!(iterator->bitmap_shifter & 1)) - goto next_entry; /* arg not present */ - - /* - * arg is present, account for alignment padding - * 8-bit args can be at any alignment - * 16-bit args must start on 16-bit boundary - * 32-bit args must start on 32-bit boundary - * 64-bit args must start on 64-bit boundary - * - * note that total arg size can differ from alignment of - * elements inside arg, so we use upper nybble of length - * table to base alignment on - * - * also note: these alignments are ** relative to the - * start of the radiotap header **. There is no guarantee - * that the radiotap header itself is aligned on any - * kind of boundary. - * - * the above is why get_unaligned() is used to dereference - * multibyte elements from the radiotap area - */ - - pad = (((ulong)iterator->arg) - - ((ulong)iterator->rtheader)) & - ((rt_sizes[iterator->arg_index] >> 4) - 1); - - if (pad) - iterator->arg += - (rt_sizes[iterator->arg_index] >> 4) - pad; - - /* - * this is what we will return to user, but we need to - * move on first so next call has something fresh to test - */ - iterator->this_arg_index = iterator->arg_index; - iterator->this_arg = iterator->arg; - hit = 1; - - /* internally move on the size of this arg */ - iterator->arg += rt_sizes[iterator->arg_index] & 0x0f; - - /* - * check for insanity where we are given a bitmap that - * claims to have more arg content than the length of the - * radiotap section. We will normally end up equalling this - * max_length on the last arg, never exceeding it. - */ - - if (((ulong)iterator->arg - (ulong)iterator->rtheader) > - (ulong) iterator->max_length) - return -EINVAL; - - next_entry: - iterator->arg_index++; - if (unlikely((iterator->arg_index & 31) == 0)) { - /* completed current u32 bitmap */ - if (iterator->bitmap_shifter & 1) { - /* b31 was set, there is more */ - /* move to next u32 bitmap */ - iterator->bitmap_shifter = le32_to_cpu( - get_unaligned(iterator->next_bitmap)); - iterator->next_bitmap++; - } else - /* no more bitmaps: end */ - iterator->arg_index = sizeof(rt_sizes); - } else /* just try the next bit */ - iterator->bitmap_shifter >>= 1; - - /* if we found a valid arg earlier, return it now */ - if (hit) - return 0; - } - - /* we don't know how to handle any more args, we're done */ - return -ENOENT; -} diff --git a/hostapd-0.8/src/utils/radiotap.h b/hostapd-0.8/src/utils/radiotap.h deleted file mode 100644 index 508264c..0000000 --- a/hostapd-0.8/src/utils/radiotap.h +++ /dev/null @@ -1,242 +0,0 @@ -/* $FreeBSD: src/sys/net80211/ieee80211_radiotap.h,v 1.5 2005/01/22 20:12:05 sam Exp $ */ -/* $NetBSD: ieee80211_radiotap.h,v 1.11 2005/06/22 06:16:02 dyoung Exp $ */ - -/*- - * Copyright (c) 2003, 2004 David Young. All rights reserved. - * - * 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. The name of David Young may not be used to endorse or promote - * products derived from this software without specific prior - * written permission. - * - * THIS SOFTWARE IS PROVIDED BY DAVID YOUNG ``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 DAVID - * YOUNG 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. - */ - -/* - * Modifications to fit into the linux IEEE 802.11 stack, - * Mike Kershaw (dragorn@kismetwireless.net) - */ - -#ifndef IEEE80211RADIOTAP_H -#define IEEE80211RADIOTAP_H - -#include - -/* Base version of the radiotap packet header data */ -#define PKTHDR_RADIOTAP_VERSION 0 - -/* A generic radio capture format is desirable. There is one for - * Linux, but it is neither rigidly defined (there were not even - * units given for some fields) nor easily extensible. - * - * I suggest the following extensible radio capture format. It is - * based on a bitmap indicating which fields are present. - * - * I am trying to describe precisely what the application programmer - * should expect in the following, and for that reason I tell the - * units and origin of each measurement (where it applies), or else I - * use sufficiently weaselly language ("is a monotonically nondecreasing - * function of...") that I cannot set false expectations for lawyerly - * readers. - */ - -/* The radio capture header precedes the 802.11 header. - * All data in the header is little endian on all platforms. - */ -struct ieee80211_radiotap_header { - uint8_t it_version; /* Version 0. Only increases - * for drastic changes, - * introduction of compatible - * new fields does not count. - */ - uint8_t it_pad; - uint16_t it_len; /* length of the whole - * header in bytes, including - * it_version, it_pad, - * it_len, and data fields. - */ - uint32_t it_present; /* A bitmap telling which - * fields are present. Set bit 31 - * (0x80000000) to extend the - * bitmap by another 32 bits. - * Additional extensions are made - * by setting bit 31. - */ -}; - -/* Name Data type Units - * ---- --------- ----- - * - * IEEE80211_RADIOTAP_TSFT __le64 microseconds - * - * Value in microseconds of the MAC's 64-bit 802.11 Time - * Synchronization Function timer when the first bit of the - * MPDU arrived at the MAC. For received frames, only. - * - * IEEE80211_RADIOTAP_CHANNEL 2 x uint16_t MHz, bitmap - * - * Tx/Rx frequency in MHz, followed by flags (see below). - * - * IEEE80211_RADIOTAP_FHSS uint16_t see below - * - * For frequency-hopping radios, the hop set (first byte) - * and pattern (second byte). - * - * IEEE80211_RADIOTAP_RATE u8 500kb/s - * - * Tx/Rx data rate - * - * IEEE80211_RADIOTAP_DBM_ANTSIGNAL s8 decibels from - * one milliwatt (dBm) - * - * RF signal power at the antenna, decibel difference from - * one milliwatt. - * - * IEEE80211_RADIOTAP_DBM_ANTNOISE s8 decibels from - * one milliwatt (dBm) - * - * RF noise power at the antenna, decibel difference from one - * milliwatt. - * - * IEEE80211_RADIOTAP_DB_ANTSIGNAL u8 decibel (dB) - * - * RF signal power at the antenna, decibel difference from an - * arbitrary, fixed reference. - * - * IEEE80211_RADIOTAP_DB_ANTNOISE u8 decibel (dB) - * - * RF noise power at the antenna, decibel difference from an - * arbitrary, fixed reference point. - * - * IEEE80211_RADIOTAP_LOCK_QUALITY uint16_t unitless - * - * Quality of Barker code lock. Unitless. Monotonically - * nondecreasing with "better" lock strength. Called "Signal - * Quality" in datasheets. (Is there a standard way to measure - * this?) - * - * IEEE80211_RADIOTAP_TX_ATTENUATION uint16_t unitless - * - * Transmit power expressed as unitless distance from max - * power set at factory calibration. 0 is max power. - * Monotonically nondecreasing with lower power levels. - * - * IEEE80211_RADIOTAP_DB_TX_ATTENUATION uint16_t decibels (dB) - * - * Transmit power expressed as decibel distance from max power - * set at factory calibration. 0 is max power. Monotonically - * nondecreasing with lower power levels. - * - * IEEE80211_RADIOTAP_DBM_TX_POWER s8 decibels from - * one milliwatt (dBm) - * - * Transmit power expressed as dBm (decibels from a 1 milliwatt - * reference). This is the absolute power level measured at - * the antenna port. - * - * IEEE80211_RADIOTAP_FLAGS u8 bitmap - * - * Properties of transmitted and received frames. See flags - * defined below. - * - * IEEE80211_RADIOTAP_ANTENNA u8 antenna index - * - * Unitless indication of the Rx/Tx antenna for this packet. - * The first antenna is antenna 0. - * - * IEEE80211_RADIOTAP_RX_FLAGS uint16_t bitmap - * - * Properties of received frames. See flags defined below. - * - * IEEE80211_RADIOTAP_TX_FLAGS uint16_t bitmap - * - * Properties of transmitted frames. See flags defined below. - * - * IEEE80211_RADIOTAP_RTS_RETRIES u8 data - * - * Number of rts retries a transmitted frame used. - * - * IEEE80211_RADIOTAP_DATA_RETRIES u8 data - * - * Number of unicast retries a transmitted frame used. - * - */ -enum ieee80211_radiotap_type { - IEEE80211_RADIOTAP_TSFT = 0, - IEEE80211_RADIOTAP_FLAGS = 1, - IEEE80211_RADIOTAP_RATE = 2, - IEEE80211_RADIOTAP_CHANNEL = 3, - IEEE80211_RADIOTAP_FHSS = 4, - IEEE80211_RADIOTAP_DBM_ANTSIGNAL = 5, - IEEE80211_RADIOTAP_DBM_ANTNOISE = 6, - IEEE80211_RADIOTAP_LOCK_QUALITY = 7, - IEEE80211_RADIOTAP_TX_ATTENUATION = 8, - IEEE80211_RADIOTAP_DB_TX_ATTENUATION = 9, - IEEE80211_RADIOTAP_DBM_TX_POWER = 10, - IEEE80211_RADIOTAP_ANTENNA = 11, - IEEE80211_RADIOTAP_DB_ANTSIGNAL = 12, - IEEE80211_RADIOTAP_DB_ANTNOISE = 13, - IEEE80211_RADIOTAP_RX_FLAGS = 14, - IEEE80211_RADIOTAP_TX_FLAGS = 15, - IEEE80211_RADIOTAP_RTS_RETRIES = 16, - IEEE80211_RADIOTAP_DATA_RETRIES = 17, - IEEE80211_RADIOTAP_EXT = 31 -}; - -/* Channel flags. */ -#define IEEE80211_CHAN_TURBO 0x0010 /* Turbo channel */ -#define IEEE80211_CHAN_CCK 0x0020 /* CCK channel */ -#define IEEE80211_CHAN_OFDM 0x0040 /* OFDM channel */ -#define IEEE80211_CHAN_2GHZ 0x0080 /* 2 GHz spectrum channel. */ -#define IEEE80211_CHAN_5GHZ 0x0100 /* 5 GHz spectrum channel */ -#define IEEE80211_CHAN_PASSIVE 0x0200 /* Only passive scan allowed */ -#define IEEE80211_CHAN_DYN 0x0400 /* Dynamic CCK-OFDM channel */ -#define IEEE80211_CHAN_GFSK 0x0800 /* GFSK channel (FHSS PHY) */ - -/* For IEEE80211_RADIOTAP_FLAGS */ -#define IEEE80211_RADIOTAP_F_CFP 0x01 /* sent/received - * during CFP - */ -#define IEEE80211_RADIOTAP_F_SHORTPRE 0x02 /* sent/received - * with short - * preamble - */ -#define IEEE80211_RADIOTAP_F_WEP 0x04 /* sent/received - * with WEP encryption - */ -#define IEEE80211_RADIOTAP_F_FRAG 0x08 /* sent/received - * with fragmentation - */ -#define IEEE80211_RADIOTAP_F_FCS 0x10 /* frame includes FCS */ -#define IEEE80211_RADIOTAP_F_DATAPAD 0x20 /* frame has padding between - * 802.11 header and payload - * (to 32-bit boundary) - */ -/* For IEEE80211_RADIOTAP_RX_FLAGS */ -#define IEEE80211_RADIOTAP_F_RX_BADFCS 0x0001 /* frame failed crc check */ - -/* For IEEE80211_RADIOTAP_TX_FLAGS */ -#define IEEE80211_RADIOTAP_F_TX_FAIL 0x0001 /* failed due to excessive - * retries */ -#define IEEE80211_RADIOTAP_F_TX_CTS 0x0002 /* used cts 'protection' */ -#define IEEE80211_RADIOTAP_F_TX_RTS 0x0004 /* used rts/cts handshake */ - -#endif /* IEEE80211_RADIOTAP_H */ diff --git a/hostapd-0.8/src/utils/radiotap_iter.h b/hostapd-0.8/src/utils/radiotap_iter.h deleted file mode 100644 index 92a798a..0000000 --- a/hostapd-0.8/src/utils/radiotap_iter.h +++ /dev/null @@ -1,41 +0,0 @@ -#ifndef __RADIOTAP_ITER_H -#define __RADIOTAP_ITER_H - -#include "radiotap.h" - -/* Radiotap header iteration - * implemented in radiotap.c - */ -/** - * struct ieee80211_radiotap_iterator - tracks walk thru present radiotap args - * @rtheader: pointer to the radiotap header we are walking through - * @max_length: length of radiotap header in cpu byte ordering - * @this_arg_index: IEEE80211_RADIOTAP_... index of current arg - * @this_arg: pointer to current radiotap arg - * @arg_index: internal next argument index - * @arg: internal next argument pointer - * @next_bitmap: internal pointer to next present u32 - * @bitmap_shifter: internal shifter for curr u32 bitmap, b0 set == arg present - */ - -struct ieee80211_radiotap_iterator { - struct ieee80211_radiotap_header *rtheader; - int max_length; - int this_arg_index; - unsigned char *this_arg; - - int arg_index; - unsigned char *arg; - uint32_t *next_bitmap; - uint32_t bitmap_shifter; -}; - -extern int ieee80211_radiotap_iterator_init( - struct ieee80211_radiotap_iterator *iterator, - struct ieee80211_radiotap_header *radiotap_header, - int max_length); - -extern int ieee80211_radiotap_iterator_next( - struct ieee80211_radiotap_iterator *iterator); - -#endif /* __RADIOTAP_ITER_H */ diff --git a/hostapd-0.8/src/utils/state_machine.h b/hostapd-0.8/src/utils/state_machine.h deleted file mode 100644 index 31f6672..0000000 --- a/hostapd-0.8/src/utils/state_machine.h +++ /dev/null @@ -1,144 +0,0 @@ -/* - * wpa_supplicant/hostapd - State machine definitions - * Copyright (c) 2002-2005, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - * - * This file includes a set of pre-processor macros that can be used to - * implement a state machine. In addition to including this header file, each - * file implementing a state machine must define STATE_MACHINE_DATA to be the - * data structure including state variables (enum machine_state, - * Boolean changed), and STATE_MACHINE_DEBUG_PREFIX to be a string that is used - * as a prefix for all debug messages. If SM_ENTRY_MA macro is used to define - * a group of state machines with shared data structure, STATE_MACHINE_ADDR - * needs to be defined to point to the MAC address used in debug output. - * SM_ENTRY_M macro can be used to define similar group of state machines - * without this additional debug info. - */ - -#ifndef STATE_MACHINE_H -#define STATE_MACHINE_H - -/** - * SM_STATE - Declaration of a state machine function - * @machine: State machine name - * @state: State machine state - * - * This macro is used to declare a state machine function. It is used in place - * of a C function definition to declare functions to be run when the state is - * entered by calling SM_ENTER or SM_ENTER_GLOBAL. - */ -#define SM_STATE(machine, state) \ -static void sm_ ## machine ## _ ## state ## _Enter(STATE_MACHINE_DATA *sm, \ - int global) - -/** - * SM_ENTRY - State machine function entry point - * @machine: State machine name - * @state: State machine state - * - * This macro is used inside each state machine function declared with - * SM_STATE. SM_ENTRY should be in the beginning of the function body, but - * after declaration of possible local variables. This macro prints debug - * information about state transition and update the state machine state. - */ -#define SM_ENTRY(machine, state) \ -if (!global || sm->machine ## _state != machine ## _ ## state) { \ - sm->changed = TRUE; \ - wpa_printf(MSG_DEBUG, STATE_MACHINE_DEBUG_PREFIX ": " #machine \ - " entering state " #state); \ -} \ -sm->machine ## _state = machine ## _ ## state; - -/** - * SM_ENTRY_M - State machine function entry point for state machine group - * @machine: State machine name - * @_state: State machine state - * @data: State variable prefix (full variable: prefix_state) - * - * This macro is like SM_ENTRY, but for state machine groups that use a shared - * data structure for more than one state machine. Both machine and prefix - * parameters are set to "sub-state machine" name. prefix is used to allow more - * than one state variable to be stored in the same data structure. - */ -#define SM_ENTRY_M(machine, _state, data) \ -if (!global || sm->data ## _ ## state != machine ## _ ## _state) { \ - sm->changed = TRUE; \ - wpa_printf(MSG_DEBUG, STATE_MACHINE_DEBUG_PREFIX ": " \ - #machine " entering state " #_state); \ -} \ -sm->data ## _ ## state = machine ## _ ## _state; - -/** - * SM_ENTRY_MA - State machine function entry point for state machine group - * @machine: State machine name - * @_state: State machine state - * @data: State variable prefix (full variable: prefix_state) - * - * This macro is like SM_ENTRY_M, but a MAC address is included in debug - * output. STATE_MACHINE_ADDR has to be defined to point to the MAC address to - * be included in debug. - */ -#define SM_ENTRY_MA(machine, _state, data) \ -if (!global || sm->data ## _ ## state != machine ## _ ## _state) { \ - sm->changed = TRUE; \ - wpa_printf(MSG_DEBUG, STATE_MACHINE_DEBUG_PREFIX ": " MACSTR " " \ - #machine " entering state " #_state, \ - MAC2STR(STATE_MACHINE_ADDR)); \ -} \ -sm->data ## _ ## state = machine ## _ ## _state; - -/** - * SM_ENTER - Enter a new state machine state - * @machine: State machine name - * @state: State machine state - * - * This macro expands to a function call to a state machine function defined - * with SM_STATE macro. SM_ENTER is used in a state machine step function to - * move the state machine to a new state. - */ -#define SM_ENTER(machine, state) \ -sm_ ## machine ## _ ## state ## _Enter(sm, 0) - -/** - * SM_ENTER_GLOBAL - Enter a new state machine state based on global rule - * @machine: State machine name - * @state: State machine state - * - * This macro is like SM_ENTER, but this is used when entering a new state - * based on a global (not specific to any particular state) rule. A separate - * macro is used to avoid unwanted debug message floods when the same global - * rule is forcing a state machine to remain in on state. - */ -#define SM_ENTER_GLOBAL(machine, state) \ -sm_ ## machine ## _ ## state ## _Enter(sm, 1) - -/** - * SM_STEP - Declaration of a state machine step function - * @machine: State machine name - * - * This macro is used to declare a state machine step function. It is used in - * place of a C function definition to declare a function that is used to move - * state machine to a new state based on state variables. This function uses - * SM_ENTER and SM_ENTER_GLOBAL macros to enter new state. - */ -#define SM_STEP(machine) \ -static void sm_ ## machine ## _Step(STATE_MACHINE_DATA *sm) - -/** - * SM_STEP_RUN - Call the state machine step function - * @machine: State machine name - * - * This macro expands to a function call to a state machine step function - * defined with SM_STEP macro. - */ -#define SM_STEP_RUN(machine) sm_ ## machine ## _Step(sm) - -#endif /* STATE_MACHINE_H */ diff --git a/hostapd-0.8/src/utils/trace.c b/hostapd-0.8/src/utils/trace.c deleted file mode 100644 index bb3eb24..0000000 --- a/hostapd-0.8/src/utils/trace.c +++ /dev/null @@ -1,329 +0,0 @@ -/* - * Backtrace debugging - * Copyright (c) 2009, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#include "includes.h" - -#include "common.h" -#include "trace.h" - -#ifdef WPA_TRACE - -static struct dl_list active_references = -{ &active_references, &active_references }; - -#ifdef WPA_TRACE_BFD -#include -#ifdef __linux__ -#include -#else /* __linux__ */ -#include -#endif /* __linux__ */ - -static char *prg_fname = NULL; -static bfd *cached_abfd = NULL; -static asymbol **syms = NULL; - -static void get_prg_fname(void) -{ - char exe[50], fname[512]; - int len; - os_snprintf(exe, sizeof(exe) - 1, "/proc/%u/exe", getpid()); - len = readlink(exe, fname, sizeof(fname) - 1); - if (len < 0 || len >= (int) sizeof(fname)) { - perror("readlink"); - return; - } - fname[len] = '\0'; - prg_fname = strdup(fname); -} - - -static bfd * open_bfd(const char *fname) -{ - bfd *abfd; - char **matching; - - abfd = bfd_openr(prg_fname, NULL); - if (abfd == NULL) { - wpa_printf(MSG_INFO, "bfd_openr failed"); - return NULL; - } - - if (bfd_check_format(abfd, bfd_archive)) { - wpa_printf(MSG_INFO, "bfd_check_format failed"); - bfd_close(abfd); - return NULL; - } - - if (!bfd_check_format_matches(abfd, bfd_object, &matching)) { - wpa_printf(MSG_INFO, "bfd_check_format_matches failed"); - free(matching); - bfd_close(abfd); - return NULL; - } - - return abfd; -} - - -static void read_syms(bfd *abfd) -{ - long storage, symcount; - bfd_boolean dynamic = FALSE; - - if (syms) - return; - - if (!(bfd_get_file_flags(abfd) & HAS_SYMS)) { - wpa_printf(MSG_INFO, "No symbols"); - return; - } - - storage = bfd_get_symtab_upper_bound(abfd); - if (storage == 0) { - storage = bfd_get_dynamic_symtab_upper_bound(abfd); - dynamic = TRUE; - } - if (storage < 0) { - wpa_printf(MSG_INFO, "Unknown symtab upper bound"); - return; - } - - syms = malloc(storage); - if (syms == NULL) { - wpa_printf(MSG_INFO, "Failed to allocate memory for symtab " - "(%ld bytes)", storage); - return; - } - if (dynamic) - symcount = bfd_canonicalize_dynamic_symtab(abfd, syms); - else - symcount = bfd_canonicalize_symtab(abfd, syms); - if (symcount < 0) { - wpa_printf(MSG_INFO, "Failed to canonicalize %ssymtab", - dynamic ? "dynamic " : ""); - free(syms); - syms = NULL; - return; - } -} - - -struct bfd_data { - bfd_vma pc; - bfd_boolean found; - const char *filename; - const char *function; - unsigned int line; -}; - - -static void find_addr_sect(bfd *abfd, asection *section, void *obj) -{ - struct bfd_data *data = obj; - bfd_vma vma; - bfd_size_type size; - - if (data->found) - return; - - if (!(bfd_get_section_vma(abfd, section))) - return; - - vma = bfd_get_section_vma(abfd, section); - if (data->pc < vma) - return; - - size = bfd_get_section_size(section); - if (data->pc >= vma + size) - return; - - data->found = bfd_find_nearest_line(abfd, section, syms, - data->pc - vma, - &data->filename, - &data->function, - &data->line); -} - - -static void wpa_trace_bfd_addr(void *pc) -{ - bfd *abfd = cached_abfd; - struct bfd_data data; - const char *name; - char *aname = NULL; - const char *filename; - - if (abfd == NULL) - return; - - data.pc = (bfd_vma) pc; - data.found = FALSE; - bfd_map_over_sections(abfd, find_addr_sect, &data); - - if (!data.found) - return; - - do { - if (data.function) - aname = bfd_demangle(abfd, data.function, - DMGL_ANSI | DMGL_PARAMS); - name = aname ? aname : data.function; - filename = data.filename; - if (filename) { - char *end = os_strrchr(filename, '/'); - int i = 0; - while (*filename && *filename == prg_fname[i] && - filename <= end) { - filename++; - i++; - } - } - wpa_printf(MSG_INFO, " %s() %s:%u", - name, filename, data.line); - free(aname); - - data.found = bfd_find_inliner_info(abfd, &data.filename, - &data.function, &data.line); - } while (data.found); -} - - -static const char * wpa_trace_bfd_addr2func(void *pc) -{ - bfd *abfd = cached_abfd; - struct bfd_data data; - - if (abfd == NULL) - return NULL; - - data.pc = (bfd_vma) pc; - data.found = FALSE; - bfd_map_over_sections(abfd, find_addr_sect, &data); - - if (!data.found) - return NULL; - - return data.function; -} - - -static void wpa_trace_bfd_init(void) -{ - if (!prg_fname) { - get_prg_fname(); - if (!prg_fname) - return; - } - - if (!cached_abfd) { - cached_abfd = open_bfd(prg_fname); - if (!cached_abfd) { - wpa_printf(MSG_INFO, "Failed to open bfd"); - return; - } - } - - read_syms(cached_abfd); - if (!syms) { - wpa_printf(MSG_INFO, "Failed to read symbols"); - return; - } -} - - -void wpa_trace_dump_funcname(const char *title, void *pc) -{ - wpa_printf(MSG_INFO, "WPA_TRACE: %s: %p", title, pc); - wpa_trace_bfd_init(); - wpa_trace_bfd_addr(pc); -} - -#else /* WPA_TRACE_BFD */ - -#define wpa_trace_bfd_init() do { } while (0) -#define wpa_trace_bfd_addr(pc) do { } while (0) -#define wpa_trace_bfd_addr2func(pc) NULL - -#endif /* WPA_TRACE_BFD */ - -void wpa_trace_dump_func(const char *title, void **btrace, int btrace_num) -{ - char **sym; - int i; - enum { TRACE_HEAD, TRACE_RELEVANT, TRACE_TAIL } state; - - wpa_trace_bfd_init(); - wpa_printf(MSG_INFO, "WPA_TRACE: %s - START", title); - sym = backtrace_symbols(btrace, btrace_num); - state = TRACE_HEAD; - for (i = 0; i < btrace_num; i++) { - const char *func = wpa_trace_bfd_addr2func(btrace[i]); - if (state == TRACE_HEAD && func && - (os_strcmp(func, "wpa_trace_add_ref_func") == 0 || - os_strcmp(func, "wpa_trace_check_ref") == 0 || - os_strcmp(func, "wpa_trace_show") == 0)) - continue; - if (state == TRACE_TAIL && sym && sym[i] && - os_strstr(sym[i], "__libc_start_main")) - break; - if (state == TRACE_HEAD) - state = TRACE_RELEVANT; - if (sym) - wpa_printf(MSG_INFO, "[%d]: %s", i, sym[i]); - else - wpa_printf(MSG_INFO, "[%d]: ?? [%p]", i, btrace[i]); - wpa_trace_bfd_addr(btrace[i]); - if (state == TRACE_RELEVANT && func && - os_strcmp(func, "main") == 0) - state = TRACE_TAIL; - } - free(sym); - wpa_printf(MSG_INFO, "WPA_TRACE: %s - END", title); -} - - -void wpa_trace_show(const char *title) -{ - struct info { - WPA_TRACE_INFO - } info; - wpa_trace_record(&info); - wpa_trace_dump(title, &info); -} - - -void wpa_trace_add_ref_func(struct wpa_trace_ref *ref, const void *addr) -{ - if (addr == NULL) - return; - ref->addr = addr; - wpa_trace_record(ref); - dl_list_add(&active_references, &ref->list); -} - - -void wpa_trace_check_ref(const void *addr) -{ - struct wpa_trace_ref *ref; - dl_list_for_each(ref, &active_references, struct wpa_trace_ref, list) { - if (addr != ref->addr) - continue; - wpa_trace_show("Freeing referenced memory"); - wpa_trace_dump("Reference registration", ref); - abort(); - } -} - -#endif /* WPA_TRACE */ diff --git a/hostapd-0.8/src/utils/trace.h b/hostapd-0.8/src/utils/trace.h deleted file mode 100644 index 22d3de0..0000000 --- a/hostapd-0.8/src/utils/trace.h +++ /dev/null @@ -1,74 +0,0 @@ -/* - * Backtrace debugging - * Copyright (c) 2009, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#ifndef TRACE_H -#define TRACE_H - -#define WPA_TRACE_LEN 16 - -#ifdef WPA_TRACE -#include - -#include "list.h" - -#define WPA_TRACE_INFO void *btrace[WPA_TRACE_LEN]; int btrace_num; - -struct wpa_trace_ref { - struct dl_list list; - const void *addr; - WPA_TRACE_INFO -}; -#define WPA_TRACE_REF(name) struct wpa_trace_ref wpa_trace_ref_##name - -#define wpa_trace_dump(title, ptr) \ - wpa_trace_dump_func((title), (ptr)->btrace, (ptr)->btrace_num) -void wpa_trace_dump_func(const char *title, void **btrace, int btrace_num); -#define wpa_trace_record(ptr) \ - (ptr)->btrace_num = backtrace((ptr)->btrace, WPA_TRACE_LEN) -void wpa_trace_show(const char *title); -#define wpa_trace_add_ref(ptr, name, addr) \ - wpa_trace_add_ref_func(&(ptr)->wpa_trace_ref_##name, (addr)) -void wpa_trace_add_ref_func(struct wpa_trace_ref *ref, const void *addr); -#define wpa_trace_remove_ref(ptr, name, addr) \ - do { \ - if ((addr)) \ - dl_list_del(&(ptr)->wpa_trace_ref_##name.list); \ - } while (0) -void wpa_trace_check_ref(const void *addr); - -#else /* WPA_TRACE */ - -#define WPA_TRACE_INFO -#define WPA_TRACE_REF(n) -#define wpa_trace_dump(title, ptr) do { } while (0) -#define wpa_trace_record(ptr) do { } while (0) -#define wpa_trace_show(title) do { } while (0) -#define wpa_trace_add_ref(ptr, name, addr) do { } while (0) -#define wpa_trace_remove_ref(ptr, name, addr) do { } while (0) -#define wpa_trace_check_ref(addr) do { } while (0) - -#endif /* WPA_TRACE */ - - -#ifdef WPA_TRACE_BFD - -void wpa_trace_dump_funcname(const char *title, void *pc); - -#else /* WPA_TRACE_BFD */ - -#define wpa_trace_dump_funcname(title, pc) do { } while (0) - -#endif /* WPA_TRACE_BFD */ - -#endif /* TRACE_H */ diff --git a/hostapd-0.8/src/utils/uuid.c b/hostapd-0.8/src/utils/uuid.c deleted file mode 100644 index d8cc267..0000000 --- a/hostapd-0.8/src/utils/uuid.c +++ /dev/null @@ -1,77 +0,0 @@ -/* - * Universally Unique IDentifier (UUID) - * Copyright (c) 2008, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#include "includes.h" - -#include "common.h" -#include "uuid.h" - -int uuid_str2bin(const char *str, u8 *bin) -{ - const char *pos; - u8 *opos; - - pos = str; - opos = bin; - - if (hexstr2bin(pos, opos, 4)) - return -1; - pos += 8; - opos += 4; - - if (*pos++ != '-' || hexstr2bin(pos, opos, 2)) - return -1; - pos += 4; - opos += 2; - - if (*pos++ != '-' || hexstr2bin(pos, opos, 2)) - return -1; - pos += 4; - opos += 2; - - if (*pos++ != '-' || hexstr2bin(pos, opos, 2)) - return -1; - pos += 4; - opos += 2; - - if (*pos++ != '-' || hexstr2bin(pos, opos, 6)) - return -1; - - return 0; -} - - -int uuid_bin2str(const u8 *bin, char *str, size_t max_len) -{ - int len; - len = os_snprintf(str, max_len, "%02x%02x%02x%02x-%02x%02x-%02x%02x-" - "%02x%02x-%02x%02x%02x%02x%02x%02x", - bin[0], bin[1], bin[2], bin[3], - bin[4], bin[5], bin[6], bin[7], - bin[8], bin[9], bin[10], bin[11], - bin[12], bin[13], bin[14], bin[15]); - if (len < 0 || (size_t) len >= max_len) - return -1; - return 0; -} - - -int is_nil_uuid(const u8 *uuid) -{ - int i; - for (i = 0; i < UUID_LEN; i++) - if (uuid[i]) - return 0; - return 1; -} diff --git a/hostapd-0.8/src/utils/uuid.h b/hostapd-0.8/src/utils/uuid.h deleted file mode 100644 index 0759165..0000000 --- a/hostapd-0.8/src/utils/uuid.h +++ /dev/null @@ -1,24 +0,0 @@ -/* - * Universally Unique IDentifier (UUID) - * Copyright (c) 2008, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#ifndef UUID_H -#define UUID_H - -#define UUID_LEN 16 - -int uuid_str2bin(const char *str, u8 *bin); -int uuid_bin2str(const u8 *bin, char *str, size_t max_len); -int is_nil_uuid(const u8 *uuid); - -#endif /* UUID_H */ diff --git a/hostapd-0.8/src/utils/wpa_debug.c b/hostapd-0.8/src/utils/wpa_debug.c deleted file mode 100644 index b8c5e2f..0000000 --- a/hostapd-0.8/src/utils/wpa_debug.c +++ /dev/null @@ -1,484 +0,0 @@ -/* - * wpa_supplicant/hostapd / Debug prints - * Copyright (c) 2002-2007, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#include "includes.h" - -#include "common.h" - -#ifdef CONFIG_DEBUG_SYSLOG -#include - -static int wpa_debug_syslog = 0; -#endif /* CONFIG_DEBUG_SYSLOG */ - - -int wpa_debug_level = MSG_INFO; -int wpa_debug_show_keys = 0; -int wpa_debug_timestamp = 0; - - -#ifdef CONFIG_ANDROID_LOG - -#include - -void android_printf(int level, char *format, ...) -{ - if (level >= wpa_debug_level) { - va_list ap; - if (level == MSG_ERROR) - level = ANDROID_LOG_ERROR; - else if (level == MSG_WARNING) - level = ANDROID_LOG_WARN; - else if (level == MSG_INFO) - level = ANDROID_LOG_INFO; - else - level = ANDROID_LOG_DEBUG; - va_start(ap, format); - __android_log_vprint(level, "wpa_supplicant", format, ap); - va_end(ap); - } -} - -#else /* CONFIG_ANDROID_LOG */ - -#ifndef CONFIG_NO_STDOUT_DEBUG - -#ifdef CONFIG_DEBUG_FILE -static FILE *out_file = NULL; -#endif /* CONFIG_DEBUG_FILE */ - - -void wpa_debug_print_timestamp(void) -{ - struct os_time tv; - - if (!wpa_debug_timestamp) - return; - - os_get_time(&tv); -#ifdef CONFIG_DEBUG_FILE - if (out_file) { - fprintf(out_file, "%ld.%06u: ", (long) tv.sec, - (unsigned int) tv.usec); - } else -#endif /* CONFIG_DEBUG_FILE */ - printf("%ld.%06u: ", (long) tv.sec, (unsigned int) tv.usec); -} - - -#ifdef CONFIG_DEBUG_SYSLOG -#ifndef LOG_HOSTAPD -#define LOG_HOSTAPD LOG_DAEMON -#endif /* LOG_HOSTAPD */ - -void wpa_debug_open_syslog(void) -{ - openlog("wpa_supplicant", LOG_PID | LOG_NDELAY, LOG_HOSTAPD); - wpa_debug_syslog++; -} - - -void wpa_debug_close_syslog(void) -{ - if (wpa_debug_syslog) - closelog(); -} - - -static int syslog_priority(int level) -{ - switch (level) { - case MSG_MSGDUMP: - case MSG_DEBUG: - return LOG_DEBUG; - case MSG_INFO: - return LOG_NOTICE; - case MSG_WARNING: - return LOG_WARNING; - case MSG_ERROR: - return LOG_ERR; - } - return LOG_INFO; -} -#endif /* CONFIG_DEBUG_SYSLOG */ - - -/** - * wpa_printf - conditional printf - * @level: priority level (MSG_*) of the message - * @fmt: printf format string, followed by optional arguments - * - * This function is used to print conditional debugging and error messages. The - * output may be directed to stdout, stderr, and/or syslog based on - * configuration. - * - * Note: New line '\n' is added to the end of the text when printing to stdout. - */ -void wpa_printf(int level, const char *fmt, ...) -{ - va_list ap; - - va_start(ap, fmt); - if (level >= wpa_debug_level) { -#ifdef CONFIG_DEBUG_SYSLOG - if (wpa_debug_syslog) { - vsyslog(syslog_priority(level), fmt, ap); - } else { -#endif /* CONFIG_DEBUG_SYSLOG */ - wpa_debug_print_timestamp(); -#ifdef CONFIG_DEBUG_FILE - if (out_file) { - vfprintf(out_file, fmt, ap); - fprintf(out_file, "\n"); - } else { -#endif /* CONFIG_DEBUG_FILE */ - vprintf(fmt, ap); - printf("\n"); -#ifdef CONFIG_DEBUG_FILE - } -#endif /* CONFIG_DEBUG_FILE */ -#ifdef CONFIG_DEBUG_SYSLOG - } -#endif /* CONFIG_DEBUG_SYSLOG */ - } - va_end(ap); -} - - -static void _wpa_hexdump(int level, const char *title, const u8 *buf, - size_t len, int show) -{ - size_t i; - if (level < wpa_debug_level) - return; - wpa_debug_print_timestamp(); -#ifdef CONFIG_DEBUG_FILE - if (out_file) { - fprintf(out_file, "%s - hexdump(len=%lu):", - title, (unsigned long) len); - if (buf == NULL) { - fprintf(out_file, " [NULL]"); - } else if (show) { - for (i = 0; i < len; i++) - fprintf(out_file, " %02x", buf[i]); - } else { - fprintf(out_file, " [REMOVED]"); - } - fprintf(out_file, "\n"); - } else { -#endif /* CONFIG_DEBUG_FILE */ - printf("%s - hexdump(len=%lu):", title, (unsigned long) len); - if (buf == NULL) { - printf(" [NULL]"); - } else if (show) { - for (i = 0; i < len; i++) - printf(" %02x", buf[i]); - } else { - printf(" [REMOVED]"); - } - printf("\n"); -#ifdef CONFIG_DEBUG_FILE - } -#endif /* CONFIG_DEBUG_FILE */ -} - -void wpa_hexdump(int level, const char *title, const u8 *buf, size_t len) -{ - _wpa_hexdump(level, title, buf, len, 1); -} - - -void wpa_hexdump_key(int level, const char *title, const u8 *buf, size_t len) -{ - _wpa_hexdump(level, title, buf, len, wpa_debug_show_keys); -} - - -static void _wpa_hexdump_ascii(int level, const char *title, const u8 *buf, - size_t len, int show) -{ - size_t i, llen; - const u8 *pos = buf; - const size_t line_len = 16; - - if (level < wpa_debug_level) - return; - wpa_debug_print_timestamp(); -#ifdef CONFIG_DEBUG_FILE - if (out_file) { - if (!show) { - fprintf(out_file, - "%s - hexdump_ascii(len=%lu): [REMOVED]\n", - title, (unsigned long) len); - return; - } - if (buf == NULL) { - fprintf(out_file, - "%s - hexdump_ascii(len=%lu): [NULL]\n", - title, (unsigned long) len); - return; - } - fprintf(out_file, "%s - hexdump_ascii(len=%lu):\n", - title, (unsigned long) len); - while (len) { - llen = len > line_len ? line_len : len; - fprintf(out_file, " "); - for (i = 0; i < llen; i++) - fprintf(out_file, " %02x", pos[i]); - for (i = llen; i < line_len; i++) - fprintf(out_file, " "); - fprintf(out_file, " "); - for (i = 0; i < llen; i++) { - if (isprint(pos[i])) - fprintf(out_file, "%c", pos[i]); - else - fprintf(out_file, "_"); - } - for (i = llen; i < line_len; i++) - fprintf(out_file, " "); - fprintf(out_file, "\n"); - pos += llen; - len -= llen; - } - } else { -#endif /* CONFIG_DEBUG_FILE */ - if (!show) { - printf("%s - hexdump_ascii(len=%lu): [REMOVED]\n", - title, (unsigned long) len); - return; - } - if (buf == NULL) { - printf("%s - hexdump_ascii(len=%lu): [NULL]\n", - title, (unsigned long) len); - return; - } - printf("%s - hexdump_ascii(len=%lu):\n", title, (unsigned long) len); - while (len) { - llen = len > line_len ? line_len : len; - printf(" "); - for (i = 0; i < llen; i++) - printf(" %02x", pos[i]); - for (i = llen; i < line_len; i++) - printf(" "); - printf(" "); - for (i = 0; i < llen; i++) { - if (isprint(pos[i])) - printf("%c", pos[i]); - else - printf("_"); - } - for (i = llen; i < line_len; i++) - printf(" "); - printf("\n"); - pos += llen; - len -= llen; - } -#ifdef CONFIG_DEBUG_FILE - } -#endif /* CONFIG_DEBUG_FILE */ -} - - -void wpa_hexdump_ascii(int level, const char *title, const u8 *buf, size_t len) -{ - _wpa_hexdump_ascii(level, title, buf, len, 1); -} - - -void wpa_hexdump_ascii_key(int level, const char *title, const u8 *buf, - size_t len) -{ - _wpa_hexdump_ascii(level, title, buf, len, wpa_debug_show_keys); -} - - -#ifdef CONFIG_DEBUG_FILE -static char *last_path = NULL; -#endif /* CONFIG_DEBUG_FILE */ - -int wpa_debug_reopen_file(void) -{ -#ifdef CONFIG_DEBUG_FILE - int rv; - if (last_path) { - char *tmp = os_strdup(last_path); - wpa_debug_close_file(); - rv = wpa_debug_open_file(tmp); - os_free(tmp); - } else { - wpa_printf(MSG_ERROR, "Last-path was not set, cannot " - "re-open log file."); - rv = -1; - } - return rv; -#else /* CONFIG_DEBUG_FILE */ - return 0; -#endif /* CONFIG_DEBUG_FILE */ -} - - -int wpa_debug_open_file(const char *path) -{ -#ifdef CONFIG_DEBUG_FILE - if (!path) - return 0; - - if (last_path == NULL || os_strcmp(last_path, path) != 0) { - /* Save our path to enable re-open */ - os_free(last_path); - last_path = os_strdup(path); - } - - out_file = fopen(path, "a"); - if (out_file == NULL) { - wpa_printf(MSG_ERROR, "wpa_debug_open_file: Failed to open " - "output file, using standard output"); - return -1; - } -#ifndef _WIN32 - setvbuf(out_file, NULL, _IOLBF, 0); -#endif /* _WIN32 */ -#endif /* CONFIG_DEBUG_FILE */ - return 0; -} - - -void wpa_debug_close_file(void) -{ -#ifdef CONFIG_DEBUG_FILE - if (!out_file) - return; - fclose(out_file); - out_file = NULL; - os_free(last_path); - last_path = NULL; -#endif /* CONFIG_DEBUG_FILE */ -} - -#endif /* CONFIG_NO_STDOUT_DEBUG */ - -#endif /* CONFIG_ANDROID_LOG */ - -#ifndef CONFIG_NO_WPA_MSG -static wpa_msg_cb_func wpa_msg_cb = NULL; - -void wpa_msg_register_cb(wpa_msg_cb_func func) -{ - wpa_msg_cb = func; -} - - -static wpa_msg_get_ifname_func wpa_msg_ifname_cb = NULL; - -void wpa_msg_register_ifname_cb(wpa_msg_get_ifname_func func) -{ - wpa_msg_ifname_cb = func; -} - - -void wpa_msg(void *ctx, int level, const char *fmt, ...) -{ - va_list ap; - char *buf; - const int buflen = 2048; - int len; - char prefix[130]; - - buf = os_malloc(buflen); - if (buf == NULL) { - wpa_printf(MSG_ERROR, "wpa_msg: Failed to allocate message " - "buffer"); - return; - } - va_start(ap, fmt); - prefix[0] = '\0'; - if (wpa_msg_ifname_cb) { - const char *ifname = wpa_msg_ifname_cb(ctx); - if (ifname) { - int res = os_snprintf(prefix, sizeof(prefix), "%s: ", - ifname); - if (res < 0 || res >= (int) sizeof(prefix)) - prefix[0] = '\0'; - } - } - len = vsnprintf(buf, buflen, fmt, ap); - va_end(ap); - wpa_printf(level, "%s%s", prefix, buf); - if (wpa_msg_cb) - wpa_msg_cb(ctx, level, buf, len); - os_free(buf); -} - - -void wpa_msg_ctrl(void *ctx, int level, const char *fmt, ...) -{ - va_list ap; - char *buf; - const int buflen = 2048; - int len; - - if (!wpa_msg_cb) - return; - - buf = os_malloc(buflen); - if (buf == NULL) { - wpa_printf(MSG_ERROR, "wpa_msg_ctrl: Failed to allocate " - "message buffer"); - return; - } - va_start(ap, fmt); - len = vsnprintf(buf, buflen, fmt, ap); - va_end(ap); - wpa_msg_cb(ctx, level, buf, len); - os_free(buf); -} -#endif /* CONFIG_NO_WPA_MSG */ - - -#ifndef CONFIG_NO_HOSTAPD_LOGGER -static hostapd_logger_cb_func hostapd_logger_cb = NULL; - -void hostapd_logger_register_cb(hostapd_logger_cb_func func) -{ - hostapd_logger_cb = func; -} - - -void hostapd_logger(void *ctx, const u8 *addr, unsigned int module, int level, - const char *fmt, ...) -{ - va_list ap; - char *buf; - const int buflen = 2048; - int len; - - buf = os_malloc(buflen); - if (buf == NULL) { - wpa_printf(MSG_ERROR, "hostapd_logger: Failed to allocate " - "message buffer"); - return; - } - va_start(ap, fmt); - len = vsnprintf(buf, buflen, fmt, ap); - va_end(ap); - if (hostapd_logger_cb) - hostapd_logger_cb(ctx, addr, module, level, buf, len); - else if (addr) - wpa_printf(MSG_DEBUG, "hostapd_logger: STA " MACSTR " - %s", - MAC2STR(addr), buf); - else - wpa_printf(MSG_DEBUG, "hostapd_logger: %s", buf); - os_free(buf); -} -#endif /* CONFIG_NO_HOSTAPD_LOGGER */ diff --git a/hostapd-0.8/src/utils/wpa_debug.h b/hostapd-0.8/src/utils/wpa_debug.h deleted file mode 100644 index ae36afe..0000000 --- a/hostapd-0.8/src/utils/wpa_debug.h +++ /dev/null @@ -1,307 +0,0 @@ -/* - * wpa_supplicant/hostapd / Debug prints - * Copyright (c) 2002-2007, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#ifndef WPA_DEBUG_H -#define WPA_DEBUG_H - -#include "wpabuf.h" - -/* Debugging function - conditional printf and hex dump. Driver wrappers can - * use these for debugging purposes. */ - -enum { - MSG_EXCESSIVE, MSG_MSGDUMP, MSG_DEBUG, MSG_INFO, MSG_WARNING, MSG_ERROR -}; - -#ifdef CONFIG_ANDROID_LOG - -#define wpa_debug_print_timestamp() do {} while (0) -#define wpa_hexdump(...) do {} while (0) -#define wpa_hexdump_key(...) do {} while (0) -#define wpa_hexdump_buf(l,t,b) do {} while (0) -#define wpa_hexdump_buf_key(l,t,b) do {} while (0) -#define wpa_hexdump_ascii(...) do {} while (0) -#define wpa_hexdump_ascii_key(...) do {} while (0) -#define wpa_debug_open_file(...) do {} while (0) -#define wpa_debug_close_file() do {} while (0) -#define wpa_dbg(...) do {} while (0) - -static inline int wpa_debug_reopen_file(void) -{ - return 0; -} - - -void android_printf(int level, char *format, ...) -PRINTF_FORMAT(2, 3); - -#define wpa_printf android_printf - -#else /* CONFIG_ANDROID_LOG */ - -#ifdef CONFIG_NO_STDOUT_DEBUG - -#define wpa_debug_print_timestamp() do { } while (0) -#define wpa_printf(args...) do { } while (0) -#define wpa_hexdump(l,t,b,le) do { } while (0) -#define wpa_hexdump_buf(l,t,b) do { } while (0) -#define wpa_hexdump_key(l,t,b,le) do { } while (0) -#define wpa_hexdump_buf_key(l,t,b) do { } while (0) -#define wpa_hexdump_ascii(l,t,b,le) do { } while (0) -#define wpa_hexdump_ascii_key(l,t,b,le) do { } while (0) -#define wpa_debug_open_file(p) do { } while (0) -#define wpa_debug_close_file() do { } while (0) -#define wpa_dbg(args...) do { } while (0) - -static inline int wpa_debug_reopen_file(void) -{ - return 0; -} - -#else /* CONFIG_NO_STDOUT_DEBUG */ - -int wpa_debug_open_file(const char *path); -int wpa_debug_reopen_file(void); -void wpa_debug_close_file(void); - -/** - * wpa_debug_printf_timestamp - Print timestamp for debug output - * - * This function prints a timestamp in seconds_from_1970.microsoconds - * format if debug output has been configured to include timestamps in debug - * messages. - */ -void wpa_debug_print_timestamp(void); - -/** - * wpa_printf - conditional printf - * @level: priority level (MSG_*) of the message - * @fmt: printf format string, followed by optional arguments - * - * This function is used to print conditional debugging and error messages. The - * output may be directed to stdout, stderr, and/or syslog based on - * configuration. - * - * Note: New line '\n' is added to the end of the text when printing to stdout. - */ -void wpa_printf(int level, const char *fmt, ...) -PRINTF_FORMAT(2, 3); - -/** - * wpa_hexdump - conditional hex dump - * @level: priority level (MSG_*) of the message - * @title: title of for the message - * @buf: data buffer to be dumped - * @len: length of the buf - * - * This function is used to print conditional debugging and error messages. The - * output may be directed to stdout, stderr, and/or syslog based on - * configuration. The contents of buf is printed out has hex dump. - */ -void wpa_hexdump(int level, const char *title, const u8 *buf, size_t len); - -static inline void wpa_hexdump_buf(int level, const char *title, - const struct wpabuf *buf) -{ - wpa_hexdump(level, title, buf ? wpabuf_head(buf) : NULL, - buf ? wpabuf_len(buf) : 0); -} - -/** - * wpa_hexdump_key - conditional hex dump, hide keys - * @level: priority level (MSG_*) of the message - * @title: title of for the message - * @buf: data buffer to be dumped - * @len: length of the buf - * - * This function is used to print conditional debugging and error messages. The - * output may be directed to stdout, stderr, and/or syslog based on - * configuration. The contents of buf is printed out has hex dump. This works - * like wpa_hexdump(), but by default, does not include secret keys (passwords, - * etc.) in debug output. - */ -void wpa_hexdump_key(int level, const char *title, const u8 *buf, size_t len); - -static inline void wpa_hexdump_buf_key(int level, const char *title, - const struct wpabuf *buf) -{ - wpa_hexdump_key(level, title, buf ? wpabuf_head(buf) : 0, - buf ? wpabuf_len(buf) : 0); -} - -/** - * wpa_hexdump_ascii - conditional hex dump - * @level: priority level (MSG_*) of the message - * @title: title of for the message - * @buf: data buffer to be dumped - * @len: length of the buf - * - * This function is used to print conditional debugging and error messages. The - * output may be directed to stdout, stderr, and/or syslog based on - * configuration. The contents of buf is printed out has hex dump with both - * the hex numbers and ASCII characters (for printable range) are shown. 16 - * bytes per line will be shown. - */ -void wpa_hexdump_ascii(int level, const char *title, const u8 *buf, - size_t len); - -/** - * wpa_hexdump_ascii_key - conditional hex dump, hide keys - * @level: priority level (MSG_*) of the message - * @title: title of for the message - * @buf: data buffer to be dumped - * @len: length of the buf - * - * This function is used to print conditional debugging and error messages. The - * output may be directed to stdout, stderr, and/or syslog based on - * configuration. The contents of buf is printed out has hex dump with both - * the hex numbers and ASCII characters (for printable range) are shown. 16 - * bytes per line will be shown. This works like wpa_hexdump_ascii(), but by - * default, does not include secret keys (passwords, etc.) in debug output. - */ -void wpa_hexdump_ascii_key(int level, const char *title, const u8 *buf, - size_t len); - -/* - * wpa_dbg() behaves like wpa_msg(), but it can be removed from build to reduce - * binary size. As such, it should be used with debugging messages that are not - * needed in the control interface while wpa_msg() has to be used for anything - * that needs to shown to control interface monitors. - */ -#define wpa_dbg(args...) wpa_msg(args) - -#endif /* CONFIG_NO_STDOUT_DEBUG */ - -#endif /* CONFIG_ANDROID_LOG */ - - -#ifdef CONFIG_NO_WPA_MSG -#define wpa_msg(args...) do { } while (0) -#define wpa_msg_ctrl(args...) do { } while (0) -#define wpa_msg_register_cb(f) do { } while (0) -#define wpa_msg_register_ifname_cb(f) do { } while (0) -#else /* CONFIG_NO_WPA_MSG */ -/** - * wpa_msg - Conditional printf for default target and ctrl_iface monitors - * @ctx: Pointer to context data; this is the ctx variable registered - * with struct wpa_driver_ops::init() - * @level: priority level (MSG_*) of the message - * @fmt: printf format string, followed by optional arguments - * - * This function is used to print conditional debugging and error messages. The - * output may be directed to stdout, stderr, and/or syslog based on - * configuration. This function is like wpa_printf(), but it also sends the - * same message to all attached ctrl_iface monitors. - * - * Note: New line '\n' is added to the end of the text when printing to stdout. - */ -void wpa_msg(void *ctx, int level, const char *fmt, ...) PRINTF_FORMAT(3, 4); - -/** - * wpa_msg_ctrl - Conditional printf for ctrl_iface monitors - * @ctx: Pointer to context data; this is the ctx variable registered - * with struct wpa_driver_ops::init() - * @level: priority level (MSG_*) of the message - * @fmt: printf format string, followed by optional arguments - * - * This function is used to print conditional debugging and error messages. - * This function is like wpa_msg(), but it sends the output only to the - * attached ctrl_iface monitors. In other words, it can be used for frequent - * events that do not need to be sent to syslog. - */ -void wpa_msg_ctrl(void *ctx, int level, const char *fmt, ...) -PRINTF_FORMAT(3, 4); - -typedef void (*wpa_msg_cb_func)(void *ctx, int level, const char *txt, - size_t len); - -/** - * wpa_msg_register_cb - Register callback function for wpa_msg() messages - * @func: Callback function (%NULL to unregister) - */ -void wpa_msg_register_cb(wpa_msg_cb_func func); - -typedef const char * (*wpa_msg_get_ifname_func)(void *ctx); -void wpa_msg_register_ifname_cb(wpa_msg_get_ifname_func func); - -#endif /* CONFIG_NO_WPA_MSG */ - -#ifdef CONFIG_NO_HOSTAPD_LOGGER -#define hostapd_logger(args...) do { } while (0) -#define hostapd_logger_register_cb(f) do { } while (0) -#else /* CONFIG_NO_HOSTAPD_LOGGER */ -void hostapd_logger(void *ctx, const u8 *addr, unsigned int module, int level, - const char *fmt, ...) PRINTF_FORMAT(5, 6); - -typedef void (*hostapd_logger_cb_func)(void *ctx, const u8 *addr, - unsigned int module, int level, - const char *txt, size_t len); - -/** - * hostapd_logger_register_cb - Register callback function for hostapd_logger() - * @func: Callback function (%NULL to unregister) - */ -void hostapd_logger_register_cb(hostapd_logger_cb_func func); -#endif /* CONFIG_NO_HOSTAPD_LOGGER */ - -#define HOSTAPD_MODULE_IEEE80211 0x00000001 -#define HOSTAPD_MODULE_IEEE8021X 0x00000002 -#define HOSTAPD_MODULE_RADIUS 0x00000004 -#define HOSTAPD_MODULE_WPA 0x00000008 -#define HOSTAPD_MODULE_DRIVER 0x00000010 -#define HOSTAPD_MODULE_IAPP 0x00000020 -#define HOSTAPD_MODULE_MLME 0x00000040 - -enum hostapd_logger_level { - HOSTAPD_LEVEL_DEBUG_VERBOSE = 0, - HOSTAPD_LEVEL_DEBUG = 1, - HOSTAPD_LEVEL_INFO = 2, - HOSTAPD_LEVEL_NOTICE = 3, - HOSTAPD_LEVEL_WARNING = 4 -}; - - -#ifdef CONFIG_DEBUG_SYSLOG - -void wpa_debug_open_syslog(void); -void wpa_debug_close_syslog(void); - -#else /* CONFIG_DEBUG_SYSLOG */ - -static inline void wpa_debug_open_syslog(void) -{ -} - -static inline void wpa_debug_close_syslog(void) -{ -} - -#endif /* CONFIG_DEBUG_SYSLOG */ - - -#ifdef EAPOL_TEST -#define WPA_ASSERT(a) \ - do { \ - if (!(a)) { \ - printf("WPA_ASSERT FAILED '" #a "' " \ - "%s %s:%d\n", \ - __FUNCTION__, __FILE__, __LINE__); \ - exit(1); \ - } \ - } while (0) -#else -#define WPA_ASSERT(a) do { } while (0) -#endif - -#endif /* WPA_DEBUG_H */ diff --git a/hostapd-0.8/src/utils/wpabuf.c b/hostapd-0.8/src/utils/wpabuf.c deleted file mode 100644 index eda779e..0000000 --- a/hostapd-0.8/src/utils/wpabuf.c +++ /dev/null @@ -1,304 +0,0 @@ -/* - * Dynamic data buffer - * Copyright (c) 2007-2009, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#include "includes.h" - -#include "common.h" -#include "trace.h" -#include "wpabuf.h" - -#ifdef WPA_TRACE -#define WPABUF_MAGIC 0x51a974e3 - -struct wpabuf_trace { - unsigned int magic; -}; - -static struct wpabuf_trace * wpabuf_get_trace(const struct wpabuf *buf) -{ - return (struct wpabuf_trace *) - ((const u8 *) buf - sizeof(struct wpabuf_trace)); -} -#endif /* WPA_TRACE */ - - -static void wpabuf_overflow(const struct wpabuf *buf, size_t len) -{ -#ifdef WPA_TRACE - struct wpabuf_trace *trace = wpabuf_get_trace(buf); - if (trace->magic != WPABUF_MAGIC) { - wpa_printf(MSG_ERROR, "wpabuf: invalid magic %x", - trace->magic); - } -#endif /* WPA_TRACE */ - wpa_printf(MSG_ERROR, "wpabuf %p (size=%lu used=%lu) overflow len=%lu", - buf, (unsigned long) buf->size, (unsigned long) buf->used, - (unsigned long) len); - wpa_trace_show("wpabuf overflow"); - abort(); -} - - -int wpabuf_resize(struct wpabuf **_buf, size_t add_len) -{ - struct wpabuf *buf = *_buf; -#ifdef WPA_TRACE - struct wpabuf_trace *trace; -#endif /* WPA_TRACE */ - - if (buf == NULL) { - *_buf = wpabuf_alloc(add_len); - return *_buf == NULL ? -1 : 0; - } - -#ifdef WPA_TRACE - trace = wpabuf_get_trace(buf); - if (trace->magic != WPABUF_MAGIC) { - wpa_printf(MSG_ERROR, "wpabuf: invalid magic %x", - trace->magic); - wpa_trace_show("wpabuf_resize invalid magic"); - abort(); - } -#endif /* WPA_TRACE */ - - if (buf->used + add_len > buf->size) { - unsigned char *nbuf; - if (buf->ext_data) { - nbuf = os_realloc(buf->ext_data, buf->used + add_len); - if (nbuf == NULL) - return -1; - os_memset(nbuf + buf->used, 0, add_len); - buf->ext_data = nbuf; - } else { -#ifdef WPA_TRACE - nbuf = os_realloc(trace, sizeof(struct wpabuf_trace) + - sizeof(struct wpabuf) + - buf->used + add_len); - if (nbuf == NULL) - return -1; - trace = (struct wpabuf_trace *) nbuf; - buf = (struct wpabuf *) (trace + 1); - os_memset(nbuf + sizeof(struct wpabuf_trace) + - sizeof(struct wpabuf) + buf->used, 0, - add_len); -#else /* WPA_TRACE */ - nbuf = os_realloc(buf, sizeof(struct wpabuf) + - buf->used + add_len); - if (nbuf == NULL) - return -1; - buf = (struct wpabuf *) nbuf; - os_memset(nbuf + sizeof(struct wpabuf) + buf->used, 0, - add_len); -#endif /* WPA_TRACE */ - *_buf = buf; - } - buf->size = buf->used + add_len; - } - - return 0; -} - - -/** - * wpabuf_alloc - Allocate a wpabuf of the given size - * @len: Length for the allocated buffer - * Returns: Buffer to the allocated wpabuf or %NULL on failure - */ -struct wpabuf * wpabuf_alloc(size_t len) -{ -#ifdef WPA_TRACE - struct wpabuf_trace *trace = os_zalloc(sizeof(struct wpabuf_trace) + - sizeof(struct wpabuf) + len); - struct wpabuf *buf; - if (trace == NULL) - return NULL; - trace->magic = WPABUF_MAGIC; - buf = (struct wpabuf *) (trace + 1); -#else /* WPA_TRACE */ - struct wpabuf *buf = os_zalloc(sizeof(struct wpabuf) + len); - if (buf == NULL) - return NULL; -#endif /* WPA_TRACE */ - - buf->size = len; - return buf; -} - - -struct wpabuf * wpabuf_alloc_ext_data(u8 *data, size_t len) -{ -#ifdef WPA_TRACE - struct wpabuf_trace *trace = os_zalloc(sizeof(struct wpabuf_trace) + - sizeof(struct wpabuf)); - struct wpabuf *buf; - if (trace == NULL) - return NULL; - trace->magic = WPABUF_MAGIC; - buf = (struct wpabuf *) (trace + 1); -#else /* WPA_TRACE */ - struct wpabuf *buf = os_zalloc(sizeof(struct wpabuf)); - if (buf == NULL) - return NULL; -#endif /* WPA_TRACE */ - - buf->size = len; - buf->used = len; - buf->ext_data = data; - - return buf; -} - - -struct wpabuf * wpabuf_alloc_copy(const void *data, size_t len) -{ - struct wpabuf *buf = wpabuf_alloc(len); - if (buf) - wpabuf_put_data(buf, data, len); - return buf; -} - - -struct wpabuf * wpabuf_dup(const struct wpabuf *src) -{ - struct wpabuf *buf = wpabuf_alloc(wpabuf_len(src)); - if (buf) - wpabuf_put_data(buf, wpabuf_head(src), wpabuf_len(src)); - return buf; -} - - -/** - * wpabuf_free - Free a wpabuf - * @buf: wpabuf buffer - */ -void wpabuf_free(struct wpabuf *buf) -{ -#ifdef WPA_TRACE - struct wpabuf_trace *trace; - if (buf == NULL) - return; - trace = wpabuf_get_trace(buf); - if (trace->magic != WPABUF_MAGIC) { - wpa_printf(MSG_ERROR, "wpabuf_free: invalid magic %x", - trace->magic); - wpa_trace_show("wpabuf_free magic mismatch"); - abort(); - } - os_free(buf->ext_data); - os_free(trace); -#else /* WPA_TRACE */ - if (buf == NULL) - return; - os_free(buf->ext_data); - os_free(buf); -#endif /* WPA_TRACE */ -} - - -void * wpabuf_put(struct wpabuf *buf, size_t len) -{ - void *tmp = wpabuf_mhead_u8(buf) + wpabuf_len(buf); - buf->used += len; - if (buf->used > buf->size) { - wpabuf_overflow(buf, len); - } - return tmp; -} - - -/** - * wpabuf_concat - Concatenate two buffers into a newly allocated one - * @a: First buffer - * @b: Second buffer - * Returns: wpabuf with concatenated a + b data or %NULL on failure - * - * Both buffers a and b will be freed regardless of the return value. Input - * buffers can be %NULL which is interpreted as an empty buffer. - */ -struct wpabuf * wpabuf_concat(struct wpabuf *a, struct wpabuf *b) -{ - struct wpabuf *n = NULL; - size_t len = 0; - - if (b == NULL) - return a; - - if (a) - len += wpabuf_len(a); - if (b) - len += wpabuf_len(b); - - n = wpabuf_alloc(len); - if (n) { - if (a) - wpabuf_put_buf(n, a); - if (b) - wpabuf_put_buf(n, b); - } - - wpabuf_free(a); - wpabuf_free(b); - - return n; -} - - -/** - * wpabuf_zeropad - Pad buffer with 0x00 octets (prefix) to specified length - * @buf: Buffer to be padded - * @len: Length for the padded buffer - * Returns: wpabuf padded to len octets or %NULL on failure - * - * If buf is longer than len octets or of same size, it will be returned as-is. - * Otherwise a new buffer is allocated and prefixed with 0x00 octets followed - * by the source data. The source buffer will be freed on error, i.e., caller - * will only be responsible on freeing the returned buffer. If buf is %NULL, - * %NULL will be returned. - */ -struct wpabuf * wpabuf_zeropad(struct wpabuf *buf, size_t len) -{ - struct wpabuf *ret; - size_t blen; - - if (buf == NULL) - return NULL; - - blen = wpabuf_len(buf); - if (blen >= len) - return buf; - - ret = wpabuf_alloc(len); - if (ret) { - os_memset(wpabuf_put(ret, len - blen), 0, len - blen); - wpabuf_put_buf(ret, buf); - } - wpabuf_free(buf); - - return ret; -} - - -void wpabuf_printf(struct wpabuf *buf, char *fmt, ...) -{ - va_list ap; - void *tmp = wpabuf_mhead_u8(buf) + wpabuf_len(buf); - int res; - - va_start(ap, fmt); - res = vsnprintf(tmp, buf->size - buf->used, fmt, ap); - va_end(ap); - if (res < 0 || (size_t) res >= buf->size - buf->used) - wpabuf_overflow(buf, res); - buf->used += res; -} diff --git a/hostapd-0.8/src/utils/wpabuf.h b/hostapd-0.8/src/utils/wpabuf.h deleted file mode 100644 index cccfcc8..0000000 --- a/hostapd-0.8/src/utils/wpabuf.h +++ /dev/null @@ -1,168 +0,0 @@ -/* - * Dynamic data buffer - * Copyright (c) 2007-2009, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#ifndef WPABUF_H -#define WPABUF_H - -/* - * Internal data structure for wpabuf. Please do not touch this directly from - * elsewhere. This is only defined in header file to allow inline functions - * from this file to access data. - */ -struct wpabuf { - size_t size; /* total size of the allocated buffer */ - size_t used; /* length of data in the buffer */ - u8 *ext_data; /* pointer to external data; NULL if data follows - * struct wpabuf */ - /* optionally followed by the allocated buffer */ -}; - - -int wpabuf_resize(struct wpabuf **buf, size_t add_len); -struct wpabuf * wpabuf_alloc(size_t len); -struct wpabuf * wpabuf_alloc_ext_data(u8 *data, size_t len); -struct wpabuf * wpabuf_alloc_copy(const void *data, size_t len); -struct wpabuf * wpabuf_dup(const struct wpabuf *src); -void wpabuf_free(struct wpabuf *buf); -void * wpabuf_put(struct wpabuf *buf, size_t len); -struct wpabuf * wpabuf_concat(struct wpabuf *a, struct wpabuf *b); -struct wpabuf * wpabuf_zeropad(struct wpabuf *buf, size_t len); -void wpabuf_printf(struct wpabuf *buf, char *fmt, ...) PRINTF_FORMAT(2, 3); - - -/** - * wpabuf_size - Get the currently allocated size of a wpabuf buffer - * @buf: wpabuf buffer - * Returns: Currently allocated size of the buffer - */ -static inline size_t wpabuf_size(const struct wpabuf *buf) -{ - return buf->size; -} - -/** - * wpabuf_len - Get the current length of a wpabuf buffer data - * @buf: wpabuf buffer - * Returns: Currently used length of the buffer - */ -static inline size_t wpabuf_len(const struct wpabuf *buf) -{ - return buf->used; -} - -/** - * wpabuf_tailroom - Get size of available tail room in the end of the buffer - * @buf: wpabuf buffer - * Returns: Tail room (in bytes) of available space in the end of the buffer - */ -static inline size_t wpabuf_tailroom(const struct wpabuf *buf) -{ - return buf->size - buf->used; -} - -/** - * wpabuf_head - Get pointer to the head of the buffer data - * @buf: wpabuf buffer - * Returns: Pointer to the head of the buffer data - */ -static inline const void * wpabuf_head(const struct wpabuf *buf) -{ - if (buf->ext_data) - return buf->ext_data; - return buf + 1; -} - -static inline const u8 * wpabuf_head_u8(const struct wpabuf *buf) -{ - return wpabuf_head(buf); -} - -/** - * wpabuf_mhead - Get modifiable pointer to the head of the buffer data - * @buf: wpabuf buffer - * Returns: Pointer to the head of the buffer data - */ -static inline void * wpabuf_mhead(struct wpabuf *buf) -{ - if (buf->ext_data) - return buf->ext_data; - return buf + 1; -} - -static inline u8 * wpabuf_mhead_u8(struct wpabuf *buf) -{ - return wpabuf_mhead(buf); -} - -static inline void wpabuf_put_u8(struct wpabuf *buf, u8 data) -{ - u8 *pos = wpabuf_put(buf, 1); - *pos = data; -} - -static inline void wpabuf_put_le16(struct wpabuf *buf, u16 data) -{ - u8 *pos = wpabuf_put(buf, 2); - WPA_PUT_LE16(pos, data); -} - -static inline void wpabuf_put_le32(struct wpabuf *buf, u32 data) -{ - u8 *pos = wpabuf_put(buf, 4); - WPA_PUT_LE32(pos, data); -} - -static inline void wpabuf_put_be16(struct wpabuf *buf, u16 data) -{ - u8 *pos = wpabuf_put(buf, 2); - WPA_PUT_BE16(pos, data); -} - -static inline void wpabuf_put_be24(struct wpabuf *buf, u32 data) -{ - u8 *pos = wpabuf_put(buf, 3); - WPA_PUT_BE24(pos, data); -} - -static inline void wpabuf_put_be32(struct wpabuf *buf, u32 data) -{ - u8 *pos = wpabuf_put(buf, 4); - WPA_PUT_BE32(pos, data); -} - -static inline void wpabuf_put_data(struct wpabuf *buf, const void *data, - size_t len) -{ - if (data) - os_memcpy(wpabuf_put(buf, len), data, len); -} - -static inline void wpabuf_put_buf(struct wpabuf *dst, - const struct wpabuf *src) -{ - wpabuf_put_data(dst, wpabuf_head(src), wpabuf_len(src)); -} - -static inline void wpabuf_set(struct wpabuf *buf, const void *data, size_t len) -{ - buf->ext_data = (u8 *) data; - buf->size = buf->used = len; -} - -static inline void wpabuf_put_str(struct wpabuf *dst, const char *str) -{ - wpabuf_put_data(dst, str, os_strlen(str)); -} - -#endif /* WPABUF_H */ diff --git a/hostapd-0.8/src/wps/Makefile b/hostapd-0.8/src/wps/Makefile deleted file mode 100644 index 9c41962..0000000 --- a/hostapd-0.8/src/wps/Makefile +++ /dev/null @@ -1,8 +0,0 @@ -all: - @echo Nothing to be made. - -clean: - rm -f *~ *.o *.d - -install: - @echo Nothing to be made. diff --git a/hostapd-0.8/src/wps/http.h b/hostapd-0.8/src/wps/http.h deleted file mode 100644 index 2fee3a8..0000000 --- a/hostapd-0.8/src/wps/http.h +++ /dev/null @@ -1,29 +0,0 @@ -/* - * HTTP for WPS - * Copyright (c) 2000-2003 Intel Corporation - * Copyright (c) 2006-2007 Sony Corporation - * Copyright (c) 2008-2009 Atheros Communications - * Copyright (c) 2009, Jouni Malinen - * - * See wps_upnp.c for more details on licensing and code history. - */ - -#ifndef HTTP_H -#define HTTP_H - -enum http_reply_code { - HTTP_OK = 200, - HTTP_BAD_REQUEST = 400, - UPNP_INVALID_ACTION = 401, - UPNP_INVALID_ARGS = 402, - HTTP_NOT_FOUND = 404, - HTTP_PRECONDITION_FAILED = 412, - HTTP_INTERNAL_SERVER_ERROR = 500, - HTTP_UNIMPLEMENTED = 501, - UPNP_ACTION_FAILED = 501, - UPNP_ARG_VALUE_INVALID = 600, - UPNP_ARG_VALUE_OUT_OF_RANGE = 601, - UPNP_OUT_OF_MEMORY = 603 -}; - -#endif /* HTTP_H */ diff --git a/hostapd-0.8/src/wps/http_client.c b/hostapd-0.8/src/wps/http_client.c deleted file mode 100644 index 9b53b80..0000000 --- a/hostapd-0.8/src/wps/http_client.c +++ /dev/null @@ -1,374 +0,0 @@ -/* - * http_client - HTTP client - * Copyright (c) 2009, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#include "includes.h" -#include - -#include "common.h" -#include "eloop.h" -#include "httpread.h" -#include "http_client.h" - - -#define HTTP_CLIENT_TIMEOUT_SEC 30 - - -struct http_client { - struct sockaddr_in dst; - int sd; - struct wpabuf *req; - size_t req_pos; - size_t max_response; - - void (*cb)(void *ctx, struct http_client *c, - enum http_client_event event); - void *cb_ctx; - struct httpread *hread; - struct wpabuf body; -}; - - -static void http_client_timeout(void *eloop_data, void *user_ctx) -{ - struct http_client *c = eloop_data; - wpa_printf(MSG_DEBUG, "HTTP: Timeout (c=%p)", c); - c->cb(c->cb_ctx, c, HTTP_CLIENT_TIMEOUT); -} - - -static void http_client_got_response(struct httpread *handle, void *cookie, - enum httpread_event e) -{ - struct http_client *c = cookie; - - wpa_printf(MSG_DEBUG, "HTTP: httpread callback: handle=%p cookie=%p " - "e=%d", handle, cookie, e); - - eloop_cancel_timeout(http_client_timeout, c, NULL); - switch (e) { - case HTTPREAD_EVENT_FILE_READY: - if (httpread_hdr_type_get(c->hread) == HTTPREAD_HDR_TYPE_REPLY) - { - int reply_code = httpread_reply_code_get(c->hread); - if (reply_code == 200 /* OK */) { - wpa_printf(MSG_DEBUG, "HTTP: Response OK from " - "%s:%d", - inet_ntoa(c->dst.sin_addr), - ntohs(c->dst.sin_port)); - c->cb(c->cb_ctx, c, HTTP_CLIENT_OK); - } else { - wpa_printf(MSG_DEBUG, "HTTP: Error %d from " - "%s:%d", reply_code, - inet_ntoa(c->dst.sin_addr), - ntohs(c->dst.sin_port)); - c->cb(c->cb_ctx, c, HTTP_CLIENT_INVALID_REPLY); - } - } else - c->cb(c->cb_ctx, c, HTTP_CLIENT_INVALID_REPLY); - break; - case HTTPREAD_EVENT_TIMEOUT: - c->cb(c->cb_ctx, c, HTTP_CLIENT_TIMEOUT); - break; - case HTTPREAD_EVENT_ERROR: - c->cb(c->cb_ctx, c, HTTP_CLIENT_FAILED); - break; - } -} - - -static void http_client_tx_ready(int sock, void *eloop_ctx, void *sock_ctx) -{ - struct http_client *c = eloop_ctx; - int res; - - wpa_printf(MSG_DEBUG, "HTTP: Send client request to %s:%d (%lu of %lu " - "bytes remaining)", - inet_ntoa(c->dst.sin_addr), ntohs(c->dst.sin_port), - (unsigned long) wpabuf_len(c->req), - (unsigned long) wpabuf_len(c->req) - c->req_pos); - - res = send(c->sd, wpabuf_head(c->req) + c->req_pos, - wpabuf_len(c->req) - c->req_pos, 0); - if (res < 0) { - wpa_printf(MSG_DEBUG, "HTTP: Failed to send buffer: %s", - strerror(errno)); - eloop_unregister_sock(c->sd, EVENT_TYPE_WRITE); - c->cb(c->cb_ctx, c, HTTP_CLIENT_FAILED); - return; - } - - if ((size_t) res < wpabuf_len(c->req) - c->req_pos) { - wpa_printf(MSG_DEBUG, "HTTP: Sent %d of %lu bytes; %lu bytes " - "remaining", - res, (unsigned long) wpabuf_len(c->req), - (unsigned long) wpabuf_len(c->req) - c->req_pos - - res); - c->req_pos += res; - return; - } - - wpa_printf(MSG_DEBUG, "HTTP: Full client request sent to %s:%d", - inet_ntoa(c->dst.sin_addr), ntohs(c->dst.sin_port)); - eloop_unregister_sock(c->sd, EVENT_TYPE_WRITE); - wpabuf_free(c->req); - c->req = NULL; - - c->hread = httpread_create(c->sd, http_client_got_response, c, - c->max_response, HTTP_CLIENT_TIMEOUT_SEC); - if (c->hread == NULL) { - c->cb(c->cb_ctx, c, HTTP_CLIENT_FAILED); - return; - } -} - - -struct http_client * http_client_addr(struct sockaddr_in *dst, - struct wpabuf *req, size_t max_response, - void (*cb)(void *ctx, - struct http_client *c, - enum http_client_event event), - void *cb_ctx) -{ - struct http_client *c; - - c = os_zalloc(sizeof(*c)); - if (c == NULL) - return NULL; - c->sd = -1; - c->dst = *dst; - c->max_response = max_response; - c->cb = cb; - c->cb_ctx = cb_ctx; - - c->sd = socket(AF_INET, SOCK_STREAM, 0); - if (c->sd < 0) { - http_client_free(c); - return NULL; - } - - if (fcntl(c->sd, F_SETFL, O_NONBLOCK) != 0) { - wpa_printf(MSG_DEBUG, "HTTP: fnctl(O_NONBLOCK) failed: %s", - strerror(errno)); - http_client_free(c); - return NULL; - } - - if (connect(c->sd, (struct sockaddr *) dst, sizeof(*dst))) { - if (errno != EINPROGRESS) { - wpa_printf(MSG_DEBUG, "HTTP: Failed to connect: %s", - strerror(errno)); - http_client_free(c); - return NULL; - } - - /* - * Continue connecting in the background; eloop will call us - * once the connection is ready (or failed). - */ - } - - if (eloop_register_sock(c->sd, EVENT_TYPE_WRITE, http_client_tx_ready, - c, NULL)) { - http_client_free(c); - return NULL; - } - - if (eloop_register_timeout(HTTP_CLIENT_TIMEOUT_SEC, 0, - http_client_timeout, c, NULL)) { - http_client_free(c); - return NULL; - } - - c->req = req; - - return c; -} - - -char * http_client_url_parse(const char *url, struct sockaddr_in *dst, - char **ret_path) -{ - char *u, *addr, *port, *path; - - u = os_strdup(url); - if (u == NULL) - return NULL; - - os_memset(dst, 0, sizeof(*dst)); - dst->sin_family = AF_INET; - addr = u + 7; - path = os_strchr(addr, '/'); - port = os_strchr(addr, ':'); - if (path == NULL) { - path = "/"; - } else { - *path = '\0'; /* temporary nul termination for address */ - if (port > path) - port = NULL; - } - if (port) - *port++ = '\0'; - - if (inet_aton(addr, &dst->sin_addr) == 0) { - /* TODO: name lookup */ - wpa_printf(MSG_DEBUG, "HTTP: Unsupported address in URL '%s' " - "(addr='%s' port='%s')", - url, addr, port); - os_free(u); - return NULL; - } - - if (port) - dst->sin_port = htons(atoi(port)); - else - dst->sin_port = htons(80); - - if (*path == '\0') { - /* remove temporary nul termination for address */ - *path = '/'; - } - - *ret_path = path; - - return u; -} - - -struct http_client * http_client_url(const char *url, - struct wpabuf *req, size_t max_response, - void (*cb)(void *ctx, - struct http_client *c, - enum http_client_event event), - void *cb_ctx) -{ - struct sockaddr_in dst; - struct http_client *c; - char *u, *path; - struct wpabuf *req_buf = NULL; - - if (os_strncmp(url, "http://", 7) != 0) - return NULL; - u = http_client_url_parse(url, &dst, &path); - if (u == NULL) - return NULL; - - if (req == NULL) { - req_buf = wpabuf_alloc(os_strlen(url) + 1000); - if (req_buf == NULL) { - os_free(u); - return NULL; - } - req = req_buf; - wpabuf_printf(req, - "GET %s HTTP/1.1\r\n" - "Cache-Control: no-cache\r\n" - "Pragma: no-cache\r\n" - "Accept: text/xml, application/xml\r\n" - "User-Agent: wpa_supplicant\r\n" - "Host: %s:%d\r\n" - "\r\n", - path, inet_ntoa(dst.sin_addr), - ntohs(dst.sin_port)); - } - os_free(u); - - c = http_client_addr(&dst, req, max_response, cb, cb_ctx); - if (c == NULL) { - wpabuf_free(req_buf); - return NULL; - } - - return c; -} - - -void http_client_free(struct http_client *c) -{ - if (c == NULL) - return; - httpread_destroy(c->hread); - wpabuf_free(c->req); - if (c->sd >= 0) { - eloop_unregister_sock(c->sd, EVENT_TYPE_WRITE); - close(c->sd); - } - eloop_cancel_timeout(http_client_timeout, c, NULL); - os_free(c); -} - - -struct wpabuf * http_client_get_body(struct http_client *c) -{ - if (c->hread == NULL) - return NULL; - wpabuf_set(&c->body, httpread_data_get(c->hread), - httpread_length_get(c->hread)); - return &c->body; -} - - -char * http_client_get_hdr_line(struct http_client *c, const char *tag) -{ - if (c->hread == NULL) - return NULL; - return httpread_hdr_line_get(c->hread, tag); -} - - -char * http_link_update(char *url, const char *base) -{ - char *n; - size_t len; - const char *pos; - - /* RFC 2396, Chapter 5.2 */ - /* TODO: consider adding all cases described in RFC 2396 */ - - if (url == NULL) - return NULL; - - if (os_strncmp(url, "http://", 7) == 0) - return url; /* absolute link */ - - if (os_strncmp(base, "http://", 7) != 0) - return url; /* unable to handle base URL */ - - len = os_strlen(url) + 1 + os_strlen(base) + 1; - n = os_malloc(len); - if (n == NULL) - return url; /* failed */ - - if (url[0] == '/') { - pos = os_strchr(base + 7, '/'); - if (pos == NULL) { - os_snprintf(n, len, "%s%s", base, url); - } else { - os_memcpy(n, base, pos - base); - os_memcpy(n + (pos - base), url, os_strlen(url) + 1); - } - } else { - pos = os_strrchr(base + 7, '/'); - if (pos == NULL) { - os_snprintf(n, len, "%s/%s", base, url); - } else { - os_memcpy(n, base, pos - base + 1); - os_memcpy(n + (pos - base) + 1, url, os_strlen(url) + - 1); - } - } - - os_free(url); - - return n; -} diff --git a/hostapd-0.8/src/wps/http_client.h b/hostapd-0.8/src/wps/http_client.h deleted file mode 100644 index 924d6ab..0000000 --- a/hostapd-0.8/src/wps/http_client.h +++ /dev/null @@ -1,46 +0,0 @@ -/* - * http_client - HTTP client - * Copyright (c) 2009, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#ifndef HTTP_CLIENT_H -#define HTTP_CLIENT_H - -struct http_client; - -enum http_client_event { - HTTP_CLIENT_FAILED, - HTTP_CLIENT_TIMEOUT, - HTTP_CLIENT_OK, - HTTP_CLIENT_INVALID_REPLY, -}; - -char * http_client_url_parse(const char *url, struct sockaddr_in *dst, - char **path); -struct http_client * http_client_addr(struct sockaddr_in *dst, - struct wpabuf *req, size_t max_response, - void (*cb)(void *ctx, - struct http_client *c, - enum http_client_event event), - void *cb_ctx); -struct http_client * http_client_url(const char *url, - struct wpabuf *req, size_t max_response, - void (*cb)(void *ctx, - struct http_client *c, - enum http_client_event event), - void *cb_ctx); -void http_client_free(struct http_client *c); -struct wpabuf * http_client_get_body(struct http_client *c); -char * http_client_get_hdr_line(struct http_client *c, const char *tag); -char * http_link_update(char *url, const char *base); - -#endif /* HTTP_CLIENT_H */ diff --git a/hostapd-0.8/src/wps/http_server.c b/hostapd-0.8/src/wps/http_server.c deleted file mode 100644 index 356f599..0000000 --- a/hostapd-0.8/src/wps/http_server.c +++ /dev/null @@ -1,312 +0,0 @@ -/* - * http_server - HTTP server - * Copyright (c) 2009, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#include "includes.h" -#include - -#include "common.h" -#include "eloop.h" -#include "httpread.h" -#include "http_server.h" - -#define HTTP_SERVER_TIMEOUT 30 -#define HTTP_SERVER_MAX_REQ_LEN 8000 -#define HTTP_SERVER_MAX_CONNECTIONS 10 - -struct http_request { - struct http_request *next; - struct http_server *srv; - int fd; - struct sockaddr_in cli; - struct httpread *hread; -}; - -struct http_server { - void (*cb)(void *ctx, struct http_request *req); - void *cb_ctx; - - int fd; - int port; - - struct http_request *requests; - unsigned int request_count; -}; - - -static void http_request_cb(struct httpread *handle, void *cookie, - enum httpread_event en) -{ - struct http_request *req = cookie; - struct http_server *srv = req->srv; - - if (en == HTTPREAD_EVENT_FILE_READY) { - wpa_printf(MSG_DEBUG, "HTTP: Request from %s:%d received", - inet_ntoa(req->cli.sin_addr), - ntohs(req->cli.sin_port)); - srv->cb(srv->cb_ctx, req); - return; - } - wpa_printf(MSG_DEBUG, "HTTP: Request from %s:%d could not be received " - "completely", inet_ntoa(req->cli.sin_addr), - ntohs(req->cli.sin_port)); - http_request_deinit(req); -} - - -static struct http_request * http_request_init(struct http_server *srv, int fd, - struct sockaddr_in *cli) -{ - struct http_request *req; - - if (srv->request_count >= HTTP_SERVER_MAX_CONNECTIONS) { - wpa_printf(MSG_DEBUG, "HTTP: Too many concurrent requests"); - return NULL; - } - - req = os_zalloc(sizeof(*req)); - if (req == NULL) - return NULL; - - req->srv = srv; - req->fd = fd; - req->cli = *cli; - - req->hread = httpread_create(req->fd, http_request_cb, req, - HTTP_SERVER_MAX_REQ_LEN, - HTTP_SERVER_TIMEOUT); - if (req->hread == NULL) { - http_request_deinit(req); - return NULL; - } - - return req; -} - - -void http_request_deinit(struct http_request *req) -{ - struct http_request *r, *p; - struct http_server *srv; - - if (req == NULL) - return; - - srv = req->srv; - p = NULL; - r = srv->requests; - while (r) { - if (r == req) { - if (p) - p->next = r->next; - else - srv->requests = r->next; - srv->request_count--; - break; - } - p = r; - r = r->next; - } - - httpread_destroy(req->hread); - close(req->fd); - os_free(req); -} - - -static void http_request_free_all(struct http_request *req) -{ - struct http_request *prev; - while (req) { - prev = req; - req = req->next; - http_request_deinit(prev); - } -} - - -void http_request_send(struct http_request *req, struct wpabuf *resp) -{ - int res; - - wpa_printf(MSG_DEBUG, "HTTP: Send %lu byte response to %s:%d", - (unsigned long) wpabuf_len(resp), - inet_ntoa(req->cli.sin_addr), - ntohs(req->cli.sin_port)); - - res = send(req->fd, wpabuf_head(resp), wpabuf_len(resp), 0); - if (res < 0) { - wpa_printf(MSG_DEBUG, "HTTP: Send failed: %s", - strerror(errno)); - } else if ((size_t) res < wpabuf_len(resp)) { - wpa_printf(MSG_DEBUG, "HTTP: Sent only %d of %lu bytes", - res, (unsigned long) wpabuf_len(resp)); - /* TODO: add eloop handler for sending rest of the data */ - } - - wpabuf_free(resp); -} - - -void http_request_send_and_deinit(struct http_request *req, - struct wpabuf *resp) -{ - http_request_send(req, resp); - http_request_deinit(req); -} - - -enum httpread_hdr_type http_request_get_type(struct http_request *req) -{ - return httpread_hdr_type_get(req->hread); -} - - -char * http_request_get_uri(struct http_request *req) -{ - return httpread_uri_get(req->hread); -} - - -char * http_request_get_hdr(struct http_request *req) -{ - return httpread_hdr_get(req->hread); -} - - -char * http_request_get_data(struct http_request *req) -{ - return httpread_data_get(req->hread); -} - - -char * http_request_get_hdr_line(struct http_request *req, const char *tag) -{ - return httpread_hdr_line_get(req->hread, tag); -} - - -struct sockaddr_in * http_request_get_cli_addr(struct http_request *req) -{ - return &req->cli; -} - - -static void http_server_cb(int sd, void *eloop_ctx, void *sock_ctx) -{ - struct sockaddr_in addr; - socklen_t addr_len = sizeof(addr); - struct http_server *srv = eloop_ctx; - int conn; - struct http_request *req; - - conn = accept(srv->fd, (struct sockaddr *) &addr, &addr_len); - if (conn < 0) { - wpa_printf(MSG_DEBUG, "HTTP: Failed to accept new connection: " - "%s", strerror(errno)); - return; - } - wpa_printf(MSG_DEBUG, "HTTP: Connection from %s:%d", - inet_ntoa(addr.sin_addr), ntohs(addr.sin_port)); - - req = http_request_init(srv, conn, &addr); - if (req == NULL) { - close(conn); - return; - } - - req->next = srv->requests; - srv->requests = req; - srv->request_count++; -} - - -struct http_server * http_server_init(struct in_addr *addr, int port, - void (*cb)(void *ctx, - struct http_request *req), - void *cb_ctx) -{ - struct sockaddr_in sin; - struct http_server *srv; - - srv = os_zalloc(sizeof(*srv)); - if (srv == NULL) - return NULL; - srv->cb = cb; - srv->cb_ctx = cb_ctx; - - srv->fd = socket(AF_INET, SOCK_STREAM, 0); - if (srv->fd < 0) - goto fail; - if (fcntl(srv->fd, F_SETFL, O_NONBLOCK) < 0) - goto fail; - if (port < 0) - srv->port = 49152; - else - srv->port = port; - - os_memset(&sin, 0, sizeof(sin)); - sin.sin_family = AF_INET; - sin.sin_addr.s_addr = addr->s_addr; - - for (;;) { - sin.sin_port = htons(srv->port); - if (bind(srv->fd, (struct sockaddr *) &sin, sizeof(sin)) == 0) - break; - if (errno == EADDRINUSE) { - /* search for unused port */ - if (++srv->port == 65535 || port >= 0) - goto fail; - continue; - } - wpa_printf(MSG_DEBUG, "HTTP: Failed to bind server port %d: " - "%s", srv->port, strerror(errno)); - goto fail; - } - if (listen(srv->fd, 10 /* max backlog */) < 0) - goto fail; - if (fcntl(srv->fd, F_SETFL, O_NONBLOCK) < 0) - goto fail; - if (eloop_register_sock(srv->fd, EVENT_TYPE_READ, http_server_cb, - srv, NULL)) - goto fail; - - wpa_printf(MSG_DEBUG, "HTTP: Started server on %s:%d", - inet_ntoa(*addr), srv->port); - - return srv; - -fail: - http_server_deinit(srv); - return NULL; -} - - -void http_server_deinit(struct http_server *srv) -{ - if (srv == NULL) - return; - if (srv->fd >= 0) { - eloop_unregister_sock(srv->fd, EVENT_TYPE_READ); - close(srv->fd); - } - http_request_free_all(srv->requests); - - os_free(srv); -} - - -int http_server_get_port(struct http_server *srv) -{ - return srv->port; -} diff --git a/hostapd-0.8/src/wps/http_server.h b/hostapd-0.8/src/wps/http_server.h deleted file mode 100644 index 219941c..0000000 --- a/hostapd-0.8/src/wps/http_server.h +++ /dev/null @@ -1,39 +0,0 @@ -/* - * http_server - HTTP server - * Copyright (c) 2009, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#ifndef HTTP_SERVER_H -#define HTTP_SERVER_H - -struct http_server; -struct http_request; - -void http_request_deinit(struct http_request *req); -void http_request_send(struct http_request *req, struct wpabuf *resp); -void http_request_send_and_deinit(struct http_request *req, - struct wpabuf *resp); -enum httpread_hdr_type http_request_get_type(struct http_request *req); -char * http_request_get_uri(struct http_request *req); -char * http_request_get_hdr(struct http_request *req); -char * http_request_get_data(struct http_request *req); -char * http_request_get_hdr_line(struct http_request *req, const char *tag); -struct sockaddr_in * http_request_get_cli_addr(struct http_request *req); - -struct http_server * http_server_init(struct in_addr *addr, int port, - void (*cb)(void *ctx, - struct http_request *req), - void *cb_ctx); -void http_server_deinit(struct http_server *srv); -int http_server_get_port(struct http_server *srv); - -#endif /* HTTP_SERVER_H */ diff --git a/hostapd-0.8/src/wps/httpread.c b/hostapd-0.8/src/wps/httpread.c deleted file mode 100644 index 40422e4..0000000 --- a/hostapd-0.8/src/wps/httpread.c +++ /dev/null @@ -1,861 +0,0 @@ -/* - * httpread - Manage reading file(s) from HTTP/TCP socket - * Author: Ted Merrill - * Copyright 2008 Atheros Communications - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - * - * The files are buffered via internal callbacks from eloop, then presented to - * an application callback routine when completely read into memory. May also - * be used if no file is expected but just to get the header, including HTTP - * replies (e.g. HTTP/1.1 200 OK etc.). - * - * This does not attempt to be an optimally efficient implementation, but does - * attempt to be of reasonably small size and memory consumption; assuming that - * only small files are to be read. A maximum file size is provided by - * application and enforced. - * - * It is assumed that the application does not expect any of the following: - * -- transfer encoding other than chunked - * -- trailer fields - * It is assumed that, even if the other side requested that the connection be - * kept open, that we will close it (thus HTTP messages sent by application - * should have the connection closed field); this is allowed by HTTP/1.1 and - * simplifies things for us. - * - * Other limitations: - * -- HTTP header may not exceed a hard-coded size. - * - * Notes: - * This code would be massively simpler without some of the new features of - * HTTP/1.1, especially chunked data. - */ - -#include "includes.h" - -#include "common.h" -#include "eloop.h" -#include "httpread.h" - - -/* Tunable parameters */ -#define HTTPREAD_READBUF_SIZE 1024 /* read in chunks of this size */ -#define HTTPREAD_HEADER_MAX_SIZE 4096 /* max allowed for headers */ -#define HTTPREAD_BODYBUF_DELTA 4096 /* increase allocation by this */ - -#if 0 -/* httpread_debug -- set this global variable > 0 e.g. from debugger - * to enable debugs (larger numbers for more debugs) - * Make this a #define of 0 to eliminate the debugging code. - */ -int httpread_debug = 99; -#else -#define httpread_debug 0 /* eliminates even the debugging code */ -#endif - - -/* control instance -- actual definition (opaque to application) - */ -struct httpread { - /* information from creation */ - int sd; /* descriptor of TCP socket to read from */ - void (*cb)(struct httpread *handle, void *cookie, - enum httpread_event e); /* call on event */ - void *cookie; /* pass to callback */ - int max_bytes; /* maximum file size else abort it */ - int timeout_seconds; /* 0 or total duration timeout period */ - - /* dynamically used information follows */ - int sd_registered; /* nonzero if we need to unregister socket */ - int to_registered; /* nonzero if we need to unregister timeout */ - - int got_hdr; /* nonzero when header is finalized */ - char hdr[HTTPREAD_HEADER_MAX_SIZE+1]; /* headers stored here */ - int hdr_nbytes; - - enum httpread_hdr_type hdr_type; - int version; /* 1 if we've seen 1.1 */ - int reply_code; /* for type REPLY, e.g. 200 for HTTP/1.1 200 OK */ - int got_content_length; /* true if we know content length for sure */ - int content_length; /* body length, iff got_content_length */ - int chunked; /* nonzero for chunked data */ - char *uri; - - int got_body; /* nonzero when body is finalized */ - char *body; - int body_nbytes; - int body_alloc_nbytes; /* amount allocated */ - - int got_file; /* here when we are done */ - - /* The following apply if data is chunked: */ - int in_chunk_data; /* 0=in/at header, 1=in the data or tail*/ - int chunk_start; /* offset in body of chunk hdr or data */ - int chunk_size; /* data of chunk (not hdr or ending CRLF)*/ - int in_trailer; /* in header fields after data (chunked only)*/ - enum trailer_state { - trailer_line_begin = 0, - trailer_empty_cr, /* empty line + CR */ - trailer_nonempty, - trailer_nonempty_cr, - } trailer_state; -}; - - -/* Check words for equality, where words consist of graphical characters - * delimited by whitespace - * Returns nonzero if "equal" doing case insensitive comparison. - */ -static int word_eq(char *s1, char *s2) -{ - int c1; - int c2; - int end1 = 0; - int end2 = 0; - for (;;) { - c1 = *s1++; - c2 = *s2++; - if (isalpha(c1) && isupper(c1)) - c1 = tolower(c1); - if (isalpha(c2) && isupper(c2)) - c2 = tolower(c2); - end1 = !isgraph(c1); - end2 = !isgraph(c2); - if (end1 || end2 || c1 != c2) - break; - } - return end1 && end2; /* reached end of both words? */ -} - - -/* convert hex to binary - * Requires that c have been previously tested true with isxdigit(). - */ -static int hex_value(int c) -{ - if (isdigit(c)) - return c - '0'; - if (islower(c)) - return 10 + c - 'a'; - return 10 + c - 'A'; -} - - -static void httpread_timeout_handler(void *eloop_data, void *user_ctx); - -/* httpread_destroy -- if h is non-NULL, clean up - * This must eventually be called by the application following - * call of the application's callback and may be called - * earlier if desired. - */ -void httpread_destroy(struct httpread *h) -{ - if (httpread_debug >= 10) - wpa_printf(MSG_DEBUG, "ENTER httpread_destroy(%p)", h); - if (!h) - return; - - if (h->to_registered) - eloop_cancel_timeout(httpread_timeout_handler, NULL, h); - h->to_registered = 0; - if (h->sd_registered) - eloop_unregister_sock(h->sd, EVENT_TYPE_READ); - h->sd_registered = 0; - os_free(h->body); - os_free(h->uri); - os_memset(h, 0, sizeof(*h)); /* aid debugging */ - h->sd = -1; /* aid debugging */ - os_free(h); -} - - -/* httpread_timeout_handler -- called on excessive total duration - */ -static void httpread_timeout_handler(void *eloop_data, void *user_ctx) -{ - struct httpread *h = user_ctx; - wpa_printf(MSG_DEBUG, "httpread timeout (%p)", h); - h->to_registered = 0; /* is self-cancelling */ - (*h->cb)(h, h->cookie, HTTPREAD_EVENT_TIMEOUT); -} - - -/* Analyze options only so far as is needed to correctly obtain the file. - * The application can look at the raw header to find other options. - */ -static int httpread_hdr_option_analyze( - struct httpread *h, - char *hbp /* pointer to current line in header buffer */ - ) -{ - if (word_eq(hbp, "CONTENT-LENGTH:")) { - while (isgraph(*hbp)) - hbp++; - while (*hbp == ' ' || *hbp == '\t') - hbp++; - if (!isdigit(*hbp)) - return -1; - h->content_length = atol(hbp); - h->got_content_length = 1; - return 0; - } - if (word_eq(hbp, "TRANSFER_ENCODING:") || - word_eq(hbp, "TRANSFER-ENCODING:")) { - while (isgraph(*hbp)) - hbp++; - while (*hbp == ' ' || *hbp == '\t') - hbp++; - /* There should (?) be no encodings of interest - * other than chunked... - */ - if (word_eq(hbp, "CHUNKED")) { - h->chunked = 1; - h->in_chunk_data = 0; - /* ignore possible ; */ - } - return 0; - } - /* skip anything we don't know, which is a lot */ - return 0; -} - - -static int httpread_hdr_analyze(struct httpread *h) -{ - char *hbp = h->hdr; /* pointer into h->hdr */ - int standard_first_line = 1; - - /* First line is special */ - h->hdr_type = HTTPREAD_HDR_TYPE_UNKNOWN; - if (!isgraph(*hbp)) - goto bad; - if (os_strncmp(hbp, "HTTP/", 5) == 0) { - h->hdr_type = HTTPREAD_HDR_TYPE_REPLY; - standard_first_line = 0; - hbp += 5; - if (hbp[0] == '1' && hbp[1] == '.' && - isdigit(hbp[2]) && hbp[2] != '0') - h->version = 1; - while (isgraph(*hbp)) - hbp++; - while (*hbp == ' ' || *hbp == '\t') - hbp++; - if (!isdigit(*hbp)) - goto bad; - h->reply_code = atol(hbp); - } else if (word_eq(hbp, "GET")) - h->hdr_type = HTTPREAD_HDR_TYPE_GET; - else if (word_eq(hbp, "HEAD")) - h->hdr_type = HTTPREAD_HDR_TYPE_HEAD; - else if (word_eq(hbp, "POST")) - h->hdr_type = HTTPREAD_HDR_TYPE_POST; - else if (word_eq(hbp, "PUT")) - h->hdr_type = HTTPREAD_HDR_TYPE_PUT; - else if (word_eq(hbp, "DELETE")) - h->hdr_type = HTTPREAD_HDR_TYPE_DELETE; - else if (word_eq(hbp, "TRACE")) - h->hdr_type = HTTPREAD_HDR_TYPE_TRACE; - else if (word_eq(hbp, "CONNECT")) - h->hdr_type = HTTPREAD_HDR_TYPE_CONNECT; - else if (word_eq(hbp, "NOTIFY")) - h->hdr_type = HTTPREAD_HDR_TYPE_NOTIFY; - else if (word_eq(hbp, "M-SEARCH")) - h->hdr_type = HTTPREAD_HDR_TYPE_M_SEARCH; - else if (word_eq(hbp, "M-POST")) - h->hdr_type = HTTPREAD_HDR_TYPE_M_POST; - else if (word_eq(hbp, "SUBSCRIBE")) - h->hdr_type = HTTPREAD_HDR_TYPE_SUBSCRIBE; - else if (word_eq(hbp, "UNSUBSCRIBE")) - h->hdr_type = HTTPREAD_HDR_TYPE_UNSUBSCRIBE; - else { - } - - if (standard_first_line) { - char *rawuri; - char *uri; - /* skip type */ - while (isgraph(*hbp)) - hbp++; - while (*hbp == ' ' || *hbp == '\t') - hbp++; - /* parse uri. - * Find length, allocate memory for translated - * copy, then translate by changing % - * into represented value. - */ - rawuri = hbp; - while (isgraph(*hbp)) - hbp++; - h->uri = os_malloc((hbp - rawuri) + 1); - if (h->uri == NULL) - goto bad; - uri = h->uri; - while (rawuri < hbp) { - int c = *rawuri; - if (c == '%' && - isxdigit(rawuri[1]) && isxdigit(rawuri[2])) { - *uri++ = (hex_value(rawuri[1]) << 4) | - hex_value(rawuri[2]); - rawuri += 3; - } else { - *uri++ = c; - rawuri++; - } - } - *uri = 0; /* null terminate */ - while (isgraph(*hbp)) - hbp++; - while (*hbp == ' ' || *hbp == '\t') - hbp++; - /* get version */ - if (0 == strncmp(hbp, "HTTP/", 5)) { - hbp += 5; - if (hbp[0] == '1' && hbp[1] == '.' && - isdigit(hbp[2]) && hbp[2] != '0') - h->version = 1; - } - } - /* skip rest of line */ - while (*hbp) - if (*hbp++ == '\n') - break; - - /* Remainder of lines are options, in any order; - * or empty line to terminate - */ - for (;;) { - /* Empty line to terminate */ - if (hbp[0] == '\n' || - (hbp[0] == '\r' && hbp[1] == '\n')) - break; - if (!isgraph(*hbp)) - goto bad; - if (httpread_hdr_option_analyze(h, hbp)) - goto bad; - /* skip line */ - while (*hbp) - if (*hbp++ == '\n') - break; - } - - /* chunked overrides content-length always */ - if (h->chunked) - h->got_content_length = 0; - - /* For some types, we should not try to read a body - * This is in addition to the application determining - * that we should not read a body. - */ - switch (h->hdr_type) { - case HTTPREAD_HDR_TYPE_REPLY: - /* Some codes can have a body and some not. - * For now, just assume that any other than 200 - * do not... - */ - if (h->reply_code != 200) - h->max_bytes = 0; - break; - case HTTPREAD_HDR_TYPE_GET: - case HTTPREAD_HDR_TYPE_HEAD: - /* in practice it appears that it is assumed - * that GETs have a body length of 0... ? - */ - if (h->chunked == 0 && h->got_content_length == 0) - h->max_bytes = 0; - break; - case HTTPREAD_HDR_TYPE_POST: - case HTTPREAD_HDR_TYPE_PUT: - case HTTPREAD_HDR_TYPE_DELETE: - case HTTPREAD_HDR_TYPE_TRACE: - case HTTPREAD_HDR_TYPE_CONNECT: - case HTTPREAD_HDR_TYPE_NOTIFY: - case HTTPREAD_HDR_TYPE_M_SEARCH: - case HTTPREAD_HDR_TYPE_M_POST: - case HTTPREAD_HDR_TYPE_SUBSCRIBE: - case HTTPREAD_HDR_TYPE_UNSUBSCRIBE: - default: - break; - } - - return 0; - -bad: - /* Error */ - return -1; -} - - -/* httpread_read_handler -- called when socket ready to read - * - * Note: any extra data we read past end of transmitted file is ignored; - * if we were to support keeping connections open for multiple files then - * this would have to be addressed. - */ -static void httpread_read_handler(int sd, void *eloop_ctx, void *sock_ctx) -{ - struct httpread *h = sock_ctx; - int nread; - char *rbp; /* pointer into read buffer */ - char *hbp; /* pointer into header buffer */ - char *bbp; /* pointer into body buffer */ - char readbuf[HTTPREAD_READBUF_SIZE]; /* temp use to read into */ - - if (httpread_debug >= 20) - wpa_printf(MSG_DEBUG, "ENTER httpread_read_handler(%p)", h); - - /* read some at a time, then search for the interal - * boundaries between header and data and etc. - */ - nread = read(h->sd, readbuf, sizeof(readbuf)); - if (nread < 0) - goto bad; - if (nread == 0) { - /* end of transmission... this may be normal - * or may be an error... in some cases we can't - * tell which so we must assume it is normal then. - */ - if (!h->got_hdr) { - /* Must at least have completed header */ - wpa_printf(MSG_DEBUG, "httpread premature eof(%p)", h); - goto bad; - } - if (h->chunked || h->got_content_length) { - /* Premature EOF; e.g. dropped connection */ - wpa_printf(MSG_DEBUG, - "httpread premature eof(%p) %d/%d", - h, h->body_nbytes, - h->content_length); - goto bad; - } - /* No explicit length, hopefully we have all the data - * although dropped connections can cause false - * end - */ - if (httpread_debug >= 10) - wpa_printf(MSG_DEBUG, "httpread ok eof(%p)", h); - h->got_body = 1; - goto got_file; - } - rbp = readbuf; - - /* Header consists of text lines (terminated by both CR and LF) - * and an empty line (CR LF only). - */ - if (!h->got_hdr) { - hbp = h->hdr + h->hdr_nbytes; - /* add to headers until: - * -- we run out of data in read buffer - * -- or, we run out of header buffer room - * -- or, we get double CRLF in headers - */ - for (;;) { - if (nread == 0) - goto get_more; - if (h->hdr_nbytes == HTTPREAD_HEADER_MAX_SIZE) { - goto bad; - } - *hbp++ = *rbp++; - nread--; - h->hdr_nbytes++; - if (h->hdr_nbytes >= 4 && - hbp[-1] == '\n' && - hbp[-2] == '\r' && - hbp[-3] == '\n' && - hbp[-4] == '\r' ) { - h->got_hdr = 1; - *hbp = 0; /* null terminate */ - break; - } - } - /* here we've just finished reading the header */ - if (httpread_hdr_analyze(h)) { - wpa_printf(MSG_DEBUG, "httpread bad hdr(%p)", h); - goto bad; - } - if (h->max_bytes == 0) { - if (httpread_debug >= 10) - wpa_printf(MSG_DEBUG, - "httpread no body hdr end(%p)", h); - goto got_file; - } - if (h->got_content_length && h->content_length == 0) { - if (httpread_debug >= 10) - wpa_printf(MSG_DEBUG, - "httpread zero content length(%p)", - h); - goto got_file; - } - } - - /* Certain types of requests never have data and so - * must be specially recognized. - */ - if (!os_strncasecmp(h->hdr, "SUBSCRIBE", 9) || - !os_strncasecmp(h->hdr, "UNSUBSCRIBE", 11) || - !os_strncasecmp(h->hdr, "HEAD", 4) || - !os_strncasecmp(h->hdr, "GET", 3)) { - if (!h->got_body) { - if (httpread_debug >= 10) - wpa_printf(MSG_DEBUG, - "httpread NO BODY for sp. type"); - } - h->got_body = 1; - goto got_file; - } - - /* Data can be just plain binary data, or if "chunked" - * consists of chunks each with a header, ending with - * an ending header. - */ - if (nread == 0) - goto get_more; - if (!h->got_body) { - /* Here to get (more of) body */ - /* ensure we have enough room for worst case for body - * plus a null termination character - */ - if (h->body_alloc_nbytes < (h->body_nbytes + nread + 1)) { - char *new_body; - int new_alloc_nbytes; - - if (h->body_nbytes >= h->max_bytes) - goto bad; - new_alloc_nbytes = h->body_alloc_nbytes + - HTTPREAD_BODYBUF_DELTA; - /* For content-length case, the first time - * through we allocate the whole amount - * we need. - */ - if (h->got_content_length && - new_alloc_nbytes < (h->content_length + 1)) - new_alloc_nbytes = h->content_length + 1; - if ((new_body = os_realloc(h->body, new_alloc_nbytes)) - == NULL) - goto bad; - - h->body = new_body; - h->body_alloc_nbytes = new_alloc_nbytes; - } - /* add bytes */ - bbp = h->body + h->body_nbytes; - for (;;) { - int ncopy; - /* See if we need to stop */ - if (h->chunked && h->in_chunk_data == 0) { - /* in chunk header */ - char *cbp = h->body + h->chunk_start; - if (bbp-cbp >= 2 && bbp[-2] == '\r' && - bbp[-1] == '\n') { - /* end of chunk hdr line */ - /* hdr line consists solely - * of a hex numeral and CFLF - */ - if (!isxdigit(*cbp)) - goto bad; - h->chunk_size = strtoul(cbp, NULL, 16); - /* throw away chunk header - * so we have only real data - */ - h->body_nbytes = h->chunk_start; - bbp = cbp; - if (h->chunk_size == 0) { - /* end of chunking */ - /* trailer follows */ - h->in_trailer = 1; - if (httpread_debug >= 20) - wpa_printf( - MSG_DEBUG, - "httpread end chunks(%p)", h); - break; - } - h->in_chunk_data = 1; - /* leave chunk_start alone */ - } - } else if (h->chunked) { - /* in chunk data */ - if ((h->body_nbytes - h->chunk_start) == - (h->chunk_size + 2)) { - /* end of chunk reached, - * new chunk starts - */ - /* check chunk ended w/ CRLF - * which we'll throw away - */ - if (bbp[-1] == '\n' && - bbp[-2] == '\r') { - } else - goto bad; - h->body_nbytes -= 2; - bbp -= 2; - h->chunk_start = h->body_nbytes; - h->in_chunk_data = 0; - h->chunk_size = 0; /* just in case */ - } - } else if (h->got_content_length && - h->body_nbytes >= h->content_length) { - h->got_body = 1; - if (httpread_debug >= 10) - wpa_printf( - MSG_DEBUG, - "httpread got content(%p)", h); - goto got_file; - } - if (nread <= 0) - break; - /* Now transfer. Optimize using memcpy where we can. */ - if (h->chunked && h->in_chunk_data) { - /* copy up to remainder of chunk data - * plus the required CR+LF at end - */ - ncopy = (h->chunk_start + h->chunk_size + 2) - - h->body_nbytes; - } else if (h->chunked) { - /*in chunk header -- don't optimize */ - *bbp++ = *rbp++; - nread--; - h->body_nbytes++; - continue; - } else if (h->got_content_length) { - ncopy = h->content_length - h->body_nbytes; - } else { - ncopy = nread; - } - /* Note: should never be 0 */ - if (ncopy > nread) - ncopy = nread; - os_memcpy(bbp, rbp, ncopy); - bbp += ncopy; - h->body_nbytes += ncopy; - rbp += ncopy; - nread -= ncopy; - } /* body copy loop */ - } /* !got_body */ - if (h->chunked && h->in_trailer) { - /* If "chunked" then there is always a trailer, - * consisting of zero or more non-empty lines - * ending with CR LF and then an empty line w/ CR LF. - * We do NOT support trailers except to skip them -- - * this is supported (generally) by the http spec. - */ - bbp = h->body + h->body_nbytes; - for (;;) { - int c; - if (nread <= 0) - break; - c = *rbp++; - nread--; - switch (h->trailer_state) { - case trailer_line_begin: - if (c == '\r') - h->trailer_state = trailer_empty_cr; - else - h->trailer_state = trailer_nonempty; - break; - case trailer_empty_cr: - /* end empty line */ - if (c == '\n') { - h->trailer_state = trailer_line_begin; - h->in_trailer = 0; - if (httpread_debug >= 10) - wpa_printf( - MSG_DEBUG, - "httpread got content(%p)", h); - h->got_body = 1; - goto got_file; - } - h->trailer_state = trailer_nonempty; - break; - case trailer_nonempty: - if (c == '\r') - h->trailer_state = trailer_nonempty_cr; - break; - case trailer_nonempty_cr: - if (c == '\n') - h->trailer_state = trailer_line_begin; - else - h->trailer_state = trailer_nonempty; - break; - } - } - } - goto get_more; - -bad: - /* Error */ - wpa_printf(MSG_DEBUG, "httpread read/parse failure (%p)", h); - (*h->cb)(h, h->cookie, HTTPREAD_EVENT_ERROR); - return; - -get_more: - return; - -got_file: - if (httpread_debug >= 10) - wpa_printf(MSG_DEBUG, - "httpread got file %d bytes type %d", - h->body_nbytes, h->hdr_type); - /* Null terminate for convenience of some applications */ - if (h->body) - h->body[h->body_nbytes] = 0; /* null terminate */ - h->got_file = 1; - /* Assume that we do NOT support keeping connection alive, - * and just in case somehow we don't get destroyed right away, - * unregister now. - */ - if (h->sd_registered) - eloop_unregister_sock(h->sd, EVENT_TYPE_READ); - h->sd_registered = 0; - /* The application can destroy us whenever they feel like... - * cancel timeout. - */ - if (h->to_registered) - eloop_cancel_timeout(httpread_timeout_handler, NULL, h); - h->to_registered = 0; - (*h->cb)(h, h->cookie, HTTPREAD_EVENT_FILE_READY); -} - - -/* httpread_create -- start a new reading session making use of eloop. - * The new instance will use the socket descriptor for reading (until - * it gets a file and not after) but will not close the socket, even - * when the instance is destroyed (the application must do that). - * Return NULL on error. - * - * Provided that httpread_create successfully returns a handle, - * the callback fnc is called to handle httpread_event events. - * The caller should do destroy on any errors or unknown events. - * - * Pass max_bytes == 0 to not read body at all (required for e.g. - * reply to HEAD request). - */ -struct httpread * httpread_create( - int sd, /* descriptor of TCP socket to read from */ - void (*cb)(struct httpread *handle, void *cookie, - enum httpread_event e), /* call on event */ - void *cookie, /* pass to callback */ - int max_bytes, /* maximum body size else abort it */ - int timeout_seconds /* 0; or total duration timeout period */ - ) -{ - struct httpread *h = NULL; - - h = os_zalloc(sizeof(*h)); - if (h == NULL) - goto fail; - h->sd = sd; - h->cb = cb; - h->cookie = cookie; - h->max_bytes = max_bytes; - h->timeout_seconds = timeout_seconds; - - if (timeout_seconds > 0) { - if (eloop_register_timeout(timeout_seconds, 0, - httpread_timeout_handler, - NULL, h)) { - /* No way to recover (from malloc failure) */ - goto fail; - } - h->to_registered = 1; - } - if (eloop_register_sock(sd, EVENT_TYPE_READ, httpread_read_handler, - NULL, h)) { - /* No way to recover (from malloc failure) */ - goto fail; - } - h->sd_registered = 1; - return h; - -fail: - - /* Error */ - httpread_destroy(h); - return NULL; -} - - -/* httpread_hdr_type_get -- When file is ready, returns header type. */ -enum httpread_hdr_type httpread_hdr_type_get(struct httpread *h) -{ - return h->hdr_type; -} - - -/* httpread_uri_get -- When file is ready, uri_get returns (translated) URI - * or possibly NULL (which would be an error). - */ -char * httpread_uri_get(struct httpread *h) -{ - return h->uri; -} - - -/* httpread_reply_code_get -- When reply is ready, returns reply code */ -int httpread_reply_code_get(struct httpread *h) -{ - return h->reply_code; -} - - -/* httpread_length_get -- When file is ready, returns file length. */ -int httpread_length_get(struct httpread *h) -{ - return h->body_nbytes; -} - - -/* httpread_data_get -- When file is ready, returns file content - * with null byte appened. - * Might return NULL in some error condition. - */ -void * httpread_data_get(struct httpread *h) -{ - return h->body ? h->body : ""; -} - - -/* httpread_hdr_get -- When file is ready, returns header content - * with null byte appended. - * Might return NULL in some error condition. - */ -char * httpread_hdr_get(struct httpread *h) -{ - return h->hdr; -} - - -/* httpread_hdr_line_get -- When file is ready, returns pointer - * to line within header content matching the given tag - * (after the tag itself and any spaces/tabs). - * - * The tag should end with a colon for reliable matching. - * - * If not found, returns NULL; - */ -char * httpread_hdr_line_get(struct httpread *h, const char *tag) -{ - int tag_len = os_strlen(tag); - char *hdr = h->hdr; - hdr = os_strchr(hdr, '\n'); - if (hdr == NULL) - return NULL; - hdr++; - for (;;) { - if (!os_strncasecmp(hdr, tag, tag_len)) { - hdr += tag_len; - while (*hdr == ' ' || *hdr == '\t') - hdr++; - return hdr; - } - hdr = os_strchr(hdr, '\n'); - if (hdr == NULL) - return NULL; - hdr++; - } -} diff --git a/hostapd-0.8/src/wps/httpread.h b/hostapd-0.8/src/wps/httpread.h deleted file mode 100644 index 51aa214..0000000 --- a/hostapd-0.8/src/wps/httpread.h +++ /dev/null @@ -1,123 +0,0 @@ -/* - * httpread - Manage reading file(s) from HTTP/TCP socket - * Author: Ted Merrill - * Copyright 2008 Atheros Communications - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#ifndef HTTPREAD_H -#define HTTPREAD_H - -/* event types (passed to callback) */ -enum httpread_event { - HTTPREAD_EVENT_FILE_READY = 1, /* including reply ready */ - HTTPREAD_EVENT_TIMEOUT = 2, - HTTPREAD_EVENT_ERROR = 3 /* misc. error, esp malloc error */ -}; - - -/* header type detected - * available to callback via call to httpread_reply_code_get() - */ -enum httpread_hdr_type { - HTTPREAD_HDR_TYPE_UNKNOWN = 0, /* none of the following */ - HTTPREAD_HDR_TYPE_REPLY = 1, /* hdr begins w/ HTTP/ */ - HTTPREAD_HDR_TYPE_GET = 2, /* hdr begins with GET */ - HTTPREAD_HDR_TYPE_HEAD = 3, /* hdr begins with HEAD */ - HTTPREAD_HDR_TYPE_POST = 4, /* hdr begins with POST */ - HTTPREAD_HDR_TYPE_PUT = 5, /* hdr begins with ... */ - HTTPREAD_HDR_TYPE_DELETE = 6, /* hdr begins with ... */ - HTTPREAD_HDR_TYPE_TRACE = 7, /* hdr begins with ... */ - HTTPREAD_HDR_TYPE_CONNECT = 8, /* hdr begins with ... */ - HTTPREAD_HDR_TYPE_NOTIFY = 9, /* hdr begins with ... */ - HTTPREAD_HDR_TYPE_M_SEARCH = 10, /* hdr begins with ... */ - HTTPREAD_HDR_TYPE_M_POST = 11, /* hdr begins with ... */ - HTTPREAD_HDR_TYPE_SUBSCRIBE = 12, /* hdr begins with ... */ - HTTPREAD_HDR_TYPE_UNSUBSCRIBE = 13, /* hdr begins with ... */ - - HTTPREAD_N_HDR_TYPES /* keep last */ -}; - - -/* control instance -- opaque struct declaration - */ -struct httpread; - - -/* httpread_destroy -- if h is non-NULL, clean up - * This must eventually be called by the application following - * call of the application's callback and may be called - * earlier if desired. - */ -void httpread_destroy(struct httpread *h); - -/* httpread_create -- start a new reading session making use of eloop. - * The new instance will use the socket descriptor for reading (until - * it gets a file and not after) but will not close the socket, even - * when the instance is destroyed (the application must do that). - * Return NULL on error. - * - * Provided that httpread_create successfully returns a handle, - * the callback fnc is called to handle httpread_event events. - * The caller should do destroy on any errors or unknown events. - * - * Pass max_bytes == 0 to not read body at all (required for e.g. - * reply to HEAD request). - */ -struct httpread * httpread_create( - int sd, /* descriptor of TCP socket to read from */ - void (*cb)(struct httpread *handle, void *cookie, - enum httpread_event e), /* call on event */ - void *cookie, /* pass to callback */ - int max_bytes, /* maximum file size else abort it */ - int timeout_seconds /* 0; or total duration timeout period */ - ); - -/* httpread_hdr_type_get -- When file is ready, returns header type. - */ -enum httpread_hdr_type httpread_hdr_type_get(struct httpread *h); - - -/* httpread_uri_get -- When file is ready, uri_get returns (translated) URI - * or possibly NULL (which would be an error). - */ -char *httpread_uri_get(struct httpread *h); - -/* httpread_reply_code_get -- When reply is ready, returns reply code */ -int httpread_reply_code_get(struct httpread *h); - - -/* httpread_length_get -- When file is ready, returns file length. */ -int httpread_length_get(struct httpread *h); - -/* httpread_data_get -- When file is ready, returns file content - * with null byte appened. - * Might return NULL in some error condition. - */ -void * httpread_data_get(struct httpread *h); - -/* httpread_hdr_get -- When file is ready, returns header content - * with null byte appended. - * Might return NULL in some error condition. - */ -char * httpread_hdr_get(struct httpread *h); - -/* httpread_hdr_line_get -- When file is ready, returns pointer - * to line within header content matching the given tag - * (after the tag itself and any spaces/tabs). - * - * The tag should end with a colon for reliable matching. - * - * If not found, returns NULL; - */ -char * httpread_hdr_line_get(struct httpread *h, const char *tag); - -#endif /* HTTPREAD_H */ diff --git a/hostapd-0.8/src/wps/ndef.c b/hostapd-0.8/src/wps/ndef.c deleted file mode 100644 index 9baec7f..0000000 --- a/hostapd-0.8/src/wps/ndef.c +++ /dev/null @@ -1,175 +0,0 @@ -/* - * NDEF(NFC Data Exchange Format) routines for Wi-Fi Protected Setup - * Reference is "NFCForum-TS-NDEF_1.0 2006-07-24". - * Copyright (c) 2009, Masashi Honma - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#include "includes.h" -#include "common.h" -#include "wps/wps.h" -#include "wps/wps_i.h" - -#define FLAG_MESSAGE_BEGIN (1 << 7) -#define FLAG_MESSAGE_END (1 << 6) -#define FLAG_CHUNK (1 << 5) -#define FLAG_SHORT_RECORD (1 << 4) -#define FLAG_ID_LENGTH_PRESENT (1 << 3) -#define FLAG_TNF_RFC2046 (0x02) - -struct ndef_record { - u8 *type; - u8 *id; - u8 *payload; - u8 type_length; - u8 id_length; - u32 payload_length; - u32 total_length; -}; - -static char wifi_handover_type[] = "application/vnd.wfa.wsc"; - -static int ndef_parse_record(u8 *data, u32 size, struct ndef_record *record) -{ - u8 *pos = data + 1; - - if (size < 2) - return -1; - record->type_length = *pos++; - if (data[0] & FLAG_SHORT_RECORD) { - if (size < 3) - return -1; - record->payload_length = *pos++; - } else { - if (size < 6) - return -1; - record->payload_length = ntohl(*(u32 *)pos); - pos += sizeof(u32); - } - - if (data[0] & FLAG_ID_LENGTH_PRESENT) { - if ((int) size < pos - data + 1) - return -1; - record->id_length = *pos++; - } else - record->id_length = 0; - - record->type = record->type_length == 0 ? NULL : pos; - pos += record->type_length; - - record->id = record->id_length == 0 ? NULL : pos; - pos += record->id_length; - - record->payload = record->payload_length == 0 ? NULL : pos; - pos += record->payload_length; - - record->total_length = pos - data; - if (record->total_length > size) - return -1; - return 0; -} - - -static struct wpabuf * ndef_parse_records(struct wpabuf *buf, - int (*filter)(struct ndef_record *)) -{ - struct ndef_record record; - int len = wpabuf_len(buf); - u8 *data = wpabuf_mhead(buf); - - while (len > 0) { - if (ndef_parse_record(data, len, &record) < 0) { - wpa_printf(MSG_ERROR, "NDEF : Failed to parse"); - return NULL; - } - if (filter == NULL || filter(&record)) - return wpabuf_alloc_copy(record.payload, - record.payload_length); - data += record.total_length; - len -= record.total_length; - } - wpa_printf(MSG_ERROR, "NDEF : Record not found"); - return NULL; -} - - -static struct wpabuf * ndef_build_record(u8 flags, void *type, - u8 type_length, void *id, - u8 id_length, void *payload, - u32 payload_length) -{ - struct wpabuf *record; - size_t total_len; - int short_record; - u8 local_flag; - - short_record = payload_length < 256 ? 1 : 0; - - total_len = 2; /* flag + type length */ - /* payload length */ - total_len += short_record ? sizeof(u8) : sizeof(u32); - if (id_length > 0) - total_len += 1; - total_len += type_length + id_length + payload_length; - record = wpabuf_alloc(total_len); - if (record == NULL) { - wpa_printf(MSG_ERROR, "NDEF : Failed to allocate " - "record for build"); - return NULL; - } - - local_flag = flags; - if (id_length > 0) - local_flag |= FLAG_ID_LENGTH_PRESENT; - if (short_record) - local_flag |= FLAG_SHORT_RECORD; - wpabuf_put_u8(record, local_flag); - - wpabuf_put_u8(record, type_length); - - if (short_record) - wpabuf_put_u8(record, payload_length); - else - wpabuf_put_be32(record, payload_length); - - if (id_length > 0) - wpabuf_put_u8(record, id_length); - wpabuf_put_data(record, type, type_length); - wpabuf_put_data(record, id, id_length); - wpabuf_put_data(record, payload, payload_length); - return record; -} - - -static int wifi_filter(struct ndef_record *record) -{ - if (record->type_length != os_strlen(wifi_handover_type)) - return 0; - if (os_memcmp(record->type, wifi_handover_type, - os_strlen(wifi_handover_type)) != 0) - return 0; - return 1; -} - - -struct wpabuf * ndef_parse_wifi(struct wpabuf *buf) -{ - return ndef_parse_records(buf, wifi_filter); -} - - -struct wpabuf * ndef_build_wifi(struct wpabuf *buf) -{ - return ndef_build_record(FLAG_MESSAGE_BEGIN | FLAG_MESSAGE_END | - FLAG_TNF_RFC2046, wifi_handover_type, - os_strlen(wifi_handover_type), NULL, 0, - wpabuf_mhead(buf), wpabuf_len(buf)); -} diff --git a/hostapd-0.8/src/wps/upnp_xml.c b/hostapd-0.8/src/wps/upnp_xml.c deleted file mode 100644 index b1b1e2b..0000000 --- a/hostapd-0.8/src/wps/upnp_xml.c +++ /dev/null @@ -1,252 +0,0 @@ -/* - * UPnP XML helper routines - * Copyright (c) 2000-2003 Intel Corporation - * Copyright (c) 2006-2007 Sony Corporation - * Copyright (c) 2008-2009 Atheros Communications - * Copyright (c) 2009, Jouni Malinen - * - * See wps_upnp.c for more details on licensing and code history. - */ - -#include "includes.h" - -#include "common.h" -#include "base64.h" -#include "http.h" -#include "upnp_xml.h" - - -/* - * XML parsing and formatting - * - * XML is a markup language based on unicode; usually (and in our case, - * always!) based on utf-8. utf-8 uses a variable number of bytes per - * character. utf-8 has the advantage that all non-ASCII unicode characters are - * represented by sequences of non-ascii (high bit set) bytes, whereas ASCII - * characters are single ascii bytes, thus we can use typical text processing. - * - * (One other interesting thing about utf-8 is that it is possible to look at - * any random byte and determine if it is the first byte of a character as - * versus a continuation byte). - * - * The base syntax of XML uses a few ASCII punctionation characters; any - * characters that would appear in the payload data are rewritten using - * sequences, e.g., & for ampersand(&) and < for left angle bracket (<). - * Five such escapes total (more can be defined but that does not apply to our - * case). Thus we can safely parse for angle brackets etc. - * - * XML describes tree structures of tagged data, with each element beginning - * with an opening tag with - * matching label. (There is also a self-closing tag